Game Development Community

Help! MouseEvent to PlayerCamera movement

by Richard Dechow · in Torque Game Engine · 09/08/2008 (11:57 am) · 21 replies

Update Title is irrelevant: A proper title would be "Camera Twitching with minor modification to C++", I'd modify the title if I could.

I've been struggling with this for days in TGE.

I'm trying to figure out exactly where in the c++ the pitch and yaw from a mouseEvent get translated to the player camera Pitch/Yaw movement.

I've gotten as far as processTick, but it doesn't appear that the majority of the function even controls actual camera movement when its mounted to a player.

My issue is, I'm Hooking mouse movement into an encoder thats part of a device were using to control the camera. We were originally translating the encoder values to exact transforms (in torque script), but for some odd reason we were getting anywhere from 1/2 to 1 second lag before the game would actually respond to any values the encoder passed. Being that mouse movement seamed to be instantaneous we hooked the encoder to the mouse x, y and what do you know, no more lag.

Now there are 2 issues with the mouse. The fist being Its not absolute, so our view will vary off over time with the same amount of movement from the encoder. the second is, when the FOV is lowered the movement from the camera is also lowered with each MouseEvent. We need the camera movement to be the same no matter the FOV. The reason being is our main game mechanic is Virtual Reality so we need game movement to correspond with real world movement.


Recap:
1. Where in the C++ is Player camera Pitch/Yaw movement controlled? (more specifically by mouseEvent?)
2. How do I remove the FOV from the camera movement equation? (e.g. Locking the FOV to 90 in the movement Equation, but still allow viewport FOV to be changed.)
Page «Previous 1 2
#1
09/08/2008 (12:09 pm)
I can only answer this for TGEA but player movement his handled with MoveManager. with the cursor showing mouse movements are handled through guiTSCtrl.cpp.
#2
09/08/2008 (12:28 pm)
I guess I should have specified that as well, we are using TGE.

I've looked threw the MoveManager, the issue with Mov Manager, is it appears to control all movement in game, I'm looking specifically for controlled player movement.

guiTSCtrl, doesn't really help either, it Doesn't really handle camera coordinates much at all.

but thanks for your help anyway.
#3
09/08/2008 (1:55 pm)
Do you mean like Player::updateMove? The mouse axis is bound to a function which sets one of the $mvMove variables, which is converted into a C++ Move object by the move manager, I believe. And then that move is processed in Player::updateMove, eg, converted into a delta.rot value.
#4
09/08/2008 (2:02 pm)
!!!!! player.cc !! That went completely over my head, thats probably exactly the area I need to be looking at! Ok, I'll be sure to give an update after I've taken a look.
#5
09/08/2008 (2:23 pm)
If u have the cursor showing then all mouse movements go through guiTSCtrl.cpp onmouseMove function instead of through the action map.
#6
09/09/2008 (10:09 am)
@timothy: Were tracking mouseEvent.x, y for camera movement the cursor is irrelevant, but thank you anyway.

I'm now controlling the Camera via the player object again, with absolute values, which im setting in the "delta.rot", and "delta.head"in "Player::UpdateMove". but this doesn't seam to be the only place were the mouse axis values get passes to the camera/player object, because if I move the mouse, the camera will twitch, even if I set the delta to a static value.

I cant seam to pinpoint where its at, but I'm guessing its the same reason I get a "flicker" when just having the game set idle (the camera randomly will rotate and point somewhere else for a frame or 2, and then reset back to where I told it to.)

I don't want to put someone into epileptic seizure, and it flickers enough at times it just might.

any other clues anyone can throw my way?

thanks for the help thus far.
#7
09/09/2008 (10:49 am)
Just out of curiosity have you changed your default.bind.cs? There is the mouse xaxis and yaxis set to move yaw and pitch respectively. You also have some FOV stuff in the getMouseAdjustAmount. *edit Be sure to delete your prefs files if you change the bind files.

