This class is a simple animator for camera scene nodes only. You can specify a path in IrrEdit using any type of scene nodes (I prefer empty scene nodes) and have the camera follow the path you defined. There must be one scene node as parent of the path and the children of this node define the waypoints. The package contains the necessary source code and a little demo app.
I am quite sure that there are some snippets like this around, but I didn't search but implemented it. Want to share it anyways.
You can either copy the code from below or download a package with a demo application from my homepage: http://bulletbyte.de/products.php?sub=irr&show=fpa.
CFollowPathAnimator.h
Code: Select all
#ifndef _C_FOLLOW_PATH_ANIMATOR
#define _C_FOLLOW_PATH_ANIMATOR
#include <irrlicht.h>
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
/**
* @class CFollowPathAnimator
* This class is a simple animator for camera scene nodes only. You can specify a path in IrrEdit using any type
* of scene nodes (I prefer empty scene nodes) and have the camera follow the path you defined. There must be one
* scene node as parent of the path and the children of this node define the waypoints.
*/
class CFollowPathAnimator : public ISceneNodeAnimator {
private:
list<vector3df>::Iterator m_cIter; /**< the iterator of the waypoints */
list<vector3df> m_cPathPoints; /**< the positions of the waypoints */
vector3df m_cCamPos, /**< the current camera position */
m_cCamTgt, /**< the next waypoint the camera goes to */
m_cCamDir, /**< the direction the camera is looking at */
m_cCamNDr, /**< the target direction of the camera when focusing the next waypoint */
m_cCamTrn; /**< the turn vector of the camera when focusing the next waypoint */
bool m_bAnimRunning, /**< is the animation still running? */
m_bStopNextHit, /**< is the animation going to be stopped once the next waypoint is reached? */
m_bLoopAnim; /**< is the anim looped? */
f32 m_fAnimSpeed, /**< the animation speed */
m_fCamTargetSpeed; /**< the speed of focusing the next waypoint */
u32 m_iLastTime, /**< the last animator time */
m_iState; /**< state of the animation */
public:
/**
* The constructor
* @param pDevice the irrlicht device
* @param sPathRootName the name of the node that is parent of the list of waypoints
* @param fAnimSpeed the animation speed
* @param fCamTargetSpeed the speed of focusing the next waypoint
*/
CFollowPathAnimator(IrrlichtDevice *pDevice, c8 *sPathRootName, f32 fAnimSpeed, f32 fCamTargetSpeed);
virtual void animateNode(ISceneNode *pNode, u32 timeMs);
virtual ISceneNodeAnimator *createClone(ISceneNode *node, ISceneManager *pNewMngr);
virtual ESCENE_NODE_ANIMATOR_TYPE getType() const;
virtual bool isEventReceiverEnabled() const;
virtual ~CFollowPathAnimator();
/**
* If you want to get notified when the animation ends derive your own class from this class and override
* the implementation of this method
*/
virtual void animatedEnded();
/**
* Call this method before you start the animation to set the camera to it's initial position and target
*/
void setCamParameter(ICameraSceneNode *pCam);
};
#endif
Code: Select all
#include <CFollowPathAnimator.h>
CFollowPathAnimator::CFollowPathAnimator(IrrlichtDevice *pDevice, c8 *sPathRootName, f32 iAnimSpeed, f32 iCamTargetSpeed) {
m_fAnimSpeed=iAnimSpeed;
m_fCamTargetSpeed=iCamTargetSpeed;
m_iLastTime=0;
m_bAnimRunning=true;
m_bStopNextHit=false;
m_bLoopAnim=true;
ISceneNode *path=pDevice->getSceneManager()->getSceneNodeFromName(sPathRootName);
if (path) {
list<ISceneNode *> children=path->getChildren();
list<ISceneNode *>::Iterator it;
for (it=children.begin(); it!=children.end(); it++) {
m_cPathPoints.push_back((*it)->getAbsolutePosition());
}
}
m_cIter=m_cPathPoints.begin();
m_cCamPos=*m_cIter; m_cIter++;
m_cCamTgt=*m_cIter; m_cIter++;
m_cCamDir=(m_cCamTgt-m_cCamPos).normalize();
m_iState=0;
}
void CFollowPathAnimator::animateNode(ISceneNode *pNode, u32 timeMs) {
f32 fTimeDiff=timeMs-m_iLastTime;
if (timeMs==m_iLastTime) return;
m_iLastTime=timeMs;
ICameraSceneNode *pCam=reinterpret_cast<ICameraSceneNode *>(pNode);
vector3df move;
f32 fLength_old,f1,f2;
static int iCnt=0;
if (m_bAnimRunning) {
switch (m_iState) {
case 0:
move=fTimeDiff*(m_cCamTgt-m_cCamPos).normalize()/m_fAnimSpeed;
fLength_old=(m_cCamTgt-m_cCamPos).getLength();
pCam->setPosition(pNode->getPosition()+move);
pCam->setTarget(pCam->getPosition()+m_cCamDir);
m_cCamPos=pCam->getPosition();
f32 fLength_new=(m_cCamTgt-m_cCamPos).getLength();
if (fLength_new-fLength_old>=0)
if (m_bStopNextHit)
m_iState=4;
else
m_iState=1;
break;
case 1:
m_cCamNDr=m_cCamDir.normalize();
m_cCamPos=m_cCamTgt;
m_cCamTgt=*m_cIter;
m_cCamDir=(m_cCamTgt-m_cCamPos).normalize();
m_cCamTrn=(m_cCamDir-m_cCamNDr)/m_fCamTargetSpeed;
m_cIter++;
if (m_cIter==m_cPathPoints.end()) m_bStopNextHit=true;
m_iState=5;
m_iNextState=2;
m_iDelayTime=0;
iCnt=0;
break;
case 2:
if (iCnt++<150) fTimeDiff=0.0f;
f1=(m_cCamNDr*100-m_cCamDir*100).getLength();
m_cCamNDr+=(m_cCamTrn*fTimeDiff);
f2=(m_cCamNDr*100-m_cCamDir*100).getLength();
pCam->setTarget(pCam->getPosition()+m_cCamNDr);
if (f1-f2<0) {
m_iState=5;
m_iNextState=3;
m_iDelayTime=0;
}
break;
case 3:
m_cCamDir=m_cCamTgt-pCam->getPosition();
pCam->setTarget(m_cCamTgt);
m_iState=0;
break;
case 4:
animatedEnded();
if (m_bLoopAnim) {
m_cIter=m_cPathPoints.begin();
m_cCamPos=*m_cIter; m_cIter++;
m_cCamTgt=*m_cIter; m_cIter++;
pCam->setPosition(m_cCamPos);
pCam->setTarget(m_cCamTgt);
m_cCamDir=(m_cCamTgt-m_cCamPos).normalize();
m_bStopNextHit=false;
m_iState=0;
}
else m_bAnimRunning=false;
case 5:
m_iDelayTime+=(u32)fTimeDiff;
if (m_iDelayTime>100) m_iState=m_iNextState;
break;
}
}
}
ISceneNodeAnimator *CFollowPathAnimator::createClone(ISceneNode *node, ISceneManager *pNewMngr) {
return NULL;
}
ESCENE_NODE_ANIMATOR_TYPE CFollowPathAnimator::getType() const {
return (ESCENE_NODE_ANIMATOR_TYPE)2305;
}
bool CFollowPathAnimator::isEventReceiverEnabled() const {
return false;
}
CFollowPathAnimator::~CFollowPathAnimator() { }
void CFollowPathAnimator::animatedEnded() {
}
void CFollowPathAnimator::setCamParameter(ICameraSceneNode *pCam) {
pCam->setPosition(m_cCamPos);
pCam->setTarget(m_cCamTgt);
}
