Changing model during run time?
Changing model during run time?
Hi, total newbie here, both to Irrlicht and to C++ (did some C coding back in the late 80s, and am fairly comfortable with Java), and I have a how-to question...
I'm using the Dev-C++ IDE, and have the Hello World and mesh Viewer tutorials up and running successfully, and am able to bring in an .obj model of my own making.
Based on my understanding (admittedly still very sketchy) of the process, the code first reads in the geometry of a model, then goes into the display loop where it's displayed and that display is refreshed during each iteration of the while loop. Am I on track thus far?
What I'd like to be able to do is over-write the contents of the .obj file during run time, and have that change reflected in the display loop. Not an animation, but a situation where the actual geometry changes over time and the display keeps up with the changes.
Is this a straightforward operation? Could some kind soul point me to help on how I'd re-work the display while loop to manage this--or is it best done in some other fashion?
Many thanks in advance!
I'm using the Dev-C++ IDE, and have the Hello World and mesh Viewer tutorials up and running successfully, and am able to bring in an .obj model of my own making.
Based on my understanding (admittedly still very sketchy) of the process, the code first reads in the geometry of a model, then goes into the display loop where it's displayed and that display is refreshed during each iteration of the while loop. Am I on track thus far?
What I'd like to be able to do is over-write the contents of the .obj file during run time, and have that change reflected in the display loop. Not an animation, but a situation where the actual geometry changes over time and the display keeps up with the changes.
Is this a straightforward operation? Could some kind soul point me to help on how I'd re-work the display while loop to manage this--or is it best done in some other fashion?
Many thanks in advance!
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
You can simply create a new scene node with the new geometry, and take the position etc. from the old one. Then remove the old node. But better use a different file and load it from there. If you get the data from a different process, you need to remove the mesh from mesh cache in order to get the same file reloaded from disk.
Thanks for your response thus far, but I'm still running into difficulty.
Let's say I have created two nodes, each with a different mesh:
And now inside the while loop, I have this from the tutorial:
That displays both nodes at the same time until I exit the loop. I tried adding, for example, node2->drop(); right after the driver->endScene(); in the idea that after one iteration the second node would disappear. All it did was crash the program.
Is it possible to have new nodes created inside the while loop? Do you put them before the beginScene() call, and does that process use the same syntax as the node definitions I have above?
How do you drop nodes inside the loop?
Is it possible (or preferable) to draw only some nodes at a time, or must you always use drawAll()?
I'm trying to get through the documentation and understand this basic process of controlling what nodes to display when, but either I'm not looking in the right places or I'm just not getting it.
Many thanks!
Let's say I have created two nodes, each with a different mesh:
Code: Select all
IMesh* mesh1 = smgr->getMesh("mesh1.obj");
if (!mesh1)
{
device->drop();
return 1;
}
IMeshSceneNode* node1 = smgr->addMeshSceneNode( mesh1 );
IMesh* mesh2 = smgr->getMesh("mesh2.obj");
if (!mesh2)
{
device->drop();
return 1;
}
IMeshSceneNode* node2 = smgr->addMeshSceneNode( mesh2 );
Code: Select all
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
}
Is it possible to have new nodes created inside the while loop? Do you put them before the beginScene() call, and does that process use the same syntax as the node definitions I have above?
How do you drop nodes inside the loop?
Is it possible (or preferable) to draw only some nodes at a time, or must you always use drawAll()?
I'm trying to get through the documentation and understand this basic process of controlling what nodes to display when, but either I'm not looking in the right places or I'm just not getting it.
Many thanks!
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
You are not supposed to drop() nodes, you remove() them. Or add them to the deletion queue of the scene manager.Spinland wrote:How do you drop nodes inside the loop?
Only drop() objects that have been created by a method starting with create, e.g. ISceneManager::createFlyCircleAnimator().
"Whoops..."
Okay, thanks. Now, it seems logical that you need a test that the node exists before you remove() it, right? I tried this:
It started out well, after 1 second the second mesh vanished, but on the second iteration the program crashed. Is that not how you're supposed to test for a node being in the scene?
Thanks!
Code: Select all
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
Sleep(1000);
if(node2) {
node2->remove();
}
}
Thanks!
-
- Posts: 1186
- Joined: Fri Dec 29, 2006 12:04 am
Yes, you could do it like thisSpinland wrote:Okay, thanks. Now, it seems logical that you need a test that the node exists before you remove() it, right?
Code: Select all
if(node2)
{
node2->remove();
node2 = 0; //don't forget to 0 the pointer
}
Having a sleep() in your main render loop's not a good idea.
"Whoops..."
-
- Admin
- Posts: 14143
- Joined: Wed Apr 19, 2006 9:20 pm
- Location: Oldenburg(Oldb), Germany
- Contact:
If you're sure that only one instance of a mesh exists in your scene, you should call remove first, then remove the mesh from mesh cache (you should store the mesh pointer for this as well), then getMesh() on that mesh again, and finally addMeshSceneNode() storing the new pointer on the old one. This will completely exchange the first mesh instance by the second.
In order to place the new mesh at the position of the old, you need to store position and rotation (if necessary) in extra variables. The old position does not exist anymore after you removed the node.
Just make sure that you don't do this too often, because loading from disk takes some time, so rendering will halt for at least a few seconds.
In order to place the new mesh at the position of the old, you need to store position and rotation (if necessary) in extra variables. The old position does not exist anymore after you removed the node.
Just make sure that you don't do this too often, because loading from disk takes some time, so rendering will halt for at least a few seconds.
Okay, I'm stuck again. I've searched through the documentation but I can't find what I need to be able to clear the mesh cache.
To recap: I have a single, static model on .obj format displayed, that never moves. The only thing that changes is the content of the .obj file gets over-written periodically, and I want the display to change to reflect the contents of the new .obj file instead of the old. Since this over-writing will happen many thousands of times over a run, using some sort of iterative node-adding technique doesn't seem advisable.
Here's what I have thus far:
Prime the node before the main loop:
Now the main loop starts: drop the node contents and re-load it from the .obj file:
When I replace the contents of the .obj file, as you probably knew, nothing changes in the display. Could you give me more specific pointers as to where and how I'm supposed to flush the cache so the new model displays when over-written?
Many thanks in advance!
To recap: I have a single, static model on .obj format displayed, that never moves. The only thing that changes is the content of the .obj file gets over-written periodically, and I want the display to change to reflect the contents of the new .obj file instead of the old. Since this over-writing will happen many thousands of times over a run, using some sort of iterative node-adding technique doesn't seem advisable.
Here's what I have thus far:
Prime the node before the main loop:
Code: Select all
IMesh* mesh1 = smgr->getMesh("media/control_loops.obj");
if (!mesh1)
{
device->drop();
return 1;
}
IMeshSceneNode* node1 = smgr->addMeshSceneNode( mesh1 );
Code: Select all
while(device->run())
{
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
node1->remove();
node1 = 0;
mesh1 = smgr->getMesh("media/control_loops.obj");
if (!mesh1)
{
device->drop();
return 1;
}
node1 = smgr->addMeshSceneNode( mesh1 );
}
device->drop();
return 0;
}
Many thanks in advance!
the problem is that the old mesh is still in mesh cache...
when you try to load another mesh with the same file name Irrlicht will search if it was already loaded and use the old one that's still in memory...
the solution is to remove the mesh from the cache, too...
before new loading try:
when you try to load another mesh with the same file name Irrlicht will search if it was already loaded and use the old one that's still in memory...
the solution is to remove the mesh from the cache, too...
before new loading try:
Code: Select all
smgr->getMeshCache()->removeMesh(mesh1);
while(!asleep) sheep++;
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
IrrExtensions:
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
Okay, so if I have this inside my loop:
And I over-write the contents of control_loops.obj with new geometry while it's running it still persists in showing the original model. Did I put the command in the wrong place?
Thanks!
Code: Select all
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
node1->remove();
node1 = 0;
smgr->getMeshCache()->removeMesh(mesh1);
mesh1 = smgr->getMesh("media/control_loops.obj");
if (!mesh1)
{
device->drop();
return 1;
}
node1 = smgr->addMeshSceneNode( mesh1 );
Thanks!
Bingo, found it. See, I do RTFM sometimes!
The answer is to add this after I've removed the node:
Now it's working perfectly. Your clue led me towards looking at the correct classes for what I needed, so thank you so much!
The answer is to add this after I've removed the node:
Code: Select all
smgr->getMeshCache()->clearUnusedMeshes();
Sounds like you've found a bug, removing the mesh should work. We only added removeUnusedMeshes for people who have a huge scene and wanted to clear down their cache (it removes all meshes with a reference count of 1, ie, those which belong only to the mesh cache).
If the size of the mesh cache doesn't change after doing
then that must be a bug!
If the size of the mesh cache doesn't change after doing
Code: Select all
smgr->getMeshCache()->removeMesh(mesh1);