function getMouseAdjustAmount(%val)
{
   // based on a default camera fov of 90'
   return(%val * ($cameraFov / 90) * 0.01);
}

function yaw(%val)
{
   $mvYaw += getMouseAdjustAmount(%val);
}

function pitch(%val)
{
   $mvPitch += getMouseAdjustAmount(%val);
}

moveMap.bind( mouse, xaxis, yaw );
moveMap.bind( mouse, yaxis, pitch );

Additionally if you check GameUpdateCameraFov() in game.cc you will see some more FOV stuff. It is called from GameTSCtrl.cc which also calls GameProcessCameraQuery(CameraQuery *query) that has even more FOV stuff.

The settings you want really are in MoveManager::mYaw and MoveManager::mPitch. I know you mentioned you looked at it. What it controls is the client. If you create multiple cameras, it controls all the cameras. This is altered as James mentioned from the $mv* variables in script, specifically in default.bind.cs. This would give you the ultimate control for what you are trying to do.

I hope I'm understanding correctly, please give some more detail or clarify a bit if I'm off base.
#8
09/09/2008 (11:59 am)
Thank you again, but I guess I'm no longer actually looking for the POV stuff, but that was exactly what I was looking for, Its sad I looked right over it.

Anyway, as far as the twitching goes,


I've looked into interpolateTick, but it doesn't appear its hit that much if not ever while on the client controlled player.
#9
09/09/2008 (12:31 pm)
InterpolateTick would only be if you needed to catch up to the server. It should only be called rarely.

processTick is called once every 32ms.

A quote from your above post that I overlooked.
Quote:
I've gotten as far as processTick, but it doesn't appear that the majority of the function even controls actual camera movement when its mounted to a player.

If you check gameProcess.cc and look for

// Sync up the control object with the latest client moves.
         Move* movePtr;
         U32 m = 0, numMoves;
         connection->getMoveList(&movePtr, &numMoves);
         while (m < numMoves)
         {
            control->processTick(&movePtr[m++]);
         }
         connection->clearMoves(m);

You'll see that players process tick deals mainly with moves in regards the the attached camera.

