PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/source/Irrlicht/CAnimatedMeshMD2.cpp

https://gitlab.com/JFT/Irrlicht_extended
C++ | 465 lines | 376 code | 62 blank | 27 comment | 27 complexity | a057687e7d1b487677c08dd0623ede6e MD5 | raw file
  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 "IrrCompileConfig.h"
  5. #ifdef _IRR_COMPILE_WITH_MD2_LOADER_
  6. #include "CAnimatedMeshMD2.h"
  7. #include "SColor.h"
  8. #include "irrMath.h"
  9. namespace irr
  10. {
  11. namespace scene
  12. {
  13. const s32 MD2_FRAME_SHIFT = 2;
  14. const f32 MD2_FRAME_SHIFT_RECIPROCAL = 1.f / (1 << MD2_FRAME_SHIFT);
  15. const s32 Q2_VERTEX_NORMAL_TABLE_SIZE = 162;
  16. static const f32 Q2_VERTEX_NORMAL_TABLE[Q2_VERTEX_NORMAL_TABLE_SIZE][3] = {
  17. {-0.525731f, 0.000000f, 0.850651f},
  18. {-0.442863f, 0.238856f, 0.864188f},
  19. {-0.295242f, 0.000000f, 0.955423f},
  20. {-0.309017f, 0.500000f, 0.809017f},
  21. {-0.162460f, 0.262866f, 0.951056f},
  22. {0.000000f, 0.000000f, 1.000000f},
  23. {0.000000f, 0.850651f, 0.525731f},
  24. {-0.147621f, 0.716567f, 0.681718f},
  25. {0.147621f, 0.716567f, 0.681718f},
  26. {0.000000f, 0.525731f, 0.850651f},
  27. {0.309017f, 0.500000f, 0.809017f},
  28. {0.525731f, 0.000000f, 0.850651f},
  29. {0.295242f, 0.000000f, 0.955423f},
  30. {0.442863f, 0.238856f, 0.864188f},
  31. {0.162460f, 0.262866f, 0.951056f},
  32. {-0.681718f, 0.147621f, 0.716567f},
  33. {-0.809017f, 0.309017f, 0.500000f},
  34. {-0.587785f, 0.425325f, 0.688191f},
  35. {-0.850651f, 0.525731f, 0.000000f},
  36. {-0.864188f, 0.442863f, 0.238856f},
  37. {-0.716567f, 0.681718f, 0.147621f},
  38. {-0.688191f, 0.587785f, 0.425325f},
  39. {-0.500000f, 0.809017f, 0.309017f},
  40. {-0.238856f, 0.864188f, 0.442863f},
  41. {-0.425325f, 0.688191f, 0.587785f},
  42. {-0.716567f, 0.681718f, -0.147621f},
  43. {-0.500000f, 0.809017f, -0.309017f},
  44. {-0.525731f, 0.850651f, 0.000000f},
  45. {0.000000f, 0.850651f, -0.525731f},
  46. {-0.238856f, 0.864188f, -0.442863f},
  47. {0.000000f, 0.955423f, -0.295242f},
  48. {-0.262866f, 0.951056f, -0.162460f},
  49. {0.000000f, 1.000000f, 0.000000f},
  50. {0.000000f, 0.955423f, 0.295242f},
  51. {-0.262866f, 0.951056f, 0.162460f},
  52. {0.238856f, 0.864188f, 0.442863f},
  53. {0.262866f, 0.951056f, 0.162460f},
  54. {0.500000f, 0.809017f, 0.309017f},
  55. {0.238856f, 0.864188f, -0.442863f},
  56. {0.262866f, 0.951056f, -0.162460f},
  57. {0.500000f, 0.809017f, -0.309017f},
  58. {0.850651f, 0.525731f, 0.000000f},
  59. {0.716567f, 0.681718f, 0.147621f},
  60. {0.716567f, 0.681718f, -0.147621f},
  61. {0.525731f, 0.850651f, 0.000000f},
  62. {0.425325f, 0.688191f, 0.587785f},
  63. {0.864188f, 0.442863f, 0.238856f},
  64. {0.688191f, 0.587785f, 0.425325f},
  65. {0.809017f, 0.309017f, 0.500000f},
  66. {0.681718f, 0.147621f, 0.716567f},
  67. {0.587785f, 0.425325f, 0.688191f},
  68. {0.955423f, 0.295242f, 0.000000f},
  69. {1.000000f, 0.000000f, 0.000000f},
  70. {0.951056f, 0.162460f, 0.262866f},
  71. {0.850651f, -0.525731f, 0.000000f},
  72. {0.955423f, -0.295242f, 0.000000f},
  73. {0.864188f, -0.442863f, 0.238856f},
  74. {0.951056f, -0.162460f, 0.262866f},
  75. {0.809017f, -0.309017f, 0.500000f},
  76. {0.681718f, -0.147621f, 0.716567f},
  77. {0.850651f, 0.000000f, 0.525731f},
  78. {0.864188f, 0.442863f, -0.238856f},
  79. {0.809017f, 0.309017f, -0.500000f},
  80. {0.951056f, 0.162460f, -0.262866f},
  81. {0.525731f, 0.000000f, -0.850651f},
  82. {0.681718f, 0.147621f, -0.716567f},
  83. {0.681718f, -0.147621f, -0.716567f},
  84. {0.850651f, 0.000000f, -0.525731f},
  85. {0.809017f, -0.309017f, -0.500000f},
  86. {0.864188f, -0.442863f, -0.238856f},
  87. {0.951056f, -0.162460f, -0.262866f},
  88. {0.147621f, 0.716567f, -0.681718f},
  89. {0.309017f, 0.500000f, -0.809017f},
  90. {0.425325f, 0.688191f, -0.587785f},
  91. {0.442863f, 0.238856f, -0.864188f},
  92. {0.587785f, 0.425325f, -0.688191f},
  93. {0.688191f, 0.587785f, -0.425325f},
  94. {-0.147621f, 0.716567f, -0.681718f},
  95. {-0.309017f, 0.500000f, -0.809017f},
  96. {0.000000f, 0.525731f, -0.850651f},
  97. {-0.525731f, 0.000000f, -0.850651f},
  98. {-0.442863f, 0.238856f, -0.864188f},
  99. {-0.295242f, 0.000000f, -0.955423f},
  100. {-0.162460f, 0.262866f, -0.951056f},
  101. {0.000000f, 0.000000f, -1.000000f},
  102. {0.295242f, 0.000000f, -0.955423f},
  103. {0.162460f, 0.262866f, -0.951056f},
  104. {-0.442863f, -0.238856f, -0.864188f},
  105. {-0.309017f, -0.500000f, -0.809017f},
  106. {-0.162460f, -0.262866f, -0.951056f},
  107. {0.000000f, -0.850651f, -0.525731f},
  108. {-0.147621f, -0.716567f, -0.681718f},
  109. {0.147621f, -0.716567f, -0.681718f},
  110. {0.000000f, -0.525731f, -0.850651f},
  111. {0.309017f, -0.500000f, -0.809017f},
  112. {0.442863f, -0.238856f, -0.864188f},
  113. {0.162460f, -0.262866f, -0.951056f},
  114. {0.238856f, -0.864188f, -0.442863f},
  115. {0.500000f, -0.809017f, -0.309017f},
  116. {0.425325f, -0.688191f, -0.587785f},
  117. {0.716567f, -0.681718f, -0.147621f},
  118. {0.688191f, -0.587785f, -0.425325f},
  119. {0.587785f, -0.425325f, -0.688191f},
  120. {0.000000f, -0.955423f, -0.295242f},
  121. {0.000000f, -1.000000f, 0.000000f},
  122. {0.262866f, -0.951056f, -0.162460f},
  123. {0.000000f, -0.850651f, 0.525731f},
  124. {0.000000f, -0.955423f, 0.295242f},
  125. {0.238856f, -0.864188f, 0.442863f},
  126. {0.262866f, -0.951056f, 0.162460f},
  127. {0.500000f, -0.809017f, 0.309017f},
  128. {0.716567f, -0.681718f, 0.147621f},
  129. {0.525731f, -0.850651f, 0.000000f},
  130. {-0.238856f, -0.864188f, -0.442863f},
  131. {-0.500000f, -0.809017f, -0.309017f},
  132. {-0.262866f, -0.951056f, -0.162460f},
  133. {-0.850651f, -0.525731f, 0.000000f},
  134. {-0.716567f, -0.681718f, -0.147621f},
  135. {-0.716567f, -0.681718f, 0.147621f},
  136. {-0.525731f, -0.850651f, 0.000000f},
  137. {-0.500000f, -0.809017f, 0.309017f},
  138. {-0.238856f, -0.864188f, 0.442863f},
  139. {-0.262866f, -0.951056f, 0.162460f},
  140. {-0.864188f, -0.442863f, 0.238856f},
  141. {-0.809017f, -0.309017f, 0.500000f},
  142. {-0.688191f, -0.587785f, 0.425325f},
  143. {-0.681718f, -0.147621f, 0.716567f},
  144. {-0.442863f, -0.238856f, 0.864188f},
  145. {-0.587785f, -0.425325f, 0.688191f},
  146. {-0.309017f, -0.500000f, 0.809017f},
  147. {-0.147621f, -0.716567f, 0.681718f},
  148. {-0.425325f, -0.688191f, 0.587785f},
  149. {-0.162460f, -0.262866f, 0.951056f},
  150. {0.442863f, -0.238856f, 0.864188f},
  151. {0.162460f, -0.262866f, 0.951056f},
  152. {0.309017f, -0.500000f, 0.809017f},
  153. {0.147621f, -0.716567f, 0.681718f},
  154. {0.000000f, -0.525731f, 0.850651f},
  155. {0.425325f, -0.688191f, 0.587785f},
  156. {0.587785f, -0.425325f, 0.688191f},
  157. {0.688191f, -0.587785f, 0.425325f},
  158. {-0.955423f, 0.295242f, 0.000000f},
  159. {-0.951056f, 0.162460f, 0.262866f},
  160. {-1.000000f, 0.000000f, 0.000000f},
  161. {-0.850651f, 0.000000f, 0.525731f},
  162. {-0.955423f, -0.295242f, 0.000000f},
  163. {-0.951056f, -0.162460f, 0.262866f},
  164. {-0.864188f, 0.442863f, -0.238856f},
  165. {-0.951056f, 0.162460f, -0.262866f},
  166. {-0.809017f, 0.309017f, -0.500000f},
  167. {-0.864188f, -0.442863f, -0.238856f},
  168. {-0.951056f, -0.162460f, -0.262866f},
  169. {-0.809017f, -0.309017f, -0.500000f},
  170. {-0.681718f, 0.147621f, -0.716567f},
  171. {-0.681718f, -0.147621f, -0.716567f},
  172. {-0.850651f, 0.000000f, -0.525731f},
  173. {-0.688191f, 0.587785f, -0.425325f},
  174. {-0.587785f, 0.425325f, -0.688191f},
  175. {-0.425325f, 0.688191f, -0.587785f},
  176. {-0.425325f, -0.688191f, -0.587785f},
  177. {-0.587785f, -0.425325f, -0.688191f},
  178. {-0.688191f, -0.587785f, -0.425325f},
  179. };
  180. struct SMD2AnimationType
  181. {
  182. s32 begin;
  183. s32 end;
  184. s32 fps;
  185. };
  186. static const SMD2AnimationType MD2AnimationTypeList[21] =
  187. {
  188. { 0, 39, 9}, // STAND
  189. { 40, 45, 10}, // RUN
  190. { 46, 53, 10}, // ATTACK
  191. { 54, 57, 7}, // PAIN_A
  192. { 58, 61, 7}, // PAIN_B
  193. { 62, 65, 7}, // PAIN_C
  194. { 66, 71, 7}, // JUMP
  195. { 72, 83, 7}, // FLIP
  196. { 84, 94, 7}, // SALUTE
  197. { 95, 111, 10}, // FALLBACK
  198. {112, 122, 7}, // WAVE
  199. {123, 134, 6}, // POINT
  200. {135, 153, 10}, // CROUCH_STAND
  201. {154, 159, 7}, // CROUCH_WALK
  202. {160, 168, 10}, // CROUCH_ATTACK
  203. {169, 172, 7}, // CROUCH_PAIN
  204. {173, 177, 5}, // CROUCH_DEATH
  205. {178, 183, 7}, // DEATH_FALLBACK
  206. {184, 189, 7}, // DEATH_FALLFORWARD
  207. {190, 197, 7}, // DEATH_FALLBACKSLOW
  208. {198, 198, 5}, // BOOM
  209. };
  210. //! constructor
  211. CAnimatedMeshMD2::CAnimatedMeshMD2()
  212. : InterpolationBuffer(0), InterpolationFirstFrame(-1), InterpolationSecondFrame(-1), InterpolationFrameDiv(0.f)
  213. , FrameList(0), FrameCount(0), FramesPerSecond((f32)(MD2AnimationTypeList[0].fps << MD2_FRAME_SHIFT))
  214. {
  215. #ifdef _DEBUG
  216. IAnimatedMesh::setDebugName("CAnimatedMeshMD2 IAnimatedMesh");
  217. IMesh::setDebugName("CAnimatedMeshMD2 IMesh");
  218. #endif
  219. InterpolationBuffer = new SMeshBuffer;
  220. }
  221. //! destructor
  222. CAnimatedMeshMD2::~CAnimatedMeshMD2()
  223. {
  224. delete [] FrameList;
  225. if (InterpolationBuffer)
  226. InterpolationBuffer->drop();
  227. }
  228. //! returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh.
  229. u32 CAnimatedMeshMD2::getFrameCount() const
  230. {
  231. return FrameCount<<MD2_FRAME_SHIFT;
  232. }
  233. //! returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. Note, that some Meshes will ignore the detail level.
  234. IMesh* CAnimatedMeshMD2::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop)
  235. {
  236. if ((u32)frame > getFrameCount())
  237. frame = (frame % getFrameCount());
  238. if (startFrameLoop == -1 && endFrameLoop == -1)
  239. {
  240. startFrameLoop = 0;
  241. endFrameLoop = getFrameCount();
  242. }
  243. updateInterpolationBuffer(frame, startFrameLoop, endFrameLoop);
  244. return this;
  245. }
  246. //! returns amount of mesh buffers. MD2 meshes only have one buffer
  247. u32 CAnimatedMeshMD2::getMeshBufferCount() const
  248. {
  249. return 1;
  250. }
  251. //! returns pointer to a mesh buffer
  252. IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(u32 nr) const
  253. {
  254. if (nr == 0)
  255. return InterpolationBuffer;
  256. else
  257. return 0;
  258. }
  259. //! Returns pointer to a mesh buffer which fits a material
  260. IMeshBuffer* CAnimatedMeshMD2::getMeshBuffer(const video::SMaterial &material) const
  261. {
  262. if (InterpolationBuffer->Material == material)
  263. return InterpolationBuffer;
  264. else
  265. return 0;
  266. }
  267. // updates the interpolation buffer
  268. void CAnimatedMeshMD2::updateInterpolationBuffer(s32 frame, s32 startFrameLoop, s32 endFrameLoop)
  269. {
  270. u32 firstFrame, secondFrame;
  271. f32 div;
  272. // TA: resolve missing ipol in loop between end-start
  273. if (endFrameLoop - startFrameLoop == 0)
  274. {
  275. firstFrame = frame>>MD2_FRAME_SHIFT;
  276. secondFrame = frame>>MD2_FRAME_SHIFT;
  277. div = 1.0f;
  278. }
  279. else
  280. {
  281. // key frames
  282. u32 s = startFrameLoop >> MD2_FRAME_SHIFT;
  283. u32 e = endFrameLoop >> MD2_FRAME_SHIFT;
  284. firstFrame = frame >> MD2_FRAME_SHIFT;
  285. secondFrame = core::if_c_a_else_b(firstFrame + 1 > e, s, firstFrame + 1);
  286. firstFrame = core::s32_min(FrameCount - 1, firstFrame);
  287. secondFrame = core::s32_min(FrameCount - 1, secondFrame);
  288. //div = (frame % (1<<MD2_FRAME_SHIFT)) / (f32)(1<<MD2_FRAME_SHIFT);
  289. frame &= (1<<MD2_FRAME_SHIFT) - 1;
  290. div = frame * MD2_FRAME_SHIFT_RECIPROCAL;
  291. }
  292. if ( firstFrame != InterpolationFirstFrame || secondFrame != InterpolationSecondFrame || div != InterpolationFrameDiv )
  293. {
  294. InterpolationFirstFrame = firstFrame;
  295. InterpolationSecondFrame = secondFrame;
  296. InterpolationFrameDiv = div;
  297. video::S3DVertex* target = static_cast<video::S3DVertex*>(InterpolationBuffer->getVertices());
  298. SMD2Vert* first = FrameList[firstFrame].pointer();
  299. SMD2Vert* second = FrameList[secondFrame].pointer();
  300. // interpolate both frames
  301. const u32 count = FrameList[firstFrame].size();
  302. for (u32 i=0; i<count; ++i)
  303. {
  304. const core::vector3df one = core::vector3df(f32(first->Pos.X) * FrameTransforms[firstFrame].scale.X + FrameTransforms[firstFrame].translate.X,
  305. f32(first->Pos.Y) * FrameTransforms[firstFrame].scale.Y + FrameTransforms[firstFrame].translate.Y,
  306. f32(first->Pos.Z) * FrameTransforms[firstFrame].scale.Z + FrameTransforms[firstFrame].translate.Z);
  307. const core::vector3df two = core::vector3df(f32(second->Pos.X) * FrameTransforms[secondFrame].scale.X + FrameTransforms[secondFrame].translate.X,
  308. f32(second->Pos.Y) * FrameTransforms[secondFrame].scale.Y + FrameTransforms[secondFrame].translate.Y,
  309. f32(second->Pos.Z) * FrameTransforms[secondFrame].scale.Z + FrameTransforms[secondFrame].translate.Z);
  310. target->Pos = two.getInterpolated(one, div);
  311. const core::vector3df n1(
  312. Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][0],
  313. Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][2],
  314. Q2_VERTEX_NORMAL_TABLE[first->NormalIdx][1]);
  315. const core::vector3df n2(
  316. Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][0],
  317. Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][2],
  318. Q2_VERTEX_NORMAL_TABLE[second->NormalIdx][1]);
  319. target->Normal = n2.getInterpolated(n1, div);
  320. ++target;
  321. ++first;
  322. ++second;
  323. }
  324. //update bounding box
  325. InterpolationBuffer->setBoundingBox(BoxList[secondFrame].getInterpolated(BoxList[firstFrame], div));
  326. InterpolationBuffer->setDirty();
  327. }
  328. }
  329. //! sets a flag of all contained materials to a new value
  330. void CAnimatedMeshMD2::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue)
  331. {
  332. InterpolationBuffer->Material.setFlag(flag, newvalue);
  333. }
  334. //! set the hardware mapping hint, for driver
  335. void CAnimatedMeshMD2::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint,
  336. E_BUFFER_TYPE buffer)
  337. {
  338. InterpolationBuffer->setHardwareMappingHint(newMappingHint, buffer);
  339. }
  340. //! flags the meshbuffer as changed, reloads hardware buffers
  341. void CAnimatedMeshMD2::setDirty(E_BUFFER_TYPE buffer)
  342. {
  343. InterpolationBuffer->setDirty(buffer);
  344. }
  345. //! returns an axis aligned bounding box
  346. const core::aabbox3d<f32>& CAnimatedMeshMD2::getBoundingBox() const
  347. {
  348. return InterpolationBuffer->BoundingBox;
  349. }
  350. //! set user axis aligned bounding box
  351. void CAnimatedMeshMD2::setBoundingBox(const core::aabbox3df& box)
  352. {
  353. InterpolationBuffer->BoundingBox = box;
  354. }
  355. //! Returns the type of the animated mesh.
  356. E_ANIMATED_MESH_TYPE CAnimatedMeshMD2::getMeshType() const
  357. {
  358. return EAMT_MD2;
  359. }
  360. //! Returns frame loop data for a special MD2 animation type.
  361. void CAnimatedMeshMD2::getFrameLoop(EMD2_ANIMATION_TYPE l,
  362. s32& outBegin, s32& outEnd, s32& outFPS) const
  363. {
  364. if (l < 0 || l >= EMAT_COUNT)
  365. return;
  366. outBegin = MD2AnimationTypeList[l].begin << MD2_FRAME_SHIFT;
  367. outEnd = MD2AnimationTypeList[l].end << MD2_FRAME_SHIFT;
  368. // correct to anim between last->first frame
  369. outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
  370. outFPS = MD2AnimationTypeList[l].fps << MD2_FRAME_SHIFT;
  371. }
  372. //! Returns frame loop data for a special MD2 animation type.
  373. bool CAnimatedMeshMD2::getFrameLoop(const c8* name,
  374. s32& outBegin, s32&outEnd, s32& outFPS) const
  375. {
  376. for (u32 i=0; i < AnimationData.size(); ++i)
  377. {
  378. if (AnimationData[i].name == name)
  379. {
  380. outBegin = AnimationData[i].begin << MD2_FRAME_SHIFT;
  381. outEnd = AnimationData[i].end << MD2_FRAME_SHIFT;
  382. outEnd += MD2_FRAME_SHIFT == 0 ? 1 : (1 << MD2_FRAME_SHIFT) - 1;
  383. outFPS = AnimationData[i].fps << MD2_FRAME_SHIFT;
  384. return true;
  385. }
  386. }
  387. return false;
  388. }
  389. //! Returns amount of md2 animations in this file.
  390. s32 CAnimatedMeshMD2::getAnimationCount() const
  391. {
  392. return AnimationData.size();
  393. }
  394. //! Returns name of md2 animation.
  395. const c8* CAnimatedMeshMD2::getAnimationName(s32 nr) const
  396. {
  397. if ((u32)nr >= AnimationData.size())
  398. return 0;
  399. return AnimationData[nr].name.c_str();
  400. }
  401. } // end namespace scene
  402. } // end namespace irr
  403. #endif // _IRR_COMPILE_WITH_MD2_LOADER_