aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp447
1 files changed, 447 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp
new file mode 100644
index 0000000..5205b4d
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/CMeshSceneNode.cpp
@@ -0,0 +1,447 @@
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 "CMeshSceneNode.h"
6#include "IVideoDriver.h"
7#include "ISceneManager.h"
8#include "S3DVertex.h"
9#include "ICameraSceneNode.h"
10#include "IMeshCache.h"
11#include "IAnimatedMesh.h"
12#include "IMaterialRenderer.h"
13#include "IFileSystem.h"
14#include "CShadowVolumeSceneNode.h"
15
16namespace irr
17{
18namespace scene
19{
20
21
22
23//! constructor
24CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
25 const core::vector3df& position, const core::vector3df& rotation,
26 const core::vector3df& scale)
27: IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0), Shadow(0),
28 PassCount(0), ReadOnlyMaterials(false)
29{
30 #ifdef _DEBUG
31 setDebugName("CMeshSceneNode");
32 #endif
33
34 setMesh(mesh);
35}
36
37
38//! destructor
39CMeshSceneNode::~CMeshSceneNode()
40{
41 if (Shadow)
42 Shadow->drop();
43 if (Mesh)
44 Mesh->drop();
45}
46
47
48//! frame
49void CMeshSceneNode::OnRegisterSceneNode()
50{
51 if (IsVisible)
52 {
53 // because this node supports rendering of mixed mode meshes consisting of
54 // transparent and solid material at the same time, we need to go through all
55 // materials, check of what type they are and register this node for the right
56 // render pass according to that.
57
58 video::IVideoDriver* driver = SceneManager->getVideoDriver();
59
60 PassCount = 0;
61 int transparentCount = 0;
62 int solidCount = 0;
63
64 // count transparent and solid materials in this scene node
65 if (ReadOnlyMaterials && Mesh)
66 {
67 // count mesh materials
68
69 for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
70 {
71 scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
72 video::IMaterialRenderer* rnd = mb ? driver->getMaterialRenderer(mb->getMaterial().MaterialType) : 0;
73
74 if (rnd && rnd->isTransparent())
75 ++transparentCount;
76 else
77 ++solidCount;
78
79 if (solidCount && transparentCount)
80 break;
81 }
82 }
83 else
84 {
85 // count copied materials
86
87 for (u32 i=0; i<Materials.size(); ++i)
88 {
89 video::IMaterialRenderer* rnd =
90 driver->getMaterialRenderer(Materials[i].MaterialType);
91
92 if (rnd && rnd->isTransparent())
93 ++transparentCount;
94 else
95 ++solidCount;
96
97 if (solidCount && transparentCount)
98 break;
99 }
100 }
101
102 // register according to material types counted
103
104 if (solidCount)
105 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
106
107 if (transparentCount)
108 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
109
110 ISceneNode::OnRegisterSceneNode();
111 }
112}
113
114
115//! renders the node.
116void CMeshSceneNode::render()
117{
118 video::IVideoDriver* driver = SceneManager->getVideoDriver();
119
120 if (!Mesh || !driver)
121 return;
122
123 bool isTransparentPass =
124 SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
125
126 ++PassCount;
127
128 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
129 Box = Mesh->getBoundingBox();
130
131 if (Shadow && PassCount==1)
132 Shadow->updateShadowVolumes();
133
134 // for debug purposes only:
135
136 bool renderMeshes = true;
137 video::SMaterial mat;
138 if (DebugDataVisible && PassCount==1)
139 {
140 // overwrite half transparency
141 if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
142 {
143 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
144 {
145 mat = Materials[g];
146 mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
147 driver->setMaterial(mat);
148 driver->drawMeshBuffer(Mesh->getMeshBuffer(g));
149 }
150 renderMeshes = false;
151 }
152 }
153
154 // render original meshes
155 if (renderMeshes)
156 {
157 for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
158 {
159 scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
160 if (mb)
161 {
162 const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
163
164 video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType);
165 bool transparent = (rnd && rnd->isTransparent());
166
167 // only render transparent buffer if this is the transparent render pass
168 // and solid only in solid pass
169 if (transparent == isTransparentPass)
170 {
171 driver->setMaterial(material);
172 driver->drawMeshBuffer(mb);
173 }
174 }
175 }
176 }
177
178 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
179
180 // for debug purposes only:
181 if (DebugDataVisible && PassCount==1)
182 {
183 video::SMaterial m;
184 m.Lighting = false;
185 m.AntiAliasing=0;
186 driver->setMaterial(m);
187
188 if (DebugDataVisible & scene::EDS_BBOX)
189 {
190 driver->draw3DBox(Box, video::SColor(255,255,255,255));
191 }
192 if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
193 {
194 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
195 {
196 driver->draw3DBox(
197 Mesh->getMeshBuffer(g)->getBoundingBox(),
198 video::SColor(255,190,128,128));
199 }
200 }
201
202 if (DebugDataVisible & scene::EDS_NORMALS)
203 {
204 // draw normals
205 const f32 debugNormalLength = SceneManager->getParameters()->getAttributeAsFloat(DEBUG_NORMAL_LENGTH);
206 const video::SColor debugNormalColor = SceneManager->getParameters()->getAttributeAsColor(DEBUG_NORMAL_COLOR);
207 const u32 count = Mesh->getMeshBufferCount();
208
209 for (u32 i=0; i != count; ++i)
210 {
211 driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor);
212 }
213 }
214
215 // show mesh
216 if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
217 {
218 m.Wireframe = true;
219 driver->setMaterial(m);
220
221 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
222 {
223 driver->drawMeshBuffer(Mesh->getMeshBuffer(g));
224 }
225 }
226 }
227}
228
229
230//! Removes a child from this scene node.
231//! Implemented here, to be able to remove the shadow properly, if there is one,
232//! or to remove attached childs.
233bool CMeshSceneNode::removeChild(ISceneNode* child)
234{
235 if (child && Shadow == child)
236 {
237 Shadow->drop();
238 Shadow = 0;
239 }
240
241 return ISceneNode::removeChild(child);
242}
243
244
245//! returns the axis aligned bounding box of this node
246const core::aabbox3d<f32>& CMeshSceneNode::getBoundingBox() const
247{
248 return Mesh ? Mesh->getBoundingBox() : Box;
249}
250
251
252//! returns the material based on the zero based index i. To get the amount
253//! of materials used by this scene node, use getMaterialCount().
254//! This function is needed for inserting the node into the scene hierarchy on a
255//! optimal position for minimizing renderstate changes, but can also be used
256//! to directly modify the material of a scene node.
257video::SMaterial& CMeshSceneNode::getMaterial(u32 i)
258{
259 if (Mesh && ReadOnlyMaterials && i<Mesh->getMeshBufferCount())
260 {
261 ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial();
262 return ReadOnlyMaterial;
263 }
264
265 if (i >= Materials.size())
266 return ISceneNode::getMaterial(i);
267
268 return Materials[i];
269}
270
271
272//! returns amount of materials used by this scene node.
273u32 CMeshSceneNode::getMaterialCount() const
274{
275 if (Mesh && ReadOnlyMaterials)
276 return Mesh->getMeshBufferCount();
277
278 return Materials.size();
279}
280
281
282//! Sets a new mesh
283void CMeshSceneNode::setMesh(IMesh* mesh)
284{
285 if (mesh)
286 {
287 mesh->grab();
288 if (Mesh)
289 Mesh->drop();
290
291 Mesh = mesh;
292 copyMaterials();
293 }
294}
295
296
297//! Creates shadow volume scene node as child of this node
298//! and returns a pointer to it.
299IShadowVolumeSceneNode* CMeshSceneNode::addShadowVolumeSceneNode(
300 const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity)
301{
302 if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER))
303 return 0;
304
305 if (!shadowMesh)
306 shadowMesh = Mesh; // if null is given, use the mesh of node
307
308 if (Shadow)
309 Shadow->drop();
310
311 Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity);
312 return Shadow;
313}
314
315
316void CMeshSceneNode::copyMaterials()
317{
318 Materials.clear();
319
320 if (Mesh)
321 {
322 video::SMaterial mat;
323
324 for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
325 {
326 IMeshBuffer* mb = Mesh->getMeshBuffer(i);
327 if (mb)
328 mat = mb->getMaterial();
329
330 Materials.push_back(mat);
331 }
332 }
333}
334
335
336//! Writes attributes of the scene node.
337void CMeshSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
338{
339 IMeshSceneNode::serializeAttributes(out, options);
340
341 if (options && (options->Flags&io::EARWF_USE_RELATIVE_PATHS) && options->Filename)
342 {
343 const io::path path = SceneManager->getFileSystem()->getRelativeFilename(
344 SceneManager->getFileSystem()->getAbsolutePath(SceneManager->getMeshCache()->getMeshName(Mesh).getPath()),
345 options->Filename);
346 out->addString("Mesh", path.c_str());
347 }
348 else
349 out->addString("Mesh", SceneManager->getMeshCache()->getMeshName(Mesh).getPath().c_str());
350 out->addBool("ReadOnlyMaterials", ReadOnlyMaterials);
351}
352
353
354//! Reads attributes of the scene node.
355void CMeshSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
356{
357 io::path oldMeshStr = SceneManager->getMeshCache()->getMeshName(Mesh);
358 io::path newMeshStr = in->getAttributeAsString("Mesh");
359 ReadOnlyMaterials = in->getAttributeAsBool("ReadOnlyMaterials");
360
361 if (newMeshStr != "" && oldMeshStr != newMeshStr)
362 {
363 IMesh* newMesh = 0;
364 IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str());
365
366 if (newAnimatedMesh)
367 newMesh = newAnimatedMesh->getMesh(0);
368
369 if (newMesh)
370 setMesh(newMesh);
371 }
372
373 // optional attribute to assign the hint to the whole mesh
374 if (in->existsAttribute("HardwareMappingHint") &&
375 in->existsAttribute("HardwareMappingBufferType"))
376 {
377 scene::E_HARDWARE_MAPPING mapping = scene::EHM_NEVER;
378 scene::E_BUFFER_TYPE bufferType = scene::EBT_NONE;
379
380 core::stringc smapping = in->getAttributeAsString("HardwareMappingHint");
381 if (smapping.equals_ignore_case("static"))
382 mapping = scene::EHM_STATIC;
383 else if (smapping.equals_ignore_case("dynamic"))
384 mapping = scene::EHM_DYNAMIC;
385 else if (smapping.equals_ignore_case("stream"))
386 mapping = scene::EHM_STREAM;
387
388 core::stringc sbufferType = in->getAttributeAsString("HardwareMappingBufferType");
389 if (sbufferType.equals_ignore_case("vertex"))
390 bufferType = scene::EBT_VERTEX;
391 else if (sbufferType.equals_ignore_case("index"))
392 bufferType = scene::EBT_INDEX;
393 else if (sbufferType.equals_ignore_case("vertexindex"))
394 bufferType = scene::EBT_VERTEX_AND_INDEX;
395
396 IMesh* mesh = getMesh();
397 if (mesh)
398 mesh->setHardwareMappingHint(mapping, bufferType);
399 }
400
401 IMeshSceneNode::deserializeAttributes(in, options);
402}
403
404
405//! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
406/* In this way it is possible to change the materials a mesh causing all mesh scene nodes
407referencing this mesh to change too. */
408void CMeshSceneNode::setReadOnlyMaterials(bool readonly)
409{
410 ReadOnlyMaterials = readonly;
411}
412
413
414//! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
415bool CMeshSceneNode::isReadOnlyMaterials() const
416{
417 return ReadOnlyMaterials;
418}
419
420
421//! Creates a clone of this scene node and its children.
422ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
423{
424 if (!newParent)
425 newParent = Parent;
426 if (!newManager)
427 newManager = SceneManager;
428
429 CMeshSceneNode* nb = new CMeshSceneNode(Mesh, newParent,
430 newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale);
431
432 nb->cloneMembers(this, newManager);
433 nb->ReadOnlyMaterials = ReadOnlyMaterials;
434 nb->Materials = Materials;
435 nb->Shadow = Shadow;
436 if ( nb->Shadow )
437 nb->Shadow->grab();
438
439 if (newParent)
440 nb->drop();
441 return nb;
442}
443
444
445} // end namespace scene
446} // end namespace irr
447