Game Development Community

Mouse value problems

by Mikael Larsson · in Torque Game Engine · 03/21/2007 (11:50 pm) · 3 replies

The problem is as follows, I control the camera with the mouse. When I move the mouse real fast the speed value overflows this giving a negative value when it should be positive and vice verse.

Do anyone have an idea what I can do to fix this? Someone else must have had the same problem.

Thanks

Mikael

#1
03/26/2007 (7:55 am)
Ok, I think this could depend on 2 things:

One, the move manager clamps the range of what mouse movement values you can pass over the net from the client to the server. I believe, for mouse rotations, it is 2 PI (360 degrees). Here is the code:

\game\gameConnectionMoves.cpp
#define FANG2IANG(x)   ((U32)((S16)((F32(0x10000) / M_2PI) * x)) & 0xFFFF)
#define IANG2FANG(x)   (F32)((M_2PI / F32(0x10000)) * (F32)((S16)x))

void Move::unclamp()
{
   yaw = IANG2FANG(pyaw);
   pitch = IANG2FANG(ppitch);
   roll = IANG2FANG(proll);

   x = (px - 16) / F32(16);
   y = (py - 16) / F32(16);
   z = (pz - 16) / F32(16);
}

void Move::clamp()
{
   // angles are all 16 bit.
   pyaw = FANG2IANG(yaw);
   ppitch = FANG2IANG(pitch);
   proll = FANG2IANG(roll);

   px = clampRangeClamp(x);
   py = clampRangeClamp(y);
   pz = clampRangeClamp(z);
   unclamp();
}

The IANG2FANG and FANG2IANG macros do the mouse clamping. So, if you pass in a value over 2 PI, you are going to end up with something a lot different - though in honesty I can't remember what it is and can't totally understand those cryptic macros unless I walk it through the debugger.

So, if the move manager clamps your mouse value, you have another problem if the control object which takes the input doesn't take that into account.

For the Player class, it stores rotations via Euler angles, and from what I remember the engine limits the amount a player can rotate to PI (180 degrees), and handles the wrap around for you:

Here's the relevant code that does this in player.cc
void Player::updateMove(const Move* move)

// .......

      // constrain the range of mRot.z
      while (mRot.z < 0)
         mRot.z += M_2PI;
      while (mRot.z > M_2PI)
         mRot.z -= M_2PI;

      delta.rot = mRot;
      delta.rotVec.x = delta.rotVec.y = 0;
      delta.rotVec.z = prevZRot - mRot.z;
      if (delta.rotVec.z > M_PI)
         delta.rotVec.z -= M_2PI;
      else if (delta.rotVec.z < -M_PI)
         delta.rotVec.z += M_2PI;


However, if you are working with a custom camera class dealing with rotation, and you don't have something like that in the tick function to handle the move manager clamp and wrap-arounds, you might start seeing the behavior you mentioned - moving in the opposite direction on a fast mouse move.

To fix the issue, either clamp the values yourself to PI before passing them into the move manager (clamp $mvYaw and $mvPitch with a script callback from GameConnection::getNextMove()) and/or make sure your custom class handles rotation wrap-arounds.

Hope this helps somewhat --- sorry if it is not so clear...
#2
04/02/2007 (2:58 am)
Thanks, now I have a starting point at least.
#3
04/02/2007 (1:27 pm)
Sure thing. :) Let us know how it goes...