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 ...@@ -125,6 +125,28 @@ namespace scene
return IsOrthogonal; 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: protected:
bool IsOrthogonal; bool IsOrthogonal;
......
...@@ -199,13 +199,28 @@ void CCameraSceneNode::recalculateProjectionMatrix() ...@@ -199,13 +199,28 @@ void CCameraSceneNode::recalculateProjectionMatrix()
//! prerender //! prerender
void CCameraSceneNode::OnRegisterSceneNode() 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 pos = getAbsolutePosition();
core::vector3df tgtv = Target - pos; core::vector3df tgtv = Target - pos;
tgtv.normalize(); 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; core::vector3df up = UpVector;
up.normalize(); up.normalize();
...@@ -257,14 +272,6 @@ void CCameraSceneNode::recalculateViewArea() ...@@ -257,14 +272,6 @@ void CCameraSceneNode::recalculateViewArea()
{ {
ViewArea.cameraPosition = getAbsolutePosition(); ViewArea.cameraPosition = getAbsolutePosition();
ViewArea.setFrom ( ViewArea.Matrices [ SViewFrustum::ETS_VIEW_PROJECTION_3 ] ); 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 ...@@ -279,6 +286,7 @@ void CCameraSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeR
out->addFloat("Aspect", Aspect); out->addFloat("Aspect", Aspect);
out->addFloat("ZNear", ZNear); out->addFloat("ZNear", ZNear);
out->addFloat("ZFar", ZFar); out->addFloat("ZFar", ZFar);
out->addInt("Binding", (int)Binding);
} }
...@@ -294,11 +302,28 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute ...@@ -294,11 +302,28 @@ void CCameraSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttribute
ZNear = in->getAttributeAsFloat("ZNear"); ZNear = in->getAttributeAsFloat("ZNear");
ZFar = in->getAttributeAsFloat("ZFar"); ZFar = in->getAttributeAsFloat("ZFar");
Binding = (ICameraSceneNode::TargetAndRotationBinding)in->getAttributeAsInt("Binding");
if(0 == Binding)
Binding = TARGET_AND_ROTATION_INDEPENDENT;
recalculateProjectionMatrix(); recalculateProjectionMatrix();
recalculateViewArea(); 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
} // end namespace } // end namespace
...@@ -120,6 +120,12 @@ namespace scene ...@@ -120,6 +120,12 @@ namespace scene
//! Returns type of the scene node //! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const { return ESNT_CAMERA; } 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: protected:
void recalculateProjectionMatrix(); void recalculateProjectionMatrix();
...@@ -136,6 +142,8 @@ namespace scene ...@@ -136,6 +142,8 @@ namespace scene
SViewFrustum ViewArea; SViewFrustum ViewArea;
bool InputReceiverEnabled; bool InputReceiverEnabled;
TargetAndRotationBinding Binding;
}; };
} // end namespace } // end namespace
......
...@@ -667,6 +667,9 @@ ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent, ...@@ -667,6 +667,9 @@ ICameraSceneNode* CSceneManager::addCameraSceneNodeFPS(ISceneNode* parent,
ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, rotateSpeed, ISceneNodeAnimator* anm = new CSceneNodeAnimatorCameraFPS(CursorControl, rotateSpeed,
moveSpeed, jumpSpeed, keyMapArray, keyMapSize, noVerticalMovement); 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); node->addAnimator(anm);
anm->drop(); anm->drop();
node->drop(); node->drop();
......
...@@ -103,6 +103,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) ...@@ -103,6 +103,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (firstUpdate) if (firstUpdate)
{ {
camera->updateAbsolutePosition();
if (CursorControl && camera) if (CursorControl && camera)
{ {
CursorControl->setPosition(0.5f, 0.5f); CursorControl->setPosition(0.5f, 0.5f);
...@@ -198,7 +199,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs) ...@@ -198,7 +199,7 @@ void CSceneNodeAnimatorCameraFPS::animateNode(ISceneNode* node, u32 timeMs)
if (CursorKeys[3]) if (CursorKeys[3])
pos -= strafevect * timeDiff * MoveSpeed; 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]) if (CursorKeys[4])
{ {
pos += camera->getUpVector() * timeDiff * JumpSpeed; 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