// 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