OctreeSceneManager

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

OctreeSceneManager

Post by sudi »

Ok this scenenode manages the scene for you in a octree like manner.
just attach the nodes you want to be managed as children to this scenenode.
rest is done for ya.

Code: Select all

#include <irrlicht.h>
#include "COcttreeManager.h"
int main()
{
   irr::IrrlichtDevice *device = irr::createDevice(irr::video::EDT_OPENGL ,irr::core::dimension2d<irr::u32>(640, 480));

   irr::scene::ISceneManager* smgr = device->getSceneManager();
   irr::scene::ISceneNode* tree = new COcttreeManager(smgr->getRootSceneNode(),  smgr, irr::core::aabbox3d<irr::f32>(-1000,-1000,-1000,1000,1000,1000));


   //now imagine you have a scenenode called Node just do
   Node->setParent(tree); //now its managed by the octtree
   //or just pass tree as parent during creation

   //now just do your normal renderloop everything is done by the tree node you don't have to call any additional code
}
COcttreeManager.h

Code: Select all

#ifndef COCTTREEMANAGER_H
#define COCTTREEMANAGER_H

#include <irrlicht.h>

class COcttreeManager : public irr::scene::ISceneNode
{
public:
    struct OcttreeNode;
    struct OcttreeAnimator : irr::scene::ISceneNodeAnimator
    {
        OcttreeAnimator(irr::scene::ISceneNode* node, OcttreeNode* Root);
        ~OcttreeAnimator(void);
        void animateNode(irr::scene::ISceneNode* node, irr::u32 timeMs);
        irr::scene::ISceneNodeAnimator* createClone(irr::scene::ISceneNode* node, irr::scene::ISceneManager* newManager=0);
        irr::scene::ESCENE_NODE_ANIMATOR_TYPE getType() const;

        bool operator==(const irr::scene::ISceneNode* node)
        {
            return Node == node?true:false;
        }
        void setNode(OcttreeNode* node);

        irr::scene::ISceneNode* Node;
        irr::core::list<OcttreeAnimator*>::Iterator IT;
        OcttreeNode* CurrentNode;
        OcttreeNode* RootNode;
    };
    struct OcttreeNode
    {
        OcttreeNode(OcttreeNode* parent, const irr::core::aabbox3d<irr::f32>& box, irr::f32 minvolume, irr::s32 iterations);
        ~OcttreeNode(void);
        bool fitIntoChild(irr::scene::ISceneNode* node);
        void insert(irr::scene::ISceneNode* node);
        void clean(void);
        void clear(void);
        OcttreeNode* getRoot(void);

        void getNodes(const irr::core::aabbox3d<irr::f32>& box, irr::core::list<irr::scene::ISceneNode*>& nodes);
        void getNodes(const irr::scene::SViewFrustum& frustrum, irr::core::list<irr::scene::ISceneNode*>& nodes);

        void renderDebug(irr::video::IVideoDriver* driver);

        irr::core::aabbox3d<irr::f32> BoundingBox;
        irr::core::list<OcttreeAnimator*> SceneNodes;
        irr::core::aabbox3d<irr::f32> ChildBoxes[8];
        OcttreeNode* Children[8];
        OcttreeNode* Parent;
        irr::f32 MinVolume;
    };
    /** Default constructor */
    COcttreeManager(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, const irr::core::aabbox3d<irr::f32>& worldsize, irr::f32 MinVolume = 100.f, irr::s32 id=-1);
    /** Default destructor */
    virtual ~COcttreeManager();

    //ISceneNode
    void OnRegisterSceneNode(void);
    void OnAnimate(irr::u32 timeMs);
    void render(void);
    const irr::core::aabbox3d<irr::f32>& getBoundingBox() const;
    void addAnimator(irr::scene::ISceneNodeAnimator* animator) {}
    void setScale(const irr::core::vector3df& scale) {}
    void setRotation(const irr::core::vector3df& rotation) {}
    void setPosition(const irr::core::vector3df& newpos) {}
    void addChild(irr::scene::ISceneNode* child);
    bool removeChild(irr::scene::ISceneNode* child);
    void serializeAttributes(irr::io::IAttributes* out, irr::io::SAttributeReadWriteOptions* options=0) const;
    void deserializeAttributes(irr::io::IAttributes* in, irr::io::SAttributeReadWriteOptions* options=0);
    irr::scene::ESCENE_NODE_TYPE getType(void);
protected:
    OcttreeNode Node;
    irr::u32 CleanCounter;
private:
};

