rigidbodycombiner

hello, due the fact im new here and my knowledge about c++ in combination with panda is more than just leak, im coming up with this cheesy question.

all my well meant tries leaded me into grey cloud without a floor.

RigidBodyCombiner rbc("rbc");
NodePath rigNode = rbc;
rigNode.reparent_to(win->get_aspect2d());
for (int i=0;i<10000000;i++) {
smiley[i] = window->load_model(framework.get_models(),"smiley");
		particles[i].set_scale(.02);
		smiley[i].set_pos(0,0,0);
smiley[i].copy_to(rigNode);
}
rbc.collect();

at this im getting the same error.

PT(RigidBodyCombiner) rbc;
NodePath rigNode = rbc;
rigNode.reparent_to(win->get_aspect2d());
for (int i=0;i<10000000;i++) {
smiley[i] = window->load_model(framework.get_models(),"smiley");
		particles[i].set_scale(.02);
		smiley[i].set_pos(0,0,0);
smiley[i].copy_to(rigNode);
}
rbc.collect();

thanks in advanced for letting me know how to use the rigidbodycombiner in c++. im very appericate all your kindness in spending your time.

greetz
logan´s run

Try replacing this:

RigidBodyCombiner rbc("rbc");

with this:

PT(RigidBodyCombiner) = new RigidBodyCombiner("rbc");

The former creates a concrete RigidBodyCombiner, then copies it into your NodePath, which is almost certainly not what you meant to do. The latter creates a pointer to a newly-allocated RigidBodyCombiner, then assigns that by pointer into your NodePath.

David

thats called speed! did i say speed, the right bunch of words would be -> superliquid zero time answer fields.

thanks alot for your quick response, i appericate that very much!

houston?

the code works and it seems there is just a tiny change to do. first, it takes amazing long to load.

wait, that behavior changed, it loads now faster. one thing makes my head a bit worried -> at 500 objects the framerate is down at 4.8 fps. ?

You might be hitting a CPU processing limit on the total number of vertices (the RigidBodyCombiner has to process all of these vertices every frame). Try it with a simpler model than smiley.

David

i will test this soon.

so in overall to say, sometimes the rigidbodycombiner could be a bottle neck. without rigidcombine is the framerate at my test file, where some tiny calculations are shaking hands, around 30 fps.

due this behavior i have to split the combiner up in more processing parts. should be possible, right? therefor i have in mind a automatical method. thats wont be a big deal write. just counting the verts at a model divide them through the cpu processing possibility and create and assign automatical a new combiner.

if im not up coming with some question about the rigidcombiner, i have to say thank you for your time and supporting.

logan´s run

Right. For ideal optimization, you can replace the parts of the scene that aren’t animation with a single static piece (for instance, generated by making a copy of the models and calling flattenStrong() on that copy, rather than using a RigidBodyCombiner). But even without that optimization, simply separating the RBC into multiple different, smaller, RBC’s can help, if most of the RBC’s aren’t animating each frame.

David

at my application i have do often to recreate or remove nodes. as i where programming a bit around, i ended into the next troubles. how do i detach or remove the rigidbodies?

for visualizing my horrible situation, i wrote this tiny test code:

//test rigidBODY node removing (not working)
//drh 2010
#include "pandaFramework.h"
#include "pandaSystem.h"
#include "texturePool.h"
#include "PGButton.h"
#include "mouseButton.h"
#include "transparencyAttrib.h"
#include "rigidBodyCombiner.h"

PandaFramework framework;
WindowFramework *window;
GraphicsEngine *engine;
PT(RigidBodyCombiner) rbc = new RigidBodyCombiner("rbc");
PT(Texture) texturePARTICLE;
PT(PGButton) newINSTANCES;
NodePath camera,rigNode[2],obj[100],buttonINS;
int rigNODEid = 0,partCOUNT=100;
float PARTposY = .5;

void windowOPEN() {
	framework.set_window_title("rigTEST");
	WindowProperties *props = new WindowProperties(); 
    props->set_size(500,500); 
	props->set_origin(500,10);
    props->set_undecorated(true); 
    window = framework.open_window(*props,0);
	window->get_graphics_window()->get_active_display_region(0)->set_clear_color(Colorf(1,1,1,1));
}

