diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshMD3.cpp | 936 |
1 files changed, 468 insertions, 468 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshMD3.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshMD3.cpp index 0d3a091..d288d4b 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshMD3.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshMD3.cpp | |||
@@ -1,468 +1,468 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt / Fabio Concas / Thomas Alten |
2 | // This file is part of the "Irrlicht Engine". | 2 | // This file is part of the "Irrlicht Engine". |
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | 3 | // For conditions of distribution and use, see copyright notice in irrlicht.h |
4 | 4 | ||
5 | #include "IrrCompileConfig.h" | 5 | #include "IrrCompileConfig.h" |
6 | #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ | 6 | #ifdef _IRR_COMPILE_WITH_MD3_LOADER_ |
7 | 7 | ||
8 | #include "CAnimatedMeshMD3.h" | 8 | #include "CAnimatedMeshMD3.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | 10 | ||
11 | namespace irr | 11 | namespace irr |
12 | { | 12 | { |
13 | namespace scene | 13 | namespace scene |
14 | { | 14 | { |
15 | 15 | ||
16 | 16 | ||
17 | // byte-align structures | 17 | // byte-align structures |
18 | #include "irrpack.h" | 18 | #include "irrpack.h" |
19 | 19 | ||
20 | //! General properties of a single animation frame. | 20 | //! General properties of a single animation frame. |
21 | struct SMD3Frame | 21 | struct SMD3Frame |
22 | { | 22 | { |
23 | f32 mins[3]; // bounding box per frame | 23 | f32 mins[3]; // bounding box per frame |
24 | f32 maxs[3]; | 24 | f32 maxs[3]; |
25 | f32 position[3]; // position of bounding box | 25 | f32 position[3]; // position of bounding box |
26 | f32 radius; // radius of bounding sphere | 26 | f32 radius; // radius of bounding sphere |
27 | c8 creator[16]; // name of frame | 27 | c8 creator[16]; // name of frame |
28 | } PACK_STRUCT; | 28 | } PACK_STRUCT; |
29 | 29 | ||
30 | 30 | ||
31 | //! An attachment point for another MD3 model. | 31 | //! An attachment point for another MD3 model. |
32 | struct SMD3Tag | 32 | struct SMD3Tag |
33 | { | 33 | { |
34 | c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part. | 34 | c8 Name[64]; //name of 'tag' as it's usually called in the md3 files try to see it as a sub-mesh/seperate mesh-part. |
35 | f32 position[3]; //relative position of tag | 35 | f32 position[3]; //relative position of tag |
36 | f32 rotationMatrix[9]; //3x3 rotation direction of tag | 36 | f32 rotationMatrix[9]; //3x3 rotation direction of tag |
37 | } PACK_STRUCT; | 37 | } PACK_STRUCT; |
38 | 38 | ||
39 | //!Shader | 39 | //!Shader |
40 | struct SMD3Shader | 40 | struct SMD3Shader |
41 | { | 41 | { |
42 | c8 name[64]; // name of shader | 42 | c8 name[64]; // name of shader |
43 | s32 shaderIndex; | 43 | s32 shaderIndex; |
44 | } PACK_STRUCT; | 44 | } PACK_STRUCT; |
45 | 45 | ||
46 | // Default alignment | 46 | // Default alignment |
47 | #include "irrunpack.h" | 47 | #include "irrunpack.h" |
48 | 48 | ||
49 | 49 | ||
50 | //! Constructor | 50 | //! Constructor |
51 | CAnimatedMeshMD3::CAnimatedMeshMD3() | 51 | CAnimatedMeshMD3::CAnimatedMeshMD3() |
52 | :Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f) | 52 | :Mesh(0), IPolShift(0), LoopMode(0), Scaling(1.f)//, FramesPerSecond(25.f) |
53 | { | 53 | { |
54 | #ifdef _DEBUG | 54 | #ifdef _DEBUG |
55 | setDebugName("CAnimatedMeshMD3"); | 55 | setDebugName("CAnimatedMeshMD3"); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | Mesh = new SMD3Mesh(); | 58 | Mesh = new SMD3Mesh(); |
59 | MeshIPol = new SMesh(); | 59 | MeshIPol = new SMesh(); |
60 | setInterpolationShift(0, 0); | 60 | setInterpolationShift(0, 0); |
61 | } | 61 | } |
62 | 62 | ||
63 | 63 | ||
64 | //! Destructor | 64 | //! Destructor |
65 | CAnimatedMeshMD3::~CAnimatedMeshMD3() | 65 | CAnimatedMeshMD3::~CAnimatedMeshMD3() |
66 | { | 66 | { |
67 | if (Mesh) | 67 | if (Mesh) |
68 | Mesh->drop(); | 68 | Mesh->drop(); |
69 | if (MeshIPol) | 69 | if (MeshIPol) |
70 | MeshIPol->drop(); | 70 | MeshIPol->drop(); |
71 | } | 71 | } |
72 | 72 | ||
73 | 73 | ||
74 | //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. | 74 | //! Returns the amount of frames in milliseconds. If the amount is 1, it is a static (=non animated) mesh. |
75 | u32 CAnimatedMeshMD3::getFrameCount() const | 75 | u32 CAnimatedMeshMD3::getFrameCount() const |
76 | { | 76 | { |
77 | return Mesh->MD3Header.numFrames << IPolShift; | 77 | return Mesh->MD3Header.numFrames << IPolShift; |
78 | } | 78 | } |
79 | 79 | ||
80 | 80 | ||
81 | //! Rendering Hint | 81 | //! Rendering Hint |
82 | void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode) | 82 | void CAnimatedMeshMD3::setInterpolationShift(u32 shift, u32 loopMode) |
83 | { | 83 | { |
84 | IPolShift = shift; | 84 | IPolShift = shift; |
85 | LoopMode = loopMode; | 85 | LoopMode = loopMode; |
86 | } | 86 | } |
87 | 87 | ||
88 | 88 | ||
89 | //! returns amount of mesh buffers. | 89 | //! returns amount of mesh buffers. |
90 | u32 CAnimatedMeshMD3::getMeshBufferCount() const | 90 | u32 CAnimatedMeshMD3::getMeshBufferCount() const |
91 | { | 91 | { |
92 | return MeshIPol->getMeshBufferCount(); | 92 | return MeshIPol->getMeshBufferCount(); |
93 | } | 93 | } |
94 | 94 | ||
95 | 95 | ||
96 | //! returns pointer to a mesh buffer | 96 | //! returns pointer to a mesh buffer |
97 | IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const | 97 | IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(u32 nr) const |
98 | { | 98 | { |
99 | return MeshIPol->getMeshBuffer(nr); | 99 | return MeshIPol->getMeshBuffer(nr); |
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | //! Returns pointer to a mesh buffer which fits a material | 103 | //! Returns pointer to a mesh buffer which fits a material |
104 | IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const | 104 | IMeshBuffer* CAnimatedMeshMD3::getMeshBuffer(const video::SMaterial &material) const |
105 | { | 105 | { |
106 | return MeshIPol->getMeshBuffer(material); | 106 | return MeshIPol->getMeshBuffer(material); |
107 | } | 107 | } |
108 | 108 | ||
109 | 109 | ||
110 | void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) | 110 | void CAnimatedMeshMD3::setMaterialFlag(video::E_MATERIAL_FLAG flag, bool newvalue) |
111 | { | 111 | { |
112 | MeshIPol->setMaterialFlag(flag, newvalue); | 112 | MeshIPol->setMaterialFlag(flag, newvalue); |
113 | } | 113 | } |
114 | 114 | ||
115 | 115 | ||
116 | //! set the hardware mapping hint, for driver | 116 | //! set the hardware mapping hint, for driver |
117 | void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, | 117 | void CAnimatedMeshMD3::setHardwareMappingHint(E_HARDWARE_MAPPING newMappingHint, |
118 | E_BUFFER_TYPE buffer) | 118 | E_BUFFER_TYPE buffer) |
119 | { | 119 | { |
120 | MeshIPol->setHardwareMappingHint(newMappingHint, buffer); | 120 | MeshIPol->setHardwareMappingHint(newMappingHint, buffer); |
121 | } | 121 | } |
122 | 122 | ||
123 | 123 | ||
124 | //! flags the meshbuffer as changed, reloads hardware buffers | 124 | //! flags the meshbuffer as changed, reloads hardware buffers |
125 | void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) | 125 | void CAnimatedMeshMD3::setDirty(E_BUFFER_TYPE buffer) |
126 | { | 126 | { |
127 | MeshIPol->setDirty(buffer); | 127 | MeshIPol->setDirty(buffer); |
128 | } | 128 | } |
129 | 129 | ||
130 | 130 | ||
131 | //! set user axis aligned bounding box | 131 | //! set user axis aligned bounding box |
132 | void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box) | 132 | void CAnimatedMeshMD3::setBoundingBox(const core::aabbox3df& box) |
133 | { | 133 | { |
134 | MeshIPol->setBoundingBox(box); | 134 | MeshIPol->setBoundingBox(box); |
135 | } | 135 | } |
136 | 136 | ||
137 | 137 | ||
138 | //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. | 138 | //! Returns the animated tag list based on a detail level. 0 is the lowest, 255 the highest detail. |
139 | SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) | 139 | SMD3QuaternionTagList *CAnimatedMeshMD3::getTagList(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) |
140 | { | 140 | { |
141 | if (0 == Mesh) | 141 | if (0 == Mesh) |
142 | return 0; | 142 | return 0; |
143 | 143 | ||
144 | getMesh(frame, detailLevel, startFrameLoop, endFrameLoop); | 144 | getMesh(frame, detailLevel, startFrameLoop, endFrameLoop); |
145 | return &TagListIPol; | 145 | return &TagListIPol; |
146 | } | 146 | } |
147 | 147 | ||
148 | 148 | ||
149 | //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. | 149 | //! Returns the animated mesh based on a detail level. 0 is the lowest, 255 the highest detail. |
150 | IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) | 150 | IMesh* CAnimatedMeshMD3::getMesh(s32 frame, s32 detailLevel, s32 startFrameLoop, s32 endFrameLoop) |
151 | { | 151 | { |
152 | if (0 == Mesh) | 152 | if (0 == Mesh) |
153 | return 0; | 153 | return 0; |
154 | 154 | ||
155 | //! check if we have the mesh in our private cache | 155 | //! check if we have the mesh in our private cache |
156 | SCacheInfo candidate(frame, startFrameLoop, endFrameLoop); | 156 | SCacheInfo candidate(frame, startFrameLoop, endFrameLoop); |
157 | if (candidate == Current) | 157 | if (candidate == Current) |
158 | return MeshIPol; | 158 | return MeshIPol; |
159 | 159 | ||
160 | startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift); | 160 | startFrameLoop = core::s32_max(0, startFrameLoop >> IPolShift); |
161 | endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift); | 161 | endFrameLoop = core::if_c_a_else_b(endFrameLoop < 0, Mesh->MD3Header.numFrames - 1, endFrameLoop >> IPolShift); |
162 | 162 | ||
163 | const u32 mask = 1 << IPolShift; | 163 | const u32 mask = 1 << IPolShift; |
164 | 164 | ||
165 | s32 frameA; | 165 | s32 frameA; |
166 | s32 frameB; | 166 | s32 frameB; |
167 | f32 iPol; | 167 | f32 iPol; |
168 | 168 | ||
169 | if (LoopMode) | 169 | if (LoopMode) |
170 | { | 170 | { |
171 | // correct frame to "pixel center" | 171 | // correct frame to "pixel center" |
172 | frame -= mask >> 1; | 172 | frame -= mask >> 1; |
173 | 173 | ||
174 | // interpolation | 174 | // interpolation |
175 | iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); | 175 | iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); |
176 | 176 | ||
177 | // wrap anim | 177 | // wrap anim |
178 | frame >>= IPolShift; | 178 | frame >>= IPolShift; |
179 | frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame); | 179 | frameA = core::if_c_a_else_b(frame < startFrameLoop, endFrameLoop, frame); |
180 | frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1); | 180 | frameB = core::if_c_a_else_b(frameA + 1 > endFrameLoop, startFrameLoop, frameA + 1); |
181 | } | 181 | } |
182 | else | 182 | else |
183 | { | 183 | { |
184 | // correct frame to "pixel center" | 184 | // correct frame to "pixel center" |
185 | frame -= mask >> 1; | 185 | frame -= mask >> 1; |
186 | 186 | ||
187 | iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); | 187 | iPol = f32(frame & (mask - 1)) * core::reciprocal(f32(mask)); |
188 | 188 | ||
189 | // clamp anim | 189 | // clamp anim |
190 | frame >>= IPolShift; | 190 | frame >>= IPolShift; |
191 | frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop); | 191 | frameA = core::s32_clamp(frame, startFrameLoop, endFrameLoop); |
192 | frameB = core::s32_min(frameA + 1, endFrameLoop); | 192 | frameB = core::s32_min(frameA + 1, endFrameLoop); |
193 | } | 193 | } |
194 | 194 | ||
195 | // build current vertex | 195 | // build current vertex |
196 | for (u32 i = 0; i!= Mesh->Buffer.size(); ++i) | 196 | for (u32 i = 0; i!= Mesh->Buffer.size(); ++i) |
197 | { | 197 | { |
198 | buildVertexArray(frameA, frameB, iPol, | 198 | buildVertexArray(frameA, frameB, iPol, |
199 | Mesh->Buffer[i], | 199 | Mesh->Buffer[i], |
200 | (SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i)); | 200 | (SMeshBufferLightMap*) MeshIPol->getMeshBuffer(i)); |
201 | } | 201 | } |
202 | MeshIPol->recalculateBoundingBox(); | 202 | MeshIPol->recalculateBoundingBox(); |
203 | 203 | ||
204 | // build current tags | 204 | // build current tags |
205 | buildTagArray(frameA, frameB, iPol); | 205 | buildTagArray(frameA, frameB, iPol); |
206 | 206 | ||
207 | Current = candidate; | 207 | Current = candidate; |
208 | return MeshIPol; | 208 | return MeshIPol; |
209 | } | 209 | } |
210 | 210 | ||
211 | 211 | ||
212 | //! create a Irrlicht MeshBuffer for a MD3 MeshBuffer | 212 | //! create a Irrlicht MeshBuffer for a MD3 MeshBuffer |
213 | IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, | 213 | IMeshBuffer * CAnimatedMeshMD3::createMeshBuffer(const SMD3MeshBuffer* source, |
214 | io::IFileSystem* fs, video::IVideoDriver * driver) | 214 | io::IFileSystem* fs, video::IVideoDriver * driver) |
215 | { | 215 | { |
216 | SMeshBufferLightMap * dest = new SMeshBufferLightMap(); | 216 | SMeshBufferLightMap * dest = new SMeshBufferLightMap(); |
217 | dest->Vertices.set_used(source->MeshHeader.numVertices); | 217 | dest->Vertices.set_used(source->MeshHeader.numVertices); |
218 | dest->Indices.set_used(source->Indices.size()); | 218 | dest->Indices.set_used(source->Indices.size()); |
219 | 219 | ||
220 | u32 i; | 220 | u32 i; |
221 | 221 | ||
222 | // fill in static face info | 222 | // fill in static face info |
223 | for (i = 0; i < source->Indices.size(); i += 3) | 223 | for (i = 0; i < source->Indices.size(); i += 3) |
224 | { | 224 | { |
225 | dest->Indices[i + 0] = (u16) source->Indices[i + 0]; | 225 | dest->Indices[i + 0] = (u16) source->Indices[i + 0]; |
226 | dest->Indices[i + 1] = (u16) source->Indices[i + 1]; | 226 | dest->Indices[i + 1] = (u16) source->Indices[i + 1]; |
227 | dest->Indices[i + 2] = (u16) source->Indices[i + 2]; | 227 | dest->Indices[i + 2] = (u16) source->Indices[i + 2]; |
228 | } | 228 | } |
229 | 229 | ||
230 | // fill in static vertex info | 230 | // fill in static vertex info |
231 | for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i) | 231 | for (i = 0; i!= (u32)source->MeshHeader.numVertices; ++i) |
232 | { | 232 | { |
233 | video::S3DVertex2TCoords &v = dest->Vertices[i]; | 233 | video::S3DVertex2TCoords &v = dest->Vertices[i]; |
234 | v.Color = 0xFFFFFFFF; | 234 | v.Color = 0xFFFFFFFF; |
235 | v.TCoords.X = source->Tex[i].u; | 235 | v.TCoords.X = source->Tex[i].u; |
236 | v.TCoords.Y = source->Tex[i].v; | 236 | v.TCoords.Y = source->Tex[i].v; |
237 | v.TCoords2.X = 0.f; | 237 | v.TCoords2.X = 0.f; |
238 | v.TCoords2.Y = 0.f; | 238 | v.TCoords2.Y = 0.f; |
239 | } | 239 | } |
240 | 240 | ||
241 | // load static texture | 241 | // load static texture |
242 | u32 pos = 0; | 242 | u32 pos = 0; |
243 | quake3::tTexArray textureArray; | 243 | quake3::tTexArray textureArray; |
244 | quake3::getTextures(textureArray, source->Shader, pos, fs, driver); | 244 | quake3::getTextures(textureArray, source->Shader, pos, fs, driver); |
245 | dest->Material.MaterialType = video::EMT_SOLID; | 245 | dest->Material.MaterialType = video::EMT_SOLID; |
246 | dest->Material.setTexture(0, textureArray[0]); | 246 | dest->Material.setTexture(0, textureArray[0]); |
247 | dest->Material.Lighting = false; | 247 | dest->Material.Lighting = false; |
248 | 248 | ||
249 | return dest; | 249 | return dest; |
250 | } | 250 | } |
251 | 251 | ||
252 | 252 | ||
253 | //! build final mesh's vertices from frames frameA and frameB with linear interpolation. | 253 | //! build final mesh's vertices from frames frameA and frameB with linear interpolation. |
254 | void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, | 254 | void CAnimatedMeshMD3::buildVertexArray(u32 frameA, u32 frameB, f32 interpolate, |
255 | const SMD3MeshBuffer* source, | 255 | const SMD3MeshBuffer* source, |
256 | SMeshBufferLightMap* dest) | 256 | SMeshBufferLightMap* dest) |
257 | { | 257 | { |
258 | const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; | 258 | const u32 frameOffsetA = frameA * source->MeshHeader.numVertices; |
259 | const u32 frameOffsetB = frameB * source->MeshHeader.numVertices; | 259 | const u32 frameOffsetB = frameB * source->MeshHeader.numVertices; |
260 | const f32 scale = (1.f/ 64.f); | 260 | const f32 scale = (1.f/ 64.f); |
261 | 261 | ||
262 | for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) | 262 | for (s32 i = 0; i != source->MeshHeader.numVertices; ++i) |
263 | { | 263 | { |
264 | video::S3DVertex2TCoords &v = dest->Vertices [ i ]; | 264 | video::S3DVertex2TCoords &v = dest->Vertices [ i ]; |
265 | 265 | ||
266 | const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ]; | 266 | const SMD3Vertex &vA = source->Vertices [ frameOffsetA + i ]; |
267 | const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; | 267 | const SMD3Vertex &vB = source->Vertices [ frameOffsetB + i ]; |
268 | 268 | ||
269 | // position | 269 | // position |
270 | v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0])); | 270 | v.Pos.X = scale * (vA.position[0] + interpolate * (vB.position[0] - vA.position[0])); |
271 | v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2])); | 271 | v.Pos.Y = scale * (vA.position[2] + interpolate * (vB.position[2] - vA.position[2])); |
272 | v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1])); | 272 | v.Pos.Z = scale * (vA.position[1] + interpolate * (vB.position[1] - vA.position[1])); |
273 | 273 | ||
274 | // normal | 274 | // normal |
275 | const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1])); | 275 | const core::vector3df nA(quake3::getMD3Normal(vA.normal[0], vA.normal[1])); |
276 | const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1])); | 276 | const core::vector3df nB(quake3::getMD3Normal(vB.normal[0], vB.normal[1])); |
277 | 277 | ||
278 | v.Normal.X = nA.X + interpolate * (nB.X - nA.X); | 278 | v.Normal.X = nA.X + interpolate * (nB.X - nA.X); |
279 | v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z); | 279 | v.Normal.Y = nA.Z + interpolate * (nB.Z - nA.Z); |
280 | v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y); | 280 | v.Normal.Z = nA.Y + interpolate * (nB.Y - nA.Y); |
281 | } | 281 | } |
282 | 282 | ||
283 | dest->recalculateBoundingBox(); | 283 | dest->recalculateBoundingBox(); |
284 | } | 284 | } |
285 | 285 | ||
286 | 286 | ||
287 | //! build final mesh's tag from frames frameA and frameB with linear interpolation. | 287 | //! build final mesh's tag from frames frameA and frameB with linear interpolation. |
288 | void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate) | 288 | void CAnimatedMeshMD3::buildTagArray(u32 frameA, u32 frameB, f32 interpolate) |
289 | { | 289 | { |
290 | const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags; | 290 | const u32 frameOffsetA = frameA * Mesh->MD3Header.numTags; |
291 | const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags; | 291 | const u32 frameOffsetB = frameB * Mesh->MD3Header.numTags; |
292 | 292 | ||
293 | for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i) | 293 | for (s32 i = 0; i != Mesh->MD3Header.numTags; ++i) |
294 | { | 294 | { |
295 | SMD3QuaternionTag &d = TagListIPol [ i ]; | 295 | SMD3QuaternionTag &d = TagListIPol [ i ]; |
296 | 296 | ||
297 | const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i]; | 297 | const SMD3QuaternionTag &qA = Mesh->TagList[ frameOffsetA + i]; |
298 | const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; | 298 | const SMD3QuaternionTag &qB = Mesh->TagList[ frameOffsetB + i]; |
299 | 299 | ||
300 | // rotation | 300 | // rotation |
301 | d.rotation.slerp(qA.rotation, qB.rotation, interpolate); | 301 | d.rotation.slerp(qA.rotation, qB.rotation, interpolate); |
302 | 302 | ||
303 | // position | 303 | // position |
304 | d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X); | 304 | d.position.X = qA.position.X + interpolate * (qB.position.X - qA.position.X); |
305 | d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y); | 305 | d.position.Y = qA.position.Y + interpolate * (qB.position.Y - qA.position.Y); |
306 | d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z); | 306 | d.position.Z = qA.position.Z + interpolate * (qB.position.Z - qA.position.Z); |
307 | } | 307 | } |
308 | } | 308 | } |
309 | 309 | ||
310 | 310 | ||
311 | /*! | 311 | /*! |
312 | loads a model | 312 | loads a model |
313 | */ | 313 | */ |
314 | bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file, | 314 | bool CAnimatedMeshMD3::loadModelFile(u32 modelIndex, io::IReadFile* file, |
315 | io::IFileSystem* fs, video::IVideoDriver* driver) | 315 | io::IFileSystem* fs, video::IVideoDriver* driver) |
316 | { | 316 | { |
317 | if (!file) | 317 | if (!file) |
318 | return false; | 318 | return false; |
319 | 319 | ||
320 | //! Check MD3Header | 320 | //! Check MD3Header |
321 | { | 321 | { |
322 | file->read(&Mesh->MD3Header, sizeof(SMD3Header)); | 322 | file->read(&Mesh->MD3Header, sizeof(SMD3Header)); |
323 | 323 | ||
324 | if (strncmp("IDP3", Mesh->MD3Header.headerID, 4)) | 324 | if (strncmp("IDP3", Mesh->MD3Header.headerID, 4)) |
325 | { | 325 | { |
326 | os::Printer::log("MD3 Loader: invalid header"); | 326 | os::Printer::log("MD3 Loader: invalid header"); |
327 | return false; | 327 | return false; |
328 | } | 328 | } |
329 | } | 329 | } |
330 | 330 | ||
331 | //! store model name | 331 | //! store model name |
332 | Mesh->Name = file->getFileName(); | 332 | Mesh->Name = file->getFileName(); |
333 | 333 | ||
334 | u32 i; | 334 | u32 i; |
335 | 335 | ||
336 | //! Frame Data (ignore) | 336 | //! Frame Data (ignore) |
337 | #if 0 | 337 | #if 0 |
338 | SMD3Frame frameImport; | 338 | SMD3Frame frameImport; |
339 | file->seek(Mesh->MD3Header.frameStart); | 339 | file->seek(Mesh->MD3Header.frameStart); |
340 | for (i = 0; i != Mesh->MD3Header.numFrames; ++i) | 340 | for (i = 0; i != Mesh->MD3Header.numFrames; ++i) |
341 | { | 341 | { |
342 | file->read(&frameImport, sizeof(frameImport)); | 342 | file->read(&frameImport, sizeof(frameImport)); |
343 | } | 343 | } |
344 | #endif | 344 | #endif |
345 | 345 | ||
346 | //! Tag Data | 346 | //! Tag Data |
347 | const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames; | 347 | const u32 totalTags = Mesh->MD3Header.numTags * Mesh->MD3Header.numFrames; |
348 | 348 | ||
349 | SMD3Tag import; | 349 | SMD3Tag import; |
350 | 350 | ||
351 | file->seek(Mesh->MD3Header.tagStart); | 351 | file->seek(Mesh->MD3Header.tagStart); |
352 | Mesh->TagList.set_used(totalTags); | 352 | Mesh->TagList.set_used(totalTags); |
353 | for (i = 0; i != totalTags; ++i) | 353 | for (i = 0; i != totalTags; ++i) |
354 | { | 354 | { |
355 | file->read(&import, sizeof(import)); | 355 | file->read(&import, sizeof(import)); |
356 | 356 | ||
357 | SMD3QuaternionTag &exp = Mesh->TagList[i]; | 357 | SMD3QuaternionTag &exp = Mesh->TagList[i]; |
358 | 358 | ||
359 | //! tag name | 359 | //! tag name |
360 | exp.Name = import.Name; | 360 | exp.Name = import.Name; |
361 | 361 | ||
362 | //! position | 362 | //! position |
363 | exp.position.X = import.position[0]; | 363 | exp.position.X = import.position[0]; |
364 | exp.position.Y = import.position[2]; | 364 | exp.position.Y = import.position[2]; |
365 | exp.position.Z = import.position[1]; | 365 | exp.position.Z = import.position[1]; |
366 | 366 | ||
367 | //! construct quaternion from a RH 3x3 Matrix | 367 | //! construct quaternion from a RH 3x3 Matrix |
368 | exp.rotation.set(import.rotationMatrix[7], | 368 | exp.rotation.set(import.rotationMatrix[7], |
369 | 0.f, | 369 | 0.f, |
370 | -import.rotationMatrix[6], | 370 | -import.rotationMatrix[6], |
371 | 1 + import.rotationMatrix[8]); | 371 | 1 + import.rotationMatrix[8]); |
372 | exp.rotation.normalize(); | 372 | exp.rotation.normalize(); |
373 | } | 373 | } |
374 | 374 | ||
375 | //! Meshes | 375 | //! Meshes |
376 | u32 offset = Mesh->MD3Header.tagEnd; | 376 | u32 offset = Mesh->MD3Header.tagEnd; |
377 | 377 | ||
378 | for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i) | 378 | for (i = 0; i != (u32)Mesh->MD3Header.numMeshes; ++i) |
379 | { | 379 | { |
380 | //! construct a new mesh buffer | 380 | //! construct a new mesh buffer |
381 | SMD3MeshBuffer * buf = new SMD3MeshBuffer(); | 381 | SMD3MeshBuffer * buf = new SMD3MeshBuffer(); |
382 | 382 | ||
383 | // !read mesh header info | 383 | // !read mesh header info |
384 | SMD3MeshHeader &meshHeader = buf->MeshHeader; | 384 | SMD3MeshHeader &meshHeader = buf->MeshHeader; |
385 | 385 | ||
386 | //! read mesh info | 386 | //! read mesh info |
387 | file->seek(offset); | 387 | file->seek(offset); |
388 | file->read(&meshHeader, sizeof(SMD3MeshHeader)); | 388 | file->read(&meshHeader, sizeof(SMD3MeshHeader)); |
389 | 389 | ||
390 | //! prepare memory | 390 | //! prepare memory |
391 | buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames); | 391 | buf->Vertices.set_used(meshHeader.numVertices * Mesh->MD3Header.numFrames); |
392 | buf->Indices.set_used(meshHeader.numTriangles * 3); | 392 | buf->Indices.set_used(meshHeader.numTriangles * 3); |
393 | buf->Tex.set_used(meshHeader.numVertices); | 393 | buf->Tex.set_used(meshHeader.numVertices); |
394 | 394 | ||
395 | //! read skins (shaders). should be 1 per meshbuffer | 395 | //! read skins (shaders). should be 1 per meshbuffer |
396 | SMD3Shader skin; | 396 | SMD3Shader skin; |
397 | file->seek(offset + buf->MeshHeader.offset_shaders); | 397 | file->seek(offset + buf->MeshHeader.offset_shaders); |
398 | for (s32 g = 0; g != buf->MeshHeader.numShader; ++g) | 398 | for (s32 g = 0; g != buf->MeshHeader.numShader; ++g) |
399 | { | 399 | { |
400 | file->read(&skin, sizeof(skin)); | 400 | file->read(&skin, sizeof(skin)); |
401 | 401 | ||
402 | io::path name; | 402 | io::path name; |
403 | cutFilenameExtension(name, skin.name); | 403 | cutFilenameExtension(name, skin.name); |
404 | name.replace('\\', '/'); | 404 | name.replace('\\', '/'); |
405 | buf->Shader = name; | 405 | buf->Shader = name; |
406 | } | 406 | } |
407 | 407 | ||
408 | //! read texture coordinates | 408 | //! read texture coordinates |
409 | file->seek(offset + buf->MeshHeader.offset_st); | 409 | file->seek(offset + buf->MeshHeader.offset_st); |
410 | file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord)); | 410 | file->read(buf->Tex.pointer(), buf->MeshHeader.numVertices * sizeof(SMD3TexCoord)); |
411 | 411 | ||
412 | //! read vertices | 412 | //! read vertices |
413 | file->seek(offset + meshHeader.vertexStart); | 413 | file->seek(offset + meshHeader.vertexStart); |
414 | file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex)); | 414 | file->read(buf->Vertices.pointer(), Mesh->MD3Header.numFrames * meshHeader.numVertices * sizeof(SMD3Vertex)); |
415 | 415 | ||
416 | //! read indices | 416 | //! read indices |
417 | file->seek(offset + meshHeader.offset_triangles); | 417 | file->seek(offset + meshHeader.offset_triangles); |
418 | file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face)); | 418 | file->read(buf->Indices.pointer(), meshHeader.numTriangles * sizeof(SMD3Face)); |
419 | 419 | ||
420 | //! store meshBuffer | 420 | //! store meshBuffer |
421 | Mesh->Buffer.push_back(buf); | 421 | Mesh->Buffer.push_back(buf); |
422 | 422 | ||
423 | offset += meshHeader.offset_end; | 423 | offset += meshHeader.offset_end; |
424 | } | 424 | } |
425 | 425 | ||
426 | // Init Mesh Interpolation | 426 | // Init Mesh Interpolation |
427 | for (i = 0; i != Mesh->Buffer.size(); ++i) | 427 | for (i = 0; i != Mesh->Buffer.size(); ++i) |
428 | { | 428 | { |
429 | IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver); | 429 | IMeshBuffer * buffer = createMeshBuffer(Mesh->Buffer[i], fs, driver); |
430 | MeshIPol->addMeshBuffer(buffer); | 430 | MeshIPol->addMeshBuffer(buffer); |
431 | buffer->drop(); | 431 | buffer->drop(); |
432 | } | 432 | } |
433 | MeshIPol->recalculateBoundingBox(); | 433 | MeshIPol->recalculateBoundingBox(); |
434 | 434 | ||
435 | // Init Tag Interpolation | 435 | // Init Tag Interpolation |
436 | for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i) | 436 | for (i = 0; i != (u32)Mesh->MD3Header.numTags; ++i) |
437 | { | 437 | { |
438 | TagListIPol.push_back(Mesh->TagList[i]); | 438 | TagListIPol.push_back(Mesh->TagList[i]); |
439 | } | 439 | } |
440 | 440 | ||
441 | return true; | 441 | return true; |
442 | } | 442 | } |
443 | 443 | ||
444 | 444 | ||
445 | SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh() | 445 | SMD3Mesh * CAnimatedMeshMD3::getOriginalMesh() |
446 | { | 446 | { |
447 | return Mesh; | 447 | return Mesh; |
448 | } | 448 | } |
449 | 449 | ||
450 | 450 | ||
451 | //! Returns an axis aligned bounding box | 451 | //! Returns an axis aligned bounding box |
452 | const core::aabbox3d<f32>& CAnimatedMeshMD3::getBoundingBox() const | 452 | const core::aabbox3d<f32>& CAnimatedMeshMD3::getBoundingBox() const |
453 | { | 453 | { |
454 | return MeshIPol->BoundingBox; | 454 | return MeshIPol->BoundingBox; |
455 | } | 455 | } |
456 | 456 | ||
457 | 457 | ||
458 | //! Returns the type of the animated mesh. | 458 | //! Returns the type of the animated mesh. |
459 | E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const | 459 | E_ANIMATED_MESH_TYPE CAnimatedMeshMD3::getMeshType() const |
460 | { | 460 | { |
461 | return EAMT_MD3; | 461 | return EAMT_MD3; |
462 | } | 462 | } |
463 | 463 | ||
464 | 464 | ||
465 | } // end namespace scene | 465 | } // end namespace scene |
466 | } // end namespace irr | 466 | } // end namespace irr |
467 | 467 | ||
468 | #endif // _IRR_COMPILE_WITH_MD3_LOADER_ | 468 | #endif // _IRR_COMPILE_WITH_MD3_LOADER_ |