followPathAnimator

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Brainsaw
Posts: 1242
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

followPathAnimator

Post by Brainsaw »

Another code-snippet from me:

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
CFollowPathAnimator.cpp

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);
}

Image
Dustbin::Games on the web: https://www.dustbin-online.de/
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

What's the difference to the follow spline animator?
Brainsaw
Posts: 1242
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

Good question ... next question ;) . Maybe I should look deeper into the code that is there before implementing something. Well ... with this code it is quite easy to add long paths to a scene in IrrEdit ... the demo scene uses (i think) 8 waypoints ... by adding empty waypoints, and the way between the points is done in a straight way. Does the follow spline animator update the target of a camera (haven't tried it .. as you might have guessed ;) )? Mine does, it's for camera scene nodes only (I think it'll crash if you add it to another type of scene node).
Image
Dustbin::Games on the web: https://www.dustbin-online.de/
Mel
Competition winner
Posts: 2293
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Post by Mel »

maybe it would be a good idea to add a path scene node and a point scene node so it was a bit more clear what kind of resources does the engine have. Just for clarity's sake. That is, you may imagine there is a "follow path" (or spline) animator if the engine had a scene node called "pathSceneNode" or "splineSceneNode" for that kind of task.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Brainsaw
Posts: 1242
Joined: Wed Jan 07, 2004 12:57 pm
Location: Bavaria

Post by Brainsaw »

Well, I didn't want to add a new scene node for that, because in that case I would have to make another plugin for IrrEdit ... and as I am lazy I just don't want to do that ;) . But feel free to add another scene node if it helps you.
Image
Dustbin::Games on the web: https://www.dustbin-online.de/
Post Reply