Commit 86382da2 authored by Rogerborg's avatar Rogerborg

Add a publicly configurable binding between camera target and scene node...

Add a publicly configurable binding between camera target and scene node rotation.  By default, they are independent.  FPS cameras have their scene node rotation follow their target, which restores the <=1.4.2 behaviour.  This is Work In Progress, as the ordering of events isn't quite correct yet: there's a visible lag between FPS camera scene node childrens' relative position catching up with the camera rotation.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1748 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 598103c2
......@@ -125,6 +125,28 @@ 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,
//! 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;
protected:
bool IsOrthogonal;
......
......@@ -199,13 +199,28 @@ void CCameraSceneNode::recalculateProjectionMatrix()
//! prerender
void CCameraSceneNode::OnRegisterSceneNode()
{
// if upvector and vector to the target are the same, we have a
// problem. so solve this problem:
core::vector3df pos = getAbsolutePosition();
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;
up.normalize();
......@@ -257,14 +272,6 @@ void CCameraSceneNode::recalculateViewArea()
{
ViewArea.cameraPosition = getAbsolutePosition();
ViewArea.setFrom ( ViewArea.Matrices [ SViewFrustum::ETS_VIEW_PROJECTION_3 ] );
/*
video::IVideoDriver* driver = SceneManager->getVideoDriver();
if ( driver)
{
driver->setTransform(video::ETS_PROJECTION, ViewArea.Matrices [ video::ETS_PROJECTION ] );
driver->setTransform(video::ETS_VIEW, ViewArea.Matrices [ video::ETS_VIEW ] );
}
*/
}
......@@ -279,6 +286,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);
}
......@@ -294,11 +302,28 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute
ZNear = in->getAttributeAsFloat("ZNear");
ZFar = in->getAttributeAsFloat("ZFar");
Binding = (ICameraSceneNode::TargetAndRotationBinding)in->getAttributeAsInt("Binding");
if(0 == Binding)
Binding = TARGET_AND_ROTATION_INDEPENDENT;
recalculateProjectionMatrix();
recalculateViewArea();
}
//! Set the binding between the camera's rotation adn target.
void CCameraSceneNode::setTargetAndRotationBinding(TargetAndRotationBinding binding)
{
Binding = binding;
}
//! Gets the binding between the camera's rotation and target.
ICameraSceneNode::TargetAndRotationBinding CCameraSceneNode::getTargetAndRotationBinding(void) const
{
return Binding;
}
} // end namespace
} // end namespace
......@@ -120,6 +120,12 @@ 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);
//! Gets the binding between the camera's rotation and target.
virtual TargetAndRotationBinding getTargetAndRotationBinding(void) const;
protected:
void recalculateProjectionMatrix();
......@@ -136,6 +142,8 @@ namespace scene
SViewFrustum ViewArea;
bool InputReceiverEnabled;
TargetAndRotationBinding Binding;
};
} // end namespace
......
......@@ -667,6 +667,9 @@ 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);
node->addAnimator(anm);
anm->drop();
node->drop();
......
......@@ -103,6 +103,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (firstUpdate)
{
camera->updateAbsolutePosition();
if (CursorControl && camera)
{
CursorControl->setPosition(0.5f, 0.5f);
......@@ -198,7 +199,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (CursorKeys[3])
pos -= strafevect * timeDiff * MoveSpeed;
// jumping ( need's a gravity , else it's a fly to the World-UpVector )
// jumping ( needs a gravity , else it's a fly to the World-UpVector )
if (CursorKeys[4])
{
pos += camera->getUpVector() * timeDiff * JumpSpeed;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment