Reducing the optional camera binding to a boolean that binds both ways (rotation to target and vice versa). Thanks to Dorth for suggesting this, which sorts the FPS camera out properly.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1750 dfc29bdd-3216-0410-991c-e03cc46cb475
master
Rogerborg 2008-11-14 18:10:47 +00:00
parent 55a8f70713
commit 06ad4408b7
4 changed files with 65 additions and 56 deletions

View File

@ -58,9 +58,18 @@ namespace scene
virtual bool OnEvent(const SEvent& event) = 0;
//! Sets the look at target of the camera
/** \param pos: Look at target of the camera. */
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's scene node rotation to match the target.
\param pos: Look at target of the camera. */
virtual void setTarget(const core::vector3df& pos) = 0;
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
virtual void setRotation(const core::vector3df& rotation) = 0;
//! Gets the current look at target of the camera
/** \return Returns the current look at target of the camera */
virtual const core::vector3df& getTarget() const = 0;
@ -125,27 +134,17 @@ namespace scene
return IsOrthogonal;
}
//! Determines how the camera's target and its scene node rotation are bound together.
typedef enum _TargetAndRotationBinding
{
//! The target and scene node rotation are independent.
/** This is the default for most cameras. */
TARGET_AND_ROTATION_INDEPENDENT = 0x10000,
//! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them.
/** When bound, calling setRotation() will update the camera's target position to be along
its +Z axis, and likewise calling setTarget() will update its rotation so that its +Z axis
will point at the target point. FPS camera use this binding by default; other cameras do not.
\param binding true to bind the camera's scene node rotation and targetting, false to unbind them.
@see getTargetAndRotationBinding() */
virtual void bindTargetAndRotation(bool bound) = 0;
//! The scene node rotation will be updated so that +Z points at the target location.
/** This is the default for FPS camera */
ROTATION_FOLLOWS_TARGET,
//! The target position will be updated to be along the node's +Z axis
TARGET_FOLLOWS_ROTATION
} TargetAndRotationBinding;
//! Set the binding between the camera's rotation adn target.
virtual void setTargetAndRotationBinding(TargetAndRotationBinding binding) = 0;
//! Gets the binding between the camera's rotation and target.
virtual TargetAndRotationBinding getTargetAndRotationBinding(void) const = 0;
//! Queries if the camera scene node's rotation and its target position are bound together.
/** @see bindTargetAndRotation() */
virtual bool getTargetAndRotationBinding(void) const = 0;
protected:

View File

@ -19,7 +19,7 @@ CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 i
: ICameraSceneNode(parent, mgr, id, position, core::vector3df(0.0f, 0.0f, 0.0f),
core::vector3df(1.0f, 1.0f, 1.0f)),
Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
InputReceiverEnabled(true)
InputReceiverEnabled(true), TargetAndRotationAreBound(false)
{
#ifdef _DEBUG
setDebugName("CCameraSceneNode");
@ -110,6 +110,26 @@ bool CCameraSceneNode::OnEvent(const SEvent& event)
void CCameraSceneNode::setTarget(const core::vector3df& pos)
{
Target = pos;
if(TargetAndRotationAreBound)
{
const core::vector3df toTarget = Target - getAbsolutePosition();
ISceneNode::setRotation(toTarget.getHorizontalAngle());
}
}
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
void CCameraSceneNode::setRotation(const core::vector3df& rotation)
{
if(TargetAndRotationAreBound)
Target = getAbsolutePosition() + rotation.rotationToDirection();
ISceneNode::setRotation(rotation);
}
@ -203,22 +223,6 @@ void CCameraSceneNode::OnRegisterSceneNode()
core::vector3df tgtv = Target - pos;
tgtv.normalize();
switch(Binding)
{
case ROTATION_FOLLOWS_TARGET:
setRotation(tgtv.getHorizontalAngle());
break;
case TARGET_FOLLOWS_ROTATION:
tgtv = getRotation().rotationToDirection(); // Already normalised
setTarget(pos + tgtv);
break;
default:
break;
}
// if upvector and vector to the target are the same, we have a
// problem. so solve this problem:
core::vector3df up = UpVector;
@ -286,7 +290,7 @@ void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR
out->addFloat("Aspect", Aspect);
out->addFloat("ZNear", ZNear);
out->addFloat("ZFar", ZFar);
out->addInt("Binding", (int)Binding);
out->addBool("Binding", TargetAndRotationAreBound);
}
@ -301,10 +305,7 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute
Aspect = in->getAttributeAsFloat("Aspect");
ZNear = in->getAttributeAsFloat("ZNear");
ZFar = in->getAttributeAsFloat("ZFar");
Binding = (ICameraSceneNode::TargetAndRotationBinding)in->getAttributeAsInt("Binding");
if(0 == Binding)
Binding = TARGET_AND_ROTATION_INDEPENDENT;
TargetAndRotationAreBound = in->getAttributeAsBool("Binding");
recalculateProjectionMatrix();
recalculateViewArea();
@ -312,15 +313,15 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute
//! Set the binding between the camera's rotation adn target.
void CCameraSceneNode::setTargetAndRotationBinding(TargetAndRotationBinding binding)
void CCameraSceneNode::bindTargetAndRotation(bool bound)
{
Binding = binding;
TargetAndRotationAreBound = bound;
}
//! Gets the binding between the camera's rotation and target.
ICameraSceneNode::TargetAndRotationBinding CCameraSceneNode::getTargetAndRotationBinding(void) const
bool CCameraSceneNode::getTargetAndRotationBinding(void) const
{
return Binding;
return TargetAndRotationAreBound;
}

View File

@ -47,10 +47,19 @@ namespace scene
//! for changing their position, look at target or whatever.
virtual bool OnEvent(const SEvent& event);
//! sets the look at target of the camera
//! \param pos: Look at target of the camera.
//! Sets the look at target of the camera
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's scene node rotation to match the target.
\param pos: Look at target of the camera. */
virtual void setTarget(const core::vector3df& pos);
//! Sets the rotation of the node.
/** This only modifies the relative rotation of the node.
/** If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
then calling this will also change the camera's target to match the rotation.
\param rotation New rotation of the node in degrees. */
virtual void setRotation(const core::vector3df& rotation);
//! Gets the current look at target of the camera
//! \return Returns the current look at target of the camera
virtual const core::vector3df& getTarget() const;
@ -120,11 +129,11 @@ namespace scene
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; }
//! Set the binding between the camera's rotation adn target.
virtual void setTargetAndRotationBinding(TargetAndRotationBinding binding);
//! Binds the camera scene node's rotation to its target position and vice vera, or unbinds them.
virtual void bindTargetAndRotation(bool bound);
//! Gets the binding between the camera's rotation and target.
virtual TargetAndRotationBinding getTargetAndRotationBinding(void) const;
//! Queries if the camera scene node's rotation and its target position are bound together.
virtual bool getTargetAndRotationBinding(void) const;
protected:
@ -143,7 +152,7 @@ namespace scene
bool InputReceiverEnabled;
TargetAndRotationBinding Binding;
bool TargetAndRotationAreBound;
};
} // end namespace

View File

@ -667,8 +667,8 @@ ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent,
ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, rotateSpeed,
moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement);
// Have the node's rotation follow its target. This is consistent with 1.4.2 and below.
node->setTargetAndRotationBinding(ICameraSceneNode::ROTATION_FOLLOWS_TARGET);
// Bind the node's rotation to its target. This is consistent with 1.4.2 and below.
node->bindTargetAndRotation(true);
node->addAnimator(anm);
anm->drop();