Merge branch '164-crash-on-patching-and-possibly-right-after-login' into main/gingo...
[ryzomcore.git] / ryzom / client / src / animated_scene_object.cpp
blob487841214ddb66b562db0d2ebe86f4b1d1f7b805
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
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/>.
19 #include "stdpch.h"
21 #include <vector>
23 #include "nel/3d/animation_time.h"
24 #include "nel/3d/u_animation.h"
25 #include "nel/3d/u_track.h"
26 #include "nel/3d/u_bone.h"
27 #include "nel/misc/command.h"
29 #include "game_share/draw_section.h"
31 #include "animated_scene_object.h"
32 #include "user_entity.h"
33 #include "view.h"
34 #include "entities.h"
36 using namespace std;
37 using namespace NLMISC;
38 using namespace NL3D;
39 using namespace NLNET;
41 // some extern of client
42 extern CUserEntity *UserEntity;
43 extern UScene *Scene;
46 // map of anilated scene object
47 TMapCAnimatedSceneObject AnimatedSceneObject;
50 // Constructor for moving object, create entity (mesh, skeleton) and build animation on it
51 CAnimatedSceneObject::CAnimatedSceneObject( const string& ObjectName, const string& ClusterIG, const string& MeshName, const string& SkeletonName, const list < string >& Animations, const CVector& Position, const CQuat& Rotation, float Distance )
53 _ObjectName = ObjectName;
54 _ClusterIG = ClusterIG;
55 _MeshName = MeshName;
56 _SkeletonName = SkeletonName;
58 _Position = Position;
59 _Rotation = Rotation;
60 _Distance = Distance * Distance; //square distance for optimize distance calculation
62 // create play list manager and animation set
63 _PlayListManager = Scene->createPlayListManager();
64 _AnimationSet = Driver->createAnimationSet();
66 //fill animation set
67 for( list< string >::const_iterator it = Animations.begin(); it != Animations.end(); ++it )
69 uint idAnim;
70 try
72 idAnim = _AnimationSet->addAnimation( ( *it + string(".anim")).c_str(), (*it).c_str() );
74 catch(Exception &)
76 idAnim = UAnimationSet::NotFound;
77 if( idAnim == UAnimationSet::NotFound)
79 nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for object %s", (*it).c_str(), _ObjectName.c_str() );
80 continue;
83 _MapAnimation.insert( make_pair( *it, idAnim ) );
86 // build animation set
87 _AnimationSet->build();
89 // create playlist
90 _PlayList = _PlayListManager->createPlayList( _AnimationSet );
92 _Status = SAnimationStatus();
93 _Status.RandomAnim = 1;
94 _Status.ApplyDisplacement = 0;
96 // load instance and bind to skeleton
97 _Instance = Scene->createInstance( _MeshName );
98 if( _Instance == NULL )
100 nlerror("CAnimatedSceneObject::CAnimatedSceneObject createInstance %s returned 0 -> no shape.", _MeshName.c_str() );
102 else
104 _Transform = _Instance;
107 // load skeleton, bind mesh and init position, rotation, cluster
108 if(!_SkeletonName.empty())
110 _Skeleton = Scene->createSkeleton(_SkeletonName);
111 if( _Skeleton == NULL )
113 nlerror("CAnimatedSceneObject::CAnimatedSceneObject createSkeleton %s returned 0 -> no skeleton.", _SkeletonName.c_str() );
115 _Transform = _Skeleton;
116 _Skeleton->bindSkin( _Instance );
117 // Enable Shadow
118 if(ClientCfg.Shadows)
120 _Skeleton->enableCastShadowMap(true);
124 // register skeleton in playlist
125 _PlayList->registerTransform( _Transform );
127 // Initialise squeleton initial state
128 if( _MapAnimation.begin() != _MapAnimation.end() )
130 _PlayList->setAnimation( 0, (*_MapAnimation.begin()).second );
131 _PlayList->setTimeOrigin(0, 0 );
132 _PlayList->setSpeedFactor( 0, 1 );
133 _PlayListManager->animate( 0 );
136 _Transform->setClusterSystem( IGCity[_ClusterIG] );
137 _Transform->setPos( _Position );
138 _Transform->setRotQuat( _Rotation );
140 _IdAnimationPlayed = -1;
144 // Constructor for moving object, it not create entity (mesh, skeleton) but build animation on pre-exist entity
145 CAnimatedSceneObject::CAnimatedSceneObject( const CEntityId& Id, const list < std::string >& Animations )
147 _Id = Id;
148 _ObjectName = "";
149 _ClusterIG = "";
150 _MeshName = "";
151 _SkeletonName = "";
152 _Distance = 0;
154 _Skeleton = NULL;
155 _Instance = NULL;
157 CEntityCL *entity = getEntity(Id);
158 if(entity)
160 _Skeleton = *entity->skeleton();
161 _Transform = _Skeleton;
163 _Position = _Skeleton->getPos();
164 _Rotation = _Skeleton->getRotQuat();
166 // create play list manager and animation set
167 _PlayListManager = Scene->createPlayListManager();
168 _AnimationSet = Driver->createAnimationSet();
170 //fill animation set
171 for( list< string >::const_iterator its = Animations.begin(); its != Animations.end(); ++its )
173 uint idAnim;
176 idAnim = _AnimationSet->addAnimation( ( *its + string(".anim") ).c_str(), (*its).c_str() );
178 catch(Exception &)
180 idAnim = UAnimationSet::NotFound;
181 if( idAnim == UAnimationSet::NotFound)
183 nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for entity CEntityId(%u,%f)", (*its).c_str(), Id.Type, (double)(sint64)Id.Id );
184 continue;
187 _MapAnimation.insert( make_pair( *its, idAnim ) );
190 // build animation set
191 _AnimationSet->build();
193 // create playlist
194 _PlayList = _PlayListManager->createPlayList( _AnimationSet );
196 _Status = SAnimationStatus();
197 _Status.SequenceAnim = 1;
198 _Status.ApplyDisplacement = 1;
200 // register skeleton in playlist
201 _PlayList->registerTransform( *entity->skeleton() );
203 // Snap to ground(the snap check if it's a flyer).
204 entity->pacsPos(_Position);
205 entity->snapToGround();
206 _Position = entity->pos();
208 CMatrix current;
209 current.identity ();
210 current.setRot (_Rotation);
212 // Rotation 90 degrees
213 CMatrix rot90;
214 rot90.identity ();
215 rot90.rotateZ (-(float)Pi/2);
216 current *= rot90;
218 _Transform->unfreezeHRC();
220 _Transform->setPos(_Position);
221 _Transform->setRotQuat(current.getRot());
223 _Transform->freezeHRC();
225 _IdAnimationPlayed = -1;
227 if( _Id.Type == RYZOMID::npc )
229 sendEndSequenceMessage( _Id, 1 );
232 else
234 _PlayList = NULL;
235 _AnimationSet = NULL;
236 _PlayListManager = NULL;
241 // Constructor for moving object, init by UTransform
242 CAnimatedSceneObject::CAnimatedSceneObject( const CEntityId& Id, UTransform *Transform, const list < std::string >& Animations, bool displacement )
244 _Id = Id;
245 _ObjectName = "";
246 _ClusterIG = "";
247 _MeshName = "";
248 _SkeletonName = "";
249 _Distance = 0;
251 _Transform = Transform;
252 _Instance = NULL;
253 _Skeleton = NULL;
254 _PlayList = NULL;
256 _Position = _Transform->getPos();
257 _Rotation = _Transform->getRotQuat();
259 // create play list manager and animation set
260 _PlayListManager = Scene->createPlayListManager();
261 _AnimationSet = Driver->createAnimationSet();
263 //fill animation set
264 for( list< string >::const_iterator its = Animations.begin(); its != Animations.end(); ++its )
266 uint idAnim;
269 idAnim = _AnimationSet->addAnimation( ( *its + string(".anim") ).c_str(), (*its).c_str() );
271 catch(Exception &)
273 idAnim = UAnimationSet::NotFound;
274 if( idAnim == UAnimationSet::NotFound)
276 nlwarning( "CAnimatedSceneObject::CAnimatedSceneObject Animation %s not found for entity CEntityId(%u,%f)", (*its).c_str(), Id.Type, (double)(sint64)Id.Id );
277 continue:
280 _MapAnimation.insert( make_pair( *its, idAnim ) );
283 _Status = SAnimationStatus();
284 _Status.SequenceAnim = 1;
285 _Status.ApplyDisplacement = displacement;
287 if( Animations.begin() != Animations.end() )
289 // build animation set
290 _AnimationSet->build();
292 // create playlist
293 _PlayList = _PlayListManager->createPlayList( _AnimationSet );
295 // register skeleton in playlist
296 _PlayList->registerTransform( _Transform );
298 _IdAnimationPlayed = -1;
303 // Reset intial pos and rot matrix
304 void CAnimatedSceneObject::resetInitialPos( void )
306 _IdAnimationPlayed = -1;
308 // Current Matrix
309 _Position = _Transform->getPos();
310 _Rotation = _Transform->getRotQuat();
312 CEntityCL *entity = getEntity(_Id);
313 if(entity)
315 // Snap to ground(the snap check if it's a flyer).
316 entity->pacsPos(_Position);
317 entity->snapToGround();
318 _Position = entity->pos();
321 CMatrix current;
322 current.identity ();
323 current.setRot (_Rotation);
325 // Rotation 90 degrees
326 CMatrix rot90;
327 rot90.identity ();
328 rot90.rotateZ (-(float)Pi/2);
329 current *= rot90;
331 _Transform->unfreezeHRC();
333 _Transform->setPos(_Position);
334 _Transform->setRotQuat(current.getRot());
336 _Transform->freezeHRC();
340 // Destructor
341 CAnimatedSceneObject::~CAnimatedSceneObject()
343 if( _Instance != NULL && !_MeshName.empty() )
345 Scene->deleteInstance( _Instance );
348 if( _Skeleton != NULL && !_SkeletonName.empty() )
350 Scene->deleteSkeleton( _Skeleton );
353 if( _PlayListManager != NULL )
355 if( _PlayList != NULL )
357 _PlayListManager->deletePlayList( _PlayList );
359 if( _AnimationSet != NULL )
361 Driver->deleteAnimationSet( _AnimationSet );
363 Scene->deletePlayListManager( _PlayListManager );
366 _MapAnimation.clear();
367 _SequenceAnimation.clear();
371 // Start an animation, if object have more than one animation, it choose one randomly
372 void CAnimatedSceneObject::StartRandomAnimation( double time, float speedFactor )
374 if( _Transform != NULL )
376 _Transform->unfreezeHRC();
379 uint numAnimation = _MapAnimation.size();
380 numAnimation = ( rand() * numAnimation ) / RAND_MAX;
381 map< string, uint >::iterator it = _MapAnimation.begin();
382 for(uint i = 0; i < numAnimation; ++i ) ++it;
383 numAnimation = (*it).second;
385 _PlayList->setAnimation( 0, numAnimation );
386 _IdAnimationPlayed = numAnimation;
387 _StartAnimationTime = time;
388 _OldAnimationTime = _StartAnimationTime;
389 _PlayList->setTimeOrigin(0, _StartAnimationTime );
390 _PlayList->setSpeedFactor( 0, speedFactor );
392 if( _Transform != NULL )
394 _Position = _Transform->getPos();
395 _Rotation = _Transform->getRotQuat();
397 CEntityCL *entity = getEntity(_Id);
398 if(entity)
400 // Snap to ground(the snap check if it's a flyer).
401 entity->pacsPos(_Position);
402 entity->snapToGround();
403 _Position = entity->pos();
406 // Read start animation rotation and position
407 _PreviousRotation = CQuat::Identity;
408 _PreviousTranslation = CVector::Null;
410 // read an animation for init matrix
411 UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
412 if( Track == NULL )
414 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
416 if( Track == NULL )
418 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
420 if( Track != NULL )
422 Track->interpolate( 0, _PreviousRotation );
425 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
426 if( Track == NULL )
428 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
430 if( Track == NULL )
432 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
434 if( Track != NULL )
436 Track->interpolate( 0, _PreviousTranslation );
439 // Animation Matrix
440 CMatrix animation;
441 animation.identity();
442 animation.setPos (_PreviousTranslation);
443 animation.setRot (_PreviousRotation);
446 // reset orientation of skeleton
447 CMatrix current;
448 current.identity();
449 current.setRot( _Rotation );
450 CVector I, J, K;
451 I = current.getJ();
452 I.z=0;
453 I.normalize ();
454 K.set (0,0,1);
455 J=K^I;
456 current.setRot (I, J, K);
457 current.setPos (_Position);
459 _AnimTransformation = current;
461 if(entity)
463 if(!entity->flyer())
465 _AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
472 // Start next animation
473 void CAnimatedSceneObject::StartNextAnimation( double time, float speedFactor )
475 if( _SequenceAnimation.begin() != _SequenceAnimation.end() )
477 if( _Transform != NULL )
479 _Transform->unfreezeHRC();
482 string animName = *_SequenceAnimation.begin();
483 _SequenceAnimation.pop_front();
485 map< string, uint >::iterator it = _MapAnimation.find( animName );
486 if( it != _MapAnimation.end() )
488 uint idAnim = (*it).second;
490 _PlayList->setAnimation( 0, idAnim );
491 _IdAnimationPlayed = idAnim;
492 _StartAnimationTime = time;
493 _OldAnimationTime = _StartAnimationTime;
494 _PlayList->setTimeOrigin(0, _StartAnimationTime );
495 _PlayList->setSpeedFactor( 0, speedFactor );
497 if( _Transform != NULL )
499 _Position = _Transform->getPos();
500 _Rotation = _Transform->getRotQuat();
502 CEntityCL *entity = getEntity(_Id);
503 if(entity)
505 // Snap to ground(the snap check if it's a flyer).
506 entity->pacsPos(_Position);
507 entity->snapToGround();
508 _Position = entity->pos();
511 // Read start animation rotation and position
512 _PreviousRotation = CQuat::Identity;
513 _PreviousTranslation = CVector::Null;
515 // read an animation for init matrix
516 UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
517 if( Track == NULL )
519 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
521 if( Track == NULL )
523 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
525 if( Track != NULL )
527 Track->interpolate( 0, _PreviousRotation );
530 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
531 if( Track == NULL )
533 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
535 if( Track == NULL )
537 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
539 if( Track != NULL )
541 Track->interpolate( 0, _PreviousTranslation );
544 // Animation Matrix
545 CMatrix animation;
546 animation.identity();
547 animation.setPos (_PreviousTranslation);
548 animation.setRot (_PreviousRotation);
550 // reset orientation of skeleton
551 CMatrix current;
552 current.identity();
553 current.setRot( _Rotation );
554 CVector I, J, K;
555 I = current.getJ();
556 I.z=0;
557 I.normalize ();
558 K.set (0,0,1);
559 J=K^I;
560 current.setRot (I, J, K);
561 current.setPos (_Position);
563 _AnimTransformation = current;
565 if(entity)
567 if(!entity->flyer() )
569 _AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
575 if( _SequenceAnimation.size() == 1 )
577 sendEndSequenceMessage( _Id, idSequence() );
580 else
582 //StartAnimation( string("FY_HOM_idlecycle") );
587 // Start animation cooresponding to numAnim
588 void CAnimatedSceneObject::StartAnimation( string& nameAnim, double time, float speedFactor )
590 if( _Transform != NULL )
592 _Transform->unfreezeHRC();
595 map< string, uint >::iterator it = _MapAnimation.find( nameAnim );
596 if( it != _MapAnimation.end() )
598 uint numAnimation = (*it).second;
600 _PlayList->setAnimation( 0, numAnimation );
601 _IdAnimationPlayed = numAnimation;
602 _StartAnimationTime = time;
603 _OldAnimationTime = _StartAnimationTime;
604 _PlayList->setTimeOrigin(0, _StartAnimationTime );
605 _PlayList->setSpeedFactor( 0, speedFactor );
608 if( _Transform != NULL )
610 _Position = _Transform->getPos();
611 _Rotation = _Transform->getRotQuat();
613 CEntityCL *entity = getEntity(_Id);
614 if(entity)
616 // Snap to ground(the snap check if it's a flyer).
617 entity->pacsPos(_Position);
618 entity->snapToGround();
619 _Position = entity->pos();
622 // Read start animation rotation and position
623 _PreviousRotation = CQuat::Identity;
624 _PreviousTranslation = CVector::Null;
626 // read an animation for init matrix
627 UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
628 if( Track == NULL )
630 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
632 if( Track == NULL )
634 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
636 if( Track != NULL )
638 Track->interpolate( 0, _PreviousRotation );
641 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
642 if( Track == NULL )
644 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
646 if( Track == NULL )
648 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
650 if( Track != NULL )
652 Track->interpolate( 0, _PreviousTranslation );
655 // Animation Matrix
656 CMatrix animation;
657 animation.identity();
658 animation.setPos (_PreviousTranslation);
659 animation.setRot (_PreviousRotation);
661 // reset orientation of skeleton
662 CMatrix current;
663 current.identity();
664 current.setRot( _Rotation );
665 CVector I, J, K;
666 I = current.getJ();
667 I.z=0;
668 I.normalize ();
669 K.set (0,0,1);
670 J=K^I;
671 current.setRot (I, J, K);
672 current.setPos (_Position);
674 _AnimTransformation = current;
676 if(entity)
678 if( !entity->flyer() )
680 _AnimTransformation.setPos( _AnimTransformation.getPos() - CVectorD( 0, 0, entity->pos().z ) );
688 // remove the initial animation offset
689 void CAnimatedSceneObject::removeOffsetAnimation ()
691 // Read start animation rotation and position
692 _PreviousRotation = CQuat::Identity;
693 _PreviousTranslation = CVector::Null;
695 // read an animation for init matrix
696 UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
697 if( Track == NULL )
699 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
701 if( Track == NULL )
703 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
705 if( Track != NULL )
707 Track->interpolate( 0, _PreviousRotation );
710 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
711 if( Track == NULL )
713 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
715 if( Track == NULL )
717 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
719 if( Track != NULL )
721 Track->interpolate( 0, _PreviousTranslation );
724 // Remove first frame animation from transform
725 CVector position = _Transform->getPos ();
726 CQuat rotation = _Transform->getRotQuat ();
728 // Build current matrix
729 CMatrix current;
730 current.identity ();
731 current.setPos (position);
732 current.setRot (rotation);
734 // Build invert first frame matrix
735 CMatrix firstFrame;
736 firstFrame.identity ();
737 firstFrame.setPos (_PreviousTranslation);
738 firstFrame.setRot (_PreviousRotation);
739 firstFrame.invert ();
741 // Remove the first frame animation
742 current *= firstFrame;
744 // Rotation 90 degrees
745 CMatrix rot90;
746 rot90.identity ();
747 rot90.rotateZ (-(float)Pi/2);
748 current *= rot90;
750 // Set transform
751 _Transform->setPos (current.getPos());
752 _Transform->setRotQuat (current.getRot());
756 // update (add to end list) Animation sequence with sequence
757 void CAnimatedSceneObject::updateAnimationSequence( const list< string >& sequence )
759 for( list< string >::const_iterator it = sequence.begin(); it != sequence.end(); ++it )
761 _SequenceAnimation.push_back( (*it) );
766 // Process logic and displacement and setup visual animation
767 void CAnimatedSceneObject::applyObjectAnimationTimeslice( double time )
769 _PlayListManager->animate( time );
771 // Apply displacement if mode set and displacement animation exist
772 if( _Status.ApplyDisplacement == 1 )
774 CQuat rot = CQuat::Identity;
775 CVector translation = CVector::Null;
776 // Read position and rotation in appropriate UTrack
777 UTrack* Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathRotQuat" );
778 if( Track == NULL )
780 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathRotQuat" );
782 if( Track == NULL )
784 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "rotquat" );
786 if( Track != NULL )
788 Track->interpolate( (float)(time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), rot );
791 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "PathPos" );
792 if( Track == NULL )
794 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "Bip01.PathPos" );
796 if( Track == NULL )
798 Track = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( "pathpos" );
800 if( Track != NULL )
802 Track->interpolate( (float)(time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), translation );
804 applyDeltaRotationAndPosition( rot, translation);
807 processLogicTemp( (_OldAnimationTime - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ), (time - _StartAnimationTime) * _PlayList->getSpeedFactor( 0 ) );
808 _OldAnimationTime = time;
812 // manage object animation
813 // TODO: manage other type animation than trigger distance and sequence list
814 void CAnimatedSceneObject::manageObjectAnimation( double Time, CVector userPos )
816 double overLoop = 0;
818 if( _IdAnimationPlayed != -1 )
820 if( Time > ( _StartAnimationTime + (double) _AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime() / _PlayList->getSpeedFactor( 0 ) ) )
822 overLoop = Time - _StartAnimationTime - (double) _AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime() / _PlayList->getSpeedFactor( 0 );
823 /* nlinfo("overLoop %f Time %f Start %f getEndTime() %f speedFactor() %f",
824 overLoop,
825 Time,
826 _StartAnimationTime,
827 _AnimationSet->getAnimation( _IdAnimationPlayed )->getEndTime(),
828 _PlayList->getSpeedFactor( 0 ));
830 nlassert( overLoop >= 0 );
832 // play through logic and movement of end of last animation before animation change
833 nlassert( Time-overLoop >= _StartAnimationTime );
834 applyObjectAnimationTimeslice(Time-overLoop);
835 nlassert( Time >= _StartAnimationTime );
837 if( _Status.LoopAnim )
839 if( _StartAnimationTime == 0 )
841 overLoop = 0;
843 _StartAnimationTime = Time - overLoop;
845 nlassert( Time >= _StartAnimationTime );
847 _PlayList->setTimeOrigin( 0, _StartAnimationTime );
849 else
851 removeOffsetAnimation ();
852 if( _Transform != NULL )
854 _Transform->freezeHRC();
856 _IdAnimationPlayed = -1;
861 if( _IdAnimationPlayed == -1 )
863 if( _Status.CodeAnim != 1 )
865 if( ( _Distance == 0 ) || ( ( userPos - _Position ).sqrnorm() < _Distance ) )
867 if( _Status.RandomAnim == 1 )
869 StartRandomAnimation( Time - overLoop );
871 else if ( _Status.SequenceAnim == 1 )
873 StartNextAnimation( Time - overLoop );
877 else
879 float angle = (float)((((uint32)Time * 1000)%(uint32)(1000*2*Pi))*0.001);
880 CMatrix rot;
881 rot.identity();
882 rot.rotateZ(angle);
884 CQuat rot = CQuat (CVector (0, 0, 1), angle) * _Transform->getRotQuat();
885 rot.normalize();
887 _Transform->setRotQuat( rot.getRot() );
891 if( _IdAnimationPlayed != -1 )
893 // play through anim visuals and logic and movement for the timeslice
894 applyObjectAnimationTimeslice(Time);
898 // Apply animation rotation and translation
899 void CAnimatedSceneObject::applyDeltaRotationAndPosition( CQuat& rot, CVector& trans )
901 if( _Transform != NULL )
903 // Animation Matrix
904 CMatrix animation;
905 animation.identity();
906 animation.setPos (trans);
907 animation.setRot (rot);
909 // Compose matrix
910 CMatrix composed;
911 composed = _AnimTransformation * animation;
913 _Rotation = composed.getRot();
914 _Position = composed.getPos();
916 CEntityCL *entity = getEntity(_Id);
917 if(entity)
919 // \todo GUIGUI : TO CHECK
920 #if 1
921 if( !entity->flyer() )
922 _Position.z += entity->pos().z;
924 entity->pacsPos(_Position);
925 entity->snapToGround();
927 if( !entity->flyer() )
928 _Position.z = entity->pos().z + composed.getPos().z;
929 // Old version
930 #else
931 if( !entity->flyer() )
933 _Position.z += entity->pos().z;
934 entity->pacsPos(_Position);
935 entity->snapToGround();
936 _Position.z = entity->pos().z + composed.getPos().z;
938 else
940 entity->pos(_Position);
942 #endif
945 _Transform->setRotQuat(_Rotation);
946 _Transform->setPos(_Position);
951 // Instanciate an object and add it to map
952 void addAnimatedSceneObject( const string& AnimatedSceneObjectName, const string& ClusterIG, const string& MeshName, const string& SkeletonName, const list <string>& Animations, const CVector& Position, const CQuat& Rotation, float Distance )
954 if( AnimatedSceneObject.find( AnimatedSceneObjectName ) == AnimatedSceneObject.end() )
956 CAnimatedSceneObject * o = new CAnimatedSceneObject( AnimatedSceneObjectName, ClusterIG, MeshName, SkeletonName, Animations, Position, Rotation, Distance );
958 if( o != NULL )
960 AnimatedSceneObject.insert( make_pair( AnimatedSceneObjectName, o) );
965 void addEntityClAnimatedSceneObject( const CEntityId& Id, const list < string >& Animations)
967 string test = string( "CEntityId") + toString( Id.Type) + toString( Id.Id);
968 if( AnimatedSceneObject.find( string( "CEntityId") + toString( Id.Type) + toString( Id.Id) ) == AnimatedSceneObject.end() )
970 CAnimatedSceneObject * o = new CAnimatedSceneObject( Id, Animations );
972 if( o != NULL )
974 AnimatedSceneObject.insert( make_pair( string( "CEntityId") + toString( Id.Type) + toString( Id.Id), o) );
979 void addUknowTypeSceneObject( const CEntityId& Id, NL3D::UTransform *Transform, const std::list < std::string >& Animations, bool displacement )
981 if( AnimatedSceneObject.find( string( "CEntityId") + toString( Id.Type) + toString( Id.Id) ) == AnimatedSceneObject.end() )
983 CAnimatedSceneObject * o = new CAnimatedSceneObject( Id, Transform, Animations, displacement );
985 if( o != NULL )
987 AnimatedSceneObject.insert( make_pair( string( "CEntityId") + toString( Id.Type) + toString( Id.Id), o) );
992 // manage animated object
993 void manageAnimatedSceneObject( double Time )
995 for( TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
997 (*it).second->manageObjectAnimation( Time, View.viewPos() );
1001 // delete
1002 void deleteAnimatedSceneObject( const string& AnimatedSceneObjectName )
1004 TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.find( AnimatedSceneObjectName );
1005 if( it != AnimatedSceneObject.end() )
1007 delete (*it).second;
1008 AnimatedSceneObject.erase( it );
1012 // update sequence animation
1013 void updateAnimationSequence( const CEntityId& id, const list< string >& sequence, uint32 idSequence )
1015 TMapCAnimatedSceneObject::iterator it;
1017 for( it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
1019 if( (*it).second->getId() == id )
1021 break;
1025 if( it != AnimatedSceneObject.end() )
1027 (*it).second->updateAnimationSequence( sequence );
1028 (*it).second->idSequence( idSequence );
1032 // Reset animation for the entity and break the current one.
1033 void resetAnimatedSceneObject(const CEntityId& id)
1035 for(TMapCAnimatedSceneObject::iterator it = AnimatedSceneObject.begin(); it != AnimatedSceneObject.end(); ++it )
1037 if((*it).second->getId() == id)
1039 (*it).second->breakCurrentAnimation();
1040 (*it).second->resetSequence();
1041 (*it).second->resetInitialPos();
1042 break;
1047 void sendEndSequenceMessage( const CEntityId& id, uint32 idSequence )
1049 SEND_MSG_MACRO
1051 "ANIME_BAR_MAN_END",
1052 SAnimeBarManEnd end;
1053 end.Id = id;
1054 end.SlotNumber = idSequence;
1055 msg.serial(end);,
1062 //---------------------------------------------------
1063 // processLogic :
1065 //---------------------------------------------------
1066 void CAnimatedSceneObject::processLogicTemp( double startOffset, double endOffset )
1068 static uint32 previousSoundIndex = 0;
1070 // get the logical animation data across the current anim segment
1071 UTrack * soundTrack = NULL;
1072 vector<CAnimationTime> result;
1074 // EAM->processLogic( _AnimationsGlobalId[MOVING], startOffset, endOffset, soundTrack, result);
1076 // get infos about the anim
1078 char *soundTrackName = "NoteTrack";
1079 soundTrack = _AnimationSet->getAnimation( _IdAnimationPlayed )->getTrackByName( soundTrackName );
1080 if( soundTrack != NULL )
1082 UTrackKeyframer * soundTrackKF = dynamic_cast<UTrackKeyframer *>(soundTrack);
1083 if( soundTrackKF == NULL )
1085 nlerror("The track %s is not a key framer track",soundTrackName);
1088 soundTrackKF->getKeysInRange((float)startOffset, (float)endOffset, result);
1091 // process sounds
1092 if( SoundMngr )
1094 if( soundTrack )
1096 vector<CAnimationTime>::iterator itResult;
1097 for( itResult = result.begin(); itResult != result.end(); ++itResult )
1099 string soundName;
1100 double keyTime = *itResult;
1101 nlinfo("keyTime = %f result size : %d",*itResult,result.size());
1103 if( !soundTrack->interpolate( *itResult, soundName) )
1105 nlwarning("The key at offset %f is not a string",*itResult);
1107 else
1109 /* // if there are step sounds
1110 if( soundName == "step" )
1112 // get the material
1113 UGlobalPosition globalPos;
1114 getPrimitive()->getGlobalPosition(globalPos, dynamicWI);
1115 uint32 material = GR->getMaterial( globalPos );
1117 // choose the sound type soft/hard
1118 bool soft;
1119 if( Type.TypeInfo.Sex == CTypeEntity::male )
1120 soft = false;
1121 if( Type.TypeInfo.Sex == CTypeEntity::female )
1122 soft = true;
1124 vector<string> sounds;
1125 uint32 soundSourceId;
1127 // choose the sound for the move type
1128 if( _AnimationsStateKey[MOVING] == "walk" )
1130 if( SoundMngr->getSounds( material, WALK, soft, sounds ) )
1132 string name = chooseRandom(sounds,previousSoundIndex );
1133 SoundMngr->spawnSound( name , pos ());
1135 else
1137 nlwarning("<CEntityCL::updatePos> : there is no walk step sound for the material %d",material);
1138 SoundMngr->spawnSource( "Fwrks_Clac_1", pos() );
1141 _SoundSourcesId.push_back( soundSourceId );
1143 else*/ if (soundName.find ("snd_") != string::npos)
1145 // need to spawn a sound linked to the anim
1146 SoundMngr->spawnSource( soundName, _Position );
1147 nlwarning ("launching sound for anim event from notetrack '%s'", soundName.c_str());
1149 else
1151 nlwarning ("unknown notetrack event: '%s'", soundName.c_str());
1158 } // processAnimSounds //