I'm not looking at your code, so I can't be sure, but to me it seems logical that the twitching comes from updateMove changing what processTick has set (that is, if you're still setting delta rotations to absolute values).

Let me know if I'm off base. :)
#10
09/09/2008 (12:53 pm)
If you want to control the delta.rot of the player yourself then you don't really need the ActionMap binds to the mouse at all right? I think thats what William was saying, just don't bind the mouse x/y axis's, or if you want this mode "toggleable" something like this:
$input::mouseControl = false;

function yaw(%val)
{
   if ( $input::mouseControl )
      $mvYaw += getMouseAdjustAmount(%val);
}

function pitch(%val)
{
   if ( $input::mouseControl )
      $mvPitch += getMouseAdjustAmount(%val);
}

moveMap.bind( mouse, xaxis, yaw );
moveMap.bind( mouse, yaxis, pitch );
#11
09/09/2008 (12:55 pm)
Absolutely James, thanks for clarifying.
#12
09/09/2008 (12:59 pm)
Well, I've set a break point on that section of the code in gameProcess.cc and it actually never hits the breakpoint.
#13
09/09/2008 (1:09 pm)
I understood William, I've already disabled the pitch and yaw functions, I was hopeing it was just garbage from the mouse that was causing the twitch but it doesn't appear to be the case.

I'm guessing where I've hacked in the delta.rot to read my encoder (around line 1446 of player.cc, in the updateMove function) isn't low enough. its to high level of variable, If I could find exactly where the camera/player object store there position, I'd just ignore everything else passed to it. But I can't seam to pinpoint where it is in the c++ code.



And to clarify on the twitching, the camera pitch and or yaw, for probably just 1 or 2 frames, goes haywire, and points in a completely different direction then I have specified in the delta.rot and head., mind that this is the only modification of the camera/player positioning system I've done. If I comment out my hack there is no issue at all.

heres literally all I've added

if(getControllingClient())
	  {
		  delta.rot.set(0,0,3.14159265);
		  delta.head.set(0.785398163,0,0);
		  delta.headVec.set(0,0,0);
	  }
	  else
	  {
		  delta.head = mHead;
		  delta.headVec -= mHead;
	  }

do you think it might be delta.headVec? if I set it to anything other then 0, it goes crazy with the camera, but I have a feeling it isn't supposed to always be 0.
#14
09/09/2008 (1:11 pm)
I just found a cool GameBase method (gameBase.h) that might be of use to you.
/// Allow object a chance to tweak move before it is sent to client and server.
virtual void preprocessMove(Move *move);
It must be new because I haven't seen it before, so may or may not be in the version you are working with. In any case, you can overload it in the player class (or your player class) and do whatever move-manipulations you want before it even gets sent out/processed.
#15
09/09/2008 (1:25 pm)
The position is stored in mTransform, getTransform(), setTransform(), setPosition() are methods you might look at.
#16
09/09/2008 (1:25 pm)
The world position? It is set in the objects transform. You can override setRenderTransform/setRenderPosition and setTransform/setPosition to manipulate what gets sent.

directly setting the objects matrix would prevent smooth interpolation however.

I've checked for the right piece of code that calls the camera. Sorry for steering you in the wrong direction. I'll be sure to test what I say before I post it in the future.

In gameProcess.cc

// If we are going to tick, or have moves pending for the
   // control object, we need to reset everyone back to their
   // last full tick pos.
   if (mLastDelta && (tickCount || control))
      for (GameBase* obj = head.mProcessLink.next; obj != &head;
            obj = obj->mProcessLink.next)
         if (obj->mProcessTick)
            obj->interpolateTick(0);

Let me know if this works. :)
#17
09/09/2008 (1:28 pm)
@James Ford: I'm using TGE 1.5.2 I do believe. It appears theres a declaration but I see nothing else in relation to in in the source code. nothing references or calls it. I'm guessing its an unfinished method as far as 1.5.2 goes.
#18
09/09/2008 (2:00 pm)
This doesn't make any sense... I've gone as far as setting the rot to a static number in Camera::setRenderPosition Which should almost definitely lock the position, but it still flickers..
#19
09/09/2008 (9:35 pm)
Sorry for the late response, I had to go in to work for a little while.

Have you found a resolution?

I dropped in your code and noticed the flicker. To stop it I added: mHead.set(0.785398163,0,0); below delta.head. Though I did not do any further testing, I image the problem is in that unpackUpdate in player.cc sets delta.head using the altered mHead from updateMove, and thereby dismissing your absolute values.

Setting delta values will not be transmitted over the network. The only reason it works most of the time is because interpolateTick sets mHead with the delta.head. If there is a call to pack/unpackUpdate after proccessTick and before interpolateTick your mHead will stay unaltered. And if there is a call to getRenderEyeTransform/getEyeTransform (since it's only first person) before the next tick it will cause a flicker. Rare case it seems.

From the little that I know about what you're trying to do, it's my humble opinion that it would work best in script and properly networked. Just an opinion.

Edit *What I wrote didn't make sense. Or at least I couldn't understand it after reading it again. I re-worded.
#20
09/10/2008 (9:25 am)
We've already tried scripting, the issue is the torque script just isn't fast enough for how fast our encoder device outputs its data, which in case causes a more then noticeable amount of delay between Input and response, which we need to be as real time as possible. I'll be sure to try mHead.set , it sounds like that was the last bit I needed, I'll be sure to tell you how it goes.

And again thanks everyone for all the help.


Update: Well that did the trick, for the most part anyway. I also ended up adding mRot.set as well but that was a given after mHead.set

Thank you William.
Page «Previous 1 2