diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp | 2258 |
1 files changed, 1129 insertions, 1129 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp index a9f1276..bded2b2 100644 --- a/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp +++ b/libraries/irrlicht-1.8/source/Irrlicht/CAnimatedMeshSceneNode.cpp | |||
@@ -1,1129 +1,1129 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | 1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt |
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 "CAnimatedMeshSceneNode.h" | 5 | #include "CAnimatedMeshSceneNode.h" |
6 | #include "IVideoDriver.h" | 6 | #include "IVideoDriver.h" |
7 | #include "ISceneManager.h" | 7 | #include "ISceneManager.h" |
8 | #include "S3DVertex.h" | 8 | #include "S3DVertex.h" |
9 | #include "os.h" | 9 | #include "os.h" |
10 | #include "CShadowVolumeSceneNode.h" | 10 | #include "CShadowVolumeSceneNode.h" |
11 | #include "IAnimatedMeshMD3.h" | 11 | #include "IAnimatedMeshMD3.h" |
12 | #include "CSkinnedMesh.h" | 12 | #include "CSkinnedMesh.h" |
13 | #include "IDummyTransformationSceneNode.h" | 13 | #include "IDummyTransformationSceneNode.h" |
14 | #include "IBoneSceneNode.h" | 14 | #include "IBoneSceneNode.h" |
15 | #include "IMaterialRenderer.h" | 15 | #include "IMaterialRenderer.h" |
16 | #include "IMesh.h" | 16 | #include "IMesh.h" |
17 | #include "IMeshCache.h" | 17 | #include "IMeshCache.h" |
18 | #include "IAnimatedMesh.h" | 18 | #include "IAnimatedMesh.h" |
19 | #include "quaternion.h" | 19 | #include "quaternion.h" |
20 | 20 | ||
21 | 21 | ||
22 | namespace irr | 22 | namespace irr |
23 | { | 23 | { |
24 | namespace scene | 24 | namespace scene |
25 | { | 25 | { |
26 | 26 | ||
27 | 27 | ||
28 | //! constructor | 28 | //! constructor |
29 | CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, | 29 | CAnimatedMeshSceneNode::CAnimatedMeshSceneNode(IAnimatedMesh* mesh, |
30 | ISceneNode* parent, ISceneManager* mgr, s32 id, | 30 | ISceneNode* parent, ISceneManager* mgr, s32 id, |
31 | const core::vector3df& position, | 31 | const core::vector3df& position, |
32 | const core::vector3df& rotation, | 32 | const core::vector3df& rotation, |
33 | const core::vector3df& scale) | 33 | const core::vector3df& scale) |
34 | : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), | 34 | : IAnimatedMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), |
35 | StartFrame(0), EndFrame(0), FramesPerSecond(0.025f), | 35 | StartFrame(0), EndFrame(0), FramesPerSecond(0.025f), |
36 | CurrentFrameNr(0.f), LastTimeMs(0), | 36 | CurrentFrameNr(0.f), LastTimeMs(0), |
37 | TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), | 37 | TransitionTime(0), Transiting(0.f), TransitingBlend(0.f), |
38 | JointMode(EJUOR_NONE), JointsUsed(false), | 38 | JointMode(EJUOR_NONE), JointsUsed(false), |
39 | Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false), | 39 | Looping(true), ReadOnlyMaterials(false), RenderFromIdentity(false), |
40 | LoopCallBack(0), PassCount(0), Shadow(0), MD3Special(0) | 40 | LoopCallBack(0), PassCount(0), Shadow(0), MD3Special(0) |
41 | { | 41 | { |
42 | #ifdef _DEBUG | 42 | #ifdef _DEBUG |
43 | setDebugName("CAnimatedMeshSceneNode"); | 43 | setDebugName("CAnimatedMeshSceneNode"); |
44 | #endif | 44 | #endif |
45 | 45 | ||
46 | setMesh(mesh); | 46 | setMesh(mesh); |
47 | } | 47 | } |
48 | 48 | ||
49 | 49 | ||
50 | //! destructor | 50 | //! destructor |
51 | CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() | 51 | CAnimatedMeshSceneNode::~CAnimatedMeshSceneNode() |
52 | { | 52 | { |
53 | if (MD3Special) | 53 | if (MD3Special) |
54 | MD3Special->drop(); | 54 | MD3Special->drop(); |
55 | 55 | ||
56 | if (Mesh) | 56 | if (Mesh) |
57 | Mesh->drop(); | 57 | Mesh->drop(); |
58 | 58 | ||
59 | if (Shadow) | 59 | if (Shadow) |
60 | Shadow->drop(); | 60 | Shadow->drop(); |
61 | 61 | ||
62 | if (LoopCallBack) | 62 | if (LoopCallBack) |
63 | LoopCallBack->drop(); | 63 | LoopCallBack->drop(); |
64 | } | 64 | } |
65 | 65 | ||
66 | 66 | ||
67 | //! Sets the current frame. From now on the animation is played from this frame. | 67 | //! Sets the current frame. From now on the animation is played from this frame. |
68 | void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame) | 68 | void CAnimatedMeshSceneNode::setCurrentFrame(f32 frame) |
69 | { | 69 | { |
70 | // if you pass an out of range value, we just clamp it | 70 | // if you pass an out of range value, we just clamp it |
71 | CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame ); | 71 | CurrentFrameNr = core::clamp ( frame, (f32)StartFrame, (f32)EndFrame ); |
72 | 72 | ||
73 | beginTransition(); //transit to this frame if enabled | 73 | beginTransition(); //transit to this frame if enabled |
74 | } | 74 | } |
75 | 75 | ||
76 | 76 | ||
77 | //! Returns the currently displayed frame number. | 77 | //! Returns the currently displayed frame number. |
78 | f32 CAnimatedMeshSceneNode::getFrameNr() const | 78 | f32 CAnimatedMeshSceneNode::getFrameNr() const |
79 | { | 79 | { |
80 | return CurrentFrameNr; | 80 | return CurrentFrameNr; |
81 | } | 81 | } |
82 | 82 | ||
83 | 83 | ||
84 | //! Get CurrentFrameNr and update transiting settings | 84 | //! Get CurrentFrameNr and update transiting settings |
85 | void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) | 85 | void CAnimatedMeshSceneNode::buildFrameNr(u32 timeMs) |
86 | { | 86 | { |
87 | if (Transiting!=0.f) | 87 | if (Transiting!=0.f) |
88 | { | 88 | { |
89 | TransitingBlend += (f32)(timeMs) * Transiting; | 89 | TransitingBlend += (f32)(timeMs) * Transiting; |
90 | if (TransitingBlend > 1.f) | 90 | if (TransitingBlend > 1.f) |
91 | { | 91 | { |
92 | Transiting=0.f; | 92 | Transiting=0.f; |
93 | TransitingBlend=0.f; | 93 | TransitingBlend=0.f; |
94 | } | 94 | } |
95 | } | 95 | } |
96 | 96 | ||
97 | if ((StartFrame==EndFrame)) | 97 | if ((StartFrame==EndFrame)) |
98 | { | 98 | { |
99 | CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes | 99 | CurrentFrameNr = (f32)StartFrame; //Support for non animated meshes |
100 | } | 100 | } |
101 | else if (Looping) | 101 | else if (Looping) |
102 | { | 102 | { |
103 | // play animation looped | 103 | // play animation looped |
104 | CurrentFrameNr += timeMs * FramesPerSecond; | 104 | CurrentFrameNr += timeMs * FramesPerSecond; |
105 | 105 | ||
106 | // We have no interpolation between EndFrame and StartFrame, | 106 | // We have no interpolation between EndFrame and StartFrame, |
107 | // the last frame must be identical to first one with our current solution. | 107 | // the last frame must be identical to first one with our current solution. |
108 | if (FramesPerSecond > 0.f) //forwards... | 108 | if (FramesPerSecond > 0.f) //forwards... |
109 | { | 109 | { |
110 | if (CurrentFrameNr > EndFrame) | 110 | if (CurrentFrameNr > EndFrame) |
111 | CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); | 111 | CurrentFrameNr = StartFrame + fmod(CurrentFrameNr - StartFrame, (f32)(EndFrame-StartFrame)); |
112 | } | 112 | } |
113 | else //backwards... | 113 | else //backwards... |
114 | { | 114 | { |
115 | if (CurrentFrameNr < StartFrame) | 115 | if (CurrentFrameNr < StartFrame) |
116 | CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); | 116 | CurrentFrameNr = EndFrame - fmod(EndFrame - CurrentFrameNr, (f32)(EndFrame-StartFrame)); |
117 | } | 117 | } |
118 | } | 118 | } |
119 | else | 119 | else |
120 | { | 120 | { |
121 | // play animation non looped | 121 | // play animation non looped |
122 | 122 | ||
123 | CurrentFrameNr += timeMs * FramesPerSecond; | 123 | CurrentFrameNr += timeMs * FramesPerSecond; |
124 | if (FramesPerSecond > 0.f) //forwards... | 124 | if (FramesPerSecond > 0.f) //forwards... |
125 | { | 125 | { |
126 | if (CurrentFrameNr > (f32)EndFrame) | 126 | if (CurrentFrameNr > (f32)EndFrame) |
127 | { | 127 | { |
128 | CurrentFrameNr = (f32)EndFrame; | 128 | CurrentFrameNr = (f32)EndFrame; |
129 | if (LoopCallBack) | 129 | if (LoopCallBack) |
130 | LoopCallBack->OnAnimationEnd(this); | 130 | LoopCallBack->OnAnimationEnd(this); |
131 | } | 131 | } |
132 | } | 132 | } |
133 | else //backwards... | 133 | else //backwards... |
134 | { | 134 | { |
135 | if (CurrentFrameNr < (f32)StartFrame) | 135 | if (CurrentFrameNr < (f32)StartFrame) |
136 | { | 136 | { |
137 | CurrentFrameNr = (f32)StartFrame; | 137 | CurrentFrameNr = (f32)StartFrame; |
138 | if (LoopCallBack) | 138 | if (LoopCallBack) |
139 | LoopCallBack->OnAnimationEnd(this); | 139 | LoopCallBack->OnAnimationEnd(this); |
140 | } | 140 | } |
141 | } | 141 | } |
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | 145 | ||
146 | void CAnimatedMeshSceneNode::OnRegisterSceneNode() | 146 | void CAnimatedMeshSceneNode::OnRegisterSceneNode() |
147 | { | 147 | { |
148 | if (IsVisible) | 148 | if (IsVisible) |
149 | { | 149 | { |
150 | // because this node supports rendering of mixed mode meshes consisting of | 150 | // because this node supports rendering of mixed mode meshes consisting of |
151 | // transparent and solid material at the same time, we need to go through all | 151 | // transparent and solid material at the same time, we need to go through all |
152 | // materials, check of what type they are and register this node for the right | 152 | // materials, check of what type they are and register this node for the right |
153 | // render pass according to that. | 153 | // render pass according to that. |
154 | 154 | ||
155 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | 155 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); |
156 | 156 | ||
157 | PassCount = 0; | 157 | PassCount = 0; |
158 | int transparentCount = 0; | 158 | int transparentCount = 0; |
159 | int solidCount = 0; | 159 | int solidCount = 0; |
160 | 160 | ||
161 | // count transparent and solid materials in this scene node | 161 | // count transparent and solid materials in this scene node |
162 | for (u32 i=0; i<Materials.size(); ++i) | 162 | for (u32 i=0; i<Materials.size(); ++i) |
163 | { | 163 | { |
164 | video::IMaterialRenderer* rnd = | 164 | video::IMaterialRenderer* rnd = |
165 | driver->getMaterialRenderer(Materials[i].MaterialType); | 165 | driver->getMaterialRenderer(Materials[i].MaterialType); |
166 | 166 | ||
167 | if (rnd && rnd->isTransparent()) | 167 | if (rnd && rnd->isTransparent()) |
168 | ++transparentCount; | 168 | ++transparentCount; |
169 | else | 169 | else |
170 | ++solidCount; | 170 | ++solidCount; |
171 | 171 | ||
172 | if (solidCount && transparentCount) | 172 | if (solidCount && transparentCount) |
173 | break; | 173 | break; |
174 | } | 174 | } |
175 | 175 | ||
176 | // register according to material types counted | 176 | // register according to material types counted |
177 | 177 | ||
178 | if (solidCount) | 178 | if (solidCount) |
179 | SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); | 179 | SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); |
180 | 180 | ||
181 | if (transparentCount) | 181 | if (transparentCount) |
182 | SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); | 182 | SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); |
183 | 183 | ||
184 | ISceneNode::OnRegisterSceneNode(); | 184 | ISceneNode::OnRegisterSceneNode(); |
185 | } | 185 | } |
186 | } | 186 | } |
187 | 187 | ||
188 | IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() | 188 | IMesh * CAnimatedMeshSceneNode::getMeshForCurrentFrame() |
189 | { | 189 | { |
190 | if(Mesh->getMeshType() != EAMT_SKINNED) | 190 | if(Mesh->getMeshType() != EAMT_SKINNED) |
191 | { | 191 | { |
192 | s32 frameNr = (s32) getFrameNr(); | 192 | s32 frameNr = (s32) getFrameNr(); |
193 | s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f); | 193 | s32 frameBlend = (s32) (core::fract ( getFrameNr() ) * 1000.f); |
194 | return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame); | 194 | return Mesh->getMesh(frameNr, frameBlend, StartFrame, EndFrame); |
195 | } | 195 | } |
196 | else | 196 | else |
197 | { | 197 | { |
198 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 198 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
199 | return 0; | 199 | return 0; |
200 | #else | 200 | #else |
201 | 201 | ||
202 | // As multiple scene nodes may be sharing the same skinned mesh, we have to | 202 | // As multiple scene nodes may be sharing the same skinned mesh, we have to |
203 | // re-animate it every frame to ensure that this node gets the mesh that it needs. | 203 | // re-animate it every frame to ensure that this node gets the mesh that it needs. |
204 | 204 | ||
205 | CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh); | 205 | CSkinnedMesh* skinnedMesh = reinterpret_cast<CSkinnedMesh*>(Mesh); |
206 | 206 | ||
207 | if (JointMode == EJUOR_CONTROL)//write to mesh | 207 | if (JointMode == EJUOR_CONTROL)//write to mesh |
208 | skinnedMesh->transferJointsToMesh(JointChildSceneNodes); | 208 | skinnedMesh->transferJointsToMesh(JointChildSceneNodes); |
209 | else | 209 | else |
210 | skinnedMesh->animateMesh(getFrameNr(), 1.0f); | 210 | skinnedMesh->animateMesh(getFrameNr(), 1.0f); |
211 | 211 | ||
212 | // Update the skinned mesh for the current joint transforms. | 212 | // Update the skinned mesh for the current joint transforms. |
213 | skinnedMesh->skinMesh(); | 213 | skinnedMesh->skinMesh(); |
214 | 214 | ||
215 | if (JointMode == EJUOR_READ)//read from mesh | 215 | if (JointMode == EJUOR_READ)//read from mesh |
216 | { | 216 | { |
217 | skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes); | 217 | skinnedMesh->recoverJointsFromMesh(JointChildSceneNodes); |
218 | 218 | ||
219 | //---slow--- | 219 | //---slow--- |
220 | for (u32 n=0;n<JointChildSceneNodes.size();++n) | 220 | for (u32 n=0;n<JointChildSceneNodes.size();++n) |
221 | if (JointChildSceneNodes[n]->getParent()==this) | 221 | if (JointChildSceneNodes[n]->getParent()==this) |
222 | { | 222 | { |
223 | JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option | 223 | JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option |
224 | } | 224 | } |
225 | } | 225 | } |
226 | 226 | ||
227 | if(JointMode == EJUOR_CONTROL) | 227 | if(JointMode == EJUOR_CONTROL) |
228 | { | 228 | { |
229 | // For meshes other than EJUOR_CONTROL, this is done by calling animateMesh() | 229 | // For meshes other than EJUOR_CONTROL, this is done by calling animateMesh() |
230 | skinnedMesh->updateBoundingBox(); | 230 | skinnedMesh->updateBoundingBox(); |
231 | } | 231 | } |
232 | 232 | ||
233 | return skinnedMesh; | 233 | return skinnedMesh; |
234 | #endif | 234 | #endif |
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | 238 | ||
239 | //! OnAnimate() is called just before rendering the whole scene. | 239 | //! OnAnimate() is called just before rendering the whole scene. |
240 | void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) | 240 | void CAnimatedMeshSceneNode::OnAnimate(u32 timeMs) |
241 | { | 241 | { |
242 | if (LastTimeMs==0) // first frame | 242 | if (LastTimeMs==0) // first frame |
243 | { | 243 | { |
244 | LastTimeMs = timeMs; | 244 | LastTimeMs = timeMs; |
245 | } | 245 | } |
246 | 246 | ||
247 | // set CurrentFrameNr | 247 | // set CurrentFrameNr |
248 | buildFrameNr(timeMs-LastTimeMs); | 248 | buildFrameNr(timeMs-LastTimeMs); |
249 | 249 | ||
250 | // update bbox | 250 | // update bbox |
251 | if (Mesh) | 251 | if (Mesh) |
252 | { | 252 | { |
253 | scene::IMesh * mesh = getMeshForCurrentFrame(); | 253 | scene::IMesh * mesh = getMeshForCurrentFrame(); |
254 | 254 | ||
255 | if (mesh) | 255 | if (mesh) |
256 | Box = mesh->getBoundingBox(); | 256 | Box = mesh->getBoundingBox(); |
257 | } | 257 | } |
258 | LastTimeMs = timeMs; | 258 | LastTimeMs = timeMs; |
259 | 259 | ||
260 | IAnimatedMeshSceneNode::OnAnimate(timeMs); | 260 | IAnimatedMeshSceneNode::OnAnimate(timeMs); |
261 | } | 261 | } |
262 | 262 | ||
263 | 263 | ||
264 | //! renders the node. | 264 | //! renders the node. |
265 | void CAnimatedMeshSceneNode::render() | 265 | void CAnimatedMeshSceneNode::render() |
266 | { | 266 | { |
267 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | 267 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); |
268 | 268 | ||
269 | if (!Mesh || !driver) | 269 | if (!Mesh || !driver) |
270 | return; | 270 | return; |
271 | 271 | ||
272 | 272 | ||
273 | bool isTransparentPass = | 273 | bool isTransparentPass = |
274 | SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; | 274 | SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; |
275 | 275 | ||
276 | ++PassCount; | 276 | ++PassCount; |
277 | 277 | ||
278 | scene::IMesh* m = getMeshForCurrentFrame(); | 278 | scene::IMesh* m = getMeshForCurrentFrame(); |
279 | 279 | ||
280 | if(m) | 280 | if(m) |
281 | { | 281 | { |
282 | Box = m->getBoundingBox(); | 282 | Box = m->getBoundingBox(); |
283 | } | 283 | } |
284 | else | 284 | else |
285 | { | 285 | { |
286 | #ifdef _DEBUG | 286 | #ifdef _DEBUG |
287 | os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING); | 287 | os::Printer::log("Animated Mesh returned no mesh to render.", Mesh->getDebugName(), ELL_WARNING); |
288 | #endif | 288 | #endif |
289 | } | 289 | } |
290 | 290 | ||
291 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); | 291 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); |
292 | 292 | ||
293 | if (Shadow && PassCount==1) | 293 | if (Shadow && PassCount==1) |
294 | Shadow->updateShadowVolumes(); | 294 | Shadow->updateShadowVolumes(); |
295 | 295 | ||
296 | // for debug purposes only: | 296 | // for debug purposes only: |
297 | 297 | ||
298 | bool renderMeshes = true; | 298 | bool renderMeshes = true; |
299 | video::SMaterial mat; | 299 | video::SMaterial mat; |
300 | if (DebugDataVisible && PassCount==1) | 300 | if (DebugDataVisible && PassCount==1) |
301 | { | 301 | { |
302 | // overwrite half transparency | 302 | // overwrite half transparency |
303 | if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) | 303 | if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY) |
304 | { | 304 | { |
305 | 305 | ||
306 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) | 306 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) |
307 | { | 307 | { |
308 | scene::IMeshBuffer* mb = m->getMeshBuffer(i); | 308 | scene::IMeshBuffer* mb = m->getMeshBuffer(i); |
309 | mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; | 309 | mat = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; |
310 | mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; | 310 | mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; |
311 | if (RenderFromIdentity) | 311 | if (RenderFromIdentity) |
312 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); | 312 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); |
313 | else if (Mesh->getMeshType() == EAMT_SKINNED) | 313 | else if (Mesh->getMeshType() == EAMT_SKINNED) |
314 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); | 314 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); |
315 | 315 | ||
316 | driver->setMaterial(mat); | 316 | driver->setMaterial(mat); |
317 | driver->drawMeshBuffer(mb); | 317 | driver->drawMeshBuffer(mb); |
318 | } | 318 | } |
319 | renderMeshes = false; | 319 | renderMeshes = false; |
320 | } | 320 | } |
321 | } | 321 | } |
322 | 322 | ||
323 | // render original meshes | 323 | // render original meshes |
324 | if (renderMeshes) | 324 | if (renderMeshes) |
325 | { | 325 | { |
326 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) | 326 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) |
327 | { | 327 | { |
328 | video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType); | 328 | video::IMaterialRenderer* rnd = driver->getMaterialRenderer(Materials[i].MaterialType); |
329 | bool transparent = (rnd && rnd->isTransparent()); | 329 | bool transparent = (rnd && rnd->isTransparent()); |
330 | 330 | ||
331 | // only render transparent buffer if this is the transparent render pass | 331 | // only render transparent buffer if this is the transparent render pass |
332 | // and solid only in solid pass | 332 | // and solid only in solid pass |
333 | if (transparent == isTransparentPass) | 333 | if (transparent == isTransparentPass) |
334 | { | 334 | { |
335 | scene::IMeshBuffer* mb = m->getMeshBuffer(i); | 335 | scene::IMeshBuffer* mb = m->getMeshBuffer(i); |
336 | const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; | 336 | const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; |
337 | if (RenderFromIdentity) | 337 | if (RenderFromIdentity) |
338 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); | 338 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); |
339 | else if (Mesh->getMeshType() == EAMT_SKINNED) | 339 | else if (Mesh->getMeshType() == EAMT_SKINNED) |
340 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); | 340 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); |
341 | 341 | ||
342 | driver->setMaterial(material); | 342 | driver->setMaterial(material); |
343 | driver->drawMeshBuffer(mb); | 343 | driver->drawMeshBuffer(mb); |
344 | } | 344 | } |
345 | } | 345 | } |
346 | } | 346 | } |
347 | 347 | ||
348 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); | 348 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); |
349 | 349 | ||
350 | // for debug purposes only: | 350 | // for debug purposes only: |
351 | if (DebugDataVisible && PassCount==1) | 351 | if (DebugDataVisible && PassCount==1) |
352 | { | 352 | { |
353 | video::SMaterial debug_mat; | 353 | video::SMaterial debug_mat; |
354 | debug_mat.Lighting = false; | 354 | debug_mat.Lighting = false; |
355 | debug_mat.AntiAliasing=0; | 355 | debug_mat.AntiAliasing=0; |
356 | driver->setMaterial(debug_mat); | 356 | driver->setMaterial(debug_mat); |
357 | // show normals | 357 | // show normals |
358 | if (DebugDataVisible & scene::EDS_NORMALS) | 358 | if (DebugDataVisible & scene::EDS_NORMALS) |
359 | { | 359 | { |
360 | const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); | 360 | const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH); |
361 | const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); | 361 | const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR); |
362 | const u32 count = m->getMeshBufferCount(); | 362 | const u32 count = m->getMeshBufferCount(); |
363 | 363 | ||
364 | // draw normals | 364 | // draw normals |
365 | for (u32 g=0; g < count; ++g) | 365 | for (u32 g=0; g < count; ++g) |
366 | { | 366 | { |
367 | driver->drawMeshBufferNormals(m->getMeshBuffer(g), debugNormalLength, debugNormalColor); | 367 | driver->drawMeshBufferNormals(m->getMeshBuffer(g), debugNormalLength, debugNormalColor); |
368 | } | 368 | } |
369 | } | 369 | } |
370 | 370 | ||
371 | debug_mat.ZBuffer = video::ECFN_NEVER; | 371 | debug_mat.ZBuffer = video::ECFN_NEVER; |
372 | debug_mat.Lighting = false; | 372 | debug_mat.Lighting = false; |
373 | driver->setMaterial(debug_mat); | 373 | driver->setMaterial(debug_mat); |
374 | 374 | ||
375 | if (DebugDataVisible & scene::EDS_BBOX) | 375 | if (DebugDataVisible & scene::EDS_BBOX) |
376 | driver->draw3DBox(Box, video::SColor(255,255,255,255)); | 376 | driver->draw3DBox(Box, video::SColor(255,255,255,255)); |
377 | 377 | ||
378 | // show bounding box | 378 | // show bounding box |
379 | if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) | 379 | if (DebugDataVisible & scene::EDS_BBOX_BUFFERS) |
380 | { | 380 | { |
381 | for (u32 g=0; g< m->getMeshBufferCount(); ++g) | 381 | for (u32 g=0; g< m->getMeshBufferCount(); ++g) |
382 | { | 382 | { |
383 | const IMeshBuffer* mb = m->getMeshBuffer(g); | 383 | const IMeshBuffer* mb = m->getMeshBuffer(g); |
384 | 384 | ||
385 | if (Mesh->getMeshType() == EAMT_SKINNED) | 385 | if (Mesh->getMeshType() == EAMT_SKINNED) |
386 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); | 386 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); |
387 | driver->draw3DBox(mb->getBoundingBox(), video::SColor(255,190,128,128)); | 387 | driver->draw3DBox(mb->getBoundingBox(), video::SColor(255,190,128,128)); |
388 | } | 388 | } |
389 | } | 389 | } |
390 | 390 | ||
391 | // show skeleton | 391 | // show skeleton |
392 | if (DebugDataVisible & scene::EDS_SKELETON) | 392 | if (DebugDataVisible & scene::EDS_SKELETON) |
393 | { | 393 | { |
394 | if (Mesh->getMeshType() == EAMT_SKINNED) | 394 | if (Mesh->getMeshType() == EAMT_SKINNED) |
395 | { | 395 | { |
396 | // draw skeleton | 396 | // draw skeleton |
397 | 397 | ||
398 | for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g) | 398 | for (u32 g=0; g < ((ISkinnedMesh*)Mesh)->getAllJoints().size(); ++g) |
399 | { | 399 | { |
400 | ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g]; | 400 | ISkinnedMesh::SJoint *joint=((ISkinnedMesh*)Mesh)->getAllJoints()[g]; |
401 | 401 | ||
402 | for (u32 n=0;n<joint->Children.size();++n) | 402 | for (u32 n=0;n<joint->Children.size();++n) |
403 | { | 403 | { |
404 | driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(), | 404 | driver->draw3DLine(joint->GlobalAnimatedMatrix.getTranslation(), |
405 | joint->Children[n]->GlobalAnimatedMatrix.getTranslation(), | 405 | joint->Children[n]->GlobalAnimatedMatrix.getTranslation(), |
406 | video::SColor(255,51,66,255)); | 406 | video::SColor(255,51,66,255)); |
407 | } | 407 | } |
408 | } | 408 | } |
409 | } | 409 | } |
410 | 410 | ||
411 | // show tag for quake3 models | 411 | // show tag for quake3 models |
412 | if (Mesh->getMeshType() == EAMT_MD3) | 412 | if (Mesh->getMeshType() == EAMT_MD3) |
413 | { | 413 | { |
414 | IAnimatedMesh * arrow = | 414 | IAnimatedMesh * arrow = |
415 | SceneManager->addArrowMesh ( | 415 | SceneManager->addArrowMesh ( |
416 | "__tag_show", | 416 | "__tag_show", |
417 | 0xFF0000FF, 0xFF000088, | 417 | 0xFF0000FF, 0xFF000088, |
418 | 4, 8, 5.f, 4.f, 0.5f, | 418 | 4, 8, 5.f, 4.f, 0.5f, |
419 | 1.f); | 419 | 1.f); |
420 | if (!arrow) | 420 | if (!arrow) |
421 | { | 421 | { |
422 | arrow = SceneManager->getMesh ( "__tag_show" ); | 422 | arrow = SceneManager->getMesh ( "__tag_show" ); |
423 | } | 423 | } |
424 | IMesh *arrowMesh = arrow->getMesh(0); | 424 | IMesh *arrowMesh = arrow->getMesh(0); |
425 | 425 | ||
426 | core::matrix4 matr; | 426 | core::matrix4 matr; |
427 | 427 | ||
428 | SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( | 428 | SMD3QuaternionTagList *taglist = ((IAnimatedMeshMD3*)Mesh)->getTagList( |
429 | (s32)getFrameNr(), 255, | 429 | (s32)getFrameNr(), 255, |
430 | getStartFrame(), getEndFrame()); | 430 | getStartFrame(), getEndFrame()); |
431 | if (taglist) | 431 | if (taglist) |
432 | { | 432 | { |
433 | for ( u32 ts = 0; ts != taglist->size(); ++ts ) | 433 | for ( u32 ts = 0; ts != taglist->size(); ++ts ) |
434 | { | 434 | { |
435 | (*taglist)[ts].setto(matr); | 435 | (*taglist)[ts].setto(matr); |
436 | 436 | ||
437 | driver->setTransform(video::ETS_WORLD, matr ); | 437 | driver->setTransform(video::ETS_WORLD, matr ); |
438 | 438 | ||
439 | for ( u32 a = 0; a != arrowMesh->getMeshBufferCount(); ++a ) | 439 | for ( u32 a = 0; a != arrowMesh->getMeshBufferCount(); ++a ) |
440 | driver->drawMeshBuffer(arrowMesh->getMeshBuffer(a)); | 440 | driver->drawMeshBuffer(arrowMesh->getMeshBuffer(a)); |
441 | } | 441 | } |
442 | } | 442 | } |
443 | } | 443 | } |
444 | } | 444 | } |
445 | 445 | ||
446 | // show mesh | 446 | // show mesh |
447 | if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) | 447 | if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY) |
448 | { | 448 | { |
449 | debug_mat.Lighting = false; | 449 | debug_mat.Lighting = false; |
450 | debug_mat.Wireframe = true; | 450 | debug_mat.Wireframe = true; |
451 | debug_mat.ZBuffer = video::ECFN_NEVER; | 451 | debug_mat.ZBuffer = video::ECFN_NEVER; |
452 | driver->setMaterial(debug_mat); | 452 | driver->setMaterial(debug_mat); |
453 | 453 | ||
454 | for (u32 g=0; g<m->getMeshBufferCount(); ++g) | 454 | for (u32 g=0; g<m->getMeshBufferCount(); ++g) |
455 | { | 455 | { |
456 | const IMeshBuffer* mb = m->getMeshBuffer(g); | 456 | const IMeshBuffer* mb = m->getMeshBuffer(g); |
457 | if (RenderFromIdentity) | 457 | if (RenderFromIdentity) |
458 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); | 458 | driver->setTransform(video::ETS_WORLD, core::IdentityMatrix ); |
459 | else if (Mesh->getMeshType() == EAMT_SKINNED) | 459 | else if (Mesh->getMeshType() == EAMT_SKINNED) |
460 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); | 460 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((SSkinMeshBuffer*)mb)->Transformation); |
461 | driver->drawMeshBuffer(mb); | 461 | driver->drawMeshBuffer(mb); |
462 | } | 462 | } |
463 | } | 463 | } |
464 | } | 464 | } |
465 | } | 465 | } |
466 | 466 | ||
467 | 467 | ||
468 | //! Returns the current start frame number. | 468 | //! Returns the current start frame number. |
469 | s32 CAnimatedMeshSceneNode::getStartFrame() const | 469 | s32 CAnimatedMeshSceneNode::getStartFrame() const |
470 | { | 470 | { |
471 | return StartFrame; | 471 | return StartFrame; |
472 | } | 472 | } |
473 | 473 | ||
474 | 474 | ||
475 | //! Returns the current start frame number. | 475 | //! Returns the current start frame number. |
476 | s32 CAnimatedMeshSceneNode::getEndFrame() const | 476 | s32 CAnimatedMeshSceneNode::getEndFrame() const |
477 | { | 477 | { |
478 | return EndFrame; | 478 | return EndFrame; |
479 | } | 479 | } |
480 | 480 | ||
481 | 481 | ||
482 | //! sets the frames between the animation is looped. | 482 | //! sets the frames between the animation is looped. |
483 | //! the default is 0 - MaximalFrameCount of the mesh. | 483 | //! the default is 0 - MaximalFrameCount of the mesh. |
484 | bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end) | 484 | bool CAnimatedMeshSceneNode::setFrameLoop(s32 begin, s32 end) |
485 | { | 485 | { |
486 | const s32 maxFrameCount = Mesh->getFrameCount() - 1; | 486 | const s32 maxFrameCount = Mesh->getFrameCount() - 1; |
487 | if (end < begin) | 487 | if (end < begin) |
488 | { | 488 | { |
489 | StartFrame = core::s32_clamp(end, 0, maxFrameCount); | 489 | StartFrame = core::s32_clamp(end, 0, maxFrameCount); |
490 | EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount); | 490 | EndFrame = core::s32_clamp(begin, StartFrame, maxFrameCount); |
491 | } | 491 | } |
492 | else | 492 | else |
493 | { | 493 | { |
494 | StartFrame = core::s32_clamp(begin, 0, maxFrameCount); | 494 | StartFrame = core::s32_clamp(begin, 0, maxFrameCount); |
495 | EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount); | 495 | EndFrame = core::s32_clamp(end, StartFrame, maxFrameCount); |
496 | } | 496 | } |
497 | if (FramesPerSecond < 0) | 497 | if (FramesPerSecond < 0) |
498 | setCurrentFrame((f32)EndFrame); | 498 | setCurrentFrame((f32)EndFrame); |
499 | else | 499 | else |
500 | setCurrentFrame((f32)StartFrame); | 500 | setCurrentFrame((f32)StartFrame); |
501 | 501 | ||
502 | return true; | 502 | return true; |
503 | } | 503 | } |
504 | 504 | ||
505 | 505 | ||
506 | //! sets the speed with witch the animation is played | 506 | //! sets the speed with witch the animation is played |
507 | void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond) | 507 | void CAnimatedMeshSceneNode::setAnimationSpeed(f32 framesPerSecond) |
508 | { | 508 | { |
509 | FramesPerSecond = framesPerSecond * 0.001f; | 509 | FramesPerSecond = framesPerSecond * 0.001f; |
510 | } | 510 | } |
511 | 511 | ||
512 | 512 | ||
513 | f32 CAnimatedMeshSceneNode::getAnimationSpeed() const | 513 | f32 CAnimatedMeshSceneNode::getAnimationSpeed() const |
514 | { | 514 | { |
515 | return FramesPerSecond * 1000.f; | 515 | return FramesPerSecond * 1000.f; |
516 | } | 516 | } |
517 | 517 | ||
518 | 518 | ||
519 | //! returns the axis aligned bounding box of this node | 519 | //! returns the axis aligned bounding box of this node |
520 | const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const | 520 | const core::aabbox3d<f32>& CAnimatedMeshSceneNode::getBoundingBox() const |
521 | { | 521 | { |
522 | return Box; | 522 | return Box; |
523 | } | 523 | } |
524 | 524 | ||
525 | 525 | ||
526 | //! returns the material based on the zero based index i. To get the amount | 526 | //! returns the material based on the zero based index i. To get the amount |
527 | //! of materials used by this scene node, use getMaterialCount(). | 527 | //! of materials used by this scene node, use getMaterialCount(). |
528 | //! This function is needed for inserting the node into the scene hirachy on a | 528 | //! This function is needed for inserting the node into the scene hirachy on a |
529 | //! optimal position for minimizing renderstate changes, but can also be used | 529 | //! optimal position for minimizing renderstate changes, but can also be used |
530 | //! to directly modify the material of a scene node. | 530 | //! to directly modify the material of a scene node. |
531 | video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i) | 531 | video::SMaterial& CAnimatedMeshSceneNode::getMaterial(u32 i) |
532 | { | 532 | { |
533 | if (i >= Materials.size()) | 533 | if (i >= Materials.size()) |
534 | return ISceneNode::getMaterial(i); | 534 | return ISceneNode::getMaterial(i); |
535 | 535 | ||
536 | return Materials[i]; | 536 | return Materials[i]; |
537 | } | 537 | } |
538 | 538 | ||
539 | 539 | ||
540 | 540 | ||
541 | //! returns amount of materials used by this scene node. | 541 | //! returns amount of materials used by this scene node. |
542 | u32 CAnimatedMeshSceneNode::getMaterialCount() const | 542 | u32 CAnimatedMeshSceneNode::getMaterialCount() const |
543 | { | 543 | { |
544 | return Materials.size(); | 544 | return Materials.size(); |
545 | } | 545 | } |
546 | 546 | ||
547 | 547 | ||
548 | //! Creates shadow volume scene node as child of this node | 548 | //! Creates shadow volume scene node as child of this node |
549 | //! and returns a pointer to it. | 549 | //! and returns a pointer to it. |
550 | IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode( | 550 | IShadowVolumeSceneNode* CAnimatedMeshSceneNode::addShadowVolumeSceneNode( |
551 | const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) | 551 | const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) |
552 | { | 552 | { |
553 | if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) | 553 | if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) |
554 | return 0; | 554 | return 0; |
555 | 555 | ||
556 | if (!shadowMesh) | 556 | if (!shadowMesh) |
557 | shadowMesh = Mesh; // if null is given, use the mesh of node | 557 | shadowMesh = Mesh; // if null is given, use the mesh of node |
558 | 558 | ||
559 | if (Shadow) | 559 | if (Shadow) |
560 | Shadow->drop(); | 560 | Shadow->drop(); |
561 | 561 | ||
562 | Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); | 562 | Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); |
563 | return Shadow; | 563 | return Shadow; |
564 | } | 564 | } |
565 | 565 | ||
566 | //! Returns a pointer to a child node, which has the same transformation as | 566 | //! Returns a pointer to a child node, which has the same transformation as |
567 | //! the corresponding joint, if the mesh in this scene node is a skinned mesh. | 567 | //! the corresponding joint, if the mesh in this scene node is a skinned mesh. |
568 | IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName) | 568 | IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(const c8* jointName) |
569 | { | 569 | { |
570 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 570 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
571 | os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); | 571 | os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); |
572 | return 0; | 572 | return 0; |
573 | #else | 573 | #else |
574 | 574 | ||
575 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) | 575 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) |
576 | { | 576 | { |
577 | os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); | 577 | os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); |
578 | return 0; | 578 | return 0; |
579 | } | 579 | } |
580 | 580 | ||
581 | checkJoints(); | 581 | checkJoints(); |
582 | 582 | ||
583 | ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; | 583 | ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; |
584 | 584 | ||
585 | const s32 number = skinnedMesh->getJointNumber(jointName); | 585 | const s32 number = skinnedMesh->getJointNumber(jointName); |
586 | 586 | ||
587 | if (number == -1) | 587 | if (number == -1) |
588 | { | 588 | { |
589 | os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG); | 589 | os::Printer::log("Joint with specified name not found in skinned mesh", jointName, ELL_DEBUG); |
590 | return 0; | 590 | return 0; |
591 | } | 591 | } |
592 | 592 | ||
593 | if ((s32)JointChildSceneNodes.size() <= number) | 593 | if ((s32)JointChildSceneNodes.size() <= number) |
594 | { | 594 | { |
595 | os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING); | 595 | os::Printer::log("Joint was found in mesh, but is not loaded into node", jointName, ELL_WARNING); |
596 | return 0; | 596 | return 0; |
597 | } | 597 | } |
598 | 598 | ||
599 | return JointChildSceneNodes[number]; | 599 | return JointChildSceneNodes[number]; |
600 | #endif | 600 | #endif |
601 | } | 601 | } |
602 | 602 | ||
603 | 603 | ||
604 | 604 | ||
605 | //! Returns a pointer to a child node, which has the same transformation as | 605 | //! Returns a pointer to a child node, which has the same transformation as |
606 | //! the corresponding joint, if the mesh in this scene node is a skinned mesh. | 606 | //! the corresponding joint, if the mesh in this scene node is a skinned mesh. |
607 | IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID) | 607 | IBoneSceneNode* CAnimatedMeshSceneNode::getJointNode(u32 jointID) |
608 | { | 608 | { |
609 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 609 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
610 | os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); | 610 | os::Printer::log("Compiled without _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_", ELL_WARNING); |
611 | return 0; | 611 | return 0; |
612 | #else | 612 | #else |
613 | 613 | ||
614 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) | 614 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) |
615 | { | 615 | { |
616 | os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); | 616 | os::Printer::log("No mesh, or mesh not of skinned mesh type", ELL_WARNING); |
617 | return 0; | 617 | return 0; |
618 | } | 618 | } |
619 | 619 | ||
620 | checkJoints(); | 620 | checkJoints(); |
621 | 621 | ||
622 | if (JointChildSceneNodes.size() <= jointID) | 622 | if (JointChildSceneNodes.size() <= jointID) |
623 | { | 623 | { |
624 | os::Printer::log("Joint not loaded into node", ELL_WARNING); | 624 | os::Printer::log("Joint not loaded into node", ELL_WARNING); |
625 | return 0; | 625 | return 0; |
626 | } | 626 | } |
627 | 627 | ||
628 | return JointChildSceneNodes[jointID]; | 628 | return JointChildSceneNodes[jointID]; |
629 | #endif | 629 | #endif |
630 | } | 630 | } |
631 | 631 | ||
632 | //! Gets joint count. | 632 | //! Gets joint count. |
633 | u32 CAnimatedMeshSceneNode::getJointCount() const | 633 | u32 CAnimatedMeshSceneNode::getJointCount() const |
634 | { | 634 | { |
635 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 635 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
636 | return 0; | 636 | return 0; |
637 | #else | 637 | #else |
638 | 638 | ||
639 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) | 639 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) |
640 | return 0; | 640 | return 0; |
641 | 641 | ||
642 | ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; | 642 | ISkinnedMesh *skinnedMesh=(ISkinnedMesh*)Mesh; |
643 | 643 | ||
644 | return skinnedMesh->getJointCount(); | 644 | return skinnedMesh->getJointCount(); |
645 | #endif | 645 | #endif |
646 | } | 646 | } |
647 | 647 | ||
648 | 648 | ||
649 | //! Returns a pointer to a child node, which has the same transformation as | 649 | //! Returns a pointer to a child node, which has the same transformation as |
650 | //! the corresponding joint, if the mesh in this scene node is a ms3d mesh. | 650 | //! the corresponding joint, if the mesh in this scene node is a ms3d mesh. |
651 | ISceneNode* CAnimatedMeshSceneNode::getMS3DJointNode(const c8* jointName) | 651 | ISceneNode* CAnimatedMeshSceneNode::getMS3DJointNode(const c8* jointName) |
652 | { | 652 | { |
653 | return getJointNode(jointName); | 653 | return getJointNode(jointName); |
654 | } | 654 | } |
655 | 655 | ||
656 | 656 | ||
657 | //! Returns a pointer to a child node, which has the same transformation as | 657 | //! Returns a pointer to a child node, which has the same transformation as |
658 | //! the corresponding joint, if the mesh in this scene node is a .x mesh. | 658 | //! the corresponding joint, if the mesh in this scene node is a .x mesh. |
659 | ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName) | 659 | ISceneNode* CAnimatedMeshSceneNode::getXJointNode(const c8* jointName) |
660 | { | 660 | { |
661 | return getJointNode(jointName); | 661 | return getJointNode(jointName); |
662 | } | 662 | } |
663 | 663 | ||
664 | //! Removes a child from this scene node. | 664 | //! Removes a child from this scene node. |
665 | //! Implemented here, to be able to remove the shadow properly, if there is one, | 665 | //! Implemented here, to be able to remove the shadow properly, if there is one, |
666 | //! or to remove attached childs. | 666 | //! or to remove attached childs. |
667 | bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child) | 667 | bool CAnimatedMeshSceneNode::removeChild(ISceneNode* child) |
668 | { | 668 | { |
669 | if (child && Shadow == child) | 669 | if (child && Shadow == child) |
670 | { | 670 | { |
671 | Shadow->drop(); | 671 | Shadow->drop(); |
672 | Shadow = 0; | 672 | Shadow = 0; |
673 | } | 673 | } |
674 | 674 | ||
675 | if (ISceneNode::removeChild(child)) | 675 | if (ISceneNode::removeChild(child)) |
676 | { | 676 | { |
677 | if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created | 677 | if (JointsUsed) //stop weird bugs caused while changing parents as the joints are being created |
678 | { | 678 | { |
679 | for (u32 i=0; i<JointChildSceneNodes.size(); ++i) | 679 | for (u32 i=0; i<JointChildSceneNodes.size(); ++i) |
680 | { | 680 | { |
681 | if (JointChildSceneNodes[i] == child) | 681 | if (JointChildSceneNodes[i] == child) |
682 | { | 682 | { |
683 | JointChildSceneNodes[i] = 0; //remove link to child | 683 | JointChildSceneNodes[i] = 0; //remove link to child |
684 | break; | 684 | break; |
685 | } | 685 | } |
686 | } | 686 | } |
687 | } | 687 | } |
688 | return true; | 688 | return true; |
689 | } | 689 | } |
690 | 690 | ||
691 | return false; | 691 | return false; |
692 | } | 692 | } |
693 | 693 | ||
694 | 694 | ||
695 | //! Starts a MD2 animation. | 695 | //! Starts a MD2 animation. |
696 | bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim) | 696 | bool CAnimatedMeshSceneNode::setMD2Animation(EMD2_ANIMATION_TYPE anim) |
697 | { | 697 | { |
698 | if (!Mesh || Mesh->getMeshType() != EAMT_MD2) | 698 | if (!Mesh || Mesh->getMeshType() != EAMT_MD2) |
699 | return false; | 699 | return false; |
700 | 700 | ||
701 | IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; | 701 | IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; |
702 | 702 | ||
703 | s32 begin, end, speed; | 703 | s32 begin, end, speed; |
704 | md->getFrameLoop(anim, begin, end, speed); | 704 | md->getFrameLoop(anim, begin, end, speed); |
705 | 705 | ||
706 | setAnimationSpeed( f32(speed) ); | 706 | setAnimationSpeed( f32(speed) ); |
707 | setFrameLoop(begin, end); | 707 | setFrameLoop(begin, end); |
708 | return true; | 708 | return true; |
709 | } | 709 | } |
710 | 710 | ||
711 | 711 | ||
712 | //! Starts a special MD2 animation. | 712 | //! Starts a special MD2 animation. |
713 | bool CAnimatedMeshSceneNode::setMD2Animation(const c8* animationName) | 713 | bool CAnimatedMeshSceneNode::setMD2Animation(const c8* animationName) |
714 | { | 714 | { |
715 | if (!Mesh || Mesh->getMeshType() != EAMT_MD2) | 715 | if (!Mesh || Mesh->getMeshType() != EAMT_MD2) |
716 | return false; | 716 | return false; |
717 | 717 | ||
718 | IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; | 718 | IAnimatedMeshMD2* md = (IAnimatedMeshMD2*)Mesh; |
719 | 719 | ||
720 | s32 begin, end, speed; | 720 | s32 begin, end, speed; |
721 | if (!md->getFrameLoop(animationName, begin, end, speed)) | 721 | if (!md->getFrameLoop(animationName, begin, end, speed)) |
722 | return false; | 722 | return false; |
723 | 723 | ||
724 | setAnimationSpeed( (f32)speed ); | 724 | setAnimationSpeed( (f32)speed ); |
725 | setFrameLoop(begin, end); | 725 | setFrameLoop(begin, end); |
726 | return true; | 726 | return true; |
727 | } | 727 | } |
728 | 728 | ||
729 | 729 | ||
730 | //! Sets looping mode which is on by default. If set to false, | 730 | //! Sets looping mode which is on by default. If set to false, |
731 | //! animations will not be looped. | 731 | //! animations will not be looped. |
732 | void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped) | 732 | void CAnimatedMeshSceneNode::setLoopMode(bool playAnimationLooped) |
733 | { | 733 | { |
734 | Looping = playAnimationLooped; | 734 | Looping = playAnimationLooped; |
735 | } | 735 | } |
736 | 736 | ||
737 | //! returns the current loop mode | 737 | //! returns the current loop mode |
738 | bool CAnimatedMeshSceneNode::getLoopMode() const | 738 | bool CAnimatedMeshSceneNode::getLoopMode() const |
739 | { | 739 | { |
740 | return Looping; | 740 | return Looping; |
741 | } | 741 | } |
742 | 742 | ||
743 | 743 | ||
744 | //! Sets a callback interface which will be called if an animation | 744 | //! Sets a callback interface which will be called if an animation |
745 | //! playback has ended. Set this to 0 to disable the callback again. | 745 | //! playback has ended. Set this to 0 to disable the callback again. |
746 | void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback) | 746 | void CAnimatedMeshSceneNode::setAnimationEndCallback(IAnimationEndCallBack* callback) |
747 | { | 747 | { |
748 | if (callback == LoopCallBack) | 748 | if (callback == LoopCallBack) |
749 | return; | 749 | return; |
750 | 750 | ||
751 | if (LoopCallBack) | 751 | if (LoopCallBack) |
752 | LoopCallBack->drop(); | 752 | LoopCallBack->drop(); |
753 | 753 | ||
754 | LoopCallBack = callback; | 754 | LoopCallBack = callback; |
755 | 755 | ||
756 | if (LoopCallBack) | 756 | if (LoopCallBack) |
757 | LoopCallBack->grab(); | 757 | LoopCallBack->grab(); |
758 | } | 758 | } |
759 | 759 | ||
760 | 760 | ||
761 | //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. | 761 | //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style. |
762 | void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly) | 762 | void CAnimatedMeshSceneNode::setReadOnlyMaterials(bool readonly) |
763 | { | 763 | { |
764 | ReadOnlyMaterials = readonly; | 764 | ReadOnlyMaterials = readonly; |
765 | } | 765 | } |
766 | 766 | ||
767 | 767 | ||
768 | //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style | 768 | //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style |
769 | bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const | 769 | bool CAnimatedMeshSceneNode::isReadOnlyMaterials() const |
770 | { | 770 | { |
771 | return ReadOnlyMaterials; | 771 | return ReadOnlyMaterials; |
772 | } | 772 | } |
773 | 773 | ||
774 | 774 | ||
775 | //! Writes attributes of the scene node. | 775 | //! Writes attributes of the scene node. |
776 | void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const | 776 | void CAnimatedMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const |
777 | { | 777 | { |
778 | IAnimatedMeshSceneNode::serializeAttributes(out, options); | 778 | IAnimatedMeshSceneNode::serializeAttributes(out, options); |
779 | 779 | ||
780 | if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename) | 780 | if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename) |
781 | { | 781 | { |
782 | const io::path path = SceneManager->getFileSystem()->getRelativeFilename( | 782 | const io::path path = SceneManager->getFileSystem()->getRelativeFilename( |
783 | SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()), | 783 | SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()), |
784 | options->Filename); | 784 | options->Filename); |
785 | out->addString("Mesh", path.c_str()); | 785 | out->addString("Mesh", path.c_str()); |
786 | } | 786 | } |
787 | else | 787 | else |
788 | out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); | 788 | out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str()); |
789 | out->addBool("Looping", Looping); | 789 | out->addBool("Looping", Looping); |
790 | out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); | 790 | out->addBool("ReadOnlyMaterials", ReadOnlyMaterials); |
791 | out->addFloat("FramesPerSecond", FramesPerSecond); | 791 | out->addFloat("FramesPerSecond", FramesPerSecond); |
792 | out->addInt("StartFrame", StartFrame); | 792 | out->addInt("StartFrame", StartFrame); |
793 | out->addInt("EndFrame", EndFrame); | 793 | out->addInt("EndFrame", EndFrame); |
794 | } | 794 | } |
795 | 795 | ||
796 | 796 | ||
797 | //! Reads attributes of the scene node. | 797 | //! Reads attributes of the scene node. |
798 | void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) | 798 | void CAnimatedMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) |
799 | { | 799 | { |
800 | IAnimatedMeshSceneNode::deserializeAttributes(in, options); | 800 | IAnimatedMeshSceneNode::deserializeAttributes(in, options); |
801 | 801 | ||
802 | io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); | 802 | io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh); |
803 | io::path newMeshStr = in->getAttributeAsString("Mesh"); | 803 | io::path newMeshStr = in->getAttributeAsString("Mesh"); |
804 | 804 | ||
805 | Looping = in->getAttributeAsBool("Looping"); | 805 | Looping = in->getAttributeAsBool("Looping"); |
806 | ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); | 806 | ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials"); |
807 | FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond"); | 807 | FramesPerSecond = in->getAttributeAsFloat("FramesPerSecond"); |
808 | StartFrame = in->getAttributeAsInt("StartFrame"); | 808 | StartFrame = in->getAttributeAsInt("StartFrame"); |
809 | EndFrame = in->getAttributeAsInt("EndFrame"); | 809 | EndFrame = in->getAttributeAsInt("EndFrame"); |
810 | 810 | ||
811 | if (newMeshStr != "" && oldMeshStr != newMeshStr) | 811 | if (newMeshStr != "" && oldMeshStr != newMeshStr) |
812 | { | 812 | { |
813 | IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); | 813 | IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); |
814 | 814 | ||
815 | if (newAnimatedMesh) | 815 | if (newAnimatedMesh) |
816 | setMesh(newAnimatedMesh); | 816 | setMesh(newAnimatedMesh); |
817 | } | 817 | } |
818 | 818 | ||
819 | // TODO: read animation names instead of frame begin and ends | 819 | // TODO: read animation names instead of frame begin and ends |
820 | } | 820 | } |
821 | 821 | ||
822 | 822 | ||
823 | //! Sets a new mesh | 823 | //! Sets a new mesh |
824 | void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) | 824 | void CAnimatedMeshSceneNode::setMesh(IAnimatedMesh* mesh) |
825 | { | 825 | { |
826 | if (!mesh) | 826 | if (!mesh) |
827 | return; // won't set null mesh | 827 | return; // won't set null mesh |
828 | 828 | ||
829 | if (Mesh != mesh) | 829 | if (Mesh != mesh) |
830 | { | 830 | { |
831 | if (Mesh) | 831 | if (Mesh) |
832 | Mesh->drop(); | 832 | Mesh->drop(); |
833 | 833 | ||
834 | Mesh = mesh; | 834 | Mesh = mesh; |
835 | 835 | ||
836 | // grab the mesh (it's non-null!) | 836 | // grab the mesh (it's non-null!) |
837 | Mesh->grab(); | 837 | Mesh->grab(); |
838 | } | 838 | } |
839 | 839 | ||
840 | // get materials and bounding box | 840 | // get materials and bounding box |
841 | Box = Mesh->getBoundingBox(); | 841 | Box = Mesh->getBoundingBox(); |
842 | 842 | ||
843 | IMesh* m = Mesh->getMesh(0,0); | 843 | IMesh* m = Mesh->getMesh(0,0); |
844 | if (m) | 844 | if (m) |
845 | { | 845 | { |
846 | Materials.clear(); | 846 | Materials.clear(); |
847 | Materials.reallocate(m->getMeshBufferCount()); | 847 | Materials.reallocate(m->getMeshBufferCount()); |
848 | 848 | ||
849 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) | 849 | for (u32 i=0; i<m->getMeshBufferCount(); ++i) |
850 | { | 850 | { |
851 | IMeshBuffer* mb = m->getMeshBuffer(i); | 851 | IMeshBuffer* mb = m->getMeshBuffer(i); |
852 | if (mb) | 852 | if (mb) |
853 | Materials.push_back(mb->getMaterial()); | 853 | Materials.push_back(mb->getMaterial()); |
854 | else | 854 | else |
855 | Materials.push_back(video::SMaterial()); | 855 | Materials.push_back(video::SMaterial()); |
856 | } | 856 | } |
857 | } | 857 | } |
858 | 858 | ||
859 | // clean up joint nodes | 859 | // clean up joint nodes |
860 | if (JointsUsed) | 860 | if (JointsUsed) |
861 | { | 861 | { |
862 | JointsUsed=false; | 862 | JointsUsed=false; |
863 | checkJoints(); | 863 | checkJoints(); |
864 | } | 864 | } |
865 | 865 | ||
866 | // get start and begin time | 866 | // get start and begin time |
867 | // setAnimationSpeed(Mesh->getAnimationSpeed()); | 867 | // setAnimationSpeed(Mesh->getAnimationSpeed()); |
868 | setFrameLoop(0, Mesh->getFrameCount()); | 868 | setFrameLoop(0, Mesh->getFrameCount()); |
869 | } | 869 | } |
870 | 870 | ||
871 | 871 | ||
872 | // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, | 872 | // returns the absolute transformation for a special MD3 Tag if the mesh is a md3 mesh, |
873 | // or the absolutetransformation if it's a normal scenenode | 873 | // or the absolutetransformation if it's a normal scenenode |
874 | const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname) | 874 | const SMD3QuaternionTag* CAnimatedMeshSceneNode::getMD3TagTransformation(const core::stringc& tagname) |
875 | { | 875 | { |
876 | return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0; | 876 | return MD3Special ? MD3Special->AbsoluteTagList.get(tagname) : 0; |
877 | } | 877 | } |
878 | 878 | ||
879 | 879 | ||
880 | //! updates the absolute position based on the relative and the parents position | 880 | //! updates the absolute position based on the relative and the parents position |
881 | void CAnimatedMeshSceneNode::updateAbsolutePosition() | 881 | void CAnimatedMeshSceneNode::updateAbsolutePosition() |
882 | { | 882 | { |
883 | IAnimatedMeshSceneNode::updateAbsolutePosition(); | 883 | IAnimatedMeshSceneNode::updateAbsolutePosition(); |
884 | 884 | ||
885 | if (!Mesh || Mesh->getMeshType() != EAMT_MD3) | 885 | if (!Mesh || Mesh->getMeshType() != EAMT_MD3) |
886 | return; | 886 | return; |
887 | 887 | ||
888 | SMD3QuaternionTagList *taglist; | 888 | SMD3QuaternionTagList *taglist; |
889 | taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () ); | 889 | taglist = ( (IAnimatedMeshMD3*) Mesh )->getTagList ( (s32)getFrameNr(),255,getStartFrame (),getEndFrame () ); |
890 | if (taglist) | 890 | if (taglist) |
891 | { | 891 | { |
892 | if (!MD3Special) | 892 | if (!MD3Special) |
893 | { | 893 | { |
894 | MD3Special = new SMD3Special(); | 894 | MD3Special = new SMD3Special(); |
895 | } | 895 | } |
896 | 896 | ||
897 | SMD3QuaternionTag parent ( MD3Special->Tagname ); | 897 | SMD3QuaternionTag parent ( MD3Special->Tagname ); |
898 | if (Parent && Parent->getType() == ESNT_ANIMATED_MESH) | 898 | if (Parent && Parent->getType() == ESNT_ANIMATED_MESH) |
899 | { | 899 | { |
900 | const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation | 900 | const SMD3QuaternionTag * p = ((IAnimatedMeshSceneNode*) Parent)->getMD3TagTransformation |
901 | ( MD3Special->Tagname ); | 901 | ( MD3Special->Tagname ); |
902 | 902 | ||
903 | if (p) | 903 | if (p) |
904 | parent = *p; | 904 | parent = *p; |
905 | } | 905 | } |
906 | 906 | ||
907 | SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation ); | 907 | SMD3QuaternionTag relative( RelativeTranslation, RelativeRotation ); |
908 | 908 | ||
909 | MD3Special->AbsoluteTagList.set_used ( taglist->size () ); | 909 | MD3Special->AbsoluteTagList.set_used ( taglist->size () ); |
910 | for ( u32 i=0; i!= taglist->size (); ++i ) | 910 | for ( u32 i=0; i!= taglist->size (); ++i ) |
911 | { | 911 | { |
912 | MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; | 912 | MD3Special->AbsoluteTagList[i].position = parent.position + (*taglist)[i].position + relative.position; |
913 | MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; | 913 | MD3Special->AbsoluteTagList[i].rotation = parent.rotation * (*taglist)[i].rotation * relative.rotation; |
914 | } | 914 | } |
915 | } | 915 | } |
916 | } | 916 | } |
917 | 917 | ||
918 | //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set) | 918 | //! Set the joint update mode (0-unused, 1-get joints only, 2-set joints only, 3-move and set) |
919 | void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode) | 919 | void CAnimatedMeshSceneNode::setJointMode(E_JOINT_UPDATE_ON_RENDER mode) |
920 | { | 920 | { |
921 | checkJoints(); | 921 | checkJoints(); |
922 | JointMode=mode; | 922 | JointMode=mode; |
923 | } | 923 | } |
924 | 924 | ||
925 | //! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2) | 925 | //! Sets the transition time in seconds (note: This needs to enable joints, and setJointmode maybe set to 2) |
926 | //! you must call animateJoints(), or the mesh will not animate | 926 | //! you must call animateJoints(), or the mesh will not animate |
927 | void CAnimatedMeshSceneNode::setTransitionTime(f32 time) | 927 | void CAnimatedMeshSceneNode::setTransitionTime(f32 time) |
928 | { | 928 | { |
929 | const u32 ttime = (u32)core::floor32(time*1000.0f); | 929 | const u32 ttime = (u32)core::floor32(time*1000.0f); |
930 | if (TransitionTime==ttime) | 930 | if (TransitionTime==ttime) |
931 | return; | 931 | return; |
932 | TransitionTime = ttime; | 932 | TransitionTime = ttime; |
933 | if (ttime != 0) | 933 | if (ttime != 0) |
934 | setJointMode(EJUOR_CONTROL); | 934 | setJointMode(EJUOR_CONTROL); |
935 | else | 935 | else |
936 | setJointMode(EJUOR_NONE); | 936 | setJointMode(EJUOR_NONE); |
937 | } | 937 | } |
938 | 938 | ||
939 | 939 | ||
940 | //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected) | 940 | //! render mesh ignoring its transformation. Used with ragdolls. (culling is unaffected) |
941 | void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable) | 941 | void CAnimatedMeshSceneNode::setRenderFromIdentity(bool enable) |
942 | { | 942 | { |
943 | RenderFromIdentity=enable; | 943 | RenderFromIdentity=enable; |
944 | } | 944 | } |
945 | 945 | ||
946 | 946 | ||
947 | //! updates the joint positions of this mesh | 947 | //! updates the joint positions of this mesh |
948 | void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) | 948 | void CAnimatedMeshSceneNode::animateJoints(bool CalculateAbsolutePositions) |
949 | { | 949 | { |
950 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 950 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
951 | return; | 951 | return; |
952 | #else | 952 | #else |
953 | if (Mesh && Mesh->getMeshType() == EAMT_SKINNED ) | 953 | if (Mesh && Mesh->getMeshType() == EAMT_SKINNED ) |
954 | { | 954 | { |
955 | checkJoints(); | 955 | checkJoints(); |
956 | const f32 frame = getFrameNr(); //old? | 956 | const f32 frame = getFrameNr(); //old? |
957 | 957 | ||
958 | CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh); | 958 | CSkinnedMesh* skinnedMesh=reinterpret_cast<CSkinnedMesh*>(Mesh); |
959 | 959 | ||
960 | skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes ); | 960 | skinnedMesh->transferOnlyJointsHintsToMesh( JointChildSceneNodes ); |
961 | skinnedMesh->animateMesh(frame, 1.0f); | 961 | skinnedMesh->animateMesh(frame, 1.0f); |
962 | skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes); | 962 | skinnedMesh->recoverJointsFromMesh( JointChildSceneNodes); |
963 | 963 | ||
964 | //----------------------------------------- | 964 | //----------------------------------------- |
965 | // Transition | 965 | // Transition |
966 | //----------------------------------------- | 966 | //----------------------------------------- |
967 | 967 | ||
968 | if (Transiting != 0.f) | 968 | if (Transiting != 0.f) |
969 | { | 969 | { |
970 | // Init additional matrices | 970 | // Init additional matrices |
971 | if (PretransitingSave.size()<JointChildSceneNodes.size()) | 971 | if (PretransitingSave.size()<JointChildSceneNodes.size()) |
972 | { | 972 | { |
973 | for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n) | 973 | for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n) |
974 | PretransitingSave.push_back(core::matrix4()); | 974 | PretransitingSave.push_back(core::matrix4()); |
975 | } | 975 | } |
976 | 976 | ||
977 | for (u32 n=0; n<JointChildSceneNodes.size(); ++n) | 977 | for (u32 n=0; n<JointChildSceneNodes.size(); ++n) |
978 | { | 978 | { |
979 | //------Position------ | 979 | //------Position------ |
980 | 980 | ||
981 | JointChildSceneNodes[n]->setPosition( | 981 | JointChildSceneNodes[n]->setPosition( |
982 | core::lerp( | 982 | core::lerp( |
983 | PretransitingSave[n].getTranslation(), | 983 | PretransitingSave[n].getTranslation(), |
984 | JointChildSceneNodes[n]->getPosition(), | 984 | JointChildSceneNodes[n]->getPosition(), |
985 | TransitingBlend)); | 985 | TransitingBlend)); |
986 | 986 | ||
987 | //------Rotation------ | 987 | //------Rotation------ |
988 | 988 | ||
989 | //Code is slow, needs to be fixed up | 989 | //Code is slow, needs to be fixed up |
990 | 990 | ||
991 | const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD); | 991 | const core::quaternion RotationStart(PretransitingSave[n].getRotationDegrees()*core::DEGTORAD); |
992 | const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD); | 992 | const core::quaternion RotationEnd(JointChildSceneNodes[n]->getRotation()*core::DEGTORAD); |
993 | 993 | ||
994 | core::quaternion QRotation; | 994 | core::quaternion QRotation; |
995 | QRotation.slerp(RotationStart, RotationEnd, TransitingBlend); | 995 | QRotation.slerp(RotationStart, RotationEnd, TransitingBlend); |
996 | 996 | ||
997 | core::vector3df tmpVector; | 997 | core::vector3df tmpVector; |
998 | QRotation.toEuler(tmpVector); | 998 | QRotation.toEuler(tmpVector); |
999 | tmpVector*=core::RADTODEG; //convert from radians back to degrees | 999 | tmpVector*=core::RADTODEG; //convert from radians back to degrees |
1000 | JointChildSceneNodes[n]->setRotation( tmpVector ); | 1000 | JointChildSceneNodes[n]->setRotation( tmpVector ); |
1001 | 1001 | ||
1002 | //------Scale------ | 1002 | //------Scale------ |
1003 | 1003 | ||
1004 | //JointChildSceneNodes[n]->setScale( | 1004 | //JointChildSceneNodes[n]->setScale( |
1005 | // core::lerp( | 1005 | // core::lerp( |
1006 | // PretransitingSave[n].getScale(), | 1006 | // PretransitingSave[n].getScale(), |
1007 | // JointChildSceneNodes[n]->getScale(), | 1007 | // JointChildSceneNodes[n]->getScale(), |
1008 | // TransitingBlend)); | 1008 | // TransitingBlend)); |
1009 | } | 1009 | } |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | if (CalculateAbsolutePositions) | 1012 | if (CalculateAbsolutePositions) |
1013 | { | 1013 | { |
1014 | //---slow--- | 1014 | //---slow--- |
1015 | for (u32 n=0;n<JointChildSceneNodes.size();++n) | 1015 | for (u32 n=0;n<JointChildSceneNodes.size();++n) |
1016 | { | 1016 | { |
1017 | if (JointChildSceneNodes[n]->getParent()==this) | 1017 | if (JointChildSceneNodes[n]->getParent()==this) |
1018 | { | 1018 | { |
1019 | JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option | 1019 | JointChildSceneNodes[n]->updateAbsolutePositionOfAllChildren(); //temp, should be an option |
1020 | } | 1020 | } |
1021 | } | 1021 | } |
1022 | } | 1022 | } |
1023 | } | 1023 | } |
1024 | #endif | 1024 | #endif |
1025 | } | 1025 | } |
1026 | 1026 | ||
1027 | /*! | 1027 | /*! |
1028 | */ | 1028 | */ |
1029 | void CAnimatedMeshSceneNode::checkJoints() | 1029 | void CAnimatedMeshSceneNode::checkJoints() |
1030 | { | 1030 | { |
1031 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ | 1031 | #ifndef _IRR_COMPILE_WITH_SKINNED_MESH_SUPPORT_ |
1032 | return; | 1032 | return; |
1033 | #else | 1033 | #else |
1034 | 1034 | ||
1035 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) | 1035 | if (!Mesh || Mesh->getMeshType() != EAMT_SKINNED) |
1036 | return; | 1036 | return; |
1037 | 1037 | ||
1038 | if (!JointsUsed) | 1038 | if (!JointsUsed) |
1039 | { | 1039 | { |
1040 | for (u32 i=0; i<JointChildSceneNodes.size(); ++i) | 1040 | for (u32 i=0; i<JointChildSceneNodes.size(); ++i) |
1041 | removeChild(JointChildSceneNodes[i]); | 1041 | removeChild(JointChildSceneNodes[i]); |
1042 | JointChildSceneNodes.clear(); | 1042 | JointChildSceneNodes.clear(); |
1043 | 1043 | ||
1044 | //Create joints for SkinnedMesh | 1044 | //Create joints for SkinnedMesh |
1045 | ((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager); | 1045 | ((CSkinnedMesh*)Mesh)->addJoints(JointChildSceneNodes, this, SceneManager); |
1046 | ((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes); | 1046 | ((CSkinnedMesh*)Mesh)->recoverJointsFromMesh(JointChildSceneNodes); |
1047 | 1047 | ||
1048 | JointsUsed=true; | 1048 | JointsUsed=true; |
1049 | JointMode=EJUOR_READ; | 1049 | JointMode=EJUOR_READ; |
1050 | } | 1050 | } |
1051 | #endif | 1051 | #endif |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | /*! | 1054 | /*! |
1055 | */ | 1055 | */ |
1056 | void CAnimatedMeshSceneNode::beginTransition() | 1056 | void CAnimatedMeshSceneNode::beginTransition() |
1057 | { | 1057 | { |
1058 | if (!JointsUsed) | 1058 | if (!JointsUsed) |
1059 | return; | 1059 | return; |
1060 | 1060 | ||
1061 | if (TransitionTime != 0) | 1061 | if (TransitionTime != 0) |
1062 | { | 1062 | { |
1063 | //Check the array is big enough | 1063 | //Check the array is big enough |
1064 | if (PretransitingSave.size()<JointChildSceneNodes.size()) | 1064 | if (PretransitingSave.size()<JointChildSceneNodes.size()) |
1065 | { | 1065 | { |
1066 | for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n) | 1066 | for(u32 n=PretransitingSave.size(); n<JointChildSceneNodes.size(); ++n) |
1067 | PretransitingSave.push_back(core::matrix4()); | 1067 | PretransitingSave.push_back(core::matrix4()); |
1068 | } | 1068 | } |
1069 | 1069 | ||
1070 | //Copy the position of joints | 1070 | //Copy the position of joints |
1071 | for (u32 n=0;n<JointChildSceneNodes.size();++n) | 1071 | for (u32 n=0;n<JointChildSceneNodes.size();++n) |
1072 | PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation(); | 1072 | PretransitingSave[n]=JointChildSceneNodes[n]->getRelativeTransformation(); |
1073 | 1073 | ||
1074 | Transiting = core::reciprocal((f32)TransitionTime); | 1074 | Transiting = core::reciprocal((f32)TransitionTime); |
1075 | } | 1075 | } |
1076 | TransitingBlend = 0.f; | 1076 | TransitingBlend = 0.f; |
1077 | } | 1077 | } |
1078 | 1078 | ||
1079 | 1079 | ||
1080 | /*! | 1080 | /*! |
1081 | */ | 1081 | */ |
1082 | ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) | 1082 | ISceneNode* CAnimatedMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager) |
1083 | { | 1083 | { |
1084 | if (!newParent) | 1084 | if (!newParent) |
1085 | newParent = Parent; | 1085 | newParent = Parent; |
1086 | if (!newManager) | 1086 | if (!newManager) |
1087 | newManager = SceneManager; | 1087 | newManager = SceneManager; |
1088 | 1088 | ||
1089 | CAnimatedMeshSceneNode* newNode = | 1089 | CAnimatedMeshSceneNode* newNode = |
1090 | new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation, | 1090 | new CAnimatedMeshSceneNode(Mesh, NULL, newManager, ID, RelativeTranslation, |
1091 | RelativeRotation, RelativeScale); | 1091 | RelativeRotation, RelativeScale); |
1092 | 1092 | ||
1093 | if (newParent) | 1093 | if (newParent) |
1094 | { | 1094 | { |
1095 | newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called | 1095 | newNode->setParent(newParent); // not in constructor because virtual overload for updateAbsolutePosition won't be called |
1096 | newNode->drop(); | 1096 | newNode->drop(); |
1097 | } | 1097 | } |
1098 | 1098 | ||
1099 | newNode->cloneMembers(this, newManager); | 1099 | newNode->cloneMembers(this, newManager); |
1100 | 1100 | ||
1101 | newNode->Materials = Materials; | 1101 | newNode->Materials = Materials; |
1102 | newNode->Box = Box; | 1102 | newNode->Box = Box; |
1103 | newNode->Mesh = Mesh; | 1103 | newNode->Mesh = Mesh; |
1104 | newNode->StartFrame = StartFrame; | 1104 | newNode->StartFrame = StartFrame; |
1105 | newNode->EndFrame = EndFrame; | 1105 | newNode->EndFrame = EndFrame; |
1106 | newNode->FramesPerSecond = FramesPerSecond; | 1106 | newNode->FramesPerSecond = FramesPerSecond; |
1107 | newNode->CurrentFrameNr = CurrentFrameNr; | 1107 | newNode->CurrentFrameNr = CurrentFrameNr; |
1108 | newNode->JointMode = JointMode; | 1108 | newNode->JointMode = JointMode; |
1109 | newNode->JointsUsed = JointsUsed; | 1109 | newNode->JointsUsed = JointsUsed; |
1110 | newNode->TransitionTime = TransitionTime; | 1110 | newNode->TransitionTime = TransitionTime; |
1111 | newNode->Transiting = Transiting; | 1111 | newNode->Transiting = Transiting; |
1112 | newNode->TransitingBlend = TransitingBlend; | 1112 | newNode->TransitingBlend = TransitingBlend; |
1113 | newNode->Looping = Looping; | 1113 | newNode->Looping = Looping; |
1114 | newNode->ReadOnlyMaterials = ReadOnlyMaterials; | 1114 | newNode->ReadOnlyMaterials = ReadOnlyMaterials; |
1115 | newNode->LoopCallBack = LoopCallBack; | 1115 | newNode->LoopCallBack = LoopCallBack; |
1116 | newNode->PassCount = PassCount; | 1116 | newNode->PassCount = PassCount; |
1117 | newNode->Shadow = Shadow; | 1117 | newNode->Shadow = Shadow; |
1118 | newNode->Shadow->grab(); | 1118 | newNode->Shadow->grab(); |
1119 | newNode->JointChildSceneNodes = JointChildSceneNodes; | 1119 | newNode->JointChildSceneNodes = JointChildSceneNodes; |
1120 | newNode->PretransitingSave = PretransitingSave; | 1120 | newNode->PretransitingSave = PretransitingSave; |
1121 | newNode->RenderFromIdentity = RenderFromIdentity; | 1121 | newNode->RenderFromIdentity = RenderFromIdentity; |
1122 | newNode->MD3Special = MD3Special; | 1122 | newNode->MD3Special = MD3Special; |
1123 | 1123 | ||
1124 | return newNode; | 1124 | return newNode; |
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | 1127 | ||
1128 | } // end namespace scene | 1128 | } // end namespace scene |
1129 | } // end namespace irr | 1129 | } // end namespace irr |