Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / src / 3d / animation.cpp
blob157ca5427f262e053f35aa9cc84d4706093daa1f
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "std3d.h"
19 #include "nel/3d/animation.h"
20 #include "nel/3d/animation_set.h"
21 #include "nel/3d/track.h"
22 #include "nel/3d/track_sampled_quat_small_header.h"
24 #include "nel/misc/file.h"
25 #include "nel/misc/path.h"
26 #include "nel/misc/hierarchical_timer.h"
27 #include "nel/misc/algo.h"
30 using namespace std;
31 using namespace NLMISC;
33 #ifdef DEBUG_NEW
34 #define new DEBUG_NEW
35 #endif
37 namespace NL3D
40 H_AUTO_DECL( NL3D_UI_Animation )
42 #define NL3D_HAUTO_UI_ANIMATION H_AUTO_USE( NL3D_UI_Animation )
45 // ***************************************************************************
47 CAnimation::CAnimation() : _BeginTimeTouched(true), _EndTimeTouched(true), _AnimLoopTouched(true)
49 _MinEndTime = -FLT_MAX;
50 _TrackSamplePack= NULL;
51 _AnimationSetOwner= NULL;
54 // ***************************************************************************
56 CAnimation::~CAnimation ()
58 // Delete all the pointers in the array
59 for (uint i=0; i<_TrackVector.size(); i++)
60 // Delete
61 delete _TrackVector[i];
63 // if created, release the _TrackSamplePack
64 if(_TrackSamplePack)
65 delete _TrackSamplePack;
66 _TrackSamplePack= NULL;
69 // ***************************************************************************
71 void CAnimation::addTrack (const std::string& name, ITrack* pChannel)
73 // must not already be HeaderOptimized
74 nlassert(_IdByChannelId.empty());
76 // Add an entry in the map
77 _IdByName.insert (TMapStringUInt::value_type (name, (uint32)_TrackVector.size()));
79 // Add an entry in the array
80 _TrackVector.push_back (pChannel);
83 _BeginTimeTouched = _EndTimeTouched = _AnimLoopTouched= true;
87 // ***************************************************************************
89 void CAnimation::serial (NLMISC::IStream& f)
91 // cannot save if anim header compressed
92 nlassert(_IdByChannelId.empty());
94 // Serial a header
95 f.serialCheck (NELID("_LEN"));
96 f.serialCheck (NELID("MINA"));
98 // Serial a version
99 sint version=f.serialVersion (2);
101 // Serial the name
102 f.serial (_Name);
104 // Serial the name/id map
105 f.serialCont(_IdByName);
107 // Serial the vector
108 f.serialContPolyPtr (_TrackVector);
110 // Serial the min end time
111 if (version>=1)
113 f.serial (_MinEndTime);
116 // Serial the SSS shapes
117 if (version>=2)
119 f.serialCont (_SSSShapes);
122 // TestYoyo
123 //nlinfo("ANIMYOYO: Anim NumTracks: %d", _TrackVector.size());
127 // ***************************************************************************
128 uint CAnimation::getIdTrackByName (const std::string& name) const
131 // if not be HeaderOptimized
132 if (_IdByChannelId.empty())
134 // Find an entry in the name/id map
135 TMapStringUInt::const_iterator ite=_IdByName.find (name);
137 // Not found ?
138 if (ite==_IdByName.end ())
139 // yes, error
140 return NotFound;
141 else
142 // no, return track ID
143 return (uint)ite->second;
145 else
147 nlassert(_AnimationSetOwner);
148 // get the channel id from name
149 uint channelId= _AnimationSetOwner->getChannelIdByName(name);
150 if(channelId==CAnimationSet::NotFound)
151 return CAnimation::NotFound;
152 else
153 return getIdTrackByChannelId(channelId);
157 // ***************************************************************************
158 void CAnimation::getTrackNames (std::set<std::string>& setString) const
161 // if not be HeaderOptimized
162 if (_IdByChannelId.empty())
164 // For each track name
165 TMapStringUInt::const_iterator ite=_IdByName.begin();
166 while (ite!=_IdByName.end())
168 // Add the name in the map
169 setString.insert (ite->first);
171 // Next track
172 ite++;
175 else
177 nlassert(_AnimationSetOwner);
178 // For each track channel Id,
179 for(uint i=0;i<_IdByChannelId.size();i++)
181 // Add in the map the channel name => same as track name
182 setString.insert ( _AnimationSetOwner->getChannelName(_IdByChannelId[i]) );
187 // ***************************************************************************
188 TAnimationTime CAnimation::getBeginTime () const
190 NL3D_HAUTO_UI_ANIMATION;
192 if (_BeginTimeTouched)
194 // Track count
195 uint trackCount=(uint)_TrackVector.size();
197 // Track count empty ?
198 if (trackCount==0)
199 return 0.f;
201 // Look for the lowest
202 _BeginTime=_TrackVector[0]->getBeginTime ();
204 // Scan all keys
205 for (uint t=1; t<trackCount; t++)
207 if (_TrackVector[t]->getBeginTime ()<_BeginTime)
208 _BeginTime=_TrackVector[t]->getBeginTime ();
211 _BeginTimeTouched = false;
214 return _BeginTime;
217 // ***************************************************************************
219 TAnimationTime CAnimation::getEndTime () const
221 NL3D_HAUTO_UI_ANIMATION;
223 if (_EndTimeTouched)
225 // Track count
226 uint trackCount=(uint)_TrackVector.size();
228 // Track count empty ?
229 if (trackCount==0)
230 return 0.f;
232 // Look for the highest
233 _EndTime=_TrackVector[0]->getEndTime ();
235 // Scan tracks keys
236 for (uint t=1; t<trackCount; t++)
238 if (_TrackVector[t]->getEndTime ()>_EndTime)
239 _EndTime=_TrackVector[t]->getEndTime ();
242 // Check min end time
243 if (_EndTime < _MinEndTime)
244 _EndTime = _MinEndTime;
246 _EndTimeTouched = false;
249 return _EndTime;
252 // ***************************************************************************
253 bool CAnimation::allTrackLoop() const
255 NL3D_HAUTO_UI_ANIMATION;
257 if(_AnimLoopTouched)
259 // Track count
260 uint trackCount=(uint)_TrackVector.size();
262 // Default is true
263 _AnimLoop= true;
265 // Scan tracks keys
266 for (uint t=0; t<trackCount; t++)
268 if (!_TrackVector[t]->getLoopMode())
270 _AnimLoop= false;
271 break;
274 _AnimLoopTouched = false;
277 return _AnimLoop;
280 // ***************************************************************************
282 UTrack* CAnimation::getTrackByName (const char* name)
284 NL3D_HAUTO_UI_ANIMATION;
286 // Get track id
287 uint id=getIdTrackByName (name);
289 // Not found ?
290 if (id==CAnimation::NotFound)
291 // Error, return NULL
292 return NULL;
293 else
294 // No error, return the track
295 return getTrack (id);
298 // ***************************************************************************
300 void CAnimation::releaseTrack (UTrack* /* track */)
302 NL3D_HAUTO_UI_ANIMATION;
304 // Nothing to do
307 // ***************************************************************************
309 void CAnimation::setMinEndTime (TAnimationTime minEndTime)
311 _MinEndTime = minEndTime;
314 // ***************************************************************************
316 UAnimation* UAnimation::createAnimation (const char* sPath)
318 NL3D_HAUTO_UI_ANIMATION;
320 // Allocate an animation
321 CUniquePtr<CAnimation> anim (new CAnimation);
323 // Read it
324 NLMISC::CIFile file;
325 if (file.open ( NLMISC::CPath::lookup( sPath ) ) )
327 // Serial the animation
328 file.serial (*anim);
330 // Return pointer
331 CAnimation *ret=anim.release ();
333 // Return the animation interface
334 return ret;
336 else
337 return NULL;
340 // ***************************************************************************
342 void UAnimation::releaseAnimation (UAnimation* animation)
344 NL3D_HAUTO_UI_ANIMATION;
346 // Cast the pointer
347 CAnimation* release=(CAnimation*)animation;
349 // Delete it
350 delete release;
353 // ***************************************************************************
354 void CAnimation::applySampleDivisor(uint sampleDivisor)
356 NL3D_HAUTO_UI_ANIMATION;
358 for(uint i=0;i<_TrackVector.size();i++)
360 ITrack *track= _TrackVector[i];
361 if(track)
362 track->applySampleDivisor(sampleDivisor);
367 // ***************************************************************************
368 void CAnimation::applyTrackQuatHeaderCompression()
370 NL3D_HAUTO_UI_ANIMATION;
372 // if the header compression has already been donne, no op
373 if(_TrackSamplePack)
374 return;
376 // **** First pass: count the number of keys to allocate
377 CTrackSampleCounter sampleCounter;
378 bool someTrackOK= false;
379 for(uint i=0;i<_TrackVector.size();i++)
381 ITrack *track= _TrackVector[i];
382 if(track)
384 // return true only for CTrackSampledQuat
385 if(track->applyTrackQuatHeaderCompressionPass0(sampleCounter))
386 someTrackOK= true;
390 // **** second pass: fill, onlmy if some track matchs (fails for instance for big animations)
391 if(someTrackOK)
393 uint i;
395 // must create the Sample packer
396 _TrackSamplePack= new CTrackSamplePack;
398 // just copy the built track headers
399 _TrackSamplePack->TrackHeaders.resize((uint32)sampleCounter.TrackHeaders.size());
400 for(i=0;i<_TrackSamplePack->TrackHeaders.size();i++)
402 _TrackSamplePack->TrackHeaders[i]= sampleCounter.TrackHeaders[i];
405 // and allocate keys
406 _TrackSamplePack->Times.resize(sampleCounter.NumKeys);
407 _TrackSamplePack->Keys.resize(sampleCounter.NumKeys);
409 // start the counter for Pass1 to work
410 uint globalKeyOffset= 0;
412 // fill it for each track
413 for(i=0;i<_TrackVector.size();i++)
415 ITrack *track= _TrackVector[i];
416 if(track)
418 ITrack *newTrack= track->applyTrackQuatHeaderCompressionPass1(globalKeyOffset, *_TrackSamplePack);
419 // if compressed
420 if(newTrack)
422 // delete the old track, and replace with compressed one
423 delete _TrackVector[i];
424 _TrackVector[i]= newTrack;
429 nlassert(globalKeyOffset == _TrackSamplePack->Keys.size());
436 // ***************************************************************************
437 struct CTempTrackInfo
439 uint16 ChannelId;
440 ITrack *Track;
442 bool operator<(const CTempTrackInfo &o) const
444 return ChannelId < o.ChannelId;
447 void CAnimation::applyAnimHeaderCompression(CAnimationSet *animationSetOwner, const std::map <std::string, uint32> &channelMap)
449 uint i;
450 nlassert(animationSetOwner);
451 // must not be already done
452 nlassert(_IdByChannelId.empty());
454 // fill the track info, with Track
455 std::vector<CTempTrackInfo> tempTrackInfo;
456 tempTrackInfo.resize(_TrackVector.size());
457 for(i=0;i<tempTrackInfo.size();i++)
459 tempTrackInfo[i].Track= _TrackVector[i];
462 // fill the track info, with ChannelId
463 TMapStringUInt::iterator it;
464 for(it= _IdByName.begin();it!=_IdByName.end();it++)
466 // search this track in the channelMap
467 std::map <std::string, uint32>::const_iterator itChan= channelMap.find(it->first);
468 nlassert(itChan!=channelMap.end());
469 // store the channelId in the associated track
470 tempTrackInfo[it->second].ChannelId= (uint16)itChan->second;
473 // sort by channelId
474 sort(tempTrackInfo.begin(), tempTrackInfo.end());
476 // refill the TrackVector (sorted)
477 _IdByChannelId.resize( tempTrackInfo.size() );
478 for(i=0;i<tempTrackInfo.size();i++)
480 _TrackVector[i]= tempTrackInfo[i].Track;
481 _IdByChannelId[i]= tempTrackInfo[i].ChannelId;
484 // clear the no more needed track map
485 contReset(_IdByName);
487 // must keep the animSet
488 _AnimationSetOwner= animationSetOwner;
492 // ***************************************************************************
493 uint CAnimation::getIdTrackByChannelId (uint16 channelId) const
495 if(_IdByChannelId.empty())
496 return CAnimation::NotFound;
497 else
499 uint trackId= searchLowerBound(_IdByChannelId, channelId);
500 // verify that the channel is really found
501 if(_IdByChannelId[trackId]==channelId)
503 return trackId;
505 else
506 return CAnimation::NotFound;
510 // ***************************************************************************
511 void CAnimation::addSSSShape(const std::string &shape)
513 _SSSShapes.push_back(shape);
517 } // NL3D