From 959831f4ef5a3e797f576c3de08cd65032c997ad Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 13 Jan 2013 18:54:10 +1000 Subject: Remove damned ancient DOS line endings from Irrlicht. Hopefully I did not go overboard. --- .../source/Irrlicht/COctreeSceneNode.cpp | 1272 ++++++++++---------- 1 file changed, 636 insertions(+), 636 deletions(-) (limited to 'libraries/irrlicht-1.8/source/Irrlicht/COctreeSceneNode.cpp') 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 @@ -// Copyright (C) 2002-2012 Nikolaus Gebhardt -// This file is part of the "Irrlicht Engine". -// For conditions of distribution and use, see copyright notice in irrlicht.h - -#include "COctreeSceneNode.h" -#include "Octree.h" -#include "ISceneManager.h" -#include "IVideoDriver.h" -#include "ICameraSceneNode.h" -#include "IMeshCache.h" -#include "IAnimatedMesh.h" -#include "IMaterialRenderer.h" -#include "os.h" -#include "CShadowVolumeSceneNode.h" - -namespace irr -{ -namespace scene -{ - - -//! constructor -COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, - s32 id, s32 minimalPolysPerNode) - : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), - TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), - MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0), - UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), - BoxBased(OCTREE_BOX_BASED) -{ -#ifdef _DEBUG - setDebugName("COctreeSceneNode"); -#endif -} - - -//! destructor -COctreeSceneNode::~COctreeSceneNode() -{ - if (Shadow) - Shadow->drop(); - deleteTree(); -} - - -void COctreeSceneNode::OnRegisterSceneNode() -{ - if (IsVisible) - { - // because this node supports rendering of mixed mode meshes consisting of - // transparent and solid material at the same time, we need to go through all - // materials, check of what type they are and register this node for the right - // render pass according to that. - - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - PassCount = 0; - u32 transparentCount = 0; - u32 solidCount = 0; - - // count transparent and solid materials in this scene node - for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); - - if (rnd && rnd->isTransparent()) - ++transparentCount; - else - ++solidCount; - - if (solidCount && transparentCount) - break; - } - - // register according to material types counted - - if (solidCount) - SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); - - if (transparentCount) - SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); - - ISceneNode::OnRegisterSceneNode(); - } -} - - -//! renders the node. -void COctreeSceneNode::render() -{ - video::IVideoDriver* driver = SceneManager->getVideoDriver(); - - if (VertexType == -1 || !driver) - return; - - ICameraSceneNode* camera = SceneManager->getActiveCamera(); - if (!camera) - return; - - bool isTransparentPass = - SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; - ++PassCount; - - driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); - - if (Shadow) - Shadow->updateShadowVolumes(); - - SViewFrustum frust = *camera->getViewFrustum(); - - //transform the frustum to the current absolute transformation - if ( !AbsoluteTransformation.isIdentity() ) - { - core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); - frust.transform(invTrans); - } - - const core::aabbox3d &box = frust.getBoundingBox(); - - switch (VertexType) - { - case video::EVT_STANDARD: - { - if (BoxBased) - StdOctree->calculatePolys(box); - else - StdOctree->calculatePolys(frust); - - const Octree::SIndexData* d = StdOctree->getIndexData(); - - for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); - const bool transparent = (rnd && rnd->isTransparent()); - - // only render transparent buffer if this is the transparent render pass - // and solid only in solid pass - if (transparent == isTransparentPass) - { - driver->setMaterial(Materials[i]); - driver->drawIndexedTriangleList( - &StdMeshes[i].Vertices[0], StdMeshes[i].Vertices.size(), - d[i].Indices, d[i].CurrentSize / 3); - } - } - - // for debug purposes only - if (DebugDataVisible && !Materials.empty() && PassCount==1) - { - const core::aabbox3df& box = frust.getBoundingBox(); - core::array< const core::aabbox3d* > boxes; - video::SMaterial m; - m.Lighting = false; - driver->setMaterial(m); - if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) - { - StdOctree->getBoundingBoxes(box, boxes); - for (u32 b=0; b!=boxes.size(); ++b) - driver->draw3DBox(*boxes[b]); - } - - if ( DebugDataVisible & scene::EDS_BBOX ) - driver->draw3DBox(Box,video::SColor(0,255,0,0)); - } - } - break; - case video::EVT_2TCOORDS: - { - if (BoxBased) - LightMapOctree->calculatePolys(box); - else - LightMapOctree->calculatePolys(frust); - - const Octree::SIndexData* d = LightMapOctree->getIndexData(); - - for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); - const bool transparent = (rnd && rnd->isTransparent()); - - // only render transparent buffer if this is the transparent render pass - // and solid only in solid pass - if (transparent == isTransparentPass) - { - driver->setMaterial(Materials[i]); - if (UseVBOs) - { - if (UseVisibilityAndVBOs) - { - u16* oldPointer = LightMapMeshes[i].Indices.pointer(); - const u32 oldSize = LightMapMeshes[i].Indices.size(); - LightMapMeshes[i].Indices.set_free_when_destroyed(false); - LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); - LightMapMeshes[i].setDirty(scene::EBT_INDEX); - driver->drawMeshBuffer ( &LightMapMeshes[i] ); - LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); - LightMapMeshes[i].setDirty(scene::EBT_INDEX); - } - else - driver->drawMeshBuffer ( &LightMapMeshes[i] ); - } - else - driver->drawIndexedTriangleList( - &LightMapMeshes[i].Vertices[0], - LightMapMeshes[i].Vertices.size(), - d[i].Indices, d[i].CurrentSize / 3); - } - } - - // for debug purposes only - if (DebugDataVisible && !Materials.empty() && PassCount==1) - { - const core::aabbox3d &box = frust.getBoundingBox(); - core::array< const core::aabbox3d* > boxes; - video::SMaterial m; - m.Lighting = false; - driver->setMaterial(m); - if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) - { - LightMapOctree->getBoundingBoxes(box, boxes); - for (u32 b=0; bdraw3DBox(*boxes[b]); - } - - if ( DebugDataVisible & scene::EDS_BBOX ) - driver->draw3DBox(Box,video::SColor(0,255,0,0)); - } - } - break; - case video::EVT_TANGENTS: - { - if (BoxBased) - TangentsOctree->calculatePolys(box); - else - TangentsOctree->calculatePolys(frust); - - const Octree::SIndexData* d = TangentsOctree->getIndexData(); - - for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); - const bool transparent = (rnd && rnd->isTransparent()); - - // only render transparent buffer if this is the transparent render pass - // and solid only in solid pass - if (transparent == isTransparentPass) - { - driver->setMaterial(Materials[i]); - driver->drawIndexedTriangleList( - &TangentsMeshes[i].Vertices[0], TangentsMeshes[i].Vertices.size(), - d[i].Indices, d[i].CurrentSize / 3); - } - } - - // for debug purposes only - if (DebugDataVisible && !Materials.empty() && PassCount==1) - { - const core::aabbox3d &box = frust.getBoundingBox(); - core::array< const core::aabbox3d* > boxes; - video::SMaterial m; - m.Lighting = false; - driver->setMaterial(m); - if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) - { - TangentsOctree->getBoundingBoxes(box, boxes); - for (u32 b=0; bdraw3DBox(*boxes[b]); - } - - if ( DebugDataVisible & scene::EDS_BBOX ) - driver->draw3DBox(Box,video::SColor(0,255,0,0)); - } - } - break; - } -} - - -//! Removes a child from this scene node. -//! Implemented here, to be able to remove the shadow properly, if there is one, -//! or to remove attached childs. -bool COctreeSceneNode::removeChild(ISceneNode* child) -{ - if (child && Shadow == child) - { - Shadow->drop(); - Shadow = 0; - } - - return ISceneNode::removeChild(child); -} - - -//! Creates shadow volume scene node as child of this node -//! and returns a pointer to it. -IShadowVolumeSceneNode* COctreeSceneNode::addShadowVolumeSceneNode( - const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) -{ - if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) - return 0; - - if (!shadowMesh) - shadowMesh = Mesh; // if null is given, use the mesh of node - - if (Shadow) - Shadow->drop(); - - Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); - return Shadow; -} - - -//! returns the axis aligned bounding box of this node -const core::aabbox3d& COctreeSceneNode::getBoundingBox() const -{ - return Box; -} - - -//! creates the tree -/* 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. -Thanks to Auria for fixing major parts of this method. */ -bool COctreeSceneNode::createTree(IMesh* mesh) -{ - if (!mesh) - return false; - - MeshName = SceneManager->getMeshCache()->getMeshName(mesh); - - mesh->grab(); - deleteTree(); - - Mesh = mesh; - - const u32 beginTime = os::Timer::getRealTime(); - - u32 nodeCount = 0; - u32 polyCount = 0; - u32 i; - - Box = mesh->getBoundingBox(); - - if (mesh->getMeshBufferCount()) - { - // check for "larger" buffer types - VertexType = video::EVT_STANDARD; - u32 meshReserve = 0; - for (i=0; igetMeshBufferCount(); ++i) - { - const IMeshBuffer* b = mesh->getMeshBuffer(i); - if (b->getVertexCount() && b->getIndexCount()) - { - ++meshReserve; - if (b->getVertexType() == video::EVT_2TCOORDS) - VertexType = video::EVT_2TCOORDS; - else if (b->getVertexType() == video::EVT_TANGENTS) - VertexType = video::EVT_TANGENTS; - } - } - Materials.reallocate(Materials.size()+meshReserve); - - switch(VertexType) - { - case video::EVT_STANDARD: - { - StdMeshes.reallocate(StdMeshes.size() + meshReserve); - for (i=0; igetMeshBufferCount(); ++i) - { - IMeshBuffer* b = mesh->getMeshBuffer(i); - - if (b->getVertexCount() && b->getIndexCount()) - { - Materials.push_back(b->getMaterial()); - - StdMeshes.push_back(Octree::SMeshChunk()); - Octree::SMeshChunk &nchunk = StdMeshes.getLast(); - nchunk.MaterialId = Materials.size() - 1; - - u32 v; - nchunk.Vertices.reallocate(b->getVertexCount()); - switch (b->getVertexType()) - { - case video::EVT_STANDARD: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); - break; - case video::EVT_2TCOORDS: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); - break; - case video::EVT_TANGENTS: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); - break; - } - - polyCount += b->getIndexCount(); - - nchunk.Indices.reallocate(b->getIndexCount()); - for (v=0; vgetIndexCount(); ++v) - nchunk.Indices.push_back(b->getIndices()[v]); - } - } - - StdOctree = new Octree(StdMeshes, MinimalPolysPerNode); - nodeCount = StdOctree->getNodeCount(); - } - break; - case video::EVT_2TCOORDS: - { - LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve); - - for ( i=0; i < mesh->getMeshBufferCount(); ++i) - { - IMeshBuffer* b = mesh->getMeshBuffer(i); - - if (b->getVertexCount() && b->getIndexCount()) - { - Materials.push_back(b->getMaterial()); - LightMapMeshes.push_back(Octree::SMeshChunk()); - Octree::SMeshChunk& nchunk = LightMapMeshes.getLast(); - nchunk.MaterialId = Materials.size() - 1; - - if (UseVisibilityAndVBOs) - { - nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); - nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); - } - else - nchunk.setHardwareMappingHint(scene::EHM_STATIC); - - u32 v; - nchunk.Vertices.reallocate(b->getVertexCount()); - switch (b->getVertexType()) - { - case video::EVT_STANDARD: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); - break; - case video::EVT_2TCOORDS: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); - break; - case video::EVT_TANGENTS: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); - break; - } - - polyCount += b->getIndexCount(); - nchunk.Indices.reallocate(b->getIndexCount()); - for (v=0; vgetIndexCount(); ++v) - nchunk.Indices.push_back(b->getIndices()[v]); - } - } - - LightMapOctree = new Octree(LightMapMeshes, MinimalPolysPerNode); - nodeCount = LightMapOctree->getNodeCount(); - } - break; - case video::EVT_TANGENTS: - { - TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve); - - for (u32 i=0; igetMeshBufferCount(); ++i) - { - IMeshBuffer* b = mesh->getMeshBuffer(i); - - if (b->getVertexCount() && b->getIndexCount()) - { - Materials.push_back(b->getMaterial()); - TangentsMeshes.push_back(Octree::SMeshChunk()); - Octree::SMeshChunk& nchunk = TangentsMeshes.getLast(); - nchunk.MaterialId = Materials.size() - 1; - - u32 v; - nchunk.Vertices.reallocate(b->getVertexCount()); - switch (b->getVertexType()) - { - case video::EVT_STANDARD: - for (v=0; vgetVertexCount(); ++v) - { - const video::S3DVertex& tmpV = ((video::S3DVertex*)b->getVertices())[v]; - nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); - } - break; - case video::EVT_2TCOORDS: - for (v=0; vgetVertexCount(); ++v) - { - const video::S3DVertex2TCoords& tmpV = ((video::S3DVertex2TCoords*)b->getVertices())[v]; - nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); - } - break; - case video::EVT_TANGENTS: - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); - break; - } - - polyCount += b->getIndexCount(); - nchunk.Indices.reallocate(b->getIndexCount()); - for (v=0; vgetIndexCount(); ++v) - nchunk.Indices.push_back(b->getIndices()[v]); - } - } - - TangentsOctree = new Octree(TangentsMeshes, MinimalPolysPerNode); - nodeCount = TangentsOctree->getNodeCount(); - } - break; - } - } - - const u32 endTime = os::Timer::getRealTime(); - c8 tmp[255]; - sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", - endTime - beginTime, nodeCount, polyCount/3); - os::Printer::log(tmp, ELL_INFORMATION); - - return true; -} - - -//! returns the material based on the zero based index i. To get the amount -//! of materials used by this scene node, use getMaterialCount(). -//! This function is needed for inserting the node into the scene hirachy on a -//! optimal position for minimizing renderstate changes, but can also be used -//! to directly modify the material of a scene node. -video::SMaterial& COctreeSceneNode::getMaterial(u32 i) -{ - if ( i >= Materials.size() ) - return ISceneNode::getMaterial(i); - - return Materials[i]; -} - - -//! returns amount of materials used by this scene node. -u32 COctreeSceneNode::getMaterialCount() const -{ - return Materials.size(); -} - - -//! Writes attributes of the scene node. -void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const -{ - ISceneNode::serializeAttributes(out, options); - - out->addInt("MinimalPolysPerNode", MinimalPolysPerNode); - out->addString("Mesh", MeshName.c_str()); -} - - -//! Reads attributes of the scene node. -void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) -{ - const s32 oldMinimal = MinimalPolysPerNode; - - MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); - io::path newMeshStr = in->getAttributeAsString("Mesh"); - - IMesh* newMesh = 0; - - if (newMeshStr == "") - newMeshStr = MeshName; - - IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); - - if (newAnimatedMesh) - newMesh = newAnimatedMesh->getMesh(0); - - if (newMesh && ((MeshName != newMeshStr) || (MinimalPolysPerNode != oldMinimal))) - { - // recalculate tree - createTree(newMesh); - } - - ISceneNode::deserializeAttributes(in, options); -} - - -void COctreeSceneNode::deleteTree() -{ - delete StdOctree; - StdOctree = 0; - StdMeshes.clear(); - - delete LightMapOctree; - LightMapOctree = 0; - LightMapMeshes.clear(); - - delete TangentsOctree; - TangentsOctree = 0; - TangentsMeshes.clear(); - - Materials.clear(); - - if(Mesh) - Mesh->drop(); -} - -void COctreeSceneNode::setMesh(IMesh* mesh) -{ - createTree(mesh); -} - -IMesh* COctreeSceneNode::getMesh(void) -{ - return Mesh; -} - -void COctreeSceneNode::setReadOnlyMaterials(bool readonly) -{ - // Do nothing -} - -bool COctreeSceneNode::isReadOnlyMaterials() const -{ - return false; -} - - -} // end namespace scene -} // end namespace irr - +// Copyright (C) 2002-2012 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "COctreeSceneNode.h" +#include "Octree.h" +#include "ISceneManager.h" +#include "IVideoDriver.h" +#include "ICameraSceneNode.h" +#include "IMeshCache.h" +#include "IAnimatedMesh.h" +#include "IMaterialRenderer.h" +#include "os.h" +#include "CShadowVolumeSceneNode.h" + +namespace irr +{ +namespace scene +{ + + +//! constructor +COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr, + s32 id, s32 minimalPolysPerNode) + : IMeshSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0), + TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1), + MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0), + UseVBOs(OCTREE_USE_HARDWARE), UseVisibilityAndVBOs(OCTREE_USE_VISIBILITY), + BoxBased(OCTREE_BOX_BASED) +{ +#ifdef _DEBUG + setDebugName("COctreeSceneNode"); +#endif +} + + +//! destructor +COctreeSceneNode::~COctreeSceneNode() +{ + if (Shadow) + Shadow->drop(); + deleteTree(); +} + + +void COctreeSceneNode::OnRegisterSceneNode() +{ + if (IsVisible) + { + // because this node supports rendering of mixed mode meshes consisting of + // transparent and solid material at the same time, we need to go through all + // materials, check of what type they are and register this node for the right + // render pass according to that. + + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + PassCount = 0; + u32 transparentCount = 0; + u32 solidCount = 0; + + // count transparent and solid materials in this scene node + for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); + + if (rnd && rnd->isTransparent()) + ++transparentCount; + else + ++solidCount; + + if (solidCount && transparentCount) + break; + } + + // register according to material types counted + + if (solidCount) + SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID); + + if (transparentCount) + SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT); + + ISceneNode::OnRegisterSceneNode(); + } +} + + +//! renders the node. +void COctreeSceneNode::render() +{ + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + + if (VertexType == -1 || !driver) + return; + + ICameraSceneNode* camera = SceneManager->getActiveCamera(); + if (!camera) + return; + + bool isTransparentPass = + SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; + ++PassCount; + + driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); + + if (Shadow) + Shadow->updateShadowVolumes(); + + SViewFrustum frust = *camera->getViewFrustum(); + + //transform the frustum to the current absolute transformation + if ( !AbsoluteTransformation.isIdentity() ) + { + core::matrix4 invTrans(AbsoluteTransformation, core::matrix4::EM4CONST_INVERSE); + frust.transform(invTrans); + } + + const core::aabbox3d &box = frust.getBoundingBox(); + + switch (VertexType) + { + case video::EVT_STANDARD: + { + if (BoxBased) + StdOctree->calculatePolys(box); + else + StdOctree->calculatePolys(frust); + + const Octree::SIndexData* d = StdOctree->getIndexData(); + + for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); + const bool transparent = (rnd && rnd->isTransparent()); + + // only render transparent buffer if this is the transparent render pass + // and solid only in solid pass + if (transparent == isTransparentPass) + { + driver->setMaterial(Materials[i]); + driver->drawIndexedTriangleList( + &StdMeshes[i].Vertices[0], StdMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); + } + } + + // for debug purposes only + if (DebugDataVisible && !Materials.empty() && PassCount==1) + { + const core::aabbox3df& box = frust.getBoundingBox(); + core::array< const core::aabbox3d* > boxes; + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) + { + StdOctree->getBoundingBoxes(box, boxes); + for (u32 b=0; b!=boxes.size(); ++b) + driver->draw3DBox(*boxes[b]); + } + + if ( DebugDataVisible & scene::EDS_BBOX ) + driver->draw3DBox(Box,video::SColor(0,255,0,0)); + } + } + break; + case video::EVT_2TCOORDS: + { + if (BoxBased) + LightMapOctree->calculatePolys(box); + else + LightMapOctree->calculatePolys(frust); + + const Octree::SIndexData* d = LightMapOctree->getIndexData(); + + for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); + const bool transparent = (rnd && rnd->isTransparent()); + + // only render transparent buffer if this is the transparent render pass + // and solid only in solid pass + if (transparent == isTransparentPass) + { + driver->setMaterial(Materials[i]); + if (UseVBOs) + { + if (UseVisibilityAndVBOs) + { + u16* oldPointer = LightMapMeshes[i].Indices.pointer(); + const u32 oldSize = LightMapMeshes[i].Indices.size(); + LightMapMeshes[i].Indices.set_free_when_destroyed(false); + LightMapMeshes[i].Indices.set_pointer(d[i].Indices, d[i].CurrentSize, false, false); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + LightMapMeshes[i].Indices.set_pointer(oldPointer, oldSize); + LightMapMeshes[i].setDirty(scene::EBT_INDEX); + } + else + driver->drawMeshBuffer ( &LightMapMeshes[i] ); + } + else + driver->drawIndexedTriangleList( + &LightMapMeshes[i].Vertices[0], + LightMapMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); + } + } + + // for debug purposes only + if (DebugDataVisible && !Materials.empty() && PassCount==1) + { + const core::aabbox3d &box = frust.getBoundingBox(); + core::array< const core::aabbox3d* > boxes; + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) + { + LightMapOctree->getBoundingBoxes(box, boxes); + for (u32 b=0; bdraw3DBox(*boxes[b]); + } + + if ( DebugDataVisible & scene::EDS_BBOX ) + driver->draw3DBox(Box,video::SColor(0,255,0,0)); + } + } + break; + case video::EVT_TANGENTS: + { + if (BoxBased) + TangentsOctree->calculatePolys(box); + else + TangentsOctree->calculatePolys(frust); + + const Octree::SIndexData* d = TangentsOctree->getIndexData(); + + for (u32 i=0; igetMaterialRenderer(Materials[i].MaterialType); + const bool transparent = (rnd && rnd->isTransparent()); + + // only render transparent buffer if this is the transparent render pass + // and solid only in solid pass + if (transparent == isTransparentPass) + { + driver->setMaterial(Materials[i]); + driver->drawIndexedTriangleList( + &TangentsMeshes[i].Vertices[0], TangentsMeshes[i].Vertices.size(), + d[i].Indices, d[i].CurrentSize / 3); + } + } + + // for debug purposes only + if (DebugDataVisible && !Materials.empty() && PassCount==1) + { + const core::aabbox3d &box = frust.getBoundingBox(); + core::array< const core::aabbox3d* > boxes; + video::SMaterial m; + m.Lighting = false; + driver->setMaterial(m); + if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) + { + TangentsOctree->getBoundingBoxes(box, boxes); + for (u32 b=0; bdraw3DBox(*boxes[b]); + } + + if ( DebugDataVisible & scene::EDS_BBOX ) + driver->draw3DBox(Box,video::SColor(0,255,0,0)); + } + } + break; + } +} + + +//! Removes a child from this scene node. +//! Implemented here, to be able to remove the shadow properly, if there is one, +//! or to remove attached childs. +bool COctreeSceneNode::removeChild(ISceneNode* child) +{ + if (child && Shadow == child) + { + Shadow->drop(); + Shadow = 0; + } + + return ISceneNode::removeChild(child); +} + + +//! Creates shadow volume scene node as child of this node +//! and returns a pointer to it. +IShadowVolumeSceneNode* COctreeSceneNode::addShadowVolumeSceneNode( + const IMesh* shadowMesh, s32 id, bool zfailmethod, f32 infinity) +{ + if (!SceneManager->getVideoDriver()->queryFeature(video::EVDF_STENCIL_BUFFER)) + return 0; + + if (!shadowMesh) + shadowMesh = Mesh; // if null is given, use the mesh of node + + if (Shadow) + Shadow->drop(); + + Shadow = new CShadowVolumeSceneNode(shadowMesh, this, SceneManager, id, zfailmethod, infinity); + return Shadow; +} + + +//! returns the axis aligned bounding box of this node +const core::aabbox3d& COctreeSceneNode::getBoundingBox() const +{ + return Box; +} + + +//! creates the tree +/* 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. +Thanks to Auria for fixing major parts of this method. */ +bool COctreeSceneNode::createTree(IMesh* mesh) +{ + if (!mesh) + return false; + + MeshName = SceneManager->getMeshCache()->getMeshName(mesh); + + mesh->grab(); + deleteTree(); + + Mesh = mesh; + + const u32 beginTime = os::Timer::getRealTime(); + + u32 nodeCount = 0; + u32 polyCount = 0; + u32 i; + + Box = mesh->getBoundingBox(); + + if (mesh->getMeshBufferCount()) + { + // check for "larger" buffer types + VertexType = video::EVT_STANDARD; + u32 meshReserve = 0; + for (i=0; igetMeshBufferCount(); ++i) + { + const IMeshBuffer* b = mesh->getMeshBuffer(i); + if (b->getVertexCount() && b->getIndexCount()) + { + ++meshReserve; + if (b->getVertexType() == video::EVT_2TCOORDS) + VertexType = video::EVT_2TCOORDS; + else if (b->getVertexType() == video::EVT_TANGENTS) + VertexType = video::EVT_TANGENTS; + } + } + Materials.reallocate(Materials.size()+meshReserve); + + switch(VertexType) + { + case video::EVT_STANDARD: + { + StdMeshes.reallocate(StdMeshes.size() + meshReserve); + for (i=0; igetMeshBufferCount(); ++i) + { + IMeshBuffer* b = mesh->getMeshBuffer(i); + + if (b->getVertexCount() && b->getIndexCount()) + { + Materials.push_back(b->getMaterial()); + + StdMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk &nchunk = StdMeshes.getLast(); + nchunk.MaterialId = Materials.size() - 1; + + u32 v; + nchunk.Vertices.reallocate(b->getVertexCount()); + switch (b->getVertexType()) + { + case video::EVT_STANDARD: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); + break; + case video::EVT_2TCOORDS: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); + break; + case video::EVT_TANGENTS: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); + break; + } + + polyCount += b->getIndexCount(); + + nchunk.Indices.reallocate(b->getIndexCount()); + for (v=0; vgetIndexCount(); ++v) + nchunk.Indices.push_back(b->getIndices()[v]); + } + } + + StdOctree = new Octree(StdMeshes, MinimalPolysPerNode); + nodeCount = StdOctree->getNodeCount(); + } + break; + case video::EVT_2TCOORDS: + { + LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve); + + for ( i=0; i < mesh->getMeshBufferCount(); ++i) + { + IMeshBuffer* b = mesh->getMeshBuffer(i); + + if (b->getVertexCount() && b->getIndexCount()) + { + Materials.push_back(b->getMaterial()); + LightMapMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = LightMapMeshes.getLast(); + nchunk.MaterialId = Materials.size() - 1; + + if (UseVisibilityAndVBOs) + { + nchunk.setHardwareMappingHint(scene::EHM_STATIC, scene::EBT_VERTEX); + nchunk.setHardwareMappingHint(scene::EHM_DYNAMIC, scene::EBT_INDEX); + } + else + nchunk.setHardwareMappingHint(scene::EHM_STATIC); + + u32 v; + nchunk.Vertices.reallocate(b->getVertexCount()); + switch (b->getVertexType()) + { + case video::EVT_STANDARD: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); + break; + case video::EVT_2TCOORDS: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); + break; + case video::EVT_TANGENTS: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); + break; + } + + polyCount += b->getIndexCount(); + nchunk.Indices.reallocate(b->getIndexCount()); + for (v=0; vgetIndexCount(); ++v) + nchunk.Indices.push_back(b->getIndices()[v]); + } + } + + LightMapOctree = new Octree(LightMapMeshes, MinimalPolysPerNode); + nodeCount = LightMapOctree->getNodeCount(); + } + break; + case video::EVT_TANGENTS: + { + TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve); + + for (u32 i=0; igetMeshBufferCount(); ++i) + { + IMeshBuffer* b = mesh->getMeshBuffer(i); + + if (b->getVertexCount() && b->getIndexCount()) + { + Materials.push_back(b->getMaterial()); + TangentsMeshes.push_back(Octree::SMeshChunk()); + Octree::SMeshChunk& nchunk = TangentsMeshes.getLast(); + nchunk.MaterialId = Materials.size() - 1; + + u32 v; + nchunk.Vertices.reallocate(b->getVertexCount()); + switch (b->getVertexType()) + { + case video::EVT_STANDARD: + for (v=0; vgetVertexCount(); ++v) + { + const video::S3DVertex& tmpV = ((video::S3DVertex*)b->getVertices())[v]; + nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); + } + break; + case video::EVT_2TCOORDS: + for (v=0; vgetVertexCount(); ++v) + { + const video::S3DVertex2TCoords& tmpV = ((video::S3DVertex2TCoords*)b->getVertices())[v]; + nchunk.Vertices.push_back(video::S3DVertexTangents(tmpV.Pos, tmpV.Color, tmpV.TCoords)); + } + break; + case video::EVT_TANGENTS: + for (v=0; vgetVertexCount(); ++v) + nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); + break; + } + + polyCount += b->getIndexCount(); + nchunk.Indices.reallocate(b->getIndexCount()); + for (v=0; vgetIndexCount(); ++v) + nchunk.Indices.push_back(b->getIndices()[v]); + } + } + + TangentsOctree = new Octree(TangentsMeshes, MinimalPolysPerNode); + nodeCount = TangentsOctree->getNodeCount(); + } + break; + } + } + + const u32 endTime = os::Timer::getRealTime(); + c8 tmp[255]; + sprintf(tmp, "Needed %ums to create Octree SceneNode.(%u nodes, %u polys)", + endTime - beginTime, nodeCount, polyCount/3); + os::Printer::log(tmp, ELL_INFORMATION); + + return true; +} + + +//! returns the material based on the zero based index i. To get the amount +//! of materials used by this scene node, use getMaterialCount(). +//! This function is needed for inserting the node into the scene hirachy on a +//! optimal position for minimizing renderstate changes, but can also be used +//! to directly modify the material of a scene node. +video::SMaterial& COctreeSceneNode::getMaterial(u32 i) +{ + if ( i >= Materials.size() ) + return ISceneNode::getMaterial(i); + + return Materials[i]; +} + + +//! returns amount of materials used by this scene node. +u32 COctreeSceneNode::getMaterialCount() const +{ + return Materials.size(); +} + + +//! Writes attributes of the scene node. +void COctreeSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const +{ + ISceneNode::serializeAttributes(out, options); + + out->addInt("MinimalPolysPerNode", MinimalPolysPerNode); + out->addString("Mesh", MeshName.c_str()); +} + + +//! Reads attributes of the scene node. +void COctreeSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options) +{ + const s32 oldMinimal = MinimalPolysPerNode; + + MinimalPolysPerNode = in->getAttributeAsInt("MinimalPolysPerNode"); + io::path newMeshStr = in->getAttributeAsString("Mesh"); + + IMesh* newMesh = 0; + + if (newMeshStr == "") + newMeshStr = MeshName; + + IAnimatedMesh* newAnimatedMesh = SceneManager->getMesh(newMeshStr.c_str()); + + if (newAnimatedMesh) + newMesh = newAnimatedMesh->getMesh(0); + + if (newMesh && ((MeshName != newMeshStr) || (MinimalPolysPerNode != oldMinimal))) + { + // recalculate tree + createTree(newMesh); + } + + ISceneNode::deserializeAttributes(in, options); +} + + +void COctreeSceneNode::deleteTree() +{ + delete StdOctree; + StdOctree = 0; + StdMeshes.clear(); + + delete LightMapOctree; + LightMapOctree = 0; + LightMapMeshes.clear(); + + delete TangentsOctree; + TangentsOctree = 0; + TangentsMeshes.clear(); + + Materials.clear(); + + if(Mesh) + Mesh->drop(); +} + +void COctreeSceneNode::setMesh(IMesh* mesh) +{ + createTree(mesh); +} + +IMesh* COctreeSceneNode::getMesh(void) +{ + return Mesh; +} + +void COctreeSceneNode::setReadOnlyMaterials(bool readonly) +{ + // Do nothing +} + +bool COctreeSceneNode::isReadOnlyMaterials() const +{ + return false; +} + + +} // end namespace scene +} // end namespace irr + -- cgit v1.1