class COcttreeManagerFactory : public irr::scene::ISceneNodeFactory
{
public:
    COcttreeManagerFactory(irr::scene::ISceneManager* smgr) : SceneManager(smgr){}
    irr::scene::ISceneNode* addSceneNode(irr::scene::ESCENE_NODE_TYPE type, irr::scene::ISceneNode* parent=0);
    irr::scene::ISceneNode* addSceneNode(const irr::c8* typeName, irr::scene::ISceneNode* parent=0);
    irr::u32 getCreatableSceneNodeTypeCount() const;
    irr::scene::ESCENE_NODE_TYPE getCreateableSceneNodeType(irr::u32 idx) const;
    const irr::c8* getCreateableSceneNodeTypeName(irr::u32 idx) const;
    const irr::c8* getCreateableSceneNodeTypeName(irr::scene::ESCENE_NODE_TYPE type) const;
    irr::scene::ISceneManager* SceneManager;
};

#endif // COCTTREEMANAGER_H
COcttreeManager.cpp

Code: Select all

/*
  Copyright (C) 2010 Daniel Sudmann

  This software is provided 'as-is', without any express or implied
  warranty.  In no event will the authors be held liable for any damages
  arising from the use of this software.

  Permission is granted to anyone to use this software for any purpose,
  including commercial applications, and to alter it and redistribute it
  freely, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not
     claim that you wrote the original software. If you use this software
     in a product, an acknowledgment in the product documentation would be
     appreciated but is not required.
  2. Altered source versions must be plainly marked as such, and must not be
     misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

  Daniel Sudmann suddani@googlemail.com
*/
#include "COcttreeManager.h"
const int OCTREEANIMATORTYPE = MAKE_IRR_ID('o','c','t','A');
const int OCTREESCENEMANAGERTYPE = MAKE_IRR_ID('o','c','t','m');;
const irr::core::stringc OCTREESCENEMANAGERTYPENAME = "OcttreeManagerSceneNode";
COcttreeManager::OcttreeAnimator::OcttreeAnimator(irr::scene::ISceneNode* node, OcttreeNode* Root)
{
    CurrentNode = 0;
    Node = node;
    RootNode = Root;
    Node->addAnimator(this);
}

COcttreeManager::OcttreeAnimator::~OcttreeAnimator(void)
{
    setNode(0);
    printf("kill manager\n");
}

void COcttreeManager::OcttreeAnimator::animateNode(irr::scene::ISceneNode* node, irr::u32 timeMs)
{
    if (CurrentNode)
    {
        if (!node->getTransformedBoundingBox().isFullInside(CurrentNode->BoundingBox))
        {
            if (CurrentNode->Parent)
                CurrentNode->Parent->insert(Node);
            else
                CurrentNode->insert(Node);
        }
        else if (CurrentNode->fitIntoChild(node))
            CurrentNode->insert(Node);
    }
    else if (!CurrentNode) //why are we not in the tree anymore??resized??
    {
        RootNode->insert(Node);
    }
}

irr::scene::ISceneNodeAnimator* COcttreeManager::OcttreeAnimator::createClone(irr::scene::ISceneNode* node, irr::scene::ISceneManager* newManager)
{
    return 0;
}

irr::scene::ESCENE_NODE_ANIMATOR_TYPE COcttreeManager::OcttreeAnimator::getType() const
{
    return (irr::scene::ESCENE_NODE_ANIMATOR_TYPE)OCTREEANIMATORTYPE;
}

void COcttreeManager::OcttreeAnimator::setNode(OcttreeNode* node)
{
    if (CurrentNode == node)
        return;
    if (CurrentNode)
    {
        CurrentNode->SceneNodes.erase(IT);
    }
    CurrentNode = node;
    if (CurrentNode)
    {
        CurrentNode->SceneNodes.push_back(this);
        IT = CurrentNode->SceneNodes.getLast();
    }
}

