Octree serialization to avoid huge loading time

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Raibaz
Posts: 4
Joined: Mon Oct 17, 2005 7:33 am

Octree serialization to avoid huge loading time

Post by Raibaz »

Hi there,

I have a very big 3d studio model representing a museum to load in my application...of course i use an OctTreeSceneNode to represent it, but the model is so big that actually creating the octree takes up to 15 seconds and creating the triangle selector takes an amazing 5 minutes...

Probably the best idea would be to split the model into separate rooms and use a scene node for each, but i'm a poop at using 3d studio and don't have anyone who could do it.

I searched the forum to find a way to serialize the octree object into a file to avoid the mesh splitting calculations every time i load the mesh, the idea would be to have a standalone program that stores all the octree and triangleselector data in a file and a method that loads this data in my application, but it seems that this issue hasn't been addressed yet...any hints about someone that had this same problem and found a solution?

Thanx in advance
hybrid

Post by hybrid »

There are file formats which support precalculated octrees, but Irrlicht does not support this, yet. Would be a good thing to add, though.
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Post by CuteAlien »

Creating an COctTreeTriangleSelector for OctTreeSceneNode's was also too slow for me. But the OctTreeSceneNode has certainly already an octree, so i wrote a selector which does use that octree and which get's created after the octree generation of the OctTreeSceneNode. I have still the problem that it returns to many triangles sometimes, but it doesn't seem to be a problem of my selector, as i have exactly the same problem with the original COctTreeTriangleSelector.

The header (called "COctTreeSceneNodeTriangleSelector.h"):

Code: Select all

#ifndef __C_OCT_TREE_SCENE_NODETRIANGLE_SELECTOR_H_INCLUDED__
#define __C_OCT_TREE_SCENE_NODETRIANGLE_SELECTOR_H_INCLUDED__

#include "ITriangleSelector.h"

namespace irr
{
namespace scene
{

class COctTreeSceneNode;

//! triangle selector which does use the OctTree already available for a COctTreeSceneNode
class COctTreeSceneNodeTriangleSelector : public ITriangleSelector
{
public:

	//! Constructs a selector based on a mesh
	COctTreeSceneNodeTriangleSelector(COctTreeSceneNode* node);

	~COctTreeSceneNodeTriangleSelector();

	//! Returns amount of all available triangles in this selector
	virtual s32 getTriangleCount() const;

	//! Gets all triangles.
	virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
		s32& outTriangleCount, const core::matrix4* transform=0);

	//! Gets all triangles which lie within a specific bounding box.
	void getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
		const core::aabbox3d<f32>& box, const core::matrix4* transform=0);

	//! Gets all triangles which have or may have contact with a 3d line.
	virtual void getTriangles(core::triangle3df* triangles, s32 arraySize,
		s32& outTriangleCount, const core::line3d<f32>& line,
		const core::matrix4* transform=0);

private:
    COctTreeSceneNode * SceneNode;
};

} // end namespace scene
} // end namespace irr

#endif // __C_OCT_TREE_SCENE_NODETRIANGLE_SELECTOR_H_INCLUDED__
The sourcefile (called "COctTreeSceneNodeTriangleSelector.cpp"):

Code: Select all

#include "COctTreeSceneNodeTriangleSelector.h"
#include "COctTreeSceneNode.h"
#include "OctTree.h"

using namespace irr;
using namespace scene;

COctTreeSceneNodeTriangleSelector::COctTreeSceneNodeTriangleSelector(COctTreeSceneNode* node)
: SceneNode(node)
{
}

COctTreeSceneNodeTriangleSelector::~COctTreeSceneNodeTriangleSelector()
{
}

s32 COctTreeSceneNodeTriangleSelector::getTriangleCount() const
{
    int triangleCount = 0;
    switch (SceneNode->vertexType)
    {
    case video::EVT_STANDARD:
        {
            for ( int i=0; i < SceneNode->StdMeshes.size(); ++i )
            {
                triangleCount += SceneNode->StdMeshes[i].Indices.size();
            }
            triangleCount /= 3;
            break;
        }
    case video::EVT_2TCOORDS:
        {
            for ( int i=0; i < SceneNode->LightMapMeshes.size(); ++i )
            {
                triangleCount += SceneNode->LightMapMeshes[i].Indices.size();
            }
            triangleCount /= 3;

            break;
        }
    }
    return triangleCount;
}

void COctTreeSceneNodeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
		s32& outTriangleCount, const core::matrix4* transform)
{
    outTriangleCount = 0;
    if ( !arraySize )
        return;
	core::matrix4 mat;

	if (transform)
		mat = (*transform);

	if (SceneNode)
		mat *= SceneNode->getAbsoluteTransformation();

    switch (SceneNode->vertexType)
    {
    case video::EVT_STANDARD:
        {
            for ( int i=0; i < SceneNode->StdMeshes.size(); ++i )
            {
                OctTree<video::S3DVertex>::SMeshChunk &mesh = SceneNode->StdMeshes[i];
                for ( int t=0; t<mesh.Indices.size(); t+=3 )
                {
                    triangles[outTriangleCount].pointA = mesh.Vertices[ mesh.Indices[t] ].Pos;
                    triangles[outTriangleCount].pointB = mesh.Vertices[ mesh.Indices[t+1] ].Pos;
                    triangles[outTriangleCount].pointC = mesh.Vertices[ mesh.Indices[t+2] ].Pos;
                    mat.transformVect(triangles[outTriangleCount].pointA);
                    mat.transformVect(triangles[outTriangleCount].pointB);
                    mat.transformVect(triangles[outTriangleCount].pointC);

                    if ( ++outTriangleCount >= arraySize )
                        return;
                }
            }
            break;
        }
    case video::EVT_2TCOORDS:
        {
            for ( int i=0; i < SceneNode->LightMapMeshes.size(); ++i )
            {
                OctTree<video::S3DVertex2TCoords>::SMeshChunk &mesh = SceneNode->LightMapMeshes[i];
                for ( int t=0; t<mesh.Indices.size(); t+=3 )
                {
                    triangles[outTriangleCount].pointA = mesh.Vertices[ mesh.Indices[t] ].Pos;
                    triangles[outTriangleCount].pointB = mesh.Vertices[ mesh.Indices[t+1] ].Pos;
                    triangles[outTriangleCount].pointC = mesh.Vertices[ mesh.Indices[t+2] ].Pos;
                    mat.transformVect(triangles[outTriangleCount].pointA);
                    mat.transformVect(triangles[outTriangleCount].pointB);
                    mat.transformVect(triangles[outTriangleCount].pointC);

                    if ( ++outTriangleCount >= arraySize )
                        return;
                }
            }
            break;
        }
    }
}

void COctTreeSceneNodeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize, s32& outTriangleCount,
		const core::aabbox3d<f32>& box, const core::matrix4* transform)
{
   outTriangleCount = 0;
    if ( !arraySize )
        return;
	core::matrix4 mat;

	if (SceneNode)
		mat = SceneNode->getAbsoluteTransformation();

	mat.makeInverse();
	core::aabbox3d<f32> invbox = box;
	mat.transformBox(invbox);

	mat.makeIdentity();

	if (transform)
		mat = (*transform);

	if (SceneNode)
		mat *= SceneNode->getAbsoluteTransformation();

	switch(SceneNode->vertexType)
	{
	case video::EVT_STANDARD:
		{
		    SceneNode->StdOctTree->calculatePolys(invbox);
            OctTree<video::S3DVertex>::SIndexData* d =  SceneNode->StdOctTree->getIndexData();

            for ( int i=0; i < SceneNode->StdMeshes.size(); ++i )
            {
                OctTree<video::S3DVertex>::SMeshChunk &mesh = SceneNode->StdMeshes[i];

                for ( int t=0; t<d[i].CurrentSize; t+=3 )
                {
                    triangles[outTriangleCount].pointA = mesh.Vertices[ d[i].Indices[t] ].Pos;
                    triangles[outTriangleCount].pointB = mesh.Vertices[ d[i].Indices[t+1] ].Pos;
                    triangles[outTriangleCount].pointC = mesh.Vertices[ d[i].Indices[t+2] ].Pos;
                    mat.transformVect(triangles[outTriangleCount].pointA);
                    mat.transformVect(triangles[outTriangleCount].pointB);
                    mat.transformVect(triangles[outTriangleCount].pointC);

                    if ( ++outTriangleCount >= arraySize )
                        return;
                }
            }

		    break;
		}
    case video::EVT_2TCOORDS:
        {
            SceneNode->LightMapOctTree->calculatePolys(invbox);
            OctTree<video::S3DVertex2TCoords>::SIndexData* d = SceneNode->LightMapOctTree->getIndexData();

            for ( int i=0; i < SceneNode->LightMapMeshes.size(); ++i )
            {
                OctTree<video::S3DVertex2TCoords>::SMeshChunk &mesh = SceneNode->LightMapMeshes[i];

                for ( int t=0; t<d[i].CurrentSize; t+=3 )
                {
                    triangles[outTriangleCount].pointA = mesh.Vertices[ d[i].Indices[t] ].Pos;
                    triangles[outTriangleCount].pointB = mesh.Vertices[ d[i].Indices[t+1] ].Pos;
                    triangles[outTriangleCount].pointC = mesh.Vertices[ d[i].Indices[t+2] ].Pos;
                    mat.transformVect(triangles[outTriangleCount].pointA);
                    mat.transformVect(triangles[outTriangleCount].pointB);
                    mat.transformVect(triangles[outTriangleCount].pointC);

                    if ( ++outTriangleCount >= arraySize )
                        return;
                }
            }

            break;
        }
	}
}

void COctTreeSceneNodeTriangleSelector::getTriangles(core::triangle3df* triangles, s32 arraySize,
		s32& outTriangleCount, const core::line3d<f32>& line, const core::matrix4* transform)
{
	core::aabbox3d<f32> box(line.start);
	box.addInternalPoint(line.end);

	// TODO: Could be optimized for line a little bit more.
	COctTreeSceneNodeTriangleSelector::getTriangles(triangles, arraySize, outTriangleCount,	box, transform);
}
in COctTreeSceneNode i added COctTreeSceneNodeTriangleSelector as friend in the public section:

Code: Select all

friend class COctTreeSceneNodeTriangleSelector;
COctTreeSceneNode.cpp needs to add the following include:

Code: Select all

#include "COctTreeSceneNodeTriangleSelector.h"
and in bool COctTreeSceneNode::createTree(IMesh* mesh) i add the selector at the end of the function:

Code: Select all

ITriangleSelector* selector = new COctTreeSceneNodeTriangleSelector(this);
setTriangleSelector(selector);

edit: Ups, found some minor bugs after posting, fixed those
Raibaz
Posts: 4
Joined: Mon Oct 17, 2005 7:33 am

Post by Raibaz »

Thanks a lot for the tip, i'll try your octtree triangle selector and give you feedback on my results :)
Post Reply