Problems in CCameraSceneNode
Posted: Sun Aug 23, 2009 1:53 am
This will be a long post, but it includes a solution, so I hope it will be worth it.
Like many others before me I was experimenting with creating a flight/space-sim type camera, and ran into a number of issues with camera positioning and rotation. After searching the forums and Internet I found some workarounds, but no real solutions. On investigating I have found a number of bugs in the CCameraSceneNode code that are responsible for these problems.
The code provided by arras in http://irrlicht.sourceforge.net/phpBB2/ ... ht&start=0 works specifically because it compensates for these bugs, and is mostly what I've used to update CCameraSceneNode.
The bugs.
First, there are two issues in setTarget. Here is the original code.
The use of getHorizontalAngle sets the Z rotation to 0. This makes it impossible to 'roll' the camera around it's Z axis, since the first call to setTarget will wipe out any Z rotation anyway.
Secondly, changing the target changes the camera's up vector, but no account is made for this.
Next, there are similar problems in setRotation. Original code:
The first problem occurs because rotationToDirection returns a unit vector. This resets the target to be one unit in front of the camera, leading to unexpected behaviours. If the target was 100 units away, moving the camera 1 unit left or right would cause a rotation of about one half of one degree. After calling setRotation, moving the camera one unit left or right would cause a rotation of 45 degrees.
The second problem here is again the up vector. Changing the rotation changes the up vector, but this is not handled.
A related issue exists in setUpVector:
The code sets the up vector, but changing the up vector also (presumably) changes the camera's direction vector, and target, neither of which are updated.
Another, minor issue exists in the code for OnRegisterSceneNode:
The "fix" used here is to add .5 to the X value of the up vector. Unfortunately this simply makes the two vectors different, and actually introduces a small Z rotation. Fortunately, if the up vector and target are updated properly, this should never happen anyway.
Using the code from arras as referenced above I have updated the code for CCameraSceneNode::setRotation() and CCamerSceneNode::setTarget(). In addition I have added two new member functions, moveCamera() and rotateCamera(), that move and rotate the camera by a relative amount.
These changes make implementing a flight-sim type camera intuitive and easy. My new code will be posted in the next couple posts, along with a demo program.
Steve
Like many others before me I was experimenting with creating a flight/space-sim type camera, and ran into a number of issues with camera positioning and rotation. After searching the forums and Internet I found some workarounds, but no real solutions. On investigating I have found a number of bugs in the CCameraSceneNode code that are responsible for these problems.
The code provided by arras in http://irrlicht.sourceforge.net/phpBB2/ ... ht&start=0 works specifically because it compensates for these bugs, and is mostly what I've used to update CCameraSceneNode.
The bugs.
First, there are two issues in setTarget. Here is the original code.
Code: Select all
//! sets the look at target of the camera
//! \param pos: Look at target of the camera.
void CCameraSceneNode::setTarget(const core::vector3df& pos)
{
Target = pos;
if(TargetAndRotationAreBound)
{
const core::vector3df toTarget = Target - getAbsolutePosition();
ISceneNode::setRotation(toTarget.getHorizontalAngle());
}
}
Secondly, changing the target changes the camera's up vector, but no account is made for this.
Next, there are similar problems in setRotation. Original code:
Code: Select all
//! Sets the rotation of the node.
void CCameraSceneNode::setRotation(const core::vector3df& rotation)
{
if(TargetAndRotationAreBound)
Target = getAbsolutePosition() + rotation.rotationToDirection();
ISceneNode::setRotation(rotation);
}
The second problem here is again the up vector. Changing the rotation changes the up vector, but this is not handled.
A related issue exists in setUpVector:
Code: Select all
void CCameraSceneNode::setUpVector(const core::vector3df& pos)
{
UpVector = pos;
}
Another, minor issue exists in the code for OnRegisterSceneNode:
Code: Select all
void CCameraSceneNode::OnRegisterSceneNode()
{
<snip>
// if upvector and vector to the target are the same, we have a
// problem. so solve this problem:
core::vector3df up = UpVector;
up.normalize();
f32 dp = tgtv.dotProduct(up);
if ( core::equals(fabsf(dp), 1.f) )
{
up.X += 0.5f;
}
<snip>
Using the code from arras as referenced above I have updated the code for CCameraSceneNode::setRotation() and CCamerSceneNode::setTarget(). In addition I have added two new member functions, moveCamera() and rotateCamera(), that move and rotate the camera by a relative amount.
These changes make implementing a flight-sim type camera intuitive and easy. My new code will be posted in the next couple posts, along with a demo program.
Steve