diff --git a/source/Irrlicht/COctreeSceneNode.cpp b/source/Irrlicht/COctreeSceneNode.cpp index 940c16ae..30072465 100644 --- a/source/Irrlicht/COctreeSceneNode.cpp +++ b/source/Irrlicht/COctreeSceneNode.cpp @@ -289,6 +289,8 @@ const core::aabbox3d& COctreeSceneNode::getBoundingBox() const //! 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) @@ -301,7 +303,7 @@ bool COctreeSceneNode::createTree(IMesh* mesh) Mesh = mesh; - u32 beginTime = os::Timer::getRealTime(); + const u32 beginTime = os::Timer::getRealTime(); u32 nodeCount = 0; u32 polyCount = 0; @@ -311,12 +313,28 @@ bool COctreeSceneNode::createTree(IMesh* mesh) if (mesh->getMeshBufferCount()) { - VertexType = mesh->getMeshBuffer(0)->getVertexType(); + // 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); @@ -331,8 +349,21 @@ bool COctreeSceneNode::createTree(IMesh* mesh) u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); + 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(); @@ -348,22 +379,11 @@ bool COctreeSceneNode::createTree(IMesh* mesh) break; case video::EVT_2TCOORDS: { - IMeshBuffer* b; - u32 meshReserve = 0; - for ( i=0; i < mesh->getMeshBufferCount(); ++i) - { - b = mesh->getMeshBuffer(i); - if (b->getVertexCount() && b->getIndexCount()) - { - meshReserve += 1; - } - - } - LightMapMeshes.reallocate ( LightMapMeshes.size() + meshReserve ); + LightMapMeshes.reallocate(LightMapMeshes.size() + meshReserve); for ( i=0; i < mesh->getMeshBufferCount(); ++i) { - b = mesh->getMeshBuffer(i); + IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { @@ -382,8 +402,21 @@ bool COctreeSceneNode::createTree(IMesh* mesh) u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); + 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()); @@ -398,6 +431,8 @@ bool COctreeSceneNode::createTree(IMesh* mesh) break; case video::EVT_TANGENTS: { + TangentsMeshes.reallocate(TangentsMeshes.size() + meshReserve); + for (u32 i=0; igetMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); @@ -411,8 +446,27 @@ bool COctreeSceneNode::createTree(IMesh* mesh) u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); - for (v=0; vgetVertexCount(); ++v) - nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); + 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()); @@ -428,7 +482,7 @@ bool COctreeSceneNode::createTree(IMesh* mesh) } } - u32 endTime = os::Timer::getRealTime(); + 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);