void getCAMERA() {
	camera = window->get_camera_group(); 
}

void paintGEO() {
	rigNode[rigNODEid] = NodePath(rbc);
	rigNode[rigNODEid].reparent_to(window->get_aspect_2d());
	//string tex = ("./textures/test.png");
	//texturePARTICLE = TexturePool::load_texture(tex);
	float PARTposX = -.5;
	
	int count = 0;
	for (int i=0;i<partCOUNT;i++){
		obj[i] = window->load_model(framework.get_models(),"box");
		obj[i].set_scale(.04);
		obj[i].set_pos(PARTposX,0,PARTposY);
		obj[i].set_p(90);
		//obj[i].set_texture(texturePARTICLE,1);
		//particles[i].set_transparency(TransparencyAttrib::Mode::M_alpha,1); // sometimes this line makes crash application!?
		obj[i].instance_to(rigNode[rigNODEid]);
		PARTposX += .04;
		count++;
		if (count > 24) {
			PARTposY -=.04;
			PARTposX = -.5;
			count = 0;
		}
	}
	rbc->collect();
}

static void NEWINSTANCES(const Event *ev, void *data){
		PGButton* CurrentButton=(PGButton *)data;
		for (int i=0;i<partCOUNT;i++) {
			obj[i].remove_node();
		}
		rigNode[0].remove_node();
		//rbc->detach(rigNode);
		rigNODEid = 1;
		paintGEO();
		PARTposY = -.5;
		for (int i=0;i<partCOUNT;i++) {
			obj[i].set_scale(.02);
		}
	}

void button() {
	newINSTANCES = new PGButton("newINSTANCES");
	newINSTANCES->setup("newINSTANCES",0.2);

	buttonINS = window->get_aspect_2d().attach_new_node(newINSTANCES);
	buttonINS.set_scale(.05);
	buttonINS.set_pos(0,0,-.5);

	framework.define_key(newINSTANCES->get_click_event(MouseButton::one() ), "button press", &NEWINSTANCES, newINSTANCES);
}

int main(int argc, char *argv[]) {
	framework.open_framework(argc, argv);
    windowOPEN();
	getCAMERA();
	paintGEO();
	button();

	framework.main_loop();
    framework.close_framework();
    return (0);
} 

Not sure what you’re asking. To remove individual bodies from the RigidBodyCombiner, you can use the NodePath::detach_node() method on the objects, then call rbc->collect() to reprocess it. To remove the entire RigidBodyCombiner, use the NodePath::detach_node() method on the RigidBodyCombiner itself.

David

thank you, i was asking excatly about this.
it seems not to fix the problem i have.

look at this code, if im reparenting my nodes to aspect_2d without using a rigidbodycombiner, im able to remove this nodes and repaint this nodes without getting displaying the nodes which create in the call before.
of course, the detaching works, but only if im not recreating this nodes again. this would be very important for me, like i mentioned before, im using often similar nodes in my application with different count and different behavior.

//test rigidBODY node removing (not working)
//drh 2010
#include "pandaFramework.h"
#include "pandaSystem.h"
#include "texturePool.h"
#include "PGButton.h"
#include "mouseButton.h"
#include "transparencyAttrib.h"
#include "rigidBodyCombiner.h"

PandaFramework framework;
WindowFramework *window;
GraphicsEngine *engine;
PT(ClockObject) globalClock = ClockObject::get_global_clock();
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr(); 
PT(RigidBodyCombiner) rbc = new RigidBodyCombiner("rbc");
PT(Texture) texturePARTICLE;
PT(PGButton) newINSTANCES;
NodePath camera,rigNode[10000],obj[100000],buttonINS;
int rigNODEid = 0,partCOUNT=100,timerX;
float PARTposY = .5;

