diff options
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp')
-rw-r--r-- | libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp deleted file mode 100644 index bcddeaf..0000000 --- a/libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp +++ /dev/null | |||
@@ -1,636 +0,0 @@ | |||
1 | // Copyright (C) 2002-2012 Nikolaus Gebhardt | ||
2 | // This file is part of the "Irrlicht Engine". | ||
3 | // For conditions of distribution and use, see copyright notice in irrlicht.h | ||
4 | |||
5 | #include "COctreeSceneNode.h" | ||
6 | #include "Octree.h" | ||
7 | #include "ISceneManager.h" | ||
8 | #include "IVideoDriver.h" | ||
9 | #include "ICameraSceneNode.h" | ||
10 | #include "IMeshCache.h" | ||
11 | #include "IAnimatedMesh.h" | ||
12 | #include "IMaterialRenderer.h" | ||
13 | #include "os.h" | ||
14 | #include "CShadowVolumeSceneNode.h" | ||
15 | |||
16 | namespace irr | ||
17 | { | ||
18 | namespace scene | ||
19 | { | ||
20 | |||
21 | |||
22 | //! constructor | ||
23 | COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, | ||
24 | s32 id, s32 minimalPolysPerNode) | ||
25 | : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), | ||
26 | TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), | ||
27 | MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0), | ||
28 | UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), | ||
29 | BoxBased(OCTREE_BOX_BASED) | ||
30 | { | ||
31 | #ifdef _DEBUG | ||
32 | setDebugName("COctreeSceneNode"); | ||
33 | #endif | ||
34 | } | ||
35 | |||
36 | |||
37 | //! destructor | ||
38 | COctreeSceneNode::~COctreeSceneNode() | ||
39 | { | ||
40 | if (Shadow) | ||
41 | Shadow->drop(); | ||
42 | deleteTree(); | ||
43 | } | ||
44 | |||
45 | |||
46 | void COctreeSceneNode::OnRegisterSceneNode() | ||
47 | { | ||
48 | if (IsVisible) | ||
49 | { | ||
50 | // because this node supports rendering of mixed mode meshes consisting of | ||
51 | // transparent and solid material at the same time, we need to go through all | ||
52 | // materials, check of what type they are and register this node for the right | ||
53 | // render pass according to that. | ||
54 | |||
55 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | ||
56 | |||
57 | PassCount = 0; | ||
58 | u32 transparentCount = 0; | ||
59 | u32 solidCount = 0; | ||
60 | |||
61 | // count transparent and solid materials in this scene node | ||
62 | for (u32 i=0; i<Materials.size(); ++i) | ||
63 | { | ||
64 | const video::IMaterialRenderer* const rnd = | ||
65 | driver->getMaterialRenderer(Materials[i].MaterialType); | ||
66 | |||
67 | if (rnd && rnd->isTransparent()) | ||
68 | ++transparentCount; | ||
69 | else | ||
70 | ++solidCount; | ||
71 | |||
72 | if (solidCount && transparentCount) | ||
73 | break; | ||
74 | } | ||
75 | |||
76 | // register according to material types counted | ||
77 | |||
78 | if (solidCount) | ||
79 | SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); | ||
80 | |||
81 | if (transparentCount) | ||
82 | SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); | ||
83 | |||
84 | ISceneNode::OnRegisterSceneNode(); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | |||
89 | //! renders the node. | ||
90 | void COctreeSceneNode::render() | ||
91 | { | ||
92 | video::IVideoDriver* driver = SceneManager->getVideoDriver(); | ||
93 | |||
94 | if (VertexType == -1 || !driver) | ||
95 | return; | ||
96 | |||
97 | ICameraSceneNode* camera = SceneManager->getActiveCamera(); | ||
98 | if (!camera) | ||
99 | return; | ||
100 | |||
101 | bool isTransparentPass = | ||
102 | SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; | ||
103 | ++PassCount; | ||
104 | |||
105 | driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); | ||
106 | |||
107 | if (Shadow) | ||
108 | Shadow->updateShadowVolumes(); | ||
109 | |||
110 | SViewFrustum frust = *camera->getViewFrustum(); | ||
111 | |||
112 | //transform the frustum to the current absolute transformation | ||
113 | if ( !AbsoluteTransformation.isIdentity() ) | ||
114 | { | ||
115 | core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); | ||
116 | frust.transform(invTrans); | ||
117 | } | ||
118 | |||
119 | const core::aabbox3d<float> &box = frust.getBoundingBox(); | ||
120 | |||
121 | switch (VertexType) | ||
122 | { | ||
123 | case video::EVT_STANDARD: | ||
124 | { | ||
125 | if (BoxBased) | ||
126 | StdOctree->calculatePolys(box); | ||
127 | else | ||
128 | StdOctree->calculatePolys(frust); | ||
129 | |||
130 | const Octree<video::S3DVertex>::SIndexData* d = StdOctree->getIndexData(); | ||
131 | |||
132 | for (u32 i=0; i<Materials.size(); ++i) | ||
133 | { | ||
134 | if ( 0 == d[i].CurrentSize ) | ||
135 | continue; | ||
136 | |||
137 | const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); | ||
138 | const bool transparent = (rnd && rnd->isTransparent()); | ||
139 | |||
140 | // only render transparent buffer if this is the transparent render pass | ||
141 | // and solid only in solid pass | ||
142 | if (transparent == isTransparentPass) | ||
143 | { | ||
144 | driver->setMaterial(Materials[i]); | ||
145 | driver->drawIndexedTriangleList( | ||
146 | &StdMeshes[i].Vertices[0], StdMeshes[i].Vertices.size(), | ||
147 | d[i].Indices, d[i].CurrentSize / 3); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | // for debug purposes only | ||
152 | if (DebugDataVisible && !Materials.empty() && PassCount==1) | ||
153 | { | ||
154 | const core::aabbox3df& box = frust.getBoundingBox(); | ||
155 | core::array< const core::aabbox3d<f32>* > boxes; | ||
156 | video::SMaterial m; | ||
157 | m.Lighting = false; | ||
158 | driver->setMaterial(m); | ||
159 | if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) | ||
160 | { | ||
161 | StdOctree->getBoundingBoxes(box, boxes); | ||
162 | for (u32 b=0; b!=boxes.size(); ++b) | ||
163 | driver->draw3DBox(*boxes[b]); | ||
164 | } | ||
165 | |||
166 | if ( DebugDataVisible & scene::EDS_BBOX ) | ||
167 | driver->draw3DBox(Box,video::SColor(0,255,0,0)); | ||
168 | } | ||
169 | } | ||
170 | break; | ||
171 | case video::EVT_2TCOORDS: | ||
172 | { | ||
173 | if (BoxBased) | ||
174 | LightMapOctree->calculatePolys(box); | ||
175 | else | ||
176 | LightMapOctree->calculatePolys(frust); | ||
177 | |||
178 | const Octree<video::S3DVertex2TCoords>::SIndexData* d = LightMapOctree->getIndexData(); | ||
179 | |||
180 | for (u32 i=0; i<Materials.size(); ++i) | ||
181 | { | ||
182 | if ( 0 == d[i].CurrentSize ) | ||
183 | continue; | ||
184 | |||
185 | const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); | ||
186 | const bool transparent = (rnd && rnd->isTransparent()); | ||
187 | |||
188 | // only render transparent buffer if this is the transparent render pass | ||
189 | // and solid only in solid pass | ||
190 | if (transparent == isTransparentPass) | ||
191 | { | ||
192 | driver->setMaterial(Materials[i]); | ||
193 | if (UseVBOs) | ||
194 | { | ||
195 | if (UseVisibilityAndVBOs) | ||
196 | { | ||
197 | u16* oldPointer = LightMapMeshes[i].Indices.pointer(); | ||
198 | const u32 oldSize = LightMapMeshes[i].Indices.size(); | ||
199 | LightMapMeshes[i].Indices.set_free_when_destroyed(false); | ||
200 | LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); | ||
201 | LightMapMeshes[i].setDirty(scene::EBT_INDEX); | ||
202 | driver->drawMeshBuffer ( &LightMapMeshes[i] ); | ||
203 | LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); | ||
204 | LightMapMeshes[i].setDirty(scene::EBT_INDEX); | ||
205 | } | ||
206 | else | ||
207 | driver->drawMeshBuffer ( &LightMapMeshes[i] ); | ||
208 | } | ||
209 | else | ||
210 | driver->drawIndexedTriangleList( | ||
211 | &LightMapMeshes[i].Vertices[0], | ||
212 | LightMapMeshes[i].Vertices.size(), | ||
213 | d[i].Indices, d[i].CurrentSize / 3); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | // for debug purposes only | ||
218 | if (DebugDataVisible && !Materials.empty() && PassCount==1) | ||
219 | { | ||
220 | const core::aabbox3d<float> &box = frust.getBoundingBox(); | ||
221 | core::array< const core::aabbox3d<f32>* > boxes; | ||
222 | video::SMaterial m; | ||
223 | m.Lighting = false; | ||
224 | driver->setMaterial(m); | ||
225 | if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) | ||
226 | { | ||
227 | LightMapOctree->getBoundingBoxes(box, boxes); | ||
228 | for (u32 b=0; b<boxes.size(); ++b) | ||
229 | driver->draw3DBox(*boxes[b]); | ||
230 | } | ||
231 | |||
232 | if ( DebugDataVisible & scene::EDS_BBOX ) | ||
233 | driver->draw3DBox(Box,video::SColor(0,255,0,0)); | ||
234 | } | ||
235 | } | ||
236 | break; | ||
237 | case video::EVT_TANGENTS: | ||
238 | { | ||
239 | if (BoxBased) | ||
240 | TangentsOctree->calculatePolys(box); | ||
241 | else | ||
242 | TangentsOctree->calculatePolys(frust); | ||
243 | |||
244 | const Octree<video::S3DVertexTangents>::SIndexData* d = TangentsOctree->getIndexData(); | ||
245 | |||
246 | for (u32 i=0; i<Materials.size(); ++i) | ||
247 | { | ||
248 | if ( 0 == d[i].CurrentSize ) | ||
249 | continue; | ||
250 | |||
251 | const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(Materials[i].MaterialType); | ||
252 | const bool transparent = (rnd && rnd->isTransparent()); | ||
253 | |||
254 | // only render transparent buffer if this is the transparent render pass | ||
255 | // and solid only in solid pass | ||
256 | if (transparent == isTransparentPass) | ||
257 | { | ||
258 | driver->setMaterial(Materials[i]); | ||
259 | driver->drawIndexedTriangleList( | ||
260 | &TangentsMeshes[i].Vertices[0], TangentsMeshes[i].Vertices.size(), | ||
261 | d[i].Indices, d[i].CurrentSize / 3); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | // for debug purposes only | ||
266 | if (DebugDataVisible && !Materials.empty() && PassCount==1) | ||
267 | { | ||
268 | const core::aabbox3d<float> &box = frust.getBoundingBox(); | ||
269 | core::array< const core::aabbox3d<f32>* > boxes; | ||
270 | video::SMaterial m; | ||
271 | m.Lighting = false; | ||
272 | driver->setMaterial(m); | ||
273 | if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) | ||
274 | { | ||
275 | TangentsOctree->getBoundingBoxes(box, boxes); | ||
276 | for (u32 b=0; b<boxes.size(); ++b) | ||
277 | driver->draw3DBox(*boxes[b]); | ||
278 | } | ||
279 | |||
280 | if ( DebugDataVisible & scene::EDS_BBOX ) | ||
281 | driver->draw3DBox(Box,video::SColor(0,255,0,0)); | ||
282 | } | ||
283 | } | ||
284 | break; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | |||
289 | //! Removes a child from this scene node. | ||
290 | //! Implemented here, to be able to remove the shadow properly, if there is one, | ||
291 | //! or to remove attached childs. | ||
292 | bool COctreeSceneNode::removeChild(ISceneNode* child) | ||
293 | { | ||
294 | if (child && Shadow == child) | ||
295 | { | ||
296 | Shadow->drop(); | ||
297 | Shadow = 0; | ||
298 | } | ||
299 | |||
300 | return ISceneNode::removeChild(child); | ||
301 | } | ||
302 | |||
303 | |||
304 | //! Creates shadow volume scene node as child of this node | ||
305 | //! and returns a pointer to it. | ||
306 | IShadowVolumeSceneNode* COctreeSceneNode::addShadowVolumeSceneNode( | ||
307 | const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) | ||
308 | { | ||
309 | if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) | ||
310 | return 0; | ||
311 | |||
312 | if (!shadowMesh) | ||
313 | shadowMesh = Mesh; // if null is given, use the mesh of node | ||
314 | |||
315 | if (Shadow) | ||
316 | Shadow->drop(); | ||
317 | |||
318 | Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); | ||
319 | return Shadow; | ||
320 | } | ||
321 | |||
322 | |||
323 | //! returns the axis aligned bounding box of this node | ||
324 | const core::aabbox3d<f32>& COctreeSceneNode::getBoundingBox() const | ||
325 | { | ||
326 | return Box; | ||
327 | } | ||
328 | |||
329 | |||
330 | //! creates the tree | ||
331 | /* This method has a lot of duplication and overhead. Moreover, the tangents mesh conversion does not really work. I think we need a a proper mesh implementation for octrees, which handle all vertex types internally. Converting all structures to just one vertex type is always problematic. | ||
332 | Thanks to Auria for fixing major parts of this method. */ | ||
333 | bool COctreeSceneNode::createTree(IMesh* mesh) | ||
334 | { | ||
335 | if (!mesh) | ||
336 | return false; | ||
337 | |||
338 | MeshName = SceneManager->getMeshCache()->getMeshName(mesh); | ||
339 | |||
340 | mesh->grab(); | ||
341 | deleteTree(); | ||
342 | |||
343 | Mesh = mesh; | ||
344 | |||
345 | const u32 beginTime = os::Timer::getRealTime(); | ||
346 | |||
347 | u32 nodeCount = 0; | ||
348 | u32 polyCount = 0; | ||
349 | u32 i; | ||
350 | |||
351 | Box = mesh->getBoundingBox(); | ||
352 | |||
353 | if (mesh->getMeshBufferCount()) | ||
354 | { | ||
355 | // check for "larger" buffer types | ||
356 | VertexType = video::EVT_STANDARD; | ||
357 | u32 meshReserve = 0; | ||
358 | for (i=0; i<mesh->getMeshBufferCount(); ++i) | ||
359 | { | ||
360 | const IMeshBuffer* b = mesh->getMeshBuffer(i); | ||
361 | if (b->getVertexCount() && b->getIndexCount()) | ||
362 | { | ||
363 | ++meshReserve; | ||
364 | if (b->getVertexType() == video::EVT_2TCOORDS) | ||
365 | VertexType = video::EVT_2TCOORDS; | ||
366 | else if (b->getVertexType() == video::EVT_TANGENTS) | ||
367 | VertexType = video::EVT_TANGENTS; | ||
368 | } | ||
369 | } | ||
370 | Materials.reallocate(Materials.size()+meshReserve); | ||
371 | |||
372 | switch(VertexType) | ||
373 | { | ||
374 | case video::EVT_STANDARD: | ||
375 | { | ||
376 | StdMeshes.reallocate(StdMeshes.size() + meshReserve); | ||
377 | for (i=0; i<mesh->getMeshBufferCount(); ++i) | ||
378 | { | ||
379 | IMeshBuffer* b = mesh->getMeshBuffer(i); | ||
380 | |||
381 | if (b->getVertexCount() && b->getIndexCount()) | ||
382 | { | ||
383 | Materials.push_back(b->getMaterial()); | ||
384 | |||
385 | StdMeshes.push_back(Octree<video::S3DVertex>::SMeshChunk()); | ||
386 | Octree<video::S3DVertex>::SMeshChunk &nchunk = StdMeshes.getLast(); | ||
387 | nchunk.MaterialId = Materials.size() - 1; | ||
388 | |||
389 | u32 v; | ||
390 | nchunk.Vertices.reallocate(b->getVertexCount()); | ||
391 | switch (b->getVertexType()) | ||
392 | { | ||
393 | case video::EVT_STANDARD: | ||
394 | for (v=0; v<b->getVertexCount(); ++v) | ||
395 | nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); | ||
396 | break; | ||
397 | case video::EVT_2TCOORDS: | ||
398 | for (v=0; v<b->getVertexCount(); ++v) | ||
399 | nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); | ||
400 | break; | ||
401 | case video::EVT_TANGENTS: | ||
402 | for (v=0; v<b->getVertexCount(); ++v) | ||
403 | nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); | ||
404 | break; | ||
405 | } | ||
406 | |||
407 | polyCount += b->getIndexCount(); | ||
408 | |||
409 | nchunk.Indices.reallocate(b->getIndexCount()); | ||
410 | for (v=0; v<b->getIndexCount(); ++v) | ||
411 | nchunk.Indices.push_back(b->getIndices()[v]); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | StdOctree = new Octree<video::S3DVertex>(StdMeshes, MinimalPolysPerNode); | ||
416 | nodeCount = StdOctree->getNodeCount(); | ||
417 | } | ||
418 | break; | ||
419 | case video::EVT_2TCOORDS: | ||
420 | { | ||
421 | LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve); | ||
422 | |||
423 | for ( i=0; i < mesh->getMeshBufferCount(); ++i) | ||
424 | { | ||
425 | IMeshBuffer* b = mesh->getMeshBuffer(i); | ||
426 | |||
427 | if (b->getVertexCount() && b->getIndexCount()) | ||
428 | { | ||
429 | Materials.push_back(b->getMaterial()); | ||
430 | LightMapMeshes.push_back(Octree<video::S3DVertex2TCoords>::SMeshChunk()); | ||
431 | Octree<video::S3DVertex2TCoords>::SMeshChunk& nchunk = LightMapMeshes.getLast(); | ||
432 | nchunk.MaterialId = Materials.size() - 1; | ||
433 | |||
434 | if (UseVisibilityAndVBOs) | ||
435 | { | ||
436 | nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); | ||
437 | nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); | ||
438 | } | ||
439 | else | ||
440 | nchunk.setHardwareMappingHint(scene::EHM_STATIC); | ||
441 | |||
442 | u32 v; | ||
443 | nchunk.Vertices.reallocate(b->getVertexCount()); | ||
444 | switch (b->getVertexType()) | ||
445 | { | ||
446 | case video::EVT_STANDARD: | ||
447 | for (v=0; v<b->getVertexCount(); ++v) | ||
448 | nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); | ||
449 | break; | ||
450 | case video::EVT_2TCOORDS: | ||
451 | for (v=0; v<b->getVertexCount(); ++v) | ||
452 | nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); | ||
453 | break; | ||
454 | case video::EVT_TANGENTS: | ||
455 | for (v=0; v<b->getVertexCount(); ++v) | ||
456 | nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); | ||
457 | break; | ||
458 | } | ||
459 | |||
460 | polyCount += b->getIndexCount(); | ||
461 | nchunk.Indices.reallocate(b->getIndexCount()); | ||
462 | for (v=0; v<b->getIndexCount(); ++v) | ||
463 | nchunk.Indices.push_back(b->getIndices()[v]); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | LightMapOctree = new Octree<video::S3DVertex2TCoords>(LightMapMeshes, MinimalPolysPerNode); | ||
468 | nodeCount = LightMapOctree->getNodeCount(); | ||
469 | } | ||
470 | break; | ||
471 | case video::EVT_TANGENTS: | ||
472 | { | ||
473 | TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve); | ||
474 | |||
475 | for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) | ||
476 | { | ||
477 | IMeshBuffer* b = mesh->getMeshBuffer(i); | ||
478 | |||
479 | if (b->getVertexCount() && b->getIndexCount()) | ||
480 | { | ||
481 | Materials.push_back(b->getMaterial()); | ||
482 | TangentsMeshes.push_back(Octree<video::S3DVertexTangents>::SMeshChunk()); | ||
483 | Octree<video::S3DVertexTangents>::SMeshChunk& nchunk = TangentsMeshes.getLast(); | ||
484 | nchunk.MaterialId = Materials.size() - 1; | ||
485 | |||
486 | u32 v; | ||
487 | nchunk.Vertices.reallocate(b->getVertexCount()); | ||
488 | switch (b->getVertexType()) | ||
489 | { | ||
490 | case video::EVT_STANDARD: | ||
491 | for (v=0; v<b->getVertexCount(); ++v) | ||
492 | { | ||
493 | const video::S3DVertex& tmpV = ((video::S3DVertex*)b->getVertices())[v]; | ||
494 | nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); | ||
495 | } | ||
496 | break; | ||
497 | case video::EVT_2TCOORDS: | ||
498 | for (v=0; v<b->getVertexCount(); ++v) | ||
499 | { | ||
500 | const video::S3DVertex2TCoords& tmpV = ((video::S3DVertex2TCoords*)b->getVertices())[v]; | ||
501 | nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); | ||
502 | } | ||
503 | break; | ||
504 | case video::EVT_TANGENTS: | ||
505 | for (v=0; v<b->getVertexCount(); ++v) | ||
506 | nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); | ||
507 | break; | ||
508 | } | ||
509 | |||
510 | polyCount += b->getIndexCount(); | ||
511 | nchunk.Indices.reallocate(b->getIndexCount()); | ||
512 | for (v=0; v<b->getIndexCount(); ++v) | ||
513 | nchunk.Indices.push_back(b->getIndices()[v]); | ||
514 | } | ||
515 | } | ||
516 | |||
517 | TangentsOctree = new Octree<video::S3DVertexTangents>(TangentsMeshes, MinimalPolysPerNode); | ||
518 | nodeCount = TangentsOctree->getNodeCount(); | ||
519 | } | ||
520 | break; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | const u32 endTime = os::Timer::getRealTime(); | ||
525 | c8 tmp[255]; | ||
526 | sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", | ||
527 | endTime - beginTime, nodeCount, polyCount/3); | ||
528 | os::Printer::log(tmp, ELL_INFORMATION); | ||
529 | |||
530 | return true; | ||
531 | } | ||
532 | |||
533 | |||
534 | //! returns the material based on the zero based index i. To get the amount | ||
535 | //! of materials used by this scene node, use getMaterialCount(). | ||
536 | //! This function is needed for inserting the node into the scene hirachy on a | ||
537 | //! optimal position for minimizing renderstate changes, but can also be used | ||
538 | //! to directly modify the material of a scene node. | ||
539 | video::SMaterial& COctreeSceneNode::getMaterial(u32 i) | ||
540 | { | ||
541 | if ( i >= Materials.size() ) | ||
542 | return ISceneNode::getMaterial(i); | ||
543 | |||
544 | return Materials[i]; | ||
545 | } | ||
546 | |||
547 | |||
548 | //! returns amount of materials used by this scene node. | ||
549 | u32 COctreeSceneNode::getMaterialCount() const | ||
550 | { | ||
551 | return Materials.size(); | ||
552 | } | ||
553 | |||
554 | |||
555 | //! Writes attributes of the scene node. | ||
556 | void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const | ||
557 | { | ||
558 | ISceneNode::serializeAttributes(out, options); | ||
559 | |||
560 | out->addInt("MinimalPolysPerNode", MinimalPolysPerNode); | ||
561 | out->addString("Mesh", MeshName.c_str()); | ||
562 | } | ||
563 | |||
564 | |||
565 | //! Reads attributes of the scene node. | ||
566 | void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) | ||
567 | { | ||
568 | const s32 oldMinimal = MinimalPolysPerNode; | ||
569 | |||
570 | MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); | ||
571 | io::path newMeshStr = in->getAttributeAsString("Mesh"); | ||
572 | |||
573 | IMesh* newMesh = 0; | ||
574 | |||
575 | if (newMeshStr == "") | ||
576 | newMeshStr = MeshName; | ||
577 | |||
578 | IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); | ||
579 | |||
580 | if (newAnimatedMesh) | ||
581 | newMesh = newAnimatedMesh->getMesh(0); | ||
582 | |||
583 | if (newMesh && ((MeshName != newMeshStr) || (MinimalPolysPerNode != oldMinimal))) | ||
584 | { | ||
585 | // recalculate tree | ||
586 | createTree(newMesh); | ||
587 | } | ||
588 | |||
589 | ISceneNode::deserializeAttributes(in, options); | ||
590 | } | ||
591 | |||
592 | |||
593 | void COctreeSceneNode::deleteTree() | ||
594 | { | ||
595 | delete StdOctree; | ||
596 | StdOctree = 0; | ||
597 | StdMeshes.clear(); | ||
598 | |||
599 | delete LightMapOctree; | ||
600 | LightMapOctree = 0; | ||
601 | LightMapMeshes.clear(); | ||
602 | |||
603 | delete TangentsOctree; | ||
604 | TangentsOctree = 0; | ||
605 | TangentsMeshes.clear(); | ||
606 | |||
607 | Materials.clear(); | ||
608 | |||
609 | if(Mesh) | ||
610 | Mesh->drop(); | ||
611 | } | ||
612 | |||
613 | void COctreeSceneNode::setMesh(IMesh* mesh) | ||
614 | { | ||
615 | createTree(mesh); | ||
616 | } | ||
617 | |||
618 | IMesh* COctreeSceneNode::getMesh(void) | ||
619 | { | ||
620 | return Mesh; | ||
621 | } | ||
622 | |||
623 | void COctreeSceneNode::setReadOnlyMaterials(bool readonly) | ||
624 | { | ||
625 | // Do nothing | ||
626 | } | ||
627 | |||
628 | bool COctreeSceneNode::isReadOnlyMaterials() const | ||
629 | { | ||
630 | return false; | ||
631 | } | ||
632 | |||
633 | |||
634 | } // end namespace scene | ||
635 | } // end namespace irr | ||
636 | |||