COcttreeManager::OcttreeNode::OcttreeNode(OcttreeNode* parent, const irr::core::aabbox3d<irr::f32>& box, irr::f32 minvolume, irr::s32 iterations)
{
    MinVolume = minvolume;
    Parent = parent;
    BoundingBox = box;
    BoundingBox.repair();
    irr::core::vector3df Edges[8];
    BoundingBox.getEdges(Edges);
    for (irr::u32 i=0; i<8; ++i)
    {
        irr::core::aabbox3d<irr::f32> tmp;
        tmp.MaxEdge = BoundingBox.getCenter();
        tmp.MinEdge = Edges[i];
        tmp.repair();
        ChildBoxes[i] = tmp;
    }
    //printf("%i Iterations left\n\n", iterations);
    if (iterations > 0)
    {
        for (irr::u32 i=0; i<8; ++i)
            Children[i] = new OcttreeNode(this, ChildBoxes[i], MinVolume, iterations-1);
    }
    else
    {
        for (irr::u32 i=0; i<8; ++i)
            Children[i] = 0;
    }
    //printf("\n");
}

COcttreeManager::OcttreeNode::~OcttreeNode(void)
{
    for (irr::u32 i=0; i<8; ++i)
    {
        if (Children[i])
            delete Children[i];
        Children[i] = 0;
    }
    irr::core::list<OcttreeAnimator*>::Iterator it = SceneNodes.begin();
    while (it != SceneNodes.end())
    {
        (*it)->setNode(0);
        it = SceneNodes.begin();
    }
}

bool COcttreeManager::OcttreeNode::fitIntoChild(irr::scene::ISceneNode* node)
{
    for (irr::u32 i=0; i<8; ++i)
    {
        if (node->getTransformedBoundingBox().isFullInside(ChildBoxes[i]))
        {
            return true;
        }
    }
    return false;
}

void COcttreeManager::OcttreeNode::insert(irr::scene::ISceneNode* node)
{
    if (!node->getTransformedBoundingBox().isFullInside(BoundingBox))
    {
        //printf("SceneNode doesn't fit into this leaf...");
        if (Parent)
        {
            //printf("push to parent\n");
            Parent->insert(node);
            return;
        }
        else //ok resize our world is to small this rebuilds the whole tree and might take some time. try to avoid this by making the world big enough in the beginning
        {
            //printf("resize world\n");
            BoundingBox.addInternalBox(node->getTransformedBoundingBox());
            clear();
            return;
        }
    }
    //printf("search for a fitting leaf...");
    for (irr::u32 i=0; i<8; ++i)
    {
        //printf("Node: %f %f %f : %f %f %f - Leaf: %f %f %f : %f %f %f\n", node->getTransformedBoundingBox().MinEdge.X, node->getTransformedBoundingBox().MinEdge.Y, node->getTransformedBoundingBox().MinEdge.Z, node->getTransformedBoundingBox().MaxEdge.X, node->getTransformedBoundingBox().MaxEdge.Y, node->getTransformedBoundingBox().MaxEdge.Z, ChildBoxes[i].MinEdge.X, ChildBoxes[i].MinEdge.Y, ChildBoxes[i].MinEdge.Z, ChildBoxes[i].MaxEdge.X, ChildBoxes[i].MaxEdge.Y, ChildBoxes[i].MaxEdge.Z);
        printf("Volume: %f : %f\n", ChildBoxes[i].getVolume(), MinVolume);
        if (ChildBoxes[i].getVolume() > MinVolume && node->getTransformedBoundingBox().isFullInside(ChildBoxes[i]))
        {
            //printf("found one..");
            if (!Children[i])
            {
                //printf("child doesn't exit yet...create it");
                Children[i] = new OcttreeNode(this, ChildBoxes[i], MinVolume, 0);
            }
            Children[i]->insert(node);
            //printf("\n");
            return;
        }
    }
    //printf("SceneNode belongs to this leaf\n");
    irr::core::list<irr::scene::ISceneNodeAnimator*> animators = node->getAnimators();
    irr::core::list<irr::scene::ISceneNodeAnimator*>::Iterator it = animators.begin();
    while (it != animators.end())
    {
        if ((*it)->getType() == (irr::scene::ESCENE_NODE_ANIMATOR_TYPE)OCTREEANIMATORTYPE)
        {
            COcttreeManager::OcttreeAnimator* anim = (COcttreeManager::OcttreeAnimator*)(*it);
            anim->setNode(this);
            return;
        }
        ++it;
    }
    COcttreeManager::OcttreeAnimator* anim = new COcttreeManager::OcttreeAnimator(node, getRoot());
    anim->setNode(this);
    anim->drop();
}

