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