# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

animation_playlist.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
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         // Empty the playlist
00043         emptyPlayList ();
00044 
00045         // Set default wrap mode
00046         for (uint i=0; i<CChannelMixer::NumAnimationSlot; i++)
00047                 _WrapMode[i]=Clamp;
00048 }
00049 
00050 // ***************************************************************************
00051 
00052 void CAnimationPlaylist::emptyPlayList ()
00053 {
00054         // Empty each slot
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         // For each slot
00176         for (uint8 s=0; s<CChannelMixer::NumAnimationSlot; s++)
00177         {
00178                 // *** Set the time
00179 
00180                 // Animation enabled
00181                 bool enabled=true;
00182 
00183                 // Get the animationSet pointer from the mixer
00184                 const CAnimationSet *animSet=mixer.getAnimationSet ();
00185 
00186                 // If is exists
00187                 if (animSet)
00188                 {
00189                         if (_Animations[s]!=empty)
00190                         {
00191                                 // Get the local time
00192                                 TAnimationTime wrappedTime = getLocalTime (s, time, *animSet);
00193 
00194                                 // Get the animation
00195                                 const CAnimation *pAnimation=animSet->getAnimation (_Animations[s]);
00196 
00197                                 // Disable mode ?
00198                                 if ((_WrapMode[s]==Disable)&&((wrappedTime<pAnimation->getBeginTime ())||(wrappedTime>pAnimation->getEndTime ())))
00199                                         enabled=false;
00200 
00201                                 // Set the time
00202                                 if (enabled)
00203                                         mixer.setSlotTime (s, wrappedTime);
00204                         }
00205                 }
00206 
00207                 // *** Set the animation
00208         
00209                 // Still enabled
00210                 if (enabled)
00211                 {
00212                         // empty ?
00213                         if (_Animations[s]==empty)
00214                                 // Empty the slot
00215                                 mixer.emptySlot (s);
00216                         else
00217                                 // Set the animation id
00218                                 mixer.setSlotAnimation (s, _Animations[s]);
00219 
00220                         // *** Set the skeleton weight
00221 
00222                         // empty ?
00223                         if (_SkeletonWeight[s]==empty)
00224                                 // Empty the slot
00225                                 mixer.resetSkeletonWeight (s);
00226                         else
00227                                 // Set the animation id
00228                                 mixer.applySkeletonWeight (s, _SkeletonWeight[s],       _InvertWeight[s]);
00229 
00230                         // *** Set the weight
00231                         mixer.setSlotWeight (s, getWeightValue (_StartWeightTime[s], _EndWeightTime[s], time, _StartWeight[s], _EndWeight[s], _Smoothness[s]));
00232                 }
00233                 else
00234                 {
00235                         // Disable this slot
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         // Clamp left
00246         if (time<=startWeightTime)
00247                 return startWeight;
00248         // Clamp left
00249         if (time>=endWeightTime)
00250                 return endWeight;
00251         
00252         // *** Interpolate
00253         
00254         // Linear value
00255         TGlobalAnimationTime linear=startWeight+(endWeight-startWeight)*(time-startWeightTime)/(endWeightTime-startWeightTime);
00256 
00257         // Linear ?
00258         if (smoothness<0.0001f)
00259                 return (float)linear;
00260 
00261         // Quadratic value
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         // Interpolate between linear and quadratic
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         // Serial a version
00292         (void)f.serialVersion (0);
00293 
00294         // Serial all the values
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         // Get the animation
00316         const CAnimation *pAnimation=animSet.getAnimation (_Animations[slot]);
00317 
00318         // If this animation exists
00319         if (pAnimation)
00320         {
00321                 // Compute the non-wrapped time
00322                 TAnimationTime wrappedTime=pAnimation->getBeginTime ()+(TAnimationTime)((globalTime-_TimeOrigin[slot])*_SpeedFactor[slot]);
00323 
00324                 // Wrap mode
00325                 switch (_WrapMode[slot])
00326                 {
00327                 case Clamp:
00328                         clamp (wrappedTime, pAnimation->getBeginTime (), pAnimation->getEndTime ());
00329                         break;
00330                 case Repeat:
00331                         // Mod repeat the time
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                 // Return localTime
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 } // NL3D