CAnimatedMeshSceneNode.cpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007
  1. // Copyright (C) 2002-2012 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "CAnimatedMeshSceneNode.h"
  5. #include "IVideoDriver.h"
  6. #include "ISceneManager.h"
  7. #include "S3DVertex.h"
  8. #include "os.h"
  9. #include "CSkinnedMesh.h"
  10. #include "IDummyTransformationSceneNode.h"
  11. #include "IBoneSceneNode.h"
  12. #include "IMaterialRenderer.h"
  13. #include "IMesh.h"
  14. #include "IMeshCache.h"
  15. #include "IAnimatedMesh.h"
  16. #include "quaternion.h"
  17. #include "IFileSystem.h"
  18. namespace irr
  19. {
  20. namespace scene
  21. {
  22. //! constructor
  23. CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh,
  24. ISceneNode* parent, ISceneManager* mgr, s32 id,
  25. const core::vector3df& position,
  26. const core::vector3df& rotation,
  27. const core::vector3df& scale)
  28. : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
  29. StartFrame(0), EndFrame(0), FramesPerSecond(0.025f),
  30. CurrentFrameNr(0.f), AnimationStrength(1.f), LastTimeMs(0),
  31. TransitionTime(0), Transiting(0.f), TransitingBlend(0.f),
  32. JointMode(EJUOR_NONE), JointsUsed(false),
  33. Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false),
  34. LoopCallBack(0), PassCount(0)
  35. {
  36. #ifdef _DEBUG
  37. setDebugName("CAnimatedMeshSceneNode");
  38. #endif
  39. setMesh(mesh);
  40. }
  41. //! destructor
  42. CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode()
  43. {
  44. if (Mesh)
  45. Mesh->drop();
  46. if (LoopCallBack)
  47. LoopCallBack->drop();
  48. }
  49. //! Sets the current frame. From now on the animation is played from this frame.
  50. void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame)
  51. {
  52. // if you pass an out of range value, we just clamp it
  53. CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame );
  54. beginTransition(); //transit to this frame if enabled
  55. }
  56. //! Returns the currently displayed frame number.
  57. f32 CAnimatedMeshSceneNode::getFrameNr() const
  58. {
  59. return CurrentFrameNr;
  60. }
  61. //! Get CurrentFrameNr and update transiting settings
  62. void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs)
  63. {
  64. if (Transiting!=0.f)
  65. {
  66. TransitingBlend += (f32)(timeMs) * Transiting;
  67. if (TransitingBlend > 1.f)
  68. {
  69. Transiting=0.f;
  70. TransitingBlend=0.f;
  71. }
  72. }
  73. if (StartFrame == EndFrame)
  74. {
  75. CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes
  76. }
  77. else if (Looping)
  78. {
  79. // play animation looped
  80. CurrentFrameNr += timeMs * FramesPerSecond;
  81. // We have no interpolation between EndFrame and StartFrame,
  82. // the last frame must be identical to first one with our current solution.
  83. if (FramesPerSecond > 0.f) //forwards...
  84. {
  85. if (CurrentFrameNr > EndFrame)
  86. CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame));
  87. }
  88. else //backwards...
  89. {
  90. if (CurrentFrameNr < StartFrame)
  91. CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame));
  92. }
  93. }
  94. else
  95. {
  96. // play animation non looped
  97. CurrentFrameNr += timeMs * FramesPerSecond;
  98. if (FramesPerSecond > 0.f) //forwards...
  99. {
  100. if (CurrentFrameNr > (f32)EndFrame)
  101. {
  102. CurrentFrameNr = (f32)EndFrame;
  103. if (LoopCallBack)
  104. LoopCallBack->OnAnimationEnd(this);
  105. }
  106. }
  107. else //backwards...
  108. {
  109. if (CurrentFrameNr < (f32)StartFrame)
  110. {
  111. CurrentFrameNr = (f32)StartFrame;
  112. if (LoopCallBack)
  113. LoopCallBack->OnAnimationEnd(this);
  114. }
  115. }
  116. }
  117. }
  118. void CAnimatedMeshSceneNode::OnRegisterSceneNode()
  119. {
  120. if (IsVisible)
  121. {
  122. // because this node supports rendering of mixed mode meshes consisting of
  123. // transparent and solid material at the same time, we need to go through all
  124. // materials, check of what type they are and register this node for the right
  125. // render pass according to that.
  126. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  127. PassCount = 0;
  128. int transparentCount = 0;
  129. int solidCount = 0;
  130. // count transparent and solid materials in this scene node
  131. for (u32 i=0; i<Materials.size(); ++i)
  132. {
  133. video::IMaterialRenderer* rnd =
  134. driver->getMaterialRenderer(Materials[i].MaterialType);
  135. if (rnd && rnd->isTransparent())
  136. ++transparentCount;
  137. else
  138. ++solidCount;
  139. if (solidCount && transparentCount)
  140. break;
  141. }
  142. // register according to material types counted
  143. if (solidCount)
  144. SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
  145. if (transparentCount)
  146. SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
  147. ISceneNode::OnRegisterSceneNode();
  148. }
  149. }
  150. IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame(SkinningCallback sc, int offset)
  151. {
  152. if(Mesh->getMeshType() != EAMT_SKINNED)
  153. {
  154. s32 frameNr = (s32) getFrameNr();
  155. s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f);
  156. return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame);
  157. }
  158. else
  159. {
  160. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  161. return 0;
  162. #else
  163. // As multiple scene nodes may be sharing the same skinned mesh, we have to
  164. // re-animate it every frame to ensure that this node gets the mesh that it needs.
  165. CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh);
  166. if (JointMode == EJUOR_CONTROL)//write to mesh
  167. skinnedMesh->transferJointsToMesh(JointChildSceneNodes);
  168. else
  169. skinnedMesh->animateMesh(getFrameNr(), 1.0f);
  170. // Update the skinned mesh for the current joint transforms.
  171. skinnedMesh->skinMesh(AnimationStrength, sc, offset);
  172. if (JointMode == EJUOR_READ)//read from mesh
  173. {
  174. skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes);
  175. //---slow---
  176. for (u32 n=0;n<JointChildSceneNodes.size();++n)
  177. if (JointChildSceneNodes[n]->getParent()==this)
  178. {
  179. JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
  180. }
  181. }
  182. if(JointMode == EJUOR_CONTROL)
  183. {
  184. // For meshes other than EJUOR_CONTROL, this is done by calling animateMesh()
  185. skinnedMesh->updateBoundingBox();
  186. }
  187. return skinnedMesh;
  188. #endif
  189. }
  190. }
  191. //! OnAnimate() is called just before rendering the whole scene.
  192. void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs)
  193. {
  194. if (LastTimeMs==0) // first frame
  195. {
  196. LastTimeMs = timeMs;
  197. }
  198. // set CurrentFrameNr
  199. buildFrameNr(timeMs-LastTimeMs);
  200. // update bbox
  201. if (Mesh)
  202. {
  203. scene::IMesh * mesh = getMeshForCurrentFrame();
  204. if (mesh)
  205. Box = mesh->getBoundingBox();
  206. }
  207. LastTimeMs = timeMs;
  208. IAnimatedMeshSceneNode::OnAnimate(timeMs);
  209. }
  210. //! renders the node.
  211. void CAnimatedMeshSceneNode::render()
  212. {
  213. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  214. if (!Mesh || !driver)
  215. return;
  216. bool isTransparentPass =
  217. SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
  218. ++PassCount;
  219. scene::IMesh* m = getMeshForCurrentFrame();
  220. if(m)
  221. {
  222. Box = m->getBoundingBox();
  223. }
  224. else
  225. {
  226. #ifdef _DEBUG
  227. os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING);
  228. #endif
  229. }
  230. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  231. // for debug purposes only:
  232. bool renderMeshes = true;
  233. video::SMaterial mat;
  234. if (DebugDataVisible && PassCount==1)
  235. {
  236. // overwrite half transparency
  237. if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
  238. {
  239. for (u32 i=0; i<m->getMeshBufferCount(); ++i)
  240. {
  241. scene::IMeshBuffer* mb = m->getMeshBuffer(i);
  242. mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
  243. mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
  244. if (RenderFromIdentity)
  245. driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
  246. else if (Mesh->getMeshType() == EAMT_SKINNED)
  247. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
  248. driver->setMaterial(mat);
  249. driver->drawMeshBuffer(mb);
  250. }
  251. renderMeshes = false;
  252. }
  253. }
  254. // render original meshes
  255. if (renderMeshes)
  256. {
  257. for (u32 i=0; i<m->getMeshBufferCount(); ++i)
  258. {
  259. video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType);
  260. bool transparent = (rnd && rnd->isTransparent());
  261. // only render transparent buffer if this is the transparent render pass
  262. // and solid only in solid pass
  263. if (transparent == isTransparentPass)
  264. {
  265. scene::IMeshBuffer* mb = m->getMeshBuffer(i);
  266. const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
  267. if (RenderFromIdentity)
  268. driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
  269. else if (Mesh->getMeshType() == EAMT_SKINNED)
  270. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
  271. driver->setMaterial(material);
  272. driver->drawMeshBuffer(mb);
  273. }
  274. }
  275. }
  276. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  277. // for debug purposes only:
  278. if (DebugDataVisible && PassCount==1)
  279. {
  280. video::SMaterial debug_mat;
  281. debug_mat.Lighting = false;
  282. debug_mat.AntiAliasing=0;
  283. driver->setMaterial(debug_mat);
  284. // show normals
  285. if (DebugDataVisible & scene::EDS_NORMALS)
  286. {
  287. const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
  288. const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
  289. const u32 count = m->getMeshBufferCount();
  290. // draw normals
  291. for (u32 g=0; g < count; ++g)
  292. {
  293. driver->drawMeshBufferNormals(m->getMeshBuffer(g), debugNormalLength, debugNormalColor);
  294. }
  295. }
  296. debug_mat.ZBuffer = video::ECFN_NEVER;
  297. debug_mat.Lighting = false;
  298. driver->setMaterial(debug_mat);
  299. if (DebugDataVisible & scene::EDS_BBOX)
  300. driver->draw3DBox(Box, video::SColor(255,255,255,255));
  301. // show bounding box
  302. if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
  303. {
  304. for (u32 g=0; g< m->getMeshBufferCount(); ++g)
  305. {
  306. const IMeshBuffer* mb = m->getMeshBuffer(g);
  307. if (Mesh->getMeshType() == EAMT_SKINNED)
  308. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
  309. driver->draw3DBox(mb->getBoundingBox(), video::SColor(255,190,128,128));
  310. }
  311. }
  312. // show skeleton
  313. if (DebugDataVisible & scene::EDS_SKELETON)
  314. {
  315. if (Mesh->getMeshType() == EAMT_SKINNED)
  316. {
  317. // draw skeleton
  318. for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g)
  319. {
  320. ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g];
  321. for (u32 n=0;n<joint->Children.size();++n)
  322. {
  323. driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(),
  324. joint->Children[n]->GlobalAnimatedMatrix.getTranslation(),
  325. video::SColor(255,51,66,255));
  326. }
  327. }
  328. }
  329. }
  330. // show mesh
  331. if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
  332. {
  333. debug_mat.Lighting = false;
  334. debug_mat.Wireframe = true;
  335. debug_mat.ZBuffer = video::ECFN_NEVER;
  336. driver->setMaterial(debug_mat);
  337. for (u32 g=0; g<m->getMeshBufferCount(); ++g)
  338. {
  339. const IMeshBuffer* mb = m->getMeshBuffer(g);
  340. if (RenderFromIdentity)
  341. driver->setTransform(video::ETS_WORLD, core::IdentityMatrix );
  342. else if (Mesh->getMeshType() == EAMT_SKINNED)
  343. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation);
  344. driver->drawMeshBuffer(mb);
  345. }
  346. }
  347. }
  348. }
  349. //! Returns the current start frame number.
  350. s32 CAnimatedMeshSceneNode::getStartFrame() const
  351. {
  352. return StartFrame;
  353. }
  354. //! Returns the current start frame number.
  355. s32 CAnimatedMeshSceneNode::getEndFrame() const
  356. {
  357. return EndFrame;
  358. }
  359. //! sets the frames between the animation is looped.
  360. //! the default is 0 - MaximalFrameCount of the mesh.
  361. bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end)
  362. {
  363. const s32 maxFrameCount = Mesh->getFrameCount() - 1;
  364. if (end < begin)
  365. {
  366. StartFrame = core::s32_clamp(end, 0, maxFrameCount);
  367. EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount);
  368. }
  369. else
  370. {
  371. StartFrame = core::s32_clamp(begin, 0, maxFrameCount);
  372. EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount);
  373. }
  374. if (FramesPerSecond < 0)
  375. setCurrentFrame((f32)EndFrame);
  376. else
  377. setCurrentFrame((f32)StartFrame);
  378. return true;
  379. }
  380. //! sets the speed with witch the animation is played
  381. void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond)
  382. {
  383. FramesPerSecond = framesPerSecond * 0.001f;
  384. }
  385. f32 CAnimatedMeshSceneNode::getAnimationSpeed() const
  386. {
  387. return FramesPerSecond * 1000.f;
  388. }
  389. //! Sets the animation strength (how important the animation is)
  390. /** \param strength: The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
  391. void CAnimatedMeshSceneNode::setAnimationStrength(f32 strength)
  392. {
  393. AnimationStrength = strength;
  394. }
  395. //! Gets the animation strength (how important the animation is)
  396. /** \return The importance of the animation: 1.f keeps the original animation, 0.f is no animation. */
  397. f32 CAnimatedMeshSceneNode::getAnimationStrength() const
  398. {
  399. return AnimationStrength;
  400. }
  401. //! returns the axis aligned bounding box of this node
  402. const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const
  403. {
  404. return Box;
  405. }
  406. //! returns the material based on the zero based index i. To get the amount
  407. //! of materials used by this scene node, use getMaterialCount().
  408. //! This function is needed for inserting the node into the scene hirachy on a
  409. //! optimal position for minimizing renderstate changes, but can also be used
  410. //! to directly modify the material of a scene node.
  411. video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i)
  412. {
  413. if (i >= Materials.size())
  414. return ISceneNode::getMaterial(i);
  415. return Materials[i];
  416. }
  417. //! returns amount of materials used by this scene node.
  418. u32 CAnimatedMeshSceneNode::getMaterialCount() const
  419. {
  420. return Materials.size();
  421. }
  422. //! Returns a pointer to a child node, which has the same transformation as
  423. //! the corresponding joint, if the mesh in this scene node is a skinned mesh.
  424. IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName)
  425. {
  426. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  427. os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
  428. return 0;
  429. #else
  430. if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
  431. {
  432. os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
  433. return 0;
  434. }
  435. checkJoints();
  436. ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
  437. const s32 number = skinnedMesh->getJointNumber(jointName);
  438. if (number == -1)
  439. {
  440. os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG);
  441. return 0;
  442. }
  443. if ((s32)JointChildSceneNodes.size() <= number)
  444. {
  445. os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING);
  446. return 0;
  447. }
  448. return JointChildSceneNodes[number];
  449. #endif
  450. }
  451. //! Returns a pointer to a child node, which has the same transformation as
  452. //! the corresponding joint, if the mesh in this scene node is a skinned mesh.
  453. IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID)
  454. {
  455. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  456. os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING);
  457. return 0;
  458. #else
  459. if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
  460. {
  461. os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING);
  462. return 0;
  463. }
  464. checkJoints();
  465. if (JointChildSceneNodes.size() <= jointID)
  466. {
  467. os::Printer::log("Joint not loaded into node", ELL_WARNING);
  468. return 0;
  469. }
  470. return JointChildSceneNodes[jointID];
  471. #endif
  472. }
  473. //! Gets joint count.
  474. u32 CAnimatedMeshSceneNode::getJointCount() const
  475. {
  476. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  477. return 0;
  478. #else
  479. if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
  480. return 0;
  481. ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh;
  482. return skinnedMesh->getJointCount();
  483. #endif
  484. }
  485. //! Returns a pointer to a child node, which has the same transformation as
  486. //! the corresponding joint, if the mesh in this scene node is a ms3d mesh.
  487. ISceneNode* CAnimatedMeshSceneNode::getMS3DJointNode(const c8* jointName)
  488. {
  489. return getJointNode(jointName);
  490. }
  491. //! Returns a pointer to a child node, which has the same transformation as
  492. //! the corresponding joint, if the mesh in this scene node is a .x mesh.
  493. ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName)
  494. {
  495. return getJointNode(jointName);
  496. }
  497. //! Removes a child from this scene node.
  498. //! Implemented here, to be able to remove the shadow properly, if there is one,
  499. //! or to remove attached childs.
  500. bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child)
  501. {
  502. if (ISceneNode::removeChild(child))
  503. {
  504. if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created
  505. {
  506. for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
  507. {
  508. if (JointChildSceneNodes[i] == child)
  509. {
  510. JointChildSceneNodes[i] = 0; //remove link to child
  511. break;
  512. }
  513. }
  514. }
  515. return true;
  516. }
  517. return false;
  518. }
  519. //! Sets looping mode which is on by default. If set to false,
  520. //! animations will not be looped.
  521. void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped)
  522. {
  523. Looping = playAnimationLooped;
  524. }
  525. //! returns the current loop mode
  526. bool CAnimatedMeshSceneNode::getLoopMode() const
  527. {
  528. return Looping;
  529. }
  530. //! Sets a callback interface which will be called if an animation
  531. //! playback has ended. Set this to 0 to disable the callback again.
  532. void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback)
  533. {
  534. if (callback == LoopCallBack)
  535. return;
  536. if (LoopCallBack)
  537. LoopCallBack->drop();
  538. LoopCallBack = callback;
  539. if (LoopCallBack)
  540. LoopCallBack->grab();
  541. }
  542. //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
  543. void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly)
  544. {
  545. ReadOnlyMaterials = readonly;
  546. }
  547. //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
  548. bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const
  549. {
  550. return ReadOnlyMaterials;
  551. }
  552. //! Writes attributes of the scene node.
  553. void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
  554. {
  555. IAnimatedMeshSceneNode::serializeAttributes(out, options);
  556. if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename)
  557. {
  558. const io::path path = SceneManager->getFileSystem()->getRelativeFilename(
  559. SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()),
  560. options->Filename);
  561. out->addString("Mesh", path.c_str());
  562. }
  563. else
  564. out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str());
  565. out->addBool("Looping", Looping);
  566. out->addBool("ReadOnlyMaterials", ReadOnlyMaterials);
  567. out->addFloat("FramesPerSecond", FramesPerSecond);
  568. out->addInt("StartFrame", StartFrame);
  569. out->addInt("EndFrame", EndFrame);
  570. }
  571. //! Reads attributes of the scene node.
  572. void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
  573. {
  574. IAnimatedMeshSceneNode::deserializeAttributes(in, options);
  575. io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh);
  576. io::path newMeshStr = in->getAttributeAsString("Mesh");
  577. Looping = in->getAttributeAsBool("Looping");
  578. ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials");
  579. FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond");
  580. StartFrame = in->getAttributeAsInt("StartFrame");
  581. EndFrame = in->getAttributeAsInt("EndFrame");
  582. if (newMeshStr != "" && oldMeshStr != newMeshStr)
  583. {
  584. IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str());
  585. if (newAnimatedMesh)
  586. setMesh(newAnimatedMesh);
  587. }
  588. // TODO: read animation names instead of frame begin and ends
  589. }
  590. //! Sets a new mesh
  591. void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh)
  592. {
  593. if (!mesh)
  594. return; // won't set null mesh
  595. if (Mesh != mesh)
  596. {
  597. if (Mesh)
  598. Mesh->drop();
  599. Mesh = mesh;
  600. // grab the mesh (it's non-null!)
  601. Mesh->grab();
  602. }
  603. // get materials and bounding box
  604. Box = Mesh->getBoundingBox();
  605. IMesh* m = Mesh->getMesh(0,0);
  606. if (m)
  607. {
  608. Materials.clear();
  609. Materials.reallocate(m->getMeshBufferCount());
  610. for (u32 i=0; i<m->getMeshBufferCount(); ++i)
  611. {
  612. IMeshBuffer* mb = m->getMeshBuffer(i);
  613. if (mb)
  614. Materials.push_back(mb->getMaterial());
  615. else
  616. Materials.push_back(video::SMaterial());
  617. }
  618. }
  619. // clean up joint nodes
  620. if (JointsUsed)
  621. {
  622. JointsUsed=false;
  623. checkJoints();
  624. }
  625. // get start and begin time
  626. // setAnimationSpeed(Mesh->getAnimationSpeed());
  627. setFrameLoop(0, Mesh->getFrameCount());
  628. }
  629. //! updates the absolute position based on the relative and the parents position
  630. void CAnimatedMeshSceneNode::updateAbsolutePosition()
  631. {
  632. IAnimatedMeshSceneNode::updateAbsolutePosition();
  633. }
  634. //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set)
  635. void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode)
  636. {
  637. checkJoints();
  638. JointMode=mode;
  639. }
  640. //! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2)
  641. //! you must call animateJoints(), or the mesh will not animate
  642. void CAnimatedMeshSceneNode::setTransitionTime(f32 time)
  643. {
  644. const u32 ttime = (u32)core::floor32(time*1000.0f);
  645. if (TransitionTime==ttime)
  646. return;
  647. TransitionTime = ttime;
  648. if (ttime != 0)
  649. setJointMode(EJUOR_CONTROL);
  650. else
  651. setJointMode(EJUOR_NONE);
  652. }
  653. //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected)
  654. void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable)
  655. {
  656. RenderFromIdentity=enable;
  657. }
  658. //! updates the joint positions of this mesh
  659. void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions)
  660. {
  661. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  662. return;
  663. #else
  664. if (Mesh && Mesh->getMeshType() == EAMT_SKINNED )
  665. {
  666. checkJoints();
  667. const f32 frame = getFrameNr(); //old?
  668. CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh);
  669. skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes );
  670. skinnedMesh->animateMesh(frame, 1.0f);
  671. skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes);
  672. //-----------------------------------------
  673. // Transition
  674. //-----------------------------------------
  675. if (Transiting != 0.f)
  676. {
  677. // Init additional matrices
  678. if (PretransitingSave.size()<JointChildSceneNodes.size())
  679. {
  680. for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
  681. PretransitingSave.push_back(core::matrix4());
  682. }
  683. for (u32 n=0; n<JointChildSceneNodes.size(); ++n)
  684. {
  685. //------Position------
  686. JointChildSceneNodes[n]->setPosition(
  687. core::lerp(
  688. PretransitingSave[n].getTranslation(),
  689. JointChildSceneNodes[n]->getPosition(),
  690. TransitingBlend));
  691. //------Rotation------
  692. //Code is slow, needs to be fixed up
  693. const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD);
  694. const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD);
  695. core::quaternion QRotation;
  696. QRotation.slerp(RotationStart, RotationEnd, TransitingBlend);
  697. core::vector3df tmpVector;
  698. QRotation.toEuler(tmpVector);
  699. tmpVector*=core::RADTODEG; //convert from radians back to degrees
  700. JointChildSceneNodes[n]->setRotation( tmpVector );
  701. //------Scale------
  702. //JointChildSceneNodes[n]->setScale(
  703. // core::lerp(
  704. // PretransitingSave[n].getScale(),
  705. // JointChildSceneNodes[n]->getScale(),
  706. // TransitingBlend));
  707. }
  708. }
  709. if (CalculateAbsolutePositions)
  710. {
  711. //---slow---
  712. for (u32 n=0;n<JointChildSceneNodes.size();++n)
  713. {
  714. if (JointChildSceneNodes[n]->getParent()==this)
  715. {
  716. JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option
  717. }
  718. }
  719. }
  720. }
  721. #endif
  722. }
  723. /*!
  724. */
  725. void CAnimatedMeshSceneNode::checkJoints()
  726. {
  727. #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_
  728. return;
  729. #else
  730. if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED)
  731. return;
  732. if (!JointsUsed)
  733. {
  734. for (u32 i=0; i<JointChildSceneNodes.size(); ++i)
  735. removeChild(JointChildSceneNodes[i]);
  736. JointChildSceneNodes.clear();
  737. //Create joints for SkinnedMesh
  738. ((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager);
  739. ((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes);
  740. JointsUsed=true;
  741. JointMode=EJUOR_READ;
  742. }
  743. #endif
  744. }
  745. /*!
  746. */
  747. void CAnimatedMeshSceneNode::beginTransition()
  748. {
  749. if (!JointsUsed)
  750. return;
  751. if (TransitionTime != 0)
  752. {
  753. //Check the array is big enough
  754. if (PretransitingSave.size()<JointChildSceneNodes.size())
  755. {
  756. for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n)
  757. PretransitingSave.push_back(core::matrix4());
  758. }
  759. //Copy the position of joints
  760. for (u32 n=0;n<JointChildSceneNodes.size();++n)
  761. PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation();
  762. Transiting = core::reciprocal((f32)TransitionTime);
  763. }
  764. TransitingBlend = 0.f;
  765. }
  766. /*!
  767. */
  768. ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
  769. {
  770. if (!newParent)
  771. newParent = Parent;
  772. if (!newManager)
  773. newManager = SceneManager;
  774. CAnimatedMeshSceneNode* newNode =
  775. new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation,
  776. RelativeRotation, RelativeScale);
  777. if (newParent)
  778. {
  779. newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called
  780. newNode->drop();
  781. }
  782. newNode->cloneMembers(this, newManager);
  783. newNode->Materials = Materials;
  784. newNode->Box = Box;
  785. newNode->Mesh = Mesh;
  786. newNode->StartFrame = StartFrame;
  787. newNode->EndFrame = EndFrame;
  788. newNode->FramesPerSecond = FramesPerSecond;
  789. newNode->CurrentFrameNr = CurrentFrameNr;
  790. newNode->JointMode = JointMode;
  791. newNode->JointsUsed = JointsUsed;
  792. newNode->TransitionTime = TransitionTime;
  793. newNode->Transiting = Transiting;
  794. newNode->TransitingBlend = TransitingBlend;
  795. newNode->Looping = Looping;
  796. newNode->ReadOnlyMaterials = ReadOnlyMaterials;
  797. newNode->LoopCallBack = LoopCallBack;
  798. newNode->PassCount = PassCount;
  799. newNode->JointChildSceneNodes = JointChildSceneNodes;
  800. newNode->PretransitingSave = PretransitingSave;
  801. newNode->RenderFromIdentity = RenderFromIdentity;
  802. return newNode;
  803. }
  804. void CAnimatedMeshSceneNode::useAnimationSet(u32 set_num)
  805. {
  806. if (m_animation_set.empty())
  807. {
  808. setFrameLoop(getStartFrame(), getEndFrame());
  809. return;
  810. }
  811. setFrameLoop(m_animation_set[set_num * 2], m_animation_set[set_num * 2 + 1]);
  812. }
  813. } // end namespace scene
  814. } // end namespace irr