void COcttreeManager::OcttreeNode::clean(void)
{
    bool selfclean = true;
    for (irr::u32 i=0; i<8; ++i)
    {
        if (Children[i])
        {
            Children[i]->clean();
            selfclean = false;
        }
    }
    if (Parent && SceneNodes.empty() && selfclean)
    {
        for (irr::u32 i=0; i<8; ++i)
            if (Parent->Children[i] == this)
            {
                Parent->Children[i] = 0;
                break;
            }
        delete this;
    }
}

void COcttreeManager::OcttreeNode::clear(void)
{
    for (irr::u32 i=0; i<8; ++i)
    {
        if (Children[i])
            delete Children[i];
        Children[i] = 0;
    }
    BoundingBox.repair();
    irr::core::vector3df Edges[8];
    BoundingBox.getEdges(Edges);
    for (irr::u32 i=0; i<8; ++i)
    {
        irr::core::aabbox3d<irr::f32> tmp;
        tmp.MaxEdge = BoundingBox.getCenter();
        tmp.MinEdge = Edges[i];
        tmp.repair();
        ChildBoxes[i] = tmp;
    }
}

COcttreeManager::OcttreeNode* COcttreeManager::OcttreeNode::getRoot(void)
{
    if (Parent)
        return Parent->getRoot();
    return this;
}

void COcttreeManager::OcttreeNode::getNodes(const irr::core::aabbox3d<irr::f32>& box, irr::core::list<irr::scene::ISceneNode*>& nodes)
{
    irr::core::list<OcttreeAnimator*>::Iterator it = SceneNodes.begin();
    while (it != SceneNodes.end())
    {
        if ((*it)->Node->getTransformedBoundingBox().intersectsWithBox(box) || (*it)->Node->getTransformedBoundingBox().isFullInside(box))
            nodes.push_back((*it)->Node);
        ++it;
    }
    for (irr::u32 i=0; i<8; ++i)
    {
        if (Children[i] && (box.intersectsWithBox(ChildBoxes[i]) || box.isFullInside(ChildBoxes[i])))
            Children[i]->getNodes(box, nodes);
    }
}

void COcttreeManager::OcttreeNode::getNodes(const irr::scene::SViewFrustum& frustrum, irr::core::list<irr::scene::ISceneNode*>& nodes)
{
    irr::core::list<OcttreeAnimator*>::Iterator it = SceneNodes.begin();
    while (it != SceneNodes.end())
    {
        bool render = true;
        for (irr::u32 i=0; i<irr::scene::SViewFrustum::VF_PLANE_COUNT; ++i)
        {
            if ((*it)->Node->getTransformedBoundingBox().classifyPlaneRelation(frustrum.planes[i]) == irr::core::ISREL3D_FRONT)
            {
                render = false;
                break;
            }
        }
        if (render)
            nodes.push_back((*it)->Node);
        ++it;
    }


    for (irr::u32 c=0; c<8; ++c)
    {
        if (Children[c])
        {
            bool render = true;
            for (irr::u32 i=0; i<irr::scene::SViewFrustum::VF_PLANE_COUNT; ++i)
            {
                if (ChildBoxes[c].classifyPlaneRelation(frustrum.planes[i]) == irr::core::ISREL3D_FRONT)
                {
                    render = false;
                    break;
                }
            }
            if (render)
                Children[c]->getNodes(frustrum, nodes);
        }
    }
}

void COcttreeManager::OcttreeNode::renderDebug(irr::video::IVideoDriver* driver)
{
    driver->draw3DBox(BoundingBox, irr::video::SColor(255,255,0,0));
    for (irr::u32 c=0; c<8; ++c)
        if (Children[c])
            Children[c]->renderDebug(driver);
}

