2013-03-28 10:04:07 -07:00
// Copyright (C) 2002-2012 Nikolaus Gebhardt
2007-05-20 11:03:49 -07:00
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
# include "CCameraSceneNode.h"
# include "ISceneManager.h"
# include "IVideoDriver.h"
# include "os.h"
namespace irr
{
namespace scene
{
//! constructor
2010-06-01 15:52:38 -07:00
CCameraSceneNode : : CCameraSceneNode ( ISceneNode * parent , ISceneManager * mgr , s32 id ,
2007-05-20 11:03:49 -07:00
const core : : vector3df & position , const core : : vector3df & lookat )
2008-11-27 15:52:13 -08:00
: ICameraSceneNode ( parent , mgr , id , position ) ,
2015-11-12 14:32:01 -08:00
BoundingBox ( core : : vector3df ( 0 , 0 , 0 ) ) , // Camera has no size. Still not sure if FLT_MAX might be the better variant
2008-08-07 05:45:53 -07:00
Target ( lookat ) , UpVector ( 0.0f , 1.0f , 0.0f ) , ZNear ( 1.0f ) , ZFar ( 3000.0f ) ,
2019-02-27 12:20:38 -08:00
InputReceiverEnabled ( true ) , TargetAndRotationAreBound ( false ) ,
HasD3DStyleProjectionMatrix ( true )
2007-05-20 11:03:49 -07:00
{
# ifdef _DEBUG
setDebugName ( " CCameraSceneNode " ) ;
# endif
// set default projection
2010-06-01 15:52:38 -07:00
Fovy = core : : PI / 2.5f ; // Field of view, in radians.
2007-05-20 11:03:49 -07:00
2008-08-07 05:45:53 -07:00
const video : : IVideoDriver * const d = mgr ? mgr - > getVideoDriver ( ) : 0 ;
2007-05-20 11:03:49 -07:00
if ( d )
2019-02-27 12:20:38 -08:00
{
2007-05-20 11:03:49 -07:00
Aspect = ( f32 ) d - > getCurrentRenderTargetSize ( ) . Width /
( f32 ) d - > getCurrentRenderTargetSize ( ) . Height ;
2019-02-27 12:20:38 -08:00
HasD3DStyleProjectionMatrix = d - > getDriverType ( ) ! = video : : EDT_OPENGL ;
}
2008-08-07 05:45:53 -07:00
else
2010-06-01 15:52:38 -07:00
Aspect = 4.0f / 3.0f ; // Aspect ratio.
2007-05-20 11:03:49 -07:00
2015-11-12 14:32:01 -08:00
ViewArea . setFarNearDistance ( ZFar - ZNear ) ;
2007-05-20 11:03:49 -07:00
recalculateProjectionMatrix ( ) ;
recalculateViewArea ( ) ;
}
//! Disables or enables the camera to get key or mouse inputs.
void CCameraSceneNode : : setInputReceiverEnabled ( bool enabled )
{
InputReceiverEnabled = enabled ;
}
//! Returns if the input receiver of the camera is currently enabled.
2007-09-16 16:41:55 -07:00
bool CCameraSceneNode : : isInputReceiverEnabled ( ) const
2007-05-20 11:03:49 -07:00
{
return InputReceiverEnabled ;
}
2008-11-27 15:52:13 -08:00
//! Sets the projection matrix of the camera.
/** The core::matrix4 class has some methods
to build a projection matrix . e . g : core : : matrix4 : : buildProjectionMatrixPerspectiveFovLH
\ param projection : The new projection matrix of the camera . */
2008-08-06 08:25:05 -07:00
void CCameraSceneNode : : setProjectionMatrix ( const core : : matrix4 & projection , bool isOrthogonal )
2007-05-20 11:03:49 -07:00
{
2008-08-06 08:25:05 -07:00
IsOrthogonal = isOrthogonal ;
2009-05-04 17:09:53 -07:00
ViewArea . getTransform ( video : : ETS_PROJECTION ) = projection ;
2007-05-20 11:03:49 -07:00
}
//! Gets the current projection matrix of the camera
//! \return Returns the current projection matrix of the camera.
2007-09-16 16:41:55 -07:00
const core : : matrix4 & CCameraSceneNode : : getProjectionMatrix ( ) const
2007-05-20 11:03:49 -07:00
{
2009-05-04 17:09:53 -07:00
return ViewArea . getTransform ( video : : ETS_PROJECTION ) ;
2007-05-20 11:03:49 -07:00
}
//! Gets the current view matrix of the camera
//! \return Returns the current view matrix of the camera.
2007-09-16 16:41:55 -07:00
const core : : matrix4 & CCameraSceneNode : : getViewMatrix ( ) const
2007-05-20 11:03:49 -07:00
{
2009-05-04 17:09:53 -07:00
return ViewArea . getTransform ( video : : ETS_VIEW ) ;
}
//! Sets a custom view matrix affector. The matrix passed here, will be
//! multiplied with the view matrix when it gets updated.
//! This allows for custom camera setups like, for example, a reflection camera.
/** \param affector: The affector matrix. */
void CCameraSceneNode : : setViewMatrixAffector ( const core : : matrix4 & affector )
{
Affector = affector ;
}
//! Gets the custom view matrix affector.
const core : : matrix4 & CCameraSceneNode : : getViewMatrixAffector ( ) const
{
return Affector ;
2007-05-20 11:03:49 -07:00
}
//! It is possible to send mouse and key events to the camera. Most cameras
2010-06-01 15:52:38 -07:00
//! may ignore this input, but camera scene nodes which are created for
2007-05-20 11:03:49 -07:00
//! example with scene::ISceneManager::addMayaCameraSceneNode or
//! scene::ISceneManager::addFPSCameraSceneNode, may want to get this input
2010-06-01 15:52:38 -07:00
//! for changing their position, look at target or whatever.
2007-09-16 16:41:55 -07:00
bool CCameraSceneNode : : OnEvent ( const SEvent & event )
2007-05-20 11:03:49 -07:00
{
2008-04-24 14:39:22 -07:00
if ( ! InputReceiverEnabled )
return false ;
// send events to event receiving animators
2009-11-20 02:08:00 -08:00
ISceneNodeAnimatorList : : Iterator ait = Animators . begin ( ) ;
2010-06-01 15:52:38 -07:00
2008-04-24 14:39:22 -07:00
for ( ; ait ! = Animators . end ( ) ; + + ait )
if ( ( * ait ) - > isEventReceiverEnabled ( ) & & ( * ait ) - > OnEvent ( event ) )
return true ;
// if nobody processed the event, return false
2007-05-20 11:03:49 -07:00
return false ;
}
//! 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 ;
2008-11-27 15:52:13 -08:00
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 ) ;
2007-05-20 11:03:49 -07:00
}
//! Gets the current look at target of the camera
//! \return Returns the current look at target of the camera
2008-08-07 05:45:53 -07:00
const core : : vector3df & CCameraSceneNode : : getTarget ( ) const
2007-05-20 11:03:49 -07:00
{
return Target ;
}
//! sets the up vector of the camera
//! \param pos: New upvector of the camera.
void CCameraSceneNode : : setUpVector ( const core : : vector3df & pos )
{
UpVector = pos ;
}
//! Gets the up vector of the camera.
//! \return Returns the up vector of the camera.
2008-08-07 05:45:53 -07:00
const core : : vector3df & CCameraSceneNode : : getUpVector ( ) const
2007-05-20 11:03:49 -07:00
{
return UpVector ;
}
2010-06-01 15:52:38 -07:00
f32 CCameraSceneNode : : getNearValue ( ) const
2007-05-20 11:03:49 -07:00
{
return ZNear ;
}
2008-08-07 05:45:53 -07:00
2010-06-01 15:52:38 -07:00
f32 CCameraSceneNode : : getFarValue ( ) const
2007-05-20 11:03:49 -07:00
{
return ZFar ;
}
2008-08-07 05:45:53 -07:00
2010-06-01 15:52:38 -07:00
f32 CCameraSceneNode : : getAspectRatio ( ) const
2007-05-20 11:03:49 -07:00
{
return Aspect ;
}
2008-08-07 05:45:53 -07:00
2010-06-01 15:52:38 -07:00
f32 CCameraSceneNode : : getFOV ( ) const
2007-05-20 11:03:49 -07:00
{
return Fovy ;
}
2008-08-07 05:45:53 -07:00
2007-05-20 11:03:49 -07:00
void CCameraSceneNode : : setNearValue ( f32 f )
{
ZNear = f ;
recalculateProjectionMatrix ( ) ;
2014-09-18 14:57:30 -07:00
ViewArea . setFarNearDistance ( ZFar - ZNear ) ;
2007-05-20 11:03:49 -07:00
}
2008-08-07 05:45:53 -07:00
2007-05-20 11:03:49 -07:00
void CCameraSceneNode : : setFarValue ( f32 f )
{
ZFar = f ;
recalculateProjectionMatrix ( ) ;
2014-09-18 14:57:30 -07:00
ViewArea . setFarNearDistance ( ZFar - ZNear ) ;
2007-05-20 11:03:49 -07:00
}
2008-08-07 05:45:53 -07:00
2007-05-20 11:03:49 -07:00
void CCameraSceneNode : : setAspectRatio ( f32 f )
{
Aspect = f ;
recalculateProjectionMatrix ( ) ;
}
2008-08-07 05:45:53 -07:00
2007-05-20 11:03:49 -07:00
void CCameraSceneNode : : setFOV ( f32 f )
{
Fovy = f ;
recalculateProjectionMatrix ( ) ;
}
2008-08-07 05:45:53 -07:00
2007-05-20 11:03:49 -07:00
void CCameraSceneNode : : recalculateProjectionMatrix ( )
{
2019-02-27 12:20:38 -08:00
ViewArea . getTransform ( video : : ETS_PROJECTION ) . buildProjectionMatrixPerspectiveFovLH ( Fovy , Aspect , ZNear , ZFar , HasD3DStyleProjectionMatrix ) ;
IsOrthogonal = false ;
2007-05-20 11:03:49 -07:00
}
//! prerender
void CCameraSceneNode : : OnRegisterSceneNode ( )
{
2009-11-02 09:20:21 -08:00
if ( SceneManager - > getActiveCamera ( ) = = this )
SceneManager - > registerNodeForRendering ( this , ESNRP_CAMERA ) ;
ISceneNode : : OnRegisterSceneNode ( ) ;
}
//! render
void CCameraSceneNode : : render ( )
2013-03-28 10:04:07 -07:00
{
updateMatrices ( ) ;
video : : IVideoDriver * driver = SceneManager - > getVideoDriver ( ) ;
if ( driver )
{
driver - > setTransform ( video : : ETS_PROJECTION , ViewArea . getTransform ( video : : ETS_PROJECTION ) ) ;
driver - > setTransform ( video : : ETS_VIEW , ViewArea . getTransform ( video : : ETS_VIEW ) ) ;
}
}
//! update
void CCameraSceneNode : : updateMatrices ( )
2010-06-01 15:52:38 -07:00
{
2022-05-04 14:38:12 -07:00
# if defined(_IRR_COMPILE_WITH_90_DEGREE_CAMERA)
ViewArea . getTransform ( video : : ETS_VIEW ) . buildCameraLookAtMatrixLH ( getAbsolutePosition ( ) , Target , UpVector ) ;
# else
2007-05-20 11:03:49 -07:00
core : : vector3df pos = getAbsolutePosition ( ) ;
core : : vector3df tgtv = Target - pos ;
tgtv . normalize ( ) ;
2008-11-27 15:52:13 -08:00
// if upvector and vector to the target are the same, we have a
// problem. so solve this problem:
2007-05-20 11:03:49 -07:00
core : : vector3df up = UpVector ;
up . normalize ( ) ;
f32 dp = tgtv . dotProduct ( up ) ;
2009-11-02 09:20:21 -08:00
if ( core : : equals ( core : : abs_ < f32 > ( dp ) , 1.f ) )
2007-05-20 11:03:49 -07:00
{
up . X + = 0.5f ;
}
2009-05-04 17:09:53 -07:00
ViewArea . getTransform ( video : : ETS_VIEW ) . buildCameraLookAtMatrixLH ( pos , Target , up ) ;
2022-05-04 14:38:12 -07:00
# endif
2009-05-04 17:09:53 -07:00
ViewArea . getTransform ( video : : ETS_VIEW ) * = Affector ;
2007-05-20 11:03:49 -07:00
recalculateViewArea ( ) ;
}
//! returns the axis aligned bounding box of this node
const core : : aabbox3d < f32 > & CCameraSceneNode : : getBoundingBox ( ) const
{
2015-11-12 14:32:01 -08:00
// NOTE: We deliberately don't return the boundingbox of the ViewArea. People can access that already.
// We want to prevent cameras from having their bounding box colliding in the SceneCollisionManager.
// If another boundingbox is ever necessary then please move BoundingBox to ICameraSceneNode and make it accessible (via a setter or an enum with options).
return BoundingBox ;
2007-05-20 11:03:49 -07:00
}
2015-11-12 14:32:01 -08:00
//! returns the view frustum.
2007-05-20 11:03:49 -07:00
const SViewFrustum * CCameraSceneNode : : getViewFrustum ( ) const
{
return & ViewArea ;
}
void CCameraSceneNode : : recalculateViewArea ( )
{
ViewArea . cameraPosition = getAbsolutePosition ( ) ;
2009-05-04 17:09:53 -07:00
core : : matrix4 m ( core : : matrix4 : : EM4CONST_NOTHING ) ;
m . setbyproduct_nocheck ( ViewArea . getTransform ( video : : ETS_PROJECTION ) ,
ViewArea . getTransform ( video : : ETS_VIEW ) ) ;
2019-02-27 12:20:38 -08:00
ViewArea . setFrom ( m , HasD3DStyleProjectionMatrix ) ;
2007-05-20 11:03:49 -07:00
}
//! Writes attributes of the scene node.
2007-09-14 15:25:59 -07:00
void CCameraSceneNode : : serializeAttributes ( io : : IAttributes * out , io : : SAttributeReadWriteOptions * options ) const
2007-05-20 11:03:49 -07:00
{
2011-06-09 00:08:47 -07:00
ICameraSceneNode : : serializeAttributes ( out , options ) ;
2007-05-20 11:03:49 -07:00
out - > addVector3d ( " Target " , Target ) ;
out - > addVector3d ( " UpVector " , UpVector ) ;
out - > addFloat ( " Fovy " , Fovy ) ;
out - > addFloat ( " Aspect " , Aspect ) ;
out - > addFloat ( " ZNear " , ZNear ) ;
out - > addFloat ( " ZFar " , ZFar ) ;
2008-11-27 15:52:13 -08:00
out - > addBool ( " Binding " , TargetAndRotationAreBound ) ;
2011-06-09 00:08:47 -07:00
out - > addBool ( " ReceiveInput " , InputReceiverEnabled ) ;
2007-05-20 11:03:49 -07:00
}
//! Reads attributes of the scene node.
void CCameraSceneNode : : deserializeAttributes ( io : : IAttributes * in , io : : SAttributeReadWriteOptions * options )
{
2011-06-09 00:08:47 -07:00
ICameraSceneNode : : deserializeAttributes ( in , options ) ;
2007-05-20 11:03:49 -07:00
Target = in - > getAttributeAsVector3d ( " Target " ) ;
UpVector = in - > getAttributeAsVector3d ( " UpVector " ) ;
Fovy = in - > getAttributeAsFloat ( " Fovy " ) ;
Aspect = in - > getAttributeAsFloat ( " Aspect " ) ;
ZNear = in - > getAttributeAsFloat ( " ZNear " ) ;
ZFar = in - > getAttributeAsFloat ( " ZFar " ) ;
2008-11-27 15:52:13 -08:00
TargetAndRotationAreBound = in - > getAttributeAsBool ( " Binding " ) ;
2011-06-09 00:08:47 -07:00
if ( in - > findAttribute ( " ReceiveInput " ) )
2015-11-28 15:18:00 -08:00
InputReceiverEnabled = in - > getAttributeAsBool ( " ReceiveInput " ) ;
2007-05-20 11:03:49 -07:00
recalculateProjectionMatrix ( ) ;
2010-06-01 15:52:38 -07:00
recalculateViewArea ( ) ;
2007-05-20 11:03:49 -07:00
}
2008-11-27 15:52:13 -08:00
//! Set the binding between the camera's rotation adn target.
void CCameraSceneNode : : bindTargetAndRotation ( bool bound )
{
TargetAndRotationAreBound = bound ;
}
2008-12-19 01:56:25 -08:00
2008-11-27 15:52:13 -08:00
//! Gets the binding between the camera's rotation and target.
bool CCameraSceneNode : : getTargetAndRotationBinding ( void ) const
{
return TargetAndRotationAreBound ;
}
2009-11-02 09:20:21 -08:00
//! Creates a clone of this scene node and its children.
ISceneNode * CCameraSceneNode : : clone ( ISceneNode * newParent , ISceneManager * newManager )
{
2011-06-09 00:08:47 -07:00
ICameraSceneNode : : clone ( newParent , newManager ) ;
2009-11-02 09:20:21 -08:00
if ( ! newParent )
newParent = Parent ;
if ( ! newManager )
newManager = SceneManager ;
2010-06-01 15:52:38 -07:00
CCameraSceneNode * nb = new CCameraSceneNode ( newParent ,
2009-11-02 09:20:21 -08:00
newManager , ID , RelativeTranslation , Target ) ;
2011-06-09 00:08:47 -07:00
nb - > ISceneNode : : cloneMembers ( this , newManager ) ;
nb - > ICameraSceneNode : : cloneMembers ( this ) ;
nb - > Target = Target ;
nb - > UpVector = UpVector ;
nb - > Fovy = Fovy ;
nb - > Aspect = Aspect ;
nb - > ZNear = ZNear ;
nb - > ZFar = ZFar ;
nb - > ViewArea = ViewArea ;
nb - > Affector = Affector ;
nb - > InputReceiverEnabled = InputReceiverEnabled ;
nb - > TargetAndRotationAreBound = TargetAndRotationAreBound ;
2009-11-02 09:20:21 -08:00
2010-06-01 15:52:38 -07:00
if ( newParent )
nb - > drop ( ) ;
2009-11-02 09:20:21 -08:00
return nb ;
}
2007-05-20 11:03:49 -07:00
} // end namespace
} // end namespace