00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028 #include "3d/animation_playlist.h"
00029 #include "nel/misc/common.h"
00030 #include "nel/misc/stream.h"
00031 #include <math.h>
00032
00033 using namespace NLMISC;
00034
00035 namespace NL3D
00036 {
00037
00038
00039
00040 CAnimationPlaylist::CAnimationPlaylist()
00041 {
00042
00043 emptyPlayList ();
00044
00045
00046 for (uint i=0; i<CChannelMixer::NumAnimationSlot; i++)
00047 _WrapMode[i]=Clamp;
00048 }
00049
00050
00051
00052 void CAnimationPlaylist::emptyPlayList ()
00053 {
00054
00055 for (uint i=0; i<CChannelMixer::NumAnimationSlot; i++)
00056 {
00057 _Animations[i]=empty;
00058 _SkeletonWeight[i]=empty;
00059 _InvertWeight[i]=false;
00060 _TimeOrigin[i]=0.f;
00061 _SpeedFactor[i]=1.f;
00062 _StartWeight[i]=1.f;
00063 _EndWeight[i]=1.f;
00064 }
00065 }
00066
00067
00068
00069 void CAnimationPlaylist::setAnimation (uint8 slot, uint animation)
00070 {
00071 _Animations[slot]=animation;
00072 }
00073
00074
00075
00076 uint CAnimationPlaylist::getAnimation (uint8 slot) const
00077 {
00078 return _Animations[slot];
00079 }
00080
00081
00082
00083 void CAnimationPlaylist::setSkeletonWeight (uint8 slot, uint skeletonId, bool inverted)
00084 {
00085 _SkeletonWeight[slot]=skeletonId;
00086 _InvertWeight[slot]=inverted;
00087 }
00088
00089
00090
00091 uint CAnimationPlaylist::getSkeletonWeight (uint8 slot, bool &inverted) const
00092 {
00093 inverted=_InvertWeight[slot];
00094 return _SkeletonWeight[slot];
00095 }
00096
00097
00098
00099 void CAnimationPlaylist::setTimeOrigin (uint8 slot, TGlobalAnimationTime timeOrigin)
00100 {
00101 _TimeOrigin[slot]=timeOrigin;
00102 }
00103
00104
00105
00106 TGlobalAnimationTime CAnimationPlaylist::getTimeOrigin (uint8 slot) const
00107 {
00108 return _TimeOrigin[slot];
00109 }
00110
00111
00112
00113 void CAnimationPlaylist::setSpeedFactor (uint8 slot, float speedFactor)
00114 {
00115 _SpeedFactor[slot]=speedFactor;
00116 }
00117
00118
00119
00120 float CAnimationPlaylist::getSpeedFactor (uint8 slot) const
00121 {
00122 return _SpeedFactor[slot];
00123 }
00124
00125
00126
00127 void CAnimationPlaylist::setStartWeight (uint8 slot, float startWeight, TGlobalAnimationTime time)
00128 {
00129 _StartWeight[slot]=startWeight;
00130 _StartWeightTime[slot]=time;
00131 }
00132
00133
00134
00135 float CAnimationPlaylist::getStartWeight (uint8 slot, TGlobalAnimationTime& time) const
00136 {
00137 time=_StartWeightTime[slot];
00138 return _StartWeight[slot];
00139 }
00140
00141
00142
00143 void CAnimationPlaylist::setEndWeight (uint8 slot, float endWeight, TGlobalAnimationTime time)
00144 {
00145 _EndWeight[slot]=endWeight;
00146 _EndWeightTime[slot]=time;
00147 }
00148
00149
00150
00151 float CAnimationPlaylist::getEndWeight (uint8 slot, TGlobalAnimationTime& time) const
00152 {
00153 time=_EndWeightTime[slot];
00154 return _EndWeight[slot];
00155 }
00156
00157
00158
00159 void CAnimationPlaylist::setWeightSmoothness (uint8 slot, float smoothness)
00160 {
00161 _Smoothness[slot]=smoothness;
00162 }
00163
00164
00165
00166 float CAnimationPlaylist::getWeightSmoothness (uint8 slot) const
00167 {
00168 return _Smoothness[slot];
00169 }
00170
00171
00172
00173 void CAnimationPlaylist::setupMixer (CChannelMixer& mixer, TGlobalAnimationTime time) const
00174 {
00175
00176 for (uint8 s=0; s<CChannelMixer::NumAnimationSlot; s++)
00177 {
00178
00179
00180
00181 bool enabled=true;
00182
00183
00184 const CAnimationSet *animSet=mixer.getAnimationSet ();
00185
00186
00187 if (animSet)
00188 {
00189 if (_Animations[s]!=empty)
00190 {
00191
00192 TAnimationTime wrappedTime = getLocalTime (s, time, *animSet);
00193
00194
00195 const CAnimation *pAnimation=animSet->getAnimation (_Animations[s]);
00196
00197
00198 if ((_WrapMode[s]==Disable)&&((wrappedTime<pAnimation->getBeginTime ())||(wrappedTime>pAnimation->getEndTime ())))
00199 enabled=false;
00200
00201
00202 if (enabled)
00203 mixer.setSlotTime (s, wrappedTime);
00204 }
00205 }
00206
00207
00208
00209
00210 if (enabled)
00211 {
00212
00213 if (_Animations[s]==empty)
00214
00215 mixer.emptySlot (s);
00216 else
00217
00218 mixer.setSlotAnimation (s, _Animations[s]);
00219
00220
00221
00222
00223 if (_SkeletonWeight[s]==empty)
00224
00225 mixer.resetSkeletonWeight (s);
00226 else
00227
00228 mixer.applySkeletonWeight (s, _SkeletonWeight[s], _InvertWeight[s]);
00229
00230
00231 mixer.setSlotWeight (s, getWeightValue (_StartWeightTime[s], _EndWeightTime[s], time, _StartWeight[s], _EndWeight[s], _Smoothness[s]));
00232 }
00233 else
00234 {
00235
00236 mixer.emptySlot (s);
00237 }
00238 }
00239 }
00240
00241
00242
00243 float CAnimationPlaylist::getWeightValue (TGlobalAnimationTime startWeightTime, TGlobalAnimationTime endWeightTime, TGlobalAnimationTime time, float startWeight, float endWeight, float smoothness)
00244 {
00245
00246 if (time<=startWeightTime)
00247 return startWeight;
00248
00249 if (time>=endWeightTime)
00250 return endWeight;
00251
00252
00253
00254
00255 TGlobalAnimationTime linear=startWeight+(endWeight-startWeight)*(time-startWeightTime)/(endWeightTime-startWeightTime);
00256
00257
00258 if (smoothness<0.0001f)
00259 return (float)linear;
00260
00261
00262 double a=2.f*startWeight-2.f*endWeight;
00263 double b=3.f*endWeight-3.f*startWeight;
00264 double x=(time-startWeightTime)/(endWeightTime-startWeightTime);
00265 double xSquare=x*x;
00266 double xCube=x*xSquare;
00267 double quad=a*xCube+b*xSquare+startWeight;
00268
00269
00270 return (float)(smoothness*quad+(1.f-smoothness)*linear);
00271 }
00272
00273
00274
00275 void CAnimationPlaylist::setWrapMode (uint8 slot, TWrapMode wrapMode)
00276 {
00277 _WrapMode[slot]=wrapMode;
00278 }
00279
00280
00281
00282 CAnimationPlaylist::TWrapMode CAnimationPlaylist::getWrapMode (uint8 slot) const
00283 {
00284 return _WrapMode[slot];
00285 }
00286
00287
00288
00289 void CAnimationPlaylist::serial (NLMISC::IStream& f)
00290 {
00291
00292 (void)f.serialVersion (0);
00293
00294
00295 for (uint i=0; i<CChannelMixer::NumAnimationSlot; i++)
00296 {
00297 f.serial (_Animations[i]);
00298 f.serial (_SkeletonWeight[i]);
00299 f.serial (_InvertWeight[i]);
00300 f.serial (_TimeOrigin[i]);
00301 f.serial (_SpeedFactor[i]);
00302 f.serial (_StartWeight[i]);
00303 f.serial (_StartWeightTime[i]);
00304 f.serial (_EndWeight[i]);
00305 f.serial (_EndWeightTime[i]);
00306 f.serial (_Smoothness[i]);
00307 f.serialEnum (_WrapMode[i]);
00308 }
00309 }
00310
00311
00312
00313 TAnimationTime CAnimationPlaylist::getLocalTime (uint8 slot, TGlobalAnimationTime globalTime, const CAnimationSet& animSet) const
00314 {
00315
00316 const CAnimation *pAnimation=animSet.getAnimation (_Animations[slot]);
00317
00318
00319 if (pAnimation)
00320 {
00321
00322 TAnimationTime wrappedTime=pAnimation->getBeginTime ()+(TAnimationTime)((globalTime-_TimeOrigin[slot])*_SpeedFactor[slot]);
00323
00324
00325 switch (_WrapMode[slot])
00326 {
00327 case Clamp:
00328 clamp (wrappedTime, pAnimation->getBeginTime (), pAnimation->getEndTime ());
00329 break;
00330 case Repeat:
00331
00332 {
00333 float length=pAnimation->getEndTime ()-pAnimation->getBeginTime();
00334 if (wrappedTime>=pAnimation->getBeginTime())
00335 wrappedTime=pAnimation->getBeginTime()+(float)fmod (wrappedTime-pAnimation->getBeginTime(), length);
00336 else
00337 wrappedTime=pAnimation->getBeginTime()+(float)fmod (wrappedTime-pAnimation->getBeginTime(), length)+length;
00338 }
00339 break;
00340 default: break;
00341 }
00342
00343
00344 return wrappedTime;
00345 }
00346
00347 return (TAnimationTime)globalTime;
00348 }
00349
00350
00351
00352 float CAnimationPlaylist::getLocalWeight (uint8 slot, TGlobalAnimationTime globalTime) const
00353 {
00354 return getWeightValue (_StartWeightTime[slot], _EndWeightTime[slot], globalTime, _StartWeight[slot], _EndWeight[slot], _Smoothness[slot]);
00355 }
00356
00357
00358
00359
00360 }