COcttreeManager::COcttreeManager(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, const irr::core::aabbox3d<irr::f32>& worldsize, irr::f32 MinVolume, irr::s32 id) :
    irr::scene::ISceneNode(parent, mgr, id,
                           irr::core::vector3df(0,0,0),
                           irr::core::vector3df(0,0,0),
                           irr::core::vector3df(1,1,1)) ,
    Node(0, worldsize, MinVolume, 0)
{
    //ctor
    CleanCounter = 0;
    //setDebugDataVisible(1);
}

COcttreeManager::~COcttreeManager()
{
    //dtor
}

void COcttreeManager::OnRegisterSceneNode(void)
{
    if (!isVisible())
        return;

    if (isDebugDataVisible())
        SceneManager->registerNodeForRendering(this);

    irr::core::list<irr::scene::ISceneNode*> nodes;
    if (SceneManager->getActiveCamera())
    {
        //printf("Search for Nodes...");
        Node.getNodes(*SceneManager->getActiveCamera()->getViewFrustum(), nodes);
        //printf("found %i\n", nodes.size());
        irr::core::list<irr::scene::ISceneNode*>::Iterator it = nodes.begin();
        while (it != nodes.end())
        {
            //printf("register node\n");
            (*it)->OnRegisterSceneNode();
            //SceneManager->registerNodeForRendering(*it);
            /*
                this sucks but i
                can't call OnRegisterSceneNode
                bc the it would normally register its children
                hmmm....
            */
            ++it;
        }
    }
}

void COcttreeManager::OnAnimate(irr::u32 timeMs)
{
    CleanCounter += timeMs;
    irr::scene::ISceneNode::OnAnimate(timeMs);
    //printf("CleanCounter: %i ", CleanCounter);
    if (CleanCounter >= 10000000)
    {
        //printf("clean");
        Node.clean();
        CleanCounter = 0;
    }
    //printf("\n");
}

void COcttreeManager::render(void)
{
    //debug render
    if (isDebugDataVisible())
    {
        irr::video::IVideoDriver* driver = SceneManager->getVideoDriver();
        driver->setTransform(irr::video::ETS_WORLD, irr::core::IdentityMatrix);
        irr::video::SMaterial material;
        material.Lighting = false;
        material.DiffuseColor = irr::video::SColor(255,255,255,255);
        driver->setMaterial(material);
        //draw bbox
        Node.renderDebug(driver);
    }
}

const irr::core::aabbox3d<irr::f32>& COcttreeManager::getBoundingBox() const
{
    return Node.BoundingBox;
}

void COcttreeManager::addChild(irr::scene::ISceneNode* child)
{
    irr::scene::ISceneNode::addChild(child);
    Node.insert(child);
}

bool COcttreeManager::removeChild(irr::scene::ISceneNode* child)
{
    if (irr::scene::ISceneNode::removeChild(child))
    {
        irr::core::list<irr::scene::ISceneNodeAnimator*> animators = child->getAnimators();
        irr::core::list<irr::scene::ISceneNodeAnimator*>::Iterator it = animators.begin();
        while (it != animators.end())
        {
            if ((*it)->getType() == OCTREEANIMATORTYPE)
            {
                printf("remove animator\n");
                child->removeAnimator(*it);
                break;
            }
            ++it;
        }
        return true;
    }
    return false;
}

void COcttreeManager::serializeAttributes(irr::io::IAttributes* out, irr::io::SAttributeReadWriteOptions* options) const
{
    if (!out)
        return;
    out->addString	("Name", Name.c_str());
    out->addInt	("Id", ID );
    out->addBox3d ("WorldSize", Node.BoundingBox);
    out->addFloat ("MinVolume", Node.MinVolume);
    out->addBool ("DebugData", isDebugDataVisible());
}

