Avoid warning and make local variable lower-case.
git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@6000 dfc29bdd-3216-0410-991c-e03cc46cb475
This commit is contained in:
681
source/Irrlicht/COctreeSceneNode.cpp
Normal file
681
source/Irrlicht/COctreeSceneNode.cpp
Normal file
@@ -0,0 +1,681 @@
|
||||
// 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 "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_OCTREE_SCENENODE_
|
||||
|
||||
#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"
|
||||
#ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
#include "CShadowVolumeSceneNode.h"
|
||||
#else
|
||||
#include "IShadowVolumeSceneNode.h"
|
||||
#endif // _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
#include "EProfileIDs.h"
|
||||
#include "IProfiler.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace scene
|
||||
{
|
||||
|
||||
|
||||
//! constructor
|
||||
COctreeSceneNode::COctreeSceneNode(ISceneNode* parent, ISceneManager* mgr,
|
||||
s32 id, s32 minimalPolysPerNode)
|
||||
: IOctreeSceneNode(parent, mgr, id), StdOctree(0), LightMapOctree(0),
|
||||
TangentsOctree(0), VertexType((video::E_VERTEX_TYPE)-1),
|
||||
MinimalPolysPerNode(minimalPolysPerNode), Mesh(0), Shadow(0),
|
||||
UseVBOs(EOV_NO_VBO), PolygonChecks(EOPC_BOX)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("COctreeSceneNode");
|
||||
#endif
|
||||
|
||||
IRR_PROFILE(
|
||||
static bool initProfile = false;
|
||||
if (!initProfile )
|
||||
{
|
||||
initProfile = true;
|
||||
getProfiler().add(EPID_OC_RENDER, L"render octnode", L"Irrlicht scene");
|
||||
getProfiler().add(EPID_OC_CALCPOLYS, L"calc octnode", L"Irrlicht scene");
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
//! 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; i<Materials.size(); ++i)
|
||||
{
|
||||
const video::IMaterialRenderer* const rnd =
|
||||
driver->getMaterialRenderer(Materials[i].MaterialType);
|
||||
|
||||
if ((rnd && rnd->isTransparent()) || Materials[i].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();
|
||||
}
|
||||
}
|
||||
|
||||
template <class VT>
|
||||
void renderMeshBuffer(video::IVideoDriver* driver, EOCTREENODE_VBO useVBO, typename Octree<VT>::SMeshChunk& meshChunk, const typename Octree<VT>::SIndexData& indexData)
|
||||
{
|
||||
switch ( useVBO )
|
||||
{
|
||||
case EOV_NO_VBO:
|
||||
driver->drawIndexedTriangleList(
|
||||
&meshChunk.Vertices[0],
|
||||
meshChunk.Vertices.size(),
|
||||
indexData.Indices, indexData.CurrentSize / 3);
|
||||
break;
|
||||
case EOV_USE_VBO:
|
||||
driver->drawMeshBuffer ( &meshChunk );
|
||||
break;
|
||||
case EOV_USE_VBO_WITH_VISIBITLY:
|
||||
{
|
||||
u16* oldPointer = meshChunk.Indices.pointer();
|
||||
const u32 oldSize = meshChunk.Indices.size();
|
||||
meshChunk.Indices.set_free_when_destroyed(false);
|
||||
meshChunk.Indices.set_pointer(indexData.Indices, indexData.CurrentSize, false, false);
|
||||
meshChunk.setDirty(scene::EBT_INDEX);
|
||||
driver->drawMeshBuffer ( &meshChunk );
|
||||
meshChunk.Indices.set_pointer(oldPointer, oldSize);
|
||||
meshChunk.setDirty(scene::EBT_INDEX);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! renders the node.
|
||||
void COctreeSceneNode::render()
|
||||
{
|
||||
IRR_PROFILE(CProfileScope psRender(EPID_OC_RENDER);)
|
||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||
|
||||
if (!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<float> &box = frust.getBoundingBox();
|
||||
|
||||
switch (VertexType)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
{
|
||||
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
|
||||
switch ( PolygonChecks )
|
||||
{
|
||||
case EOPC_BOX:
|
||||
StdOctree->calculatePolys(box);
|
||||
break;
|
||||
case EOPC_FRUSTUM:
|
||||
StdOctree->calculatePolys(frust);
|
||||
break;
|
||||
}
|
||||
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
|
||||
|
||||
const Octree<video::S3DVertex>::SIndexData* d = StdOctree->getIndexData();
|
||||
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
{
|
||||
if ( 0 == d[i].CurrentSize )
|
||||
continue;
|
||||
|
||||
const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(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]);
|
||||
renderMeshBuffer<video::S3DVertex>(driver, UseVBOs, StdMeshes[i], d[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
{
|
||||
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
|
||||
switch ( PolygonChecks )
|
||||
{
|
||||
case EOPC_BOX:
|
||||
LightMapOctree->calculatePolys(box);
|
||||
break;
|
||||
case EOPC_FRUSTUM:
|
||||
LightMapOctree->calculatePolys(frust);
|
||||
break;
|
||||
}
|
||||
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
|
||||
|
||||
const Octree<video::S3DVertex2TCoords>::SIndexData* d = LightMapOctree->getIndexData();
|
||||
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
{
|
||||
if ( 0 == d[i].CurrentSize )
|
||||
continue;
|
||||
|
||||
const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(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]);
|
||||
|
||||
renderMeshBuffer<video::S3DVertex2TCoords>(driver, UseVBOs, LightMapMeshes[i], d[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
IRR_PROFILE(getProfiler().start(EPID_OC_CALCPOLYS));
|
||||
switch ( PolygonChecks )
|
||||
{
|
||||
case EOPC_BOX:
|
||||
TangentsOctree->calculatePolys(box);
|
||||
break;
|
||||
case EOPC_FRUSTUM:
|
||||
TangentsOctree->calculatePolys(frust);
|
||||
break;
|
||||
}
|
||||
IRR_PROFILE(getProfiler().stop(EPID_OC_CALCPOLYS));
|
||||
|
||||
const Octree<video::S3DVertexTangents>::SIndexData* d = TangentsOctree->getIndexData();
|
||||
|
||||
for (u32 i=0; i<Materials.size(); ++i)
|
||||
{
|
||||
if ( 0 == d[i].CurrentSize )
|
||||
continue;
|
||||
|
||||
const video::IMaterialRenderer* const rnd = driver->getMaterialRenderer(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]);
|
||||
renderMeshBuffer<video::S3DVertexTangents>(driver, UseVBOs, TangentsMeshes[i], d[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// for debug purposes only
|
||||
if (DebugDataVisible && !Materials.empty() && PassCount==1)
|
||||
{
|
||||
core::array< const core::aabbox3d<f32>* > boxes;
|
||||
video::SMaterial m;
|
||||
m.Lighting = false;
|
||||
driver->setMaterial(m);
|
||||
if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS )
|
||||
{
|
||||
switch (VertexType)
|
||||
{
|
||||
case video::EVT_STANDARD:
|
||||
StdOctree->getBoundingBoxes(box, boxes);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
LightMapOctree->getBoundingBoxes(box, boxes);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
TangentsOctree->getBoundingBoxes(box, boxes);
|
||||
break;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//! 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);
|
||||
}
|
||||
|
||||
void COctreeSceneNode::setUseVBO(EOCTREENODE_VBO useVBO)
|
||||
{
|
||||
UseVBOs = useVBO;
|
||||
if ( Mesh )
|
||||
createTree(Mesh);
|
||||
}
|
||||
|
||||
EOCTREENODE_VBO COctreeSceneNode::getUseVBO() const
|
||||
{
|
||||
return UseVBOs;
|
||||
}
|
||||
|
||||
void COctreeSceneNode::setPolygonChecks(EOCTREE_POLYGON_CHECKS checks)
|
||||
{
|
||||
PolygonChecks = checks;
|
||||
}
|
||||
|
||||
EOCTREE_POLYGON_CHECKS COctreeSceneNode::getPolygonChecks() const
|
||||
{
|
||||
return PolygonChecks;
|
||||
}
|
||||
|
||||
//! 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)
|
||||
{
|
||||
#ifdef _IRR_COMPILE_WITH_SHADOW_VOLUME_SCENENODE_
|
||||
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;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//! returns the axis aligned bounding box of this node
|
||||
const core::aabbox3d<f32>& 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 "largest" buffer types
|
||||
// Also dropping buffers/materials for empty buffer
|
||||
// (which looks like a horrible idea. If a user wanted that material without mesh he should still get it...
|
||||
// but not going to change that now. Only documenting it after figuring out what happens here.
|
||||
// It works at least as Materials are reset in deleteTree).
|
||||
VertexType = video::EVT_STANDARD;
|
||||
u32 meshReserve = 0;
|
||||
for (i=0; i<mesh->getMeshBufferCount(); ++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; i<mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
|
||||
if (b->getVertexCount() && b->getIndexCount())
|
||||
{
|
||||
Materials.push_back(b->getMaterial());
|
||||
|
||||
StdMeshes.push_back(Octree<video::S3DVertex>::SMeshChunk());
|
||||
Octree<video::S3DVertex>::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; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
|
||||
nchunk.Indices.reallocate(b->getIndexCount());
|
||||
for (v=0; v<b->getIndexCount(); ++v)
|
||||
nchunk.Indices.push_back(b->getIndices()[v]);
|
||||
}
|
||||
}
|
||||
|
||||
StdOctree = new Octree<video::S3DVertex>(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<video::S3DVertex2TCoords>::SMeshChunk());
|
||||
Octree<video::S3DVertex2TCoords>::SMeshChunk& nchunk = LightMapMeshes.getLast();
|
||||
nchunk.MaterialId = Materials.size() - 1;
|
||||
|
||||
if (UseVBOs == EOV_USE_VBO_WITH_VISIBITLY)
|
||||
{
|
||||
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; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_2TCOORDS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]);
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
for (v=0; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
nchunk.Indices.reallocate(b->getIndexCount());
|
||||
for (v=0; v<b->getIndexCount(); ++v)
|
||||
nchunk.Indices.push_back(b->getIndices()[v]);
|
||||
}
|
||||
}
|
||||
|
||||
LightMapOctree = new Octree<video::S3DVertex2TCoords>(LightMapMeshes, MinimalPolysPerNode);
|
||||
nodeCount = LightMapOctree->getNodeCount();
|
||||
}
|
||||
break;
|
||||
case video::EVT_TANGENTS:
|
||||
{
|
||||
TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve);
|
||||
|
||||
for (u32 i=0; i<mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
IMeshBuffer* b = mesh->getMeshBuffer(i);
|
||||
|
||||
if (b->getVertexCount() && b->getIndexCount())
|
||||
{
|
||||
Materials.push_back(b->getMaterial());
|
||||
TangentsMeshes.push_back(Octree<video::S3DVertexTangents>::SMeshChunk());
|
||||
Octree<video::S3DVertexTangents>::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; v<b->getVertexCount(); ++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; v<b->getVertexCount(); ++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; v<b->getVertexCount(); ++v)
|
||||
nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]);
|
||||
break;
|
||||
}
|
||||
|
||||
polyCount += b->getIndexCount();
|
||||
nchunk.Indices.reallocate(b->getIndexCount());
|
||||
for (v=0; v<b->getIndexCount(); ++v)
|
||||
nchunk.Indices.push_back(b->getIndices()[v]);
|
||||
}
|
||||
}
|
||||
|
||||
TangentsOctree = new Octree<video::S3DVertexTangents>(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.
|
||||
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
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_OCTREE_SCENENODE_
|
Reference in New Issue
Block a user