SceneNodeAnimatorFollowSpline(with rotation)

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
hahajiang
Posts: 7
Joined: Tue May 12, 2015 2:49 am

SceneNodeAnimatorFollowSpline(with rotation)

Post by hahajiang »

I just change a little to add the rotation into the animator on basis of the original one in irrlicht.
Here is the code:

SceneNodeAnimatorFollowSpline2.h

Code: Select all

 
#pragma once
#include "ISceneNode.h"
#include "irrArray.h"
#include "ISceneNodeAnimatorFinishing.h"
 
#define PI 3.1415926
namespace irr
{
    namespace scene
    {
        class CSceneNodeAnimatorFollowSpline2: public ISceneNodeAnimatorFinishing
        {
        public:
            CSceneNodeAnimatorFollowSpline2(u32 startTime,
                const core::array< core::vector3df >& points,
                f32 speed = 1.0f, f32 tightness = 0.5f, bool loop=true, bool pingpong=false);
 
            virtual ~CSceneNodeAnimatorFollowSpline2(void);
 
            //! animates a scene node
            virtual void animateNode(ISceneNode* node, u32 timeMs);
 
            //! Writes attributes of the scene node animator.
            virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const;
 
            //! Reads attributes of the scene node animator.
            virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0);
 
            //! Returns type of the scene node animator
            virtual ESCENE_NODE_ANIMATOR_TYPE getType() const { return ESNAT_FOLLOW_SPLINE; }
 
            //! Creates a clone of this animator.
            /** Please note that you will have to drop
            (IReferenceCounted::drop()) the returned pointer after calling
            this. */
            virtual ISceneNodeAnimator* createClone(ISceneNode* node, ISceneManager* newManager=0);
 
        protected:
 
            //! clamps a the value idx to fit into range 0..size-1
            s32 clamp(s32 idx, s32 size);
 
            core::array< core::vector3df > Points;
            f32 Speed;
            f32 Tightness;
            u32 StartTime;
            bool Loop;
            bool PingPong;
        };
    }
}
 

SceneNodeAnimatorFollowSpline2.cpp

Code: Select all

 
#include "SceneNodeAnimatorFollowSpline2.h"
#include <cmath>
#include <iostream>
#include <fstream>
 
namespace irr
{
    namespace scene
    {
        CSceneNodeAnimatorFollowSpline2::CSceneNodeAnimatorFollowSpline2(u32 time,
            const core::array<core::vector3df>& points, f32 speed,
            f32 tightness, bool loop, bool pingpong)
            : ISceneNodeAnimatorFinishing(0), Points(points), Speed(speed), Tightness(tightness), StartTime(time)
            , Loop(loop), PingPong(pingpong)
        {
#ifdef _DEBUG
            setDebugName("CSceneNodeAnimatorFollowSpline2");
#endif
        }
 
 
        CSceneNodeAnimatorFollowSpline2::~CSceneNodeAnimatorFollowSpline2(void)
        {
        }
 
        inline s32 CSceneNodeAnimatorFollowSpline2::clamp(s32 idx, s32 size)
        {
            return ( idx<0 ? size+idx : ( idx>=size ? idx-size : idx ) );
        }
 
        //! animates a scene node
        void CSceneNodeAnimatorFollowSpline2::animateNode(ISceneNode* node, u32 timeMs)
        {
            if(!node)
                return;
 
            const u32 pSize = Points.size();
            if (pSize==0)
            {
                if ( !Loop )
                    HasFinished = true;
                return;
            }
            if (pSize==1)
            {
                if ( timeMs > StartTime )
                {
                    node->setPosition(Points[0]);
                    if ( !Loop )
                        HasFinished = true;
                }
                return;
            }
 
            const f32 dt = ( (timeMs-StartTime) * Speed * 0.001f );
            const s32 unwrappedIdx = core::floor32( dt );
            if ( !Loop && unwrappedIdx >= (s32)pSize-1 )
            {
                node->setPosition(Points[pSize-1]);
                HasFinished = true;
                return;
            }
            const bool pong = PingPong && (unwrappedIdx/(pSize-1))%2;
            const f32 u =  pong ? 1.f-core::fract ( dt ) : core::fract ( dt );
            const s32 idx = pong ?  (pSize-2) - (unwrappedIdx % (pSize-1))
                : (PingPong ? unwrappedIdx % (pSize-1)
                : unwrappedIdx % pSize);
            //const f32 u = 0.001f * fmodf( dt, 1000.0f );
 
            const core::vector3df& p0 = Points[ clamp( idx - 1, pSize ) ];
            const core::vector3df& p1 = Points[ clamp( idx + 0, pSize ) ]; // starting point
            const core::vector3df& p2 = Points[ clamp( idx + 1, pSize ) ]; // end point
            const core::vector3df& p3 = Points[ clamp( idx + 2, pSize ) ];
 
            // hermite polynomials
            const f32 h1 = 2.0f * u * u * u - 3.0f * u * u + 1.0f;
            const f32 h2 = -2.0f * u * u * u + 3.0f * u * u;
            const f32 h3 = u * u * u - 2.0f * u * u + u;
            const f32 h4 = u * u * u - u * u;
 
            // tangents
            const core::vector3df t1 = ( p2 - p0 ) * Tightness;
            const core::vector3df t2 = ( p3 - p1 ) * Tightness;
 
            core::vector3df prePos = node->getPosition();
            // interpolated point
            node->setPosition(p1 * h1 + p2 * h2 + t1 * h3 + t2 * h4);
            core::vector3df nextPos = node->getPosition();
 
            core::vector3df forward = core::vector3df(sin(node->getRotation().Y * PI /180.0), 0, cos(node->getRotation().Y * PI /180.0)).normalize();
            core::vector3df p1p2 = (nextPos - prePos).normalize();
            f32 angle = std::acos(forward.dotProduct(p1p2)) * 180 / PI;
 
            core::vector3df vertical = core::vector3df(forward.Z, 0, -forward.X);
            if(vertical.dotProduct(p1p2) < 0.f)
                angle = -angle;
 
            node->setRotation(node->getRotation() + core::vector3df(0, angle, 0));
        }
 
 
        //! Writes attributes of the scene node animator.
        void CSceneNodeAnimatorFollowSpline2::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
        {
            out->addFloat("Speed", Speed);
            out->addFloat("Tightness", Tightness);
            out->addBool("Loop", Loop);
            out->addBool("PingPong", PingPong);
 
            u32 count = Points.size();
 
            if ( options && (options->Flags & io::EARWF_FOR_EDITOR))
            {
                // add one point in addition when serializing for editors
                // to make it easier to add points quickly
                count += 1;
            }
 
            for (u32 i=0; i<count; ++i)
            {
                core::stringc tname = "Point";
                tname += (int)(i+1);
 
                out->addVector3d(tname.c_str(), i<Points.size() ? Points[i] : core::vector3df(0,0,0) );
            }
        }
 
 
        //! Reads attributes of the scene node animator.
        void CSceneNodeAnimatorFollowSpline2::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
        {
            Speed = in->getAttributeAsFloat("Speed");
            Tightness = in->getAttributeAsFloat("Tightness");
            Loop = in->getAttributeAsBool("Loop");
            PingPong = in->getAttributeAsBool("PingPong");
            Points.clear();
 
            for(u32 i=1; true; ++i)
            {
                core::stringc pname = "Point";
                pname += i;
 
                if (in->existsAttribute(pname.c_str()))
                    Points.push_back(in->getAttributeAsVector3d(pname.c_str()));
                else
                    break;
            }
 
            // remove last point if double entry from editor
            if ( options && (options->Flags & io::EARWF_FOR_EDITOR) &&
                Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0))
            {
                Points.erase(Points.size()-1);
 
                if (Points.size() > 2 && Points.getLast() == core::vector3df(0,0,0))
                    Points.erase(Points.size()-1);
            }
        }
 
 
        ISceneNodeAnimator* CSceneNodeAnimatorFollowSpline2::createClone(ISceneNode* node, ISceneManager* newManager)
        {
            CSceneNodeAnimatorFollowSpline2 * newAnimator =
                new CSceneNodeAnimatorFollowSpline2(StartTime, Points, Speed, Tightness);
 
            return newAnimator;
        }
    }
}
 

how to use in main.cpp

Code: Select all

 
//create a animatedSceneNode
scene::IAnimatedMeshSceneNode* DynamicNode = smgr->addAnimatedMeshSceneNode(smgr->getMesh("here is the file path of your mesh"));
 
//then you will need to define your waypoints
core::array<core::vector3df> waypoints;
 
//CSceneNodeAnimatorFollowSpline2 here, it's easy!
CSceneNodeAnimatorFollowSpline2* anim = new CSceneNodeAnimatorFollowSpline2(0, waypoints, 1.f, 0.5f, true, false);
DynamicNode->addAnimator(anim);
anim->drop();
 
hahajiang
Posts: 7
Joined: Tue May 12, 2015 2:49 am

Re: SceneNodeAnimatorFollowSpline(with rotation)

Post by hahajiang »

In the method animateNode() I modified the rotation of Y axis, you may change it according to your needs.
Post Reply