Smooth FPS camera
Posted: Mon Apr 19, 2004 2:19 pm
Hi!
As we all know rotation in Irrlichts default cameras is really jerky. There are two reasons for that:
1) small mouse position changes are not regonized
2) rotation angle may differ between frames because of aproximation (ex: if you move your mouse with a speed of 3.5 pixels per frame in one frame it will be treated as you had moved 3 pixel and in next frame as 4 pixels)
Ad.1
Quite easy to fix. Just change this lines in
CCameraFPSSceneNode::animate() (CCameraFPSSceneNode.cpp)to
Ad.2
The way to solve this is taking average mouse posiotion change of last 3 frames instead of only last one.
First we have to add to tables to hold last two mouse positions and a variable to checkif it is the first time we make rotation. Just put this into CCameraFPSSceneNode definition (CCameraFPSSceneNode.h)
Then in CCameraFPSSceneNode::animate() (CCameraFPSSceneNode.cpp) change the following:
Now compile and enjoy smooth rotation
It's still not perfect but works well most of the time.
If you find some bugs or have some improvements i'll be glad to read them.
To Nico: How about adding it to SDK ? And another thing. Why default value for FOV is set to 45 degrees ? With it camera works like in alien mode form AvP
Set it to 90 or something. I know it's easy to change via FOV(), but some newbies might have problems with "what's wrong with the camer" while watching techdemo or examples.
As we all know rotation in Irrlichts default cameras is really jerky. There are two reasons for that:
1) small mouse position changes are not regonized
2) rotation angle may differ between frames because of aproximation (ex: if you move your mouse with a speed of 3.5 pixels per frame in one frame it will be treated as you had moved 3 pixel and in next frame as 4 pixels)
Ad.1
Quite easy to fix. Just change this lines in
CCameraFPSSceneNode::animate() (CCameraFPSSceneNode.cpp)
Code: Select all
if (cursorpos.X < 0.49f || cursorpos.X > 0.51f ||
cursorpos.Y < 0.49f || cursorpos.Y > 0.51f)
Code: Select all
if (cursorpos.X < 0.5f || cursorpos.X > 0.5f ||
cursorpos.Y < 0.5f || cursorpos.Y > 0.5f)
The way to solve this is taking average mouse posiotion change of last 3 frames instead of only last one.
First we have to add to tables to hold last two mouse positions and a variable to checkif it is the first time we make rotation. Just put this into CCameraFPSSceneNode definition (CCameraFPSSceneNode.h)
Code: Select all
f32 rotX[3];
f32 rotY[3];
bool firstRot;
Code: Select all
// Update rotation
Target.set(0,0,1);
if (!CursorControl)
return;
RelativeRotation.X *= -1.0f;
RelativeRotation.Y *= -1.0f;
if (InputReceiverEnabled)
{
core::position2d<f32> cursorpos = CursorControl->getRelativePosition();
if(firstRot) // it checks if it is the first time camera rotates and than fill tables with proper values
{
rotX[0] = rotX[1] = 0.5f - cursorpos.X;
rotY[0] = rotY[1] = 0.5f - cursorpos.Y;
firstRot=false;
}
rotX[2] = 0.5f - cursorpos.X; // puts values from this frame
rotY[2] = 0.5f - cursorpos.Y;// into table
if (cursorpos.X < 0.5 || cursorpos.X > 0.5 ||
cursorpos.Y < 0.5 || cursorpos.Y > 0.5 )
{
RelativeRotation.Y += (rotX[0]+rotX[1]+rotX[2])/3 * RotateSpeed; // here we use the average value i mentioned before
RelativeRotation.X += (rotY[0]+rotY[1]+rotY[2])/3 * RotateSpeed; // and here too ;)
CursorControl->setPosition(0.5f, 0.5f);
if (RelativeRotation.X > 89.0f) RelativeRotation.X = 89.0f;
if (RelativeRotation.X < -89.0f) RelativeRotation.X = -89.0f;
}
rotX[0] = rotX[1]; // finaly we move values to make room for a new ones
rotX[1] = rotX[2];
rotY[0] = rotY[1];
rotY[1] = rotY[2];
}
// set target

If you find some bugs or have some improvements i'll be glad to read them.
To Nico: How about adding it to SDK ? And another thing. Why default value for FOV is set to 45 degrees ? With it camera works like in alien mode form AvP
