3 Copyright (C) 2010 Dzmitry Kamiahin <dnk-88@tut.by>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <QtCore/QString>
26 #include <nel/misc/path.h>
27 #include <nel/3d/u_driver.h>
28 #include <nel/3d/u_scene.h>
29 #include <nel/3d/u_animation_set.h>
30 #include <nel/3d/u_animation.h>
31 #include <nel/3d/u_play_list_manager.h>
32 #include <nel/3d/u_play_list.h>
33 #include <nel/3d/u_track.h>
38 using namespace NLMISC
;
44 CSlotInfo::CSlotInfo()
55 SkeletonInverted(false),
60 CSlotInfo
&CSlotInfo::operator=(const CSlotInfo
&slotInfo
)
62 if ( this != &slotInfo
)
64 Animation
= slotInfo
.Animation
;
65 ClampMode
= slotInfo
.ClampMode
;
66 Enable
= slotInfo
.Enable
;
67 EndBlend
= slotInfo
.EndBlend
;
68 EndTime
= slotInfo
.EndTime
;
69 Offset
= slotInfo
.Offset
;
70 Skeleton
= slotInfo
.Skeleton
;
71 SkeletonInverted
= slotInfo
.SkeletonInverted
;
72 Smoothness
= slotInfo
.Smoothness
;
73 SpeedFactor
= slotInfo
.SpeedFactor
;
74 StartBlend
= slotInfo
.StartBlend
;
75 StartTime
= slotInfo
.StartTime
;
80 CEntity::CEntity(void)
83 _FileNameSkeleton(""),
91 _CharacterScalePos
= 1;
94 CEntity::~CEntity(void)
96 if (_PlayList
!= NULL
)
98 _PlayList
->resetAllChannels();
99 Modules::objView().getPlayListManager()->deletePlayList (_PlayList
);
102 if (_AnimationSet
!= NULL
)
104 Modules::objView().getDriver()->deleteAnimationSet(_AnimationSet
);
105 _AnimationSet
= NULL
;
107 if (!_Skeleton
.empty())
109 _Skeleton
.detachSkeletonSon(_Instance
);
110 Modules::objView().getScene()->deleteSkeleton(_Skeleton
);
113 if (!_Instance
.empty())
115 Modules::objView().getScene()->deleteInstance(_Instance
);
120 void CEntity::loadAnimation(const std::string
&fileName
)
122 uint id
= _AnimationSet
->addAnimation(fileName
.c_str(),CFile::getFilenameWithoutExtension(fileName
).c_str());
123 _AnimationList
.push_back(_AnimationSet
->getAnimationName(id
));
124 _AnimationSet
->build();
125 if (!_Skeleton
.empty())
126 _PlayList
->registerTransform(_Skeleton
);
128 _PlayList
->registerTransform(_Instance
);
131 void CEntity::loadSWT(const std::string
&fileName
)
133 uint id
= _AnimationSet
->addSkeletonWeight(fileName
.c_str(),CFile::getFilenameWithoutExtension(fileName
).c_str());
134 _SWTList
.push_back(_AnimationSet
->getSkeletonWeightName(id
));
137 void CEntity::addAnimToPlayList(const std::string
&name
)
139 _PlayListAnimation
.push_back(name
);
141 _AnimationStatus
.EndAnim
= this->getPlayListLength();
146 void CEntity::removeAnimToPlayList(uint row
)
148 if (row
< _PlayListAnimation
.size())
149 _PlayListAnimation
.erase(_PlayListAnimation
.begin() + row
);
151 _AnimationStatus
.EndAnim
= this->getPlayListLength();
154 void CEntity::swapAnimToPlayList(uint row1
, uint row2
)
156 if ((row1
< _PlayListAnimation
.size()) && (row2
< _PlayListAnimation
.size()))
157 std::swap(_PlayListAnimation
[row1
], _PlayListAnimation
[row2
]);
160 void CEntity::playbackAnim(bool play
)
162 _AnimationStatus
.PlayAnim
= play
;
167 _Instance
.freezeHRC();
170 void CEntity::reset()
172 _PlayListAnimation
.clear();
173 _AnimationList
.clear();
176 _PlayList
->resetAllChannels();
179 float CEntity::getPlayListLength() const
181 // Accumul all the time
183 for(size_t i
= 0; i
< _PlayListAnimation
.size(); ++i
)
184 time
+= getAnimLength(_PlayListAnimation
[i
]);
188 float CEntity::getAnimLength(const std::string
&name
) const
190 uint id
= _AnimationSet
->getAnimationIdByName(name
.c_str());
191 NL3D::UAnimation
*anim
= _AnimationSet
->getAnimation(id
);
192 return anim
->getEndTime() - anim
->getBeginTime();
195 void CEntity::update(NL3D::TAnimationTime time
)
197 this->resetChannel();
198 switch (_AnimationStatus
.Mode
)
201 animatePlayList(time
);
204 animateChannelMixer();
210 void CEntity::resetChannel()
212 for(uint i
= 0; i
< NL3D::CChannelMixer::NumAnimationSlot
; ++i
)
213 _PlayList
->setAnimation(i
, UPlayList::empty
);
216 void CEntity::addTransformation (CMatrix
¤t
, UAnimation
*anim
, float begin
, float end
, UTrack
*posTrack
, UTrack
*rotquatTrack
,
217 UTrack
*nextPosTrack
, UTrack
*nextRotquatTrack
, bool removeLast
)
227 // Remove the start of the animation
228 CQuat
rotEnd (0,0,0,1);
229 CVector
posEnd (0,0,0);
232 // Interpolate the rotation
233 rotquatTrack
->interpolate (end
, rotEnd
);
237 // Interpolate the position
238 posTrack
->interpolate (end
, posEnd
);
241 // Add the final rotation and position
255 CQuat
rotStart (0,0,0,1);
256 CVector
posStart (0,0,0);
257 if (nextRotquatTrack
)
259 // Interpolate the rotation
260 nextRotquatTrack
->interpolate (begin
, rotStart
);
264 // Interpolate the position
265 nextPosTrack
->interpolate (begin
, posStart
);
267 // Remove the init rotation and position of the next animation
269 tmp
.setRot (rotStart
);
270 tmp
.setPos (posStart
);
275 CVector I
= current
.getI ();
276 CVector J
= current
.getJ ();
284 tmp
.setRot (I
, J
, K
);
285 tmp
.setPos (current
.getPos ());
291 void CEntity::animatePlayList(NL3D::TAnimationTime time
)
293 if (!_PlayListAnimation
.empty())
296 uint id
= _AnimationSet
->getAnimationIdByName(_PlayListAnimation
[0].c_str());
298 // Try channel AnimationSet
299 NL3D::UAnimation
*anim
= _AnimationSet
->getAnimation(id
);
303 UTrack
*posTrack
= NULL
;
304 UTrack
*rotQuatTrack
= NULL
;
310 // read an animation for init matrix
311 rotQuatTrack
= anim
->getTrackByName("rotquat");
312 posTrack
= anim
->getTrackByName("pos");
314 there
= posTrack
|| rotQuatTrack
;
318 float endTime
= anim
->getEndTime() - anim
->getBeginTime();
321 while (time
>= endTime
)
324 if (index
< _PlayListAnimation
.size())
326 id
= _AnimationSet
->getAnimationIdByName(_PlayListAnimation
[index
].c_str());
327 NL3D::UAnimation
*newAnim
= _AnimationSet
->getAnimation(id
);
329 UTrack
*newPosTrack
= newAnim
->getTrackByName ("pos");
330 UTrack
*newRotquatTrack
= newAnim
->getTrackByName ("rotquat");
332 // Add the transformation
333 addTransformation (current
, anim
, newAnim
->getBeginTime(), anim
->getEndTime(), posTrack
, rotQuatTrack
, newPosTrack
, newRotquatTrack
, true);
337 posTrack
= newPosTrack
;
338 rotQuatTrack
= newRotquatTrack
;
342 endTime
= startTime
+ (anim
->getEndTime() - anim
->getBeginTime());
346 // Add the transformation
347 addTransformation (current
, anim
, 0, anim
->getEndTime(), posTrack
, rotQuatTrack
, NULL
, NULL
, false);
353 if (index
>= _PlayListAnimation
.size())
357 id
= _AnimationSet
->getAnimationIdByName(_PlayListAnimation
[index
].c_str());
358 anim
= _AnimationSet
->getAnimation(id
);
360 // End time for last anim
361 startTime
= anim
->getEndTime() - time
;
367 // Add the transformation
368 addTransformation (current
, anim
, 0, anim
->getBeginTime() + time
- startTime
, posTrack
, rotQuatTrack
, NULL
, NULL
, false);
370 id
= _AnimationSet
->getAnimationIdByName(_PlayListAnimation
[index
].c_str());
371 anim
= _AnimationSet
->getAnimation(id
);
374 startTime
-= anim
->getBeginTime();
378 _PlayList
->setAnimation(0, id
);
379 _PlayList
->setTimeOrigin(0, startTime
);
380 _PlayList
->setSpeedFactor(0, 1.0f
);
381 _PlayList
->setWeightSmoothness(0, 1.0f
);
382 _PlayList
->setStartWeight(0, 1, 0);
383 _PlayList
->setEndWeight(0, 1, 1);
384 _PlayList
->setWrapMode(0, UPlayList::Clamp
);
386 // Setup the pos and rot for this shape
389 CVector pos
= current
.getPos();
391 // If a skeleton model
392 if(!_Skeleton
.empty())
394 _Skeleton
.setTransformMode(NL3D::UTransformable::RotQuat
);
395 // scale animated pos value with the CFG scale
396 pos
*= _CharacterScalePos
;
397 _Skeleton
.setPos(pos
);
398 _Skeleton
.setRotQuat(current
.getRot());
402 _Instance
.setTransformMode(NL3D::UTransformable::RotQuat
);
403 _Instance
.setPos(pos
);
404 _Instance
.setRotQuat(current
.getRot());
410 void CEntity::animateChannelMixer()
412 for (uint i
= 0; i
< NL3D::CChannelMixer::NumAnimationSlot
; ++i
)
414 if (_SlotInfo
[i
].Enable
)
417 uint animId
= _AnimationSet
->getAnimationIdByName(_SlotInfo
[i
].Animation
);
418 if (animId
== UAnimationSet::NotFound
)
419 _PlayList
->setAnimation(i
, UPlayList::empty
);
421 _PlayList
->setAnimation(i
, animId
);
423 // Set the skeleton weight
424 uint skelId
= _AnimationSet
->getSkeletonWeightIdByName(_SlotInfo
[i
].Skeleton
);
425 if (skelId
== UAnimationSet::NotFound
)
426 _PlayList
->setSkeletonWeight(i
, UPlayList::empty
, false);
428 _PlayList
->setSkeletonWeight(i
, skelId
, _SlotInfo
[i
].SkeletonInverted
);
431 _PlayList
->setTimeOrigin(i
, _SlotInfo
[i
].Offset
);
432 _PlayList
->setSpeedFactor(i
, _SlotInfo
[i
].SpeedFactor
);
433 _PlayList
->setStartWeight(i
, _SlotInfo
[i
].StartBlend
, _SlotInfo
[i
].StartTime
);
434 _PlayList
->setEndWeight(i
, _SlotInfo
[i
].EndBlend
, _SlotInfo
[i
].EndTime
);
435 _PlayList
->setWeightSmoothness(i
, _SlotInfo
[i
].Smoothness
);
437 // Switch between wrap modes
438 switch (_SlotInfo
[i
].ClampMode
)
441 _PlayList
->setWrapMode (i
, UPlayList::Clamp
);
444 _PlayList
->setWrapMode (i
, UPlayList::Repeat
);
447 _PlayList
->setWrapMode (i
, UPlayList::Disable
);
454 } /* namespace NLQT */