1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
2
// This file is part of the "Irrlicht Engine".
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
5
#include "CAnimatedMeshSceneNode.h"
6
#include "IVideoDriver.h"
7
#include "ISceneManager.h"
10
#include "CShadowVolumeSceneNode.h"
11
#include "IAnimatedMeshMD3.h"
12
#include "CSkinnedMesh.h"
13
#include "IDummyTransformationSceneNode.h"
14
#include "IBoneSceneNode.h"
15
#include "IMaterialRenderer.h"
17
#include "IMeshCache.h"
18
#include "IAnimatedMesh.h"
19
#include "quaternion.h"
29
CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
30
ISceneNode* parent, ISceneManager* mgr, s32 id,
31
const core::vector3df& position,
32
const core::vector3df& rotation,
33
const core::vector3df& scale)
34
: IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
35
StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
36
CurrentFrameNr(0.f), LastTimeMs(0),
37
TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
38
JointMode(EJUOR_NONE), JointsUsed(false),
39
Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
40
LoopCallBack(0), PassCount(0), Shadow(0), MD3Special(0)
43
setDebugName("CAnimatedMeshSceneNode");
51
CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
67
//! Sets the current frame. From now on the animation is played from this frame.
68
void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame)
70
// if you pass an out of range value, we just clamp it
71
CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame );
73
beginTransition(); //transit to this frame if enabled
77
//! Returns the currently displayed frame number.
78
f32 CAnimatedMeshSceneNode::getFrameNr() const
80
return CurrentFrameNr;
84
void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
88
TransitingBlend += (f32)(timeMs) * Transiting;
89
if (TransitingBlend > 1.f)
96
if ((StartFrame==EndFrame))
98
CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes
102
// play animation looped
103
CurrentFrameNr += timeMs * FramesPerSecond;
105
// We have no interpolation between EndFrame and StartFrame,
106
// the last frame must be identical to first one with our current solution.
107
if (FramesPerSecond > 0.f) //forwards...
109
if (CurrentFrameNr > EndFrame)
110
CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame));
114
if (CurrentFrameNr < StartFrame)
115
CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame));
120
// play animation non looped
122
CurrentFrameNr += timeMs * FramesPerSecond;
123
if (FramesPerSecond > 0.f) //forwards...
125
if (CurrentFrameNr > (f32)EndFrame)
127
CurrentFrameNr = (f32)EndFrame;
129
LoopCallBack->OnAnimationEnd(this);
134
if (CurrentFrameNr < (f32)StartFrame)
136
CurrentFrameNr = (f32)StartFrame;
138
LoopCallBack->OnAnimationEnd(this);
145
void CAnimatedMeshSceneNode::OnRegisterSceneNode()
149
// because this node supports rendering of mixed mode meshes consisting of
150
// transparent and solid material at the same time, we need to go through all
151
// materials, check of what type they are and register this node for the right
152
// render pass according to that.
154
video::IVideoDriver* driver = SceneManager->getVideoDriver();
157
int transparentCount = 0;
160
// count transparent and solid materials in this scene node
161
for (u32 i=0; i<Materials.size(); ++i)
163
video::IMaterialRenderer* rnd =
164
driver->getMaterialRenderer(Materials[i].MaterialType);
166
if (rnd && rnd->isTransparent())
171
if (solidCount && transparentCount)
175
// register according to material types counted
178
SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
180
if (transparentCount)
181
SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
183
ISceneNode::OnRegisterSceneNode();
187
IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame()
189
if(Mesh->getMeshType() != EAMT_SKINNED)
191
s32 frameNr = (s32) getFrameNr();
192
s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f);
193
return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame);
197
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
201
// As multiple scene nodes may be sharing the same skinned mesh, we have to
202
// re-animate it every frame to ensure that this node gets the mesh that it needs.
204
CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
206
if (JointMode == EJUOR_CONTROL)//write to mesh
207
skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
209
skinnedMesh->animateMesh(getFrameNr(), 1.0f);
211
// Update the skinned mesh for the current joint transforms.
212
skinnedMesh->skinMesh();
214
if (JointMode == EJUOR_READ)//read from mesh
216
skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
219
for (u32 n=0;n<JointChildSceneNodes.size();++n)
220
if (JointChildSceneNodes[n]->getParent()==this)
222
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
226
if(JointMode == EJUOR_CONTROL)
228
// For meshes other than EJUOR_CONTROL, this is done by calling animateMesh()
229
skinnedMesh->updateBoundingBox();
238
//! OnAnimate() is called just before rendering the whole scene.
239
void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
241
buildFrameNr(timeMs-LastTimeMs);
245
scene::IMesh * mesh = getMeshForCurrentFrame();
248
Box = mesh->getBoundingBox();
252
IAnimatedMeshSceneNode::OnAnimate ( timeMs );
256
//! renders the node.
257
void CAnimatedMeshSceneNode::render()
259
video::IVideoDriver* driver = SceneManager->getVideoDriver();
261
if (!Mesh || !driver)
265
bool isTransparentPass =
266
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
270
scene::IMesh* m = getMeshForCurrentFrame();
274
Box = m->getBoundingBox();
279
os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING);
283
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
286
if (Shadow && PassCount==1)
287
Shadow->updateShadowVolumes();
289
// for debug purposes only:
291
bool renderMeshes = true;
292
video::SMaterial mat;
293
if (DebugDataVisible && PassCount==1)
295
// overwrite half transparency
296
if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
299
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
301
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
302
mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
303
mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
304
if (RenderFromIdentity)
305
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
306
else if (Mesh->getMeshType() == EAMT_SKINNED)
307
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
309
driver->setMaterial(mat);
310
driver->drawMeshBuffer(mb);
312
renderMeshes = false;
316
// render original meshes
319
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
321
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType);
322
bool transparent = (rnd && rnd->isTransparent());
324
// only render transparent buffer if this is the transparent render pass
325
// and solid only in solid pass
326
if (transparent == isTransparentPass)
328
scene::IMeshBuffer* mb = m->getMeshBuffer(i);
329
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
330
if (RenderFromIdentity)
331
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
332
else if (Mesh->getMeshType() == EAMT_SKINNED)
333
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
335
driver->setMaterial(material);
336
driver->drawMeshBuffer(mb);
341
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
343
// for debug purposes only:
344
if (DebugDataVisible && PassCount==1)
346
video::SMaterial debug_mat;
347
debug_mat.Lighting = false;
348
debug_mat.AntiAliasing=0;
349
driver->setMaterial(debug_mat);
351
if (DebugDataVisible & scene::EDS_NORMALS)
353
core::vector3df normalizedNormal;
354
const f32 DebugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
355
const video::SColor DebugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
358
for (u32 g=0; g < m->getMeshBufferCount(); ++g)
360
const scene::IMeshBuffer* mb = m->getMeshBuffer(g);
361
const u32 vSize = video::getVertexPitchFromType(mb->getVertexType());
362
const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices();
363
const bool normalize = mb->getMaterial().NormalizeNormals;
365
for (u32 i=0; i != mb->getVertexCount(); ++i)
367
normalizedNormal = v->Normal;
369
normalizedNormal.normalize();
371
driver->draw3DLine(v->Pos, v->Pos + (normalizedNormal * DebugNormalLength), DebugNormalColor);
373
v = (const video::S3DVertex*) ( (u8*) v+vSize );
376
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
379
debug_mat.ZBuffer = video::ECFN_NEVER;
380
debug_mat.Lighting = false;
381
driver->setMaterial(debug_mat);
383
if (DebugDataVisible & scene::EDS_BBOX)
384
driver->draw3DBox(Box, video::SColor(255,255,255,255));
387
if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
390
for (u32 g=0; g< m->getMeshBufferCount(); ++g)
392
const IMeshBuffer* mb = m->getMeshBuffer(g);
394
if (Mesh->getMeshType() == EAMT_SKINNED)
395
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
396
driver->draw3DBox( mb->getBoundingBox(),
397
video::SColor(255,190,128,128) );
402
if (DebugDataVisible & scene::EDS_SKELETON)
404
if (Mesh->getMeshType() == EAMT_SKINNED)
408
for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g)
410
ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g];
412
for (u32 n=0;n<joint->Children.size();++n)
414
driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(),
415
joint->Children[n]->GlobalAnimatedMatrix.getTranslation(),
416
video::SColor(255,51,66,255));
421
// show tag for quake3 models
422
if (Mesh->getMeshType() == EAMT_MD3)
424
IAnimatedMesh * arrow =
425
SceneManager->addArrowMesh (
427
0xFF0000FF, 0xFF000088,
428
4, 8, 5.f, 4.f, 0.5f,
432
arrow = SceneManager->getMesh ( "__tag_show" );
434
IMesh *arrowMesh = arrow->getMesh(0);
438
SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList(
439
(s32)getFrameNr(), 255,
440
getStartFrame(), getEndFrame());
443
for ( u32 ts = 0; ts != taglist->size(); ++ts )
445
(*taglist)[ts].setto(matr);
447
driver->setTransform(video::ETS_WORLD, matr );
449
for ( u32 a = 0; a != arrowMesh->getMeshBufferCount(); ++a )
450
driver->drawMeshBuffer(arrowMesh->getMeshBuffer(a));
457
if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
459
debug_mat.Lighting = false;
460
debug_mat.Wireframe = true;
461
debug_mat.ZBuffer = video::ECFN_NEVER;
462
driver->setMaterial(debug_mat);
464
for (u32 g=0; g<m->getMeshBufferCount(); ++g)
466
const IMeshBuffer* mb = m->getMeshBuffer(g);
467
if (RenderFromIdentity)
468
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
469
else if (Mesh->getMeshType() == EAMT_SKINNED)
470
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
471
driver->drawMeshBuffer(mb);
478
//! Returns the current start frame number.
479
s32 CAnimatedMeshSceneNode::getStartFrame() const
485
//! Returns the current start frame number.
486
s32 CAnimatedMeshSceneNode::getEndFrame() const
492
//! sets the frames between the animation is looped.
493
//! the default is 0 - MaximalFrameCount of the mesh.
494
bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end)
496
const s32 maxFrameCount = Mesh->getFrameCount() - 1;
499
StartFrame = core::s32_clamp(end, 0, maxFrameCount);
500
EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount);
504
StartFrame = core::s32_clamp(begin, 0, maxFrameCount);
505
EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount);
507
if (FramesPerSecond < 0)
508
setCurrentFrame((f32)EndFrame);
510
setCurrentFrame((f32)StartFrame);
516
//! sets the speed with witch the animation is played
517
void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond)
519
FramesPerSecond = framesPerSecond * 0.001f;
523
f32 CAnimatedMeshSceneNode::getAnimationSpeed() const
525
return FramesPerSecond * 1000.f;
529
//! returns the axis aligned bounding box of this node
530
const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const
536
//! returns the material based on the zero based index i. To get the amount
537
//! of materials used by this scene node, use getMaterialCount().
538
//! This function is needed for inserting the node into the scene hirachy on a
539
//! optimal position for minimizing renderstate changes, but can also be used
540
//! to directly modify the material of a scene node.
541
video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i)
543
if (i >= Materials.size())
544
return ISceneNode::getMaterial(i);
551
//! returns amount of materials used by this scene node.
552
u32 CAnimatedMeshSceneNode::getMaterialCount() const
554
return Materials.size();
558
//! Creates shadow volume scene node as child of this node
559
//! and returns a pointer to it.
560
IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode(
561
const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
563
if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
567
shadowMesh = Mesh; // if null is given, use the mesh of node
572
Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
576
//! Returns a pointer to a child node, which has the same transformation as
577
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
578
IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
580
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
581
os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
585
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
587
os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
593
ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
595
const s32 number = skinnedMesh->getJointNumber(jointName);
599
os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG);
603
if ((s32)JointChildSceneNodes.size() <= number)
605
os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING);
609
return JointChildSceneNodes[number];
615
//! Returns a pointer to a child node, which has the same transformation as
616
//! the corresponding joint, if the mesh in this scene node is a skinned mesh.
617
IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID)
619
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
620
os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
624
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
626
os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
632
if (JointChildSceneNodes.size() <= jointID)
634
os::Printer::log("Joint not loaded into node", ELL_WARNING);
638
return JointChildSceneNodes[jointID];
642
//! Gets joint count.
643
u32 CAnimatedMeshSceneNode::getJointCount() const
645
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
649
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
652
ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
654
return skinnedMesh->getJointCount();
659
//! Returns a pointer to a child node, which has the same transformation as
660
//! the corresponding joint, if the mesh in this scene node is a ms3d mesh.
661
ISceneNode* CAnimatedMeshSceneNode::getMS3DJointNode(const c8* jointName)
663
return getJointNode(jointName);
667
//! Returns a pointer to a child node, which has the same transformation as
668
//! the corresponding joint, if the mesh in this scene node is a .x mesh.
669
ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName)
671
return getJointNode(jointName);
674
//! Removes a child from this scene node.
675
//! Implemented here, to be able to remove the shadow properly, if there is one,
676
//! or to remove attached childs.
677
bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
679
if (child && Shadow == child)
685
if (ISceneNode::removeChild(child))
687
if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
689
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
691
if (JointChildSceneNodes[i] == child)
693
JointChildSceneNodes[i] = 0; //remove link to child
705
//! Starts a MD2 animation.
706
bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim)
708
if (!Mesh || Mesh->getMeshType() != EAMT_MD2)
711
IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh;
713
s32 begin, end, speed;
714
md->getFrameLoop(anim, begin, end, speed);
716
setAnimationSpeed( f32(speed) );
717
setFrameLoop(begin, end);
722
//! Starts a special MD2 animation.
723
bool CAnimatedMeshSceneNode::setMD2Animation(const c8* animationName)
725
if (!Mesh || Mesh->getMeshType() != EAMT_MD2)
728
IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh;
730
s32 begin, end, speed;
731
if (!md->getFrameLoop(animationName, begin, end, speed))
734
setAnimationSpeed( (f32)speed );
735
setFrameLoop(begin, end);
740
//! Sets looping mode which is on by default. If set to false,
741
//! animations will not be looped.
742
void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped)
744
Looping = playAnimationLooped;
748
//! Sets a callback interface which will be called if an animation
749
//! playback has ended. Set this to 0 to disable the callback again.
750
void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback)
752
if (callback == LoopCallBack)
756
LoopCallBack->drop();
758
LoopCallBack = callback;
761
LoopCallBack->grab();
765
//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
766
void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly)
768
ReadOnlyMaterials = readonly;
772
//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
773
bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const
775
return ReadOnlyMaterials;
779
//! Writes attributes of the scene node.
780
void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
782
IAnimatedMeshSceneNode::serializeAttributes(out, options);
784
if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename)
786
const io::path path = SceneManager->getFileSystem()->getRelativeFilename(
787
SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()),
789
out->addString("Mesh", path.c_str());
792
out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str());
793
out->addBool("Looping", Looping);
794
out->addBool("ReadOnlyMaterials", ReadOnlyMaterials);
795
out->addFloat("FramesPerSecond", FramesPerSecond);
796
out->addInt("StartFrame", StartFrame);
797
out->addInt("EndFrame", EndFrame);
801
//! Reads attributes of the scene node.
802
void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
804
IAnimatedMeshSceneNode::deserializeAttributes(in, options);
806
io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh);
807
io::path newMeshStr = in->getAttributeAsString("Mesh");
809
Looping = in->getAttributeAsBool("Looping");
810
ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials");
811
FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond");
812
StartFrame = in->getAttributeAsInt("StartFrame");
813
EndFrame = in->getAttributeAsInt("EndFrame");
815
if (newMeshStr != "" && oldMeshStr != newMeshStr)
817
IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str());
820
setMesh(newAnimatedMesh);
823
// TODO: read animation names instead of frame begin and ends
828
void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
831
return; // won't set null mesh
840
// grab the mesh (it's non-null!)
844
// get materials and bounding box
845
Box = Mesh->getBoundingBox();
847
IMesh* m = Mesh->getMesh(0,0);
851
Materials.reallocate(m->getMeshBufferCount());
853
for (u32 i=0; i<m->getMeshBufferCount(); ++i)
855
IMeshBuffer* mb = m->getMeshBuffer(i);
857
Materials.push_back(mb->getMaterial());
859
Materials.push_back(video::SMaterial());
863
// clean up joint nodes
870
// get start and begin time
871
// setAnimationSpeed(Mesh->getAnimationSpeed());
872
setFrameLoop(0, Mesh->getFrameCount());
876
// returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh,
877
// or the absolutetransformation if it's a normal scenenode
878
const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname)
880
return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0;
884
//! updates the absolute position based on the relative and the parents position
885
void CAnimatedMeshSceneNode::updateAbsolutePosition()
887
IAnimatedMeshSceneNode::updateAbsolutePosition();
889
if (!Mesh || Mesh->getMeshType() != EAMT_MD3)
892
SMD3QuaternionTagList *taglist;
893
taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () );
898
MD3Special = new SMD3Special();
901
SMD3QuaternionTag parent ( MD3Special->Tagname );
902
if (Parent && Parent->getType() == ESNT_ANIMATED_MESH)
904
const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation
905
( MD3Special->Tagname );
911
SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation );
913
MD3Special->AbsoluteTagList.set_used ( taglist->size () );
914
for ( u32 i=0; i!= taglist->size (); ++i )
916
MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position;
917
MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation;
922
//! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
923
void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode)
929
//! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
930
//! you must call animateJoints(), or the mesh will not animate
931
void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
933
const u32 ttime = (u32)core::floor32(time*1000.0f);
934
if (TransitionTime==ttime)
936
TransitionTime = ttime;
938
setJointMode(EJUOR_CONTROL);
940
setJointMode(EJUOR_NONE);
944
//! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
945
void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
947
RenderFromIdentity=enable;
951
//! updates the joint positions of this mesh
952
void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
954
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
957
if (Mesh && Mesh->getMeshType() == EAMT_SKINNED )
960
const f32 frame = getFrameNr(); //old?
962
CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh);
964
skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
965
skinnedMesh->animateMesh(frame, 1.0f);
966
skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes);
968
//-----------------------------------------
970
//-----------------------------------------
972
if (Transiting != 0.f)
974
// Init additional matrices
975
if (PretransitingSave.size()<JointChildSceneNodes.size())
977
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
978
PretransitingSave.push_back(core::matrix4());
981
for (u32 n=0; n<JointChildSceneNodes.size(); ++n)
983
//------Position------
985
JointChildSceneNodes[n]->setPosition(
987
PretransitingSave[n].getTranslation(),
988
JointChildSceneNodes[n]->getPosition(),
991
//------Rotation------
993
//Code is slow, needs to be fixed up
995
const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD);
996
const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD);
998
core::quaternion QRotation;
999
QRotation.slerp(RotationStart, RotationEnd, TransitingBlend);
1001
core::vector3df tmpVector;
1002
QRotation.toEuler(tmpVector);
1003
tmpVector*=core::RADTODEG; //convert from radians back to degrees
1004
JointChildSceneNodes[n]->setRotation( tmpVector );
1008
//JointChildSceneNodes[n]->setScale(
1010
// PretransitingSave[n].getScale(),
1011
// JointChildSceneNodes[n]->getScale(),
1012
// TransitingBlend));
1016
if (CalculateAbsolutePositions)
1019
for (u32 n=0;n<JointChildSceneNodes.size();++n)
1021
if (JointChildSceneNodes[n]->getParent()==this)
1023
JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
1033
void CAnimatedMeshSceneNode::checkJoints()
1035
#ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
1039
if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
1044
for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
1045
removeChild(JointChildSceneNodes[i]);
1046
JointChildSceneNodes.clear();
1048
//Create joints for SkinnedMesh
1049
((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
1050
((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
1053
JointMode=EJUOR_READ;
1060
void CAnimatedMeshSceneNode::beginTransition()
1065
if (TransitionTime != 0)
1067
//Check the array is big enough
1068
if (PretransitingSave.size()<JointChildSceneNodes.size())
1070
for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
1071
PretransitingSave.push_back(core::matrix4());
1074
//Copy the position of joints
1075
for (u32 n=0;n<JointChildSceneNodes.size();++n)
1076
PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation();
1078
Transiting = core::reciprocal((f32)TransitionTime);
1080
TransitingBlend = 0.f;
1086
ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
1091
newManager = SceneManager;
1093
CAnimatedMeshSceneNode* newNode =
1094
new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation,
1095
RelativeRotation, RelativeScale);
1099
newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called
1103
newNode->cloneMembers(this, newManager);
1105
newNode->Materials = Materials;
1107
newNode->Mesh = Mesh;
1108
newNode->StartFrame = StartFrame;
1109
newNode->EndFrame = EndFrame;
1110
newNode->FramesPerSecond = FramesPerSecond;
1111
newNode->CurrentFrameNr = CurrentFrameNr;
1112
newNode->JointMode = JointMode;
1113
newNode->JointsUsed = JointsUsed;
1114
newNode->TransitionTime = TransitionTime;
1115
newNode->Transiting = Transiting;
1116
newNode->TransitingBlend = TransitingBlend;
1117
newNode->Looping = Looping;
1118
newNode->ReadOnlyMaterials = ReadOnlyMaterials;
1119
newNode->LoopCallBack = LoopCallBack;
1120
newNode->PassCount = PassCount;
1121
newNode->Shadow = Shadow;
1122
newNode->JointChildSceneNodes = JointChildSceneNodes;
1123
newNode->PretransitingSave = PretransitingSave;
1124
newNode->RenderFromIdentity = RenderFromIdentity;
1125
newNode->MD3Special = MD3Special;
1131
} // end namespace scene
1132
} // end namespace irr