void windowOPEN() {
	framework.set_window_title("rigTEST");
	WindowProperties *props = new WindowProperties(); 
    props->set_size(500,500); 
	props->set_origin(500,10);
    props->set_undecorated(true); 
    window = framework.open_window(*props,0);
	window->get_graphics_window()->get_active_display_region(0)->set_clear_color(Colorf(1,1,1,1));
}

void getCAMERA() {
	camera = window->get_camera_group(); 
}

void paintGEO() {
	rigNode[rigNODEid] = NodePath(rbc);
	rigNode[rigNODEid].reparent_to(window->get_aspect_2d());
	float PARTposX = -.5;
	int count = 0;
	for (int i=0;i<partCOUNT;i++){
		obj[i] = window->load_model(framework.get_models(),"box");
		obj[i].set_scale(.04);
		obj[i].set_pos(PARTposX,0,PARTposY);
		obj[i].set_p(90);
		obj[i].instance_to(rigNode[rigNODEid]);
		PARTposX += .04;
		count++;
		if (count > 24) {
			PARTposY -=.04;
			PARTposX = -.5;
			count = 0;
		}
	}
	rbc->collect();
}

static void NEWINSTANCES(const Event *ev, void *data){
		PGButton* CurrentButton=(PGButton *)data;
		for (int i=0;i<partCOUNT;i++) {
			obj[i].detach_node();
		}
		rbc->collect();
		rigNode[rigNODEid].detach_node();
		rigNode[rigNODEid].remove_node();
		PARTposY -= .10;
		partCOUNT += 100;
		paintGEO();
		for (int i=0;i<partCOUNT;i++) {
			obj[i].set_scale(.02);
		}
		rigNODEid++;
	}

void button() {
	newINSTANCES = new PGButton("newINSTANCES");
	newINSTANCES->setup("newINSTANCES",0.2);

	buttonINS = window->get_aspect_2d().attach_new_node(newINSTANCES);
	buttonINS.set_scale(.05);
	buttonINS.set_pos(0,0,-.5);

	framework.define_key(newINSTANCES->get_click_event(MouseButton::one() ), "button press", &NEWINSTANCES, newINSTANCES);
}

int main(int argc, char *argv[]) {
	framework.open_framework(argc, argv);
    windowOPEN();
	getCAMERA();
	paintGEO();
	button();

	framework.main_loop();
    framework.close_framework();
    return (0);
} 

i appericate your help very deeply!

greetz
logans run

Replace this line in paintGEO():

      obj[i].instance_to(rigNode[rigNODEid]);

with this instead:

      obj[i].reparent_to(rigNode[rigNODEid]);

The former line creates a new instance of obj[i] and attaches that new instance to the RBC, but it does not modify obj[i] itself. So this means that you no longer have a handle to the new instance, and any further operations on obj[i] do nothing. But there’s no reason to create a new instance at all, because you have just retrieved this NodePath from load_model(), which returns a unique copy not used anywhere else. You should just reparent this new copy directly.

David

oops, wrong user :smiley:
:slight_smile: that is it! thanks a lot!!! :slight_smile:

im going to post the final code here, maybe someone is in need for.

//test rigidBODY node removing (working)
//drh 2010 with kind supporting by drwr
#include "pandaFramework.h"
#include "pandaSystem.h"
#include "texturePool.h"
#include "PGButton.h"
#include "mouseButton.h"
#include "transparencyAttrib.h"
#include "rigidBodyCombiner.h"

PandaFramework framework;
WindowFramework *window;
GraphicsEngine *engine;
PT(ClockObject) globalClock = ClockObject::get_global_clock();
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr(); 
PT(RigidBodyCombiner) rbc = new RigidBodyCombiner("rbc");
PT(Texture) texturePARTICLE;
PT(PGButton) newINSTANCES;
NodePath camera,rigNode[10000],obj[100000],buttonINS;
int rigNODEid = 0,partCOUNT=100,timerX;
float PARTposY = .5;

void windowOPEN() {
	framework.set_window_title("rigTEST");
	WindowProperties *props = new WindowProperties(); 
    props->set_size(500,500); 
	props->set_origin(500,10);
    props->set_undecorated(true); 
    window = framework.open_window(*props,0);
	window->get_graphics_window()->get_active_display_region(0)->set_clear_color(Colorf(1,1,1,1));
}