void COcttreeManager::deserializeAttributes(irr::io::IAttributes* in, irr::io::SAttributeReadWriteOptions* options)
{
    if (!in)
        return;
    Name = in->getAttributeAsString("Name");
    ID = in->getAttributeAsInt("Id");

    irr::core::aabbox3d<irr::f32> world = in->getAttributeAsBox3d("WorldSize");
    irr::f32 minvolume = in->getAttributeAsFloat("MinVolume");
    bool debug = in->getAttributeAsBool("DebugData");
    if (debug)
        setDebugDataVisible(1);
    else
        setDebugDataVisible(0);

    if (minvolume != Node.MinVolume || world != Node.BoundingBox)
    {
        Node.MinVolume = minvolume;
        Node.BoundingBox = world;
        Node.clear();
    }
}

irr::scene::ESCENE_NODE_TYPE COcttreeManager::getType(void)
{
    return (irr::scene::ESCENE_NODE_TYPE)OCTREESCENEMANAGERTYPE;
}

irr::scene::ISceneNode* COcttreeManagerFactory::addSceneNode(irr::scene::ESCENE_NODE_TYPE type, irr::scene::ISceneNode* parent)
{
    if (!parent)
        parent = SceneManager->getRootSceneNode();
    if ((irr::scene::ESCENE_NODE_TYPE)OCTREESCENEMANAGERTYPE == type)
    {
        COcttreeManager* node = new COcttreeManager(parent, SceneManager, irr::core::aabbox3d<irr::f32>(-1000, -1000, -1000, 1000, 1000, 1000), 100.f, -1);
        node->drop();
        return node;
    }
    return 0;
}

irr::scene::ISceneNode* COcttreeManagerFactory::addSceneNode(const irr::c8* typeName, irr::scene::ISceneNode* parent)
{
    if (!parent)
        parent = SceneManager->getRootSceneNode();
    if (OCTREESCENEMANAGERTYPENAME == typeName)
    {
        COcttreeManager* node = new COcttreeManager(parent, SceneManager, irr::core::aabbox3d<irr::f32>(-1000, -1000, -1000, 1000, 1000, 1000), 100.f, -1);
        node->drop();
        return node;
    }
    return 0;
}

irr::u32 COcttreeManagerFactory::getCreatableSceneNodeTypeCount() const
{
    return 1;
}

irr::scene::ESCENE_NODE_TYPE COcttreeManagerFactory::getCreateableSceneNodeType(irr::u32 idx) const
{
    if (idx == 0)
        return (irr::scene::ESCENE_NODE_TYPE)OCTREESCENEMANAGERTYPE;
    return irr::scene::ESNT_UNKNOWN;
}

const irr::c8* COcttreeManagerFactory::getCreateableSceneNodeTypeName(irr::u32 idx) const
{
    if (idx == 0)
        return OCTREESCENEMANAGERTYPENAME.c_str();
    return 0;
}

const irr::c8* COcttreeManagerFactory::getCreateableSceneNodeTypeName(irr::scene::ESCENE_NODE_TYPE type) const
{
    if (type == OCTREESCENEMANAGERTYPE)
        return OCTREESCENEMANAGERTYPENAME.c_str();
    return 0;
}
Last edited by sudi on Wed Jun 30, 2010 9:26 pm, edited 1 time in total.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
blackMasoon
Posts: 149
Joined: Wed Sep 09, 2009 4:57 pm
Contact:

Post by blackMasoon »

Any short example of how to initiate the base node?
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

added example to first post
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

How is this different from the default scene manager? I assumed it did some culling like this already.
blackMasoon
Posts: 149
Joined: Wed Sep 09, 2009 4:57 pm
Contact:

Post by blackMasoon »

did it ;) But well... haven't noticed any differences in the framerate...
Virion
Competition winner
Posts: 2149
Joined: Mon Dec 18, 2006 5:04 am

Post by Virion »

i would like to know the difference as well. any advantage of this over irrlicht's default scene manager?
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

slavik262 wrote:How is this different from the default scene manager? I assumed it did some culling like this already.
The default scenemnager is checking every scenenode either against the ViewFrustrum or the ViewBBox.
This manager however changes this by checking if space is containing scenenodes and then actually only checks the scenenodes which are inside the viewable area if they should be culled or not. all others are directly culled without checking. this really has an impact when u are using alot of nodes.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
blackMasoon
Posts: 149
Joined: Wed Sep 09, 2009 4:57 pm
Contact:

Post by blackMasoon »

