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