1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CMeshSceneNode.h"
\r
6 #include "IVideoDriver.h"
\r
7 #include "ISceneManager.h"
\r
8 #include "S3DVertex.h"
\r
9 #include "ICameraSceneNode.h"
\r
10 #include "IMeshCache.h"
\r
11 #include "IAnimatedMesh.h"
\r
12 #include "IMaterialRenderer.h"
\r
13 #include "IFileSystem.h"
\r
23 CMeshSceneNode::CMeshSceneNode(IMesh* mesh, ISceneNode* parent, ISceneManager* mgr, s32 id,
\r
24 const core::vector3df& position, const core::vector3df& rotation,
\r
25 const core::vector3df& scale)
\r
26 : IMeshSceneNode(parent, mgr, id, position, rotation, scale), Mesh(0),
\r
27 PassCount(0), ReadOnlyMaterials(false)
\r
30 setDebugName("CMeshSceneNode");
\r
38 CMeshSceneNode::~CMeshSceneNode()
\r
46 void CMeshSceneNode::OnRegisterSceneNode()
\r
48 if (IsVisible && Mesh)
\r
50 // because this node supports rendering of mixed mode meshes consisting of
\r
51 // transparent and solid material at the same time, we need to go through all
\r
52 // materials, check of what type they are and register this node for the right
\r
53 // render pass according to that.
\r
55 video::IVideoDriver* driver = SceneManager->getVideoDriver();
\r
58 int transparentCount = 0;
\r
61 // count transparent and solid materials in this scene node
\r
62 const u32 numMaterials = ReadOnlyMaterials ? Mesh->getMeshBufferCount() : Materials.size();
\r
63 for (u32 i=0; i<numMaterials; ++i)
\r
65 const video::SMaterial& material = ReadOnlyMaterials ? Mesh->getMeshBuffer(i)->getMaterial() : Materials[i];
\r
67 if ( driver->needsTransparentRenderPass(material) )
\r
72 if (solidCount && transparentCount)
\r
76 // register according to material types counted
\r
79 SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
\r
81 if (transparentCount)
\r
82 SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
\r
84 ISceneNode::OnRegisterSceneNode();
\r
89 //! renders the node.
\r
90 void CMeshSceneNode::render()
\r
92 video::IVideoDriver* driver = SceneManager->getVideoDriver();
\r
94 if (!Mesh || !driver)
\r
97 const bool isTransparentPass =
\r
98 SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
\r
102 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
\r
103 Box = Mesh->getBoundingBox();
\r
105 // for debug purposes only:
\r
107 bool renderMeshes = true;
\r
108 video::SMaterial mat;
\r
109 if (DebugDataVisible && PassCount==1)
\r
111 // overwrite half transparency
\r
112 if (DebugDataVisible & scene::EDS_HALF_TRANSPARENCY)
\r
114 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
\r
116 mat = Materials[g];
\r
117 mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
\r
118 driver->setMaterial(mat);
\r
119 driver->drawMeshBuffer(Mesh->getMeshBuffer(g));
\r
121 renderMeshes = false;
\r
125 // render original meshes
\r
128 for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
\r
130 scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
\r
133 const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
\r
135 const bool transparent = driver->needsTransparentRenderPass(material);
\r
137 // only render transparent buffer if this is the transparent render pass
\r
138 // and solid only in solid pass
\r
139 if (transparent == isTransparentPass)
\r
141 driver->setMaterial(material);
\r
142 driver->drawMeshBuffer(mb);
\r
148 // for debug purposes only:
\r
149 if (DebugDataVisible && PassCount==1)
\r
151 video::SMaterial m;
\r
152 m.Lighting = false;
\r
154 driver->setMaterial(m);
\r
156 if (DebugDataVisible & scene::EDS_BBOX)
\r
158 driver->draw3DBox(Box, video::SColor(255,255,255,255));
\r
160 if (DebugDataVisible & scene::EDS_BBOX_BUFFERS)
\r
162 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
\r
165 Mesh->getMeshBuffer(g)->getBoundingBox(),
\r
166 video::SColor(255,190,128,128));
\r
170 if (DebugDataVisible & scene::EDS_NORMALS)
\r
173 const f32 debugNormalLength = 1.f;
\r
174 const video::SColor debugNormalColor = video::SColor(255, 34, 221, 221);
\r
175 const u32 count = Mesh->getMeshBufferCount();
\r
177 for (u32 i=0; i != count; ++i)
\r
179 driver->drawMeshBufferNormals(Mesh->getMeshBuffer(i), debugNormalLength, debugNormalColor);
\r
184 if (DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY)
\r
186 m.Wireframe = true;
\r
187 driver->setMaterial(m);
\r
189 for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g)
\r
191 driver->drawMeshBuffer(Mesh->getMeshBuffer(g));
\r
198 //! Removes a child from this scene node.
\r
199 //! Implemented here, to be able to remove the shadow properly, if there is one,
\r
200 //! or to remove attached childs.
\r
201 bool CMeshSceneNode::removeChild(ISceneNode* child)
\r
203 return ISceneNode::removeChild(child);
\r
207 //! returns the axis aligned bounding box of this node
\r
208 const core::aabbox3d<f32>& CMeshSceneNode::getBoundingBox() const
\r
210 return Mesh ? Mesh->getBoundingBox() : Box;
\r
214 //! returns the material based on the zero based index i. To get the amount
\r
215 //! of materials used by this scene node, use getMaterialCount().
\r
216 //! This function is needed for inserting the node into the scene hierarchy on a
\r
217 //! optimal position for minimizing renderstate changes, but can also be used
\r
218 //! to directly modify the material of a scene node.
\r
219 video::SMaterial& CMeshSceneNode::getMaterial(u32 i)
\r
221 if (Mesh && ReadOnlyMaterials && i<Mesh->getMeshBufferCount())
\r
223 ReadOnlyMaterial = Mesh->getMeshBuffer(i)->getMaterial();
\r
224 return ReadOnlyMaterial;
\r
227 if (i >= Materials.size())
\r
228 return ISceneNode::getMaterial(i);
\r
230 return Materials[i];
\r
234 //! returns amount of materials used by this scene node.
\r
235 u32 CMeshSceneNode::getMaterialCount() const
\r
237 if (Mesh && ReadOnlyMaterials)
\r
238 return Mesh->getMeshBufferCount();
\r
240 return Materials.size();
\r
244 //! Sets a new mesh
\r
245 void CMeshSceneNode::setMesh(IMesh* mesh)
\r
259 void CMeshSceneNode::copyMaterials()
\r
265 video::SMaterial mat;
\r
267 for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
\r
269 IMeshBuffer* mb = Mesh->getMeshBuffer(i);
\r
271 mat = mb->getMaterial();
\r
273 Materials.push_back(mat);
\r
279 //! Sets if the scene node should not copy the materials of the mesh but use them in a read only style.
\r
280 /* In this way it is possible to change the materials a mesh causing all mesh scene nodes
\r
281 referencing this mesh to change too. */
\r
282 void CMeshSceneNode::setReadOnlyMaterials(bool readonly)
\r
284 ReadOnlyMaterials = readonly;
\r
288 //! Returns if the scene node should not copy the materials of the mesh but use them in a read only style
\r
289 bool CMeshSceneNode::isReadOnlyMaterials() const
\r
291 return ReadOnlyMaterials;
\r
295 //! Creates a clone of this scene node and its children.
\r
296 ISceneNode* CMeshSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
\r
299 newParent = Parent;
\r
301 newManager = SceneManager;
\r
303 CMeshSceneNode* nb = new CMeshSceneNode(Mesh, newParent,
\r
304 newManager, ID, RelativeTranslation, RelativeRotation, RelativeScale);
\r
306 nb->cloneMembers(this, newManager);
\r
307 nb->ReadOnlyMaterials = ReadOnlyMaterials;
\r
308 nb->Materials = Materials;
\r
316 } // end namespace scene
\r
317 } // end namespace irr
\r