So when will it going to work better? If I have an array of nodes or if I initialize one node many times in a loop? Because now I have an array of nodes and I don't feel any difference...
I did it like this:

Code: Select all

IMeshSceneNode* tree = pManager->getSceneManager()->addMeshSceneNode(
			pManager->getSceneManager()->getMesh("media/models/tree4-1.X"));
	tree->setParent(octCull);

	trees = new CTreeSceneNode(terrain,pManager->getSceneManager(), pManager->getDriver(), treeMap, tree);
	trees->create();
	counter = trees->getNumberOfTrees();
	trees->render();
and here's how render method looks like:


Code: Select all

void CTreeSceneNode::render()
	{
		video::ITexture* normalMap =
			_driver->getTexture("media/models/bark4_nmp.tga");

			if (normalMap)
				_driver->makeNormalMapTexture(normalMap, 6.0f);
		for(int i = 0; i < _numberOfTrees; ++i)
		{
			
			scene::IMesh* tangentMesh = _smgr->getMeshManipulator()->
				createMeshWithTangents(_treeModel->getMesh());

			//room = smgr->addMeshSceneNode(tangentMesh);
			_treeSet[i] = _smgr->addMeshSceneNode(tangentMesh);
			_treeSet[i]->setPosition(core::vector3df(treePosition[i].X,treePosition[i].Y,treePosition[i].Z));
// other methods for each node
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

you have to make the manager the parent each node you create with _treeSet = _smgr->addMeshSceneNode(tangentMesh); otherwise it won't do anything
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
blackMasoon
Posts: 149
Joined: Wed Sep 09, 2009 4:57 pm
Contact:

Post by blackMasoon »

Thanks :) Now I really feel it works ;) On my old Intel graphics adapter I've noticed a 30-40 % growth of framerate ;)
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

that seams good. maybe i can improve the speed of culling a little more.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
slavik262
Posts: 753
Joined: Sun Nov 22, 2009 9:25 pm
Location: Wisconsin, USA

Post by slavik262 »

I've been watching this from afar. :P

Any news or updates lately?
Dareltibus
Posts: 115
Joined: Mon May 17, 2010 7:42 am

Post by Dareltibus »

1 q every time i remove a scene node from the octtre it must perform a search right? so it is not really suitable for realtime updating if it contains to many scene nodes (hundreds)..is it correct ?

and if the nodes removal are multiples the CPU slow down very fast. i'm going to test it next days but i expect something similiar
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

Dareltibus wrote:1 q every time i remove a scene node from the octtre it must perform a search right? so it is not really suitable for realtime updating if it contains to many scene nodes (hundreds)..is it correct ?

and if the nodes removal are multiples the CPU slow down very fast. i'm going to test it next days but i expect something similiar
Wait what?
if u have a pointer to your scenenode just call remove and it will be removed. and yes actually this is ment for realtime and moving objects. the way i designed it the adding and removing should be quit fast.
slavik262 wrote:I've been watching this from afar. Razz

Any news or updates lately?
Well actually there is but i was to lazy to update the code. i will do when i get home and have some time to do it.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Dareltibus
Posts: 115
Joined: Mon May 17, 2010 7:42 am

Post by Dareltibus »

I mean, in your code you also call "removeChild" from ISceneNode.

Code: Select all


bool COcttreeManager::removeChild(irr::scene::ISceneNode* child)
{
    if (irr::scene::ISceneNode::removeChild(child))
    
ISceneNode::removeChild(child).
ISceneNode.h line 297

Code: Select all


		virtual bool removeChild(ISceneNode* child)
		{
			ISceneNodeList::Iterator it = Children.begin();
			for (; it != Children.end(); ++it)
				if ((*it) == child)
				{
					(*it)->Parent = 0;
					(*it)->drop();
					Children.erase(it);
					return true;
				}

			_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
			return false;
		}

there is a way to address node IDs in a way that they can be found/removed immediatly instead of iterating a nodelist?
(anyway i made a test with 600 scene nodes with 200 removal/adding per second and it is ok :) .. but maybe can become a lot faster! all scene nodes i added had a random RotationAnimator and position in a big cube )
if i find something interesting i will post it to contribute. ("if" of course :) )
Post Reply