void getCAMERA() {
	camera = window->get_camera_group(); 
}

void paintGEO() {
	rigNode[rigNODEid] = NodePath(rbc);
	rigNode[rigNODEid].reparent_to(window->get_aspect_2d());
	float PARTposX = -.5;
	int count = 0;
	for (int i=0;i<partCOUNT;i++){
		obj[i] = window->load_model(framework.get_models(),"box");
		obj[i].set_scale(.04);
		obj[i].set_pos(PARTposX,0,PARTposY);
		obj[i].set_p(90);
		obj[i].reparent_to(rigNode[rigNODEid]);
		PARTposX += .04;
		count++;
		if (count > 24) {
			PARTposY -=.04;
			PARTposX = -.5;
			count = 0;
		}
	}
	rbc->collect();
}

static void NEWINSTANCES(const Event *ev, void *data){
		PGButton* CurrentButton=(PGButton *)data;
		for (int i=0;i<partCOUNT;i++) {
			obj[i].detach_node();
			obj[i].remove_node();
		}
		rbc->collect();
		rigNode[rigNODEid].detach_node();
		rigNode[rigNODEid].remove_node();
		PARTposY = .5;
		partCOUNT += 100;
		paintGEO();
		for (int i=0;i<partCOUNT;i++) {
			obj[i].set_scale(.02);
		}
		rigNODEid++;
	}

void button() {
	newINSTANCES = new PGButton("newINSTANCES");
	newINSTANCES->setup("newINSTANCES",0.2);

	buttonINS = window->get_aspect_2d().attach_new_node(newINSTANCES);
	buttonINS.set_scale(.05);
	buttonINS.set_pos(0,0,-.5);

	framework.define_key(newINSTANCES->get_click_event(MouseButton::one() ), "button press", &NEWINSTANCES, newINSTANCES);
}

int main(int argc, char *argv[]) {
	framework.open_framework(argc, argv);
    windowOPEN();
	getCAMERA();
	paintGEO();
	button();

	framework.main_loop();
    framework.close_framework();
    return (0);
} 

im watching some pretty good video lectures at the moment. and one thing should be really important, its the documentation. so i fixed this and added some comments in. most of the time are comments interrupting me by reading a code. but im sure that makes sense, maybe not at a such tiny program like this, but at a huge and a very complex program, there im sure about. at the game im working, its also just a tiny one, im getting lost sometimes by searching anything. so if i had use to documented my code, i would be such faster in find the needed point.

so here is the comment version, oh and i commented out the complete node detaching.

//test rigidBODY node removing (not working)
//drh 2010 with kind supporting by drwr

#include "pandaFramework.h"
#include "pandaSystem.h"
#include "texturePool.h"
#include "PGButton.h"
#include "mouseButton.h"
#include "transparencyAttrib.h"
#include "rigidBodyCombiner.h"



PandaFramework framework;
WindowFramework *window;
GraphicsEngine *engine;
PT(ClockObject) globalClock = ClockObject::get_global_clock();
PT(AsyncTaskManager) taskMgr = AsyncTaskManager::get_global_ptr(); 
PT(RigidBodyCombiner) rbc = new RigidBodyCombiner("rbc");
PT(Texture) texturePARTICLE;
PT(PGButton) newINSTANCES;
NodePath camera,rigNODE[10000],obj[100000],buttonINS;
int rigNODEid = 0,partCOUNT=100,timerX;
float PARTposY = .5;


