1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CCameraSceneNode.h"
\r
6 #include "ISceneManager.h"
\r
7 #include "IVideoDriver.h"
\r
17 CCameraSceneNode::CCameraSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
\r
18 const core::vector3df& position, const core::vector3df& lookat)
\r
19 : ICameraSceneNode(parent, mgr, id, position),
\r
20 BoundingBox(core::vector3df(0, 0, 0)), // Camera has no size. Still not sure if FLT_MAX might be the better variant
\r
21 Target(lookat), UpVector(0.0f, 1.0f, 0.0f), ZNear(1.0f), ZFar(3000.0f),
\r
22 InputReceiverEnabled(true), TargetAndRotationAreBound(false),
\r
23 HasD3DStyleProjectionMatrix(true)
\r
26 setDebugName("CCameraSceneNode");
\r
29 // set default projection
\r
30 Fovy = core::PI / 2.5f; // Field of view, in radians.
\r
31 Aspect = 4.0f / 3.0f; // Aspect ratio.
\r
33 const video::IVideoDriver* const d = mgr?mgr->getVideoDriver():0;
\r
36 if ( d->getCurrentRenderTargetSize().Height )
\r
37 Aspect = (f32)d->getCurrentRenderTargetSize().Width /
\r
38 (f32)d->getCurrentRenderTargetSize().Height;
\r
39 HasD3DStyleProjectionMatrix = d->getDriverType() != video::EDT_OPENGL;
\r
42 ViewArea.setFarNearDistance(ZFar - ZNear);
\r
43 recalculateProjectionMatrix();
\r
44 recalculateViewArea();
\r
48 //! Disables or enables the camera to get key or mouse inputs.
\r
49 void CCameraSceneNode::setInputReceiverEnabled(bool enabled)
\r
51 InputReceiverEnabled = enabled;
\r
55 //! Returns if the input receiver of the camera is currently enabled.
\r
56 bool CCameraSceneNode::isInputReceiverEnabled() const
\r
58 return InputReceiverEnabled;
\r
62 //! Sets the projection matrix of the camera.
\r
63 /** The core::matrix4 class has some methods
\r
64 to build a projection matrix. e.g: core::matrix4::buildProjectionMatrixPerspectiveFovLH
\r
65 \param projection: The new projection matrix of the camera. */
\r
66 void CCameraSceneNode::setProjectionMatrix(const core::matrix4& projection, bool isOrthogonal)
\r
68 IsOrthogonal = isOrthogonal;
\r
69 ViewArea.getTransform ( video::ETS_PROJECTION ) = projection;
\r
73 //! Gets the current projection matrix of the camera
\r
74 //! \return Returns the current projection matrix of the camera.
\r
75 const core::matrix4& CCameraSceneNode::getProjectionMatrix() const
\r
77 return ViewArea.getTransform ( video::ETS_PROJECTION );
\r
81 //! Gets the current view matrix of the camera
\r
82 //! \return Returns the current view matrix of the camera.
\r
83 const core::matrix4& CCameraSceneNode::getViewMatrix() const
\r
85 return ViewArea.getTransform ( video::ETS_VIEW );
\r
89 //! Sets a custom view matrix affector. The matrix passed here, will be
\r
90 //! multiplied with the view matrix when it gets updated.
\r
91 //! This allows for custom camera setups like, for example, a reflection camera.
\r
92 /** \param affector: The affector matrix. */
\r
93 void CCameraSceneNode::setViewMatrixAffector(const core::matrix4& affector)
\r
95 Affector = affector;
\r
99 //! Gets the custom view matrix affector.
\r
100 const core::matrix4& CCameraSceneNode::getViewMatrixAffector() const
\r
106 //! It is possible to send mouse and key events to the camera. Most cameras
\r
107 //! may ignore this input, but camera scene nodes which are created for
\r
108 //! example with scene::ISceneManager::addMayaCameraSceneNode or
\r
109 //! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
\r
110 //! for changing their position, look at target or whatever.
\r
111 bool CCameraSceneNode::OnEvent(const SEvent& event)
\r
113 // animators have been deleted; nothing happens here now!
\r
118 //! sets the look at target of the camera
\r
119 //! \param pos: Look at target of the camera.
\r
120 void CCameraSceneNode::setTarget(const core::vector3df& pos)
\r
124 if(TargetAndRotationAreBound)
\r
126 const core::vector3df toTarget = Target - getAbsolutePosition();
\r
127 ISceneNode::setRotation(toTarget.getHorizontalAngle());
\r
132 //! Sets the rotation of the node.
\r
133 /** This only modifies the relative rotation of the node.
\r
134 If the camera's target and rotation are bound ( @see bindTargetAndRotation() )
\r
135 then calling this will also change the camera's target to match the rotation.
\r
136 \param rotation New rotation of the node in degrees. */
\r
137 void CCameraSceneNode::setRotation(const core::vector3df& rotation)
\r
139 if(TargetAndRotationAreBound)
\r
140 Target = getAbsolutePosition() + rotation.rotationToDirection();
\r
142 ISceneNode::setRotation(rotation);
\r
146 //! Gets the current look at target of the camera
\r
147 //! \return Returns the current look at target of the camera
\r
148 const core::vector3df& CCameraSceneNode::getTarget() const
\r
154 //! sets the up vector of the camera
\r
155 //! \param pos: New upvector of the camera.
\r
156 void CCameraSceneNode::setUpVector(const core::vector3df& pos)
\r
162 //! Gets the up vector of the camera.
\r
163 //! \return Returns the up vector of the camera.
\r
164 const core::vector3df& CCameraSceneNode::getUpVector() const
\r
170 f32 CCameraSceneNode::getNearValue() const
\r
176 f32 CCameraSceneNode::getFarValue() const
\r
182 f32 CCameraSceneNode::getAspectRatio() const
\r
188 f32 CCameraSceneNode::getFOV() const
\r
194 void CCameraSceneNode::setNearValue(f32 f)
\r
197 recalculateProjectionMatrix();
\r
198 ViewArea.setFarNearDistance(ZFar - ZNear);
\r
202 void CCameraSceneNode::setFarValue(f32 f)
\r
205 recalculateProjectionMatrix();
\r
206 ViewArea.setFarNearDistance(ZFar - ZNear);
\r
210 void CCameraSceneNode::setAspectRatio(f32 f)
\r
213 recalculateProjectionMatrix();
\r
217 void CCameraSceneNode::setFOV(f32 f)
\r
220 recalculateProjectionMatrix();
\r
224 void CCameraSceneNode::recalculateProjectionMatrix()
\r
226 ViewArea.getTransform ( video::ETS_PROJECTION ).buildProjectionMatrixPerspectiveFovLH(Fovy, Aspect, ZNear, ZFar, HasD3DStyleProjectionMatrix);
\r
227 IsOrthogonal = false;
\r
232 void CCameraSceneNode::OnRegisterSceneNode()
\r
234 if ( SceneManager->getActiveCamera () == this )
\r
235 SceneManager->registerNodeForRendering(this, ESNRP_CAMERA);
\r
237 ISceneNode::OnRegisterSceneNode();
\r
242 void CCameraSceneNode::render()
\r
246 video::IVideoDriver* driver = SceneManager->getVideoDriver();
\r
249 driver->setTransform(video::ETS_PROJECTION, ViewArea.getTransform ( video::ETS_PROJECTION) );
\r
250 driver->setTransform(video::ETS_VIEW, ViewArea.getTransform ( video::ETS_VIEW) );
\r
255 void CCameraSceneNode::updateMatrices()
\r
257 core::vector3df pos = getAbsolutePosition();
\r
258 core::vector3df tgtv = Target - pos;
\r
261 // if upvector and vector to the target are the same, we have a
\r
262 // problem. so solve this problem:
\r
263 core::vector3df up = UpVector;
\r
266 f32 dp = tgtv.dotProduct(up);
\r
268 if ( core::equals(core::abs_<f32>(dp), 1.f) )
\r
273 ViewArea.getTransform(video::ETS_VIEW).buildCameraLookAtMatrixLH(pos, Target, up);
\r
274 ViewArea.getTransform(video::ETS_VIEW) *= Affector;
\r
275 recalculateViewArea();
\r
278 //! returns the axis aligned bounding box of this node
\r
279 const core::aabbox3d<f32>& CCameraSceneNode::getBoundingBox() const
\r
281 return BoundingBox;
\r
285 //! returns the view frustum.
\r
286 const SViewFrustum* CCameraSceneNode::getViewFrustum() const
\r
292 void CCameraSceneNode::recalculateViewArea()
\r
294 ViewArea.cameraPosition = getAbsolutePosition();
\r
296 core::matrix4 m(core::matrix4::EM4CONST_NOTHING);
\r
297 m.setbyproduct_nocheck(ViewArea.getTransform(video::ETS_PROJECTION),
\r
298 ViewArea.getTransform(video::ETS_VIEW));
\r
299 ViewArea.setFrom(m, HasD3DStyleProjectionMatrix);
\r
303 //! Set the binding between the camera's rotation adn target.
\r
304 void CCameraSceneNode::bindTargetAndRotation(bool bound)
\r
306 TargetAndRotationAreBound = bound;
\r
310 //! Gets the binding between the camera's rotation and target.
\r
311 bool CCameraSceneNode::getTargetAndRotationBinding(void) const
\r
313 return TargetAndRotationAreBound;
\r
317 //! Creates a clone of this scene node and its children.
\r
318 ISceneNode* CCameraSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
\r
320 ICameraSceneNode::clone(newParent, newManager);
\r
323 newParent = Parent;
\r
325 newManager = SceneManager;
\r
327 CCameraSceneNode* nb = new CCameraSceneNode(newParent,
\r
328 newManager, ID, RelativeTranslation, Target);
\r
330 nb->ISceneNode::cloneMembers(this, newManager);
\r
331 nb->ICameraSceneNode::cloneMembers(this);
\r
333 nb->Target = Target;
\r
334 nb->UpVector = UpVector;
\r
336 nb->Aspect = Aspect;
\r
339 nb->ViewArea = ViewArea;
\r
340 nb->Affector = Affector;
\r
341 nb->InputReceiverEnabled = InputReceiverEnabled;
\r
342 nb->TargetAndRotationAreBound = TargetAndRotationAreBound;
\r