Loading and unloading an irr file and destroying some nodes

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Loading and unloading an irr file and destroying some nodes

Post by nayon »

Hello everyone, I have a problem.

I have the meshviewer example, and I want to keep to mesh constant, but I want to be able to load an irr file as a background envionment. Then I want to unload it and load a new one.

Right now I can load the irr file (by loadScene) and the mesh stays too, but I can't unload the irr file without cleaning everything. But I want the user to be able to manipulate the mesh, and it should stay the same while the environment changes.

Can anyone give me a few tips for this one? I can clarify my problem if you think it isn't clear.

Thanks in advance for your help.
Last edited by nayon on Mon Mar 23, 2009 10:19 am, edited 1 time in total.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

How are you removing the contents of the .irr file?

Presumably something like smgr->clear()?

You could just walk through the scene graph (get the root scene node and then recurse through its children) and delete any nodes which aren't the one you want to keep?
Image Image Image
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Post by nayon »

The mesh isn't in the irr file, it is loaded independently from a 3ds file. So smgr->clear removes the mesh too, which I do not want. The program looks like this:

load animated scene node (the 3ds mesh)
load scene (the irr file)


Now after that step I need to somehow unload the irr file, but I can't do it. Is it clearer now?

Thanks.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

You could just walk through the scene graph (get the root scene node and then recurse through its children) and delete any nodes which aren't the one you want to keep?
Image Image Image
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

just put all stuff from the .irr file in a new empty scene node. Removing all children of that node recursively should clear the background.
We could probably simplify this situation by adding a parent node in the loadScene call, which would create the scene under this node.
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Post by nayon »

Thanks, I get it. That was quite helpful.
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Post by nayon »

Alright, now I have a new problem. I have a few IAnimatedMeshSceneNodes, and I want to destroy them when loading a new irr file. But I can't figure out how. If I just call their deconstructor, it gives an error. Is it due to the collision animators they contain? Just dropping doesn't seem to work when I try to add new ones. What should I do?

ie, how do I truly destroy a scene node that has animators ( I also want to destroy the animators too)
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You have to call remove() on the node. This will remove it from the scene graph, destroy the node if no other place holds a grab on it, and also drop each of the animators once.
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Post by nayon »

It just generates an exception when I try to do that...

Well let me share the relevant parts of my code if you want:


This is the agent class, and I want to call the destroy method in my loadLevel method, which I will post after the Agent

Code: Select all

class Agent{
public:
	scene::IAnimatedMeshSceneNode *agent_node;
	enum animation {RUN, STAND};
	core::vector3df prevPos;
	animation enim;

public: Agent (core::vector3df pos){
		enim  = RUN;
		core::array<scene::ISceneNode *> nodes;
		scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector();
		smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes
		for (u32 i=0; i < nodes.size(); ++i)
		{
			scene::ISceneNode * node = nodes[i];
			scene::ITriangleSelector * selector = 0;
			switch(node->getType())
			{
				case scene::ESNT_CUBE:
				case scene::ESNT_ANIMATED_MESH:
				// Because the selector won't animate with the mesh,
				// and is only being used for camera collision, we'll just use an approximate
				// bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0)
					selector = smgr->createTriangleSelectorFromBoundingBox(node);
				break;

				case scene::ESNT_MESH:
				case scene::ESNT_SPHERE: // Derived from IMeshSceneNode
					selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
					break;

				case scene::ESNT_TERRAIN:
					selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node);
					break;

				case scene::ESNT_OCT_TREE:
					selector = smgr->createOctTreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
					break;

				default:
					// Don't create a selector for this node type
					break;
			}
			if(selector)
			{
				// Add it to the meta selector, which will take a reference to it
				meta->addTriangleSelector(selector);
				// And drop my reference to it, so that the meta selector owns it.
				selector->drop();
			}
        }
		video::SMaterial material;
		material.setTexture(0, driver->getTexture("../../media/faerie2.bmp"));
		material.Lighting = true;
		scene::IAnimatedMesh* faerie =  smgr->getMesh("../../media/faerie.md2");
		agent_node = smgr->addAnimatedMeshSceneNode(faerie);
		faerie->drop();
		agent_node->setPosition(pos);
		agent_node->setMD2Animation(scene::EMAT_RUN);
		agent_node->getMaterial(0) = material;
		scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(meta,agent_node, core::vector3df(20,40,20),
							core::vector3df(0,-10,0),
							core::vector3df(0,0,0));
		agent_node->addAnimator(anim);
		anim->drop();
		material.setTexture(0, 0);
		material.Lighting = false;
	}

	void destroy(){
		
		agent_node->remove();
		
	}

This is the loadLevel method called by main, agents is a vector containing all Agent s. Is the problem clear now? What am I doing wrong?

Code: Select all

void loadLevel(const c8* fn){
	core::stringc filename(fn);
	for ( unsigned int gg = 0; gg < agents.size(); gg ++ ){
	
		agents[gg]->destroy();
	
	}
	agents.clear();
	smgr->loadScene(filename.c_str());
nayon
Posts: 16
Joined: Mon Mar 16, 2009 1:07 pm

Post by nayon »

EDIT: I also tried clearing the meshCache before deleting the agents, but I still get the crash described below...

I have changed the code a bit, so it doesn't give any more errors when removing agents, I call this within my loadLevel method:

Code: Select all

void loadLevel(const c8* fn){
	core::stringc filename(fn);
	addingAgent = false;
	for ( unsigned int gg = 0; gg < agents.size(); gg ++ ){
	
		agents[gg]->destroy();
	
	}
	agents.clear();
	core::array<scene::ISceneNode *> nodes1;
	smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes1); // Find all nodes
		for (u32 i=0; i < nodes1.size(); ++i)
		{
			if( nodes1[i]->getType() != scene::ESNT_CAMERA ){
				nodes1[i]->remove();
			
			}
		
		}
	smgr->loadScene(filename.c_str());

But now I get an error when I try to add a new agent, at the last line of this code:

Code: Select all

public: Agent (core::vector3df pos){
		enim  = RUN;
		core::array<scene::ISceneNode *> nodes;
		scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector();
		smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes); // Find all nodes
		for (u32 i=0; i < nodes.size(); ++i)
		{
			scene::ISceneNode * node = nodes[i];
			scene::ITriangleSelector * selector = 0;
			switch(node->getType())
			{
				case scene::ESNT_CUBE:
				case scene::ESNT_ANIMATED_MESH:
				// Because the selector won't animate with the mesh,
				// and is only being used for camera collision, we'll just use an approximate
				// bounding box instead of ((scene::IAnimatedMeshSceneNode*)node)->getMesh(0)
					selector = smgr->createTriangleSelectorFromBoundingBox(node);
				break;

				case scene::ESNT_MESH:
				case scene::ESNT_SPHERE: // Derived from IMeshSceneNode
					selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
					break;

				case scene::ESNT_TERRAIN:
					selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node);
					break;

				case scene::ESNT_OCT_TREE:
					selector = smgr->createOctTreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
					break;

				default:
					// Don't create a selector for this node type
					break;
			}
			if(selector)
			{
				// Add it to the meta selector, which will take a reference to it
				meta->addTriangleSelector(selector);
				// And drop my reference to it, so that the meta selector owns it.
				selector->drop();
			}
        }
		video::SMaterial material;
		material.setTexture(0, driver->getTexture("../../media/faerie2.bmp"));
		material.Lighting = true;
		scene::IAnimatedMesh* faerie =  smgr->getMesh("../../media/faerie.md2");
		agent_node = smgr->addAnimatedMeshSceneNode(faerie);

yes, at the AddAnimatedMeshSceneNode, why might that be?
Post Reply