/*
opens a window, setting some things, like size, origin on the screen...
*/
void windowOPEN() {
	framework.set_window_title("rigTEST");
	WindowProperties *props = new WindowProperties(); 
    props->set_size(500,500); 
	props->set_origin(500,10);
    props->set_undecorated(true); 
    window = framework.open_window(*props,0);
	window->get_graphics_window()->get_active_display_region(0)->set_clear_color(Colorf(1,1,1,1));
}
// get the camera and stored in var camera
void getCAMERA() {
	camera = window->get_camera_group(); 
}
/*
paints the geometry and assign it on a rigid body
*/
void paintGEO() {
	rigNODE[rigNODEid] = NodePath(rbc);
	rigNODE[rigNODEid].reparent_to(window->get_aspect_2d());
	float PARTposX = -.5;
	int count = 0;
	for (int i=0;i<partCOUNT;i++){
		obj[i] = window->load_model(framework.get_models(),"box");
		obj[i].set_scale(.04);
		obj[i].set_pos(PARTposX,0,PARTposY);
		obj[i].set_p(90);
		obj[i].reparent_to(rigNODE[rigNODEid]);
		PARTposX += .04;
		count++;
		if (count > 24) {
			PARTposY -=.04;
			PARTposX = -.5;
			count = 0;
		}
	}
	rbc->collect();
}
/*
detach the not needed nodes out of the rigid body and detach the rigid body completly and removes the nodes 
(just to be sure that everything is deleted, its not really important, to do this thing twice)
 setting some things, like add 100 new objects , getting back to the start position...
 loop over all objects and set a new scale for it
*/
static void NEWINSTANCES(const Event *ev, void *data){
		PGButton* CurrentButton=(PGButton *)data;
		for (int i=0;i<partCOUNT;i++) {
			obj[i].detach_node();
			obj[i].remove_node();
		}
		rbc->collect();
	//	rigNODE[rigNODEid].detach_node();
	//	rigNODE[rigNODEid].remove_node();
		PARTposY = .5;
		partCOUNT += 100;
		paintGEO();
		for (int i=0;i<partCOUNT;i++) {
			obj[i].set_scale(.02);
		}
		rigNODEid++;
	}
// get a button
void button() {
	newINSTANCES = new PGButton("newINSTANCES");
	newINSTANCES->setup("newINSTANCES",0.2);

	buttonINS = window->get_aspect_2d().attach_new_node(newINSTANCES);
	buttonINS.set_scale(.05);
	buttonINS.set_pos(0,0,-.5);

	framework.define_key(newINSTANCES->get_click_event(MouseButton::one() ), "button press", &NEWINSTANCES, newINSTANCES);
}
// init the main program
int main(int argc, char *argv[]) {
	framework.open_framework(argc, argv);
    windowOPEN();
	getCAMERA();
	paintGEO();
	button();

	framework.main_loop();
    framework.close_framework();
    return (0);
} 

just curious, if im collecting my models in serval threads, how is the rbc reacting? in need to reach a good processing performance, by splitting the animated objects up, i have to use therefor my second cpu. instead it wouldnt make a huge difference till zero difference, i think. so i need my second cpu for. is that possible, to assign a rbc to a different cpu by using a thread? i have to ask this first, not that i spend much time into something which wont work.

anyway, threads is the next chapter in my basic diary of c++. im already in need for using threads and there kindness.

Good luck with that. I’ve had mixed results using threads for optimization. The downside of enabling true threads in the build (which is necessary to take advantage of multiple CPU’s) is that it also causes a low-level overhead that impacts all operations in Panda everywhere, slowing everything down by about 10% across the board. So you have to be able to more than make up for this difference with your parallelization.

That’s doable, but only if all of your algorithms are fully isolated and don’t impact each other much. If they do, you’ll end up blocking threads on contention for the same resources, and you won’t get much benefit from multiple CPU’s.

As to whether the RBC can properly deal with multiple threads, in theory it can, but it hasn’t been tested and you might need to be really, really good with C++ in order to blaze this trail alone.

David

in the main reason, i just need to use threads in poor calculation power, therefor i dont need to build panda with multithreading enable. and so far my results are from my research about multithreading from today, it seems to work. but i have no idea about how far it will decrease my performance. only two smiley was crashing together, for each smiley i used a thread for the movement and distance calculation. but in overall the threading works. now im just at testing about the communication between the threads. it seems one thread is dominating the other one. but this isnt much a problem, i think thats easy to fix(maybe a delay works).

ok my experience with c++ are more than leak, im learning it for just ~4 weeks. but im sure i will try it, but as you said, you need to be experienced in c++… so i think my results will end somewhere.