// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "std3d.h" #include "nel/3d/animation_playlist.h" #include "nel/misc/common.h" #include "nel/misc/stream.h" using namespace NLMISC; namespace NL3D { // *************************************************************************** CAnimationPlaylist::CAnimationPlaylist() { // Empty the playlist emptyPlayList (); // Set default wrap mode for (uint i=0; igetAnimation (_Animations[s]); // Disable mode ? if ((_WrapMode[s]==Disable)&&((wrappedTimegetBeginTime ())||(wrappedTime>pAnimation->getEndTime ()))) enabled=false; // Set the time if (enabled) mixer.setSlotTime (s, wrappedTime); } } // *** Set the animation // Still enabled if (enabled) { // empty ? if (_Animations[s]==empty) // Empty the slot mixer.emptySlot (s); else // Set the animation id mixer.setSlotAnimation (s, _Animations[s]); // *** Set the skeleton weight // empty ? if (_SkeletonWeight[s]==empty) // Empty the slot mixer.resetSkeletonWeight (s); else // Set the animation id mixer.applySkeletonWeight (s, _SkeletonWeight[s], _InvertWeight[s]); // *** Set the weight mixer.setSlotWeight (s, getWeightValue (_StartWeightTime[s], _EndWeightTime[s], time, _StartWeight[s], _EndWeight[s], _Smoothness[s])); } else { // Disable this slot mixer.emptySlot (s); } } } // *************************************************************************** float CAnimationPlaylist::getWeightValue (TGlobalAnimationTime startWeightTime, TGlobalAnimationTime endWeightTime, TGlobalAnimationTime time, float startWeight, float endWeight, float smoothness) { // Clamp left if (time<=startWeightTime) return startWeight; // Clamp left if (time>=endWeightTime) return endWeight; // *** Interpolate // Linear value TGlobalAnimationTime linear=startWeight+(endWeight-startWeight)*(time-startWeightTime)/(endWeightTime-startWeightTime); // Linear ? if (smoothness<0.0001f) return (float)linear; // Quadratic value double a=2.f*startWeight-2.f*endWeight; double b=3.f*endWeight-3.f*startWeight; double x=(time-startWeightTime)/(endWeightTime-startWeightTime); double xSquare=x*x; double xCube=x*xSquare; double quad=a*xCube+b*xSquare+startWeight; // Interpolate between linear and quadratic return (float)(smoothness*quad+(1.f-smoothness)*linear); } // *************************************************************************** void CAnimationPlaylist::setWrapMode (uint8 slot, TWrapMode wrapMode) { _WrapMode[slot]=wrapMode; } // *************************************************************************** CAnimationPlaylist::TWrapMode CAnimationPlaylist::getWrapMode (uint8 slot) const { return _WrapMode[slot]; } // *************************************************************************** void CAnimationPlaylist::serial (NLMISC::IStream& f) { // Serial a version (void)f.serialVersion (0); // Serial all the values for (uint i=0; igetBeginTime ()+(TAnimationTime)((globalTime-_TimeOrigin[slot])*_SpeedFactor[slot]); // Wrap mode switch (_WrapMode[slot]) { case Clamp: clamp (wrappedTime, pAnimation->getBeginTime (), pAnimation->getEndTime ()); break; case Repeat: // Mod repeat the time { float length=pAnimation->getEndTime ()-pAnimation->getBeginTime(); if (wrappedTime>=pAnimation->getBeginTime()) wrappedTime=pAnimation->getBeginTime()+(float)fmod (wrappedTime-pAnimation->getBeginTime(), length); else wrappedTime=pAnimation->getBeginTime()+(float)fmod (wrappedTime-pAnimation->getBeginTime(), length)+length; } break; default: break; } // Return localTime return wrappedTime; } return (TAnimationTime)globalTime; } // *************************************************************************** float CAnimationPlaylist::getLocalWeight (uint8 slot, TGlobalAnimationTime globalTime) const { return getWeightValue (_StartWeightTime[slot], _EndWeightTime[slot], globalTime, _StartWeight[slot], _EndWeight[slot], _Smoothness[slot]); } // *************************************************************************** } // NL3D