Page 1 of 1

Simulation differs after deleting and readding objects

Posted: Sat Feb 09, 2008 1:17 am
by lucas
Hi,
I'm making a wrapper library for chipmunk (more for my use than anyone else).
I'm surprised how well it's working, really. It is lacking quite a many features of chipmunk (eg. joints), but it is in a working condition, as far as I can tell.
I've made a test demo that makes stacks of circles and a controllable square (its lots of fun). The problem is, when pushing 'v' to reset the objects, which are removed, freed then re-added, sometimes a few of the stacks don't form a line. This especially happens when the circles are in the middle of being knocked about. I can't find an explanation, as I would have thought it used new memory, etc.

I've included the source to the demo which you can build with "g++ -Wall *.cpp -o main -lchipmunk -lglut", assuming you have gcc, glut and libchipmunk.a wherever you keep your libraries.

Demo instructions:
Move with arrows
Create circles with 'c'
Reset with 'v'
Create a large block with space.

You can use the library if you want, but who knows why you would:D It's pretty self-explanatory.

Here are the functions that would create the error if there was a bug:

Code: Select all

/*Note:
Memory management is automatic if you use the Physics::AddObject function
*/

void Physics::ClearObjects(void) {
	for (unsigned int j = 0; j < objects.size(); j++) {
		PhysicsObject *object = objects[j];
		for (unsigned int i = 0; i < object->shapes.size(); i++) cpSpaceRemoveShape(space, object->shapes[i]);
		cpSpaceRemoveBody(space, object->body);
		delete object;
	}
	objects.clear();
}
void addObjects(void) {

	PhysicsObject *staticObject = physics->CreateStaticObject();

	staticObject->AddLineShape(cpv(0, 0), cpv(SCREEN_WIDTH, 0));

	staticObject->AddLineShape(cpv(SCREEN_WIDTH, 0), cpv(SCREEN_WIDTH, SCREEN_HEIGHT));

	staticObject->AddLineShape(cpv(SCREEN_WIDTH, SCREEN_HEIGHT), cpv(0, SCREEN_HEIGHT));

	staticObject->AddLineShape(cpv(0, SCREEN_HEIGHT), cpv(0, 0));

	physics->InitObject(staticObject);

	man = physics->CreateObject(cpv(5, 500), 45);
 //man is the user's square
	man->AddSquareShape(15, 15);

	physics->InitObject(man);

	for (int j = 0; j < 20; j++) {

		for (int i = 0; i < 10; i++) {

			PhysicsObject *obj = physics->CreateObject(cpv(50+j*40, 100+i), 0.001f);

			obj->AddCircleShape(5);

			physics->InitObject(obj);

		}

	}

}

PhysicsObject *CreateObject(cpVect pos = cpv(0, 0), cpFloat mass = 10, cpFloat frict = 0.5f, cpFloat elast = 0.0f, cpFloat rot = 0.0f, bool infinteMoment = false);
PhysicsObject *CreateStaticObject(cpVect pos = cpv(0, 0), cpFloat frict = 0.5f, cpFloat elast = 0.0f, cpFloat rot = 0.0f);
void InitObject(PhysicsObject *object); //add the object+shapes to the space
void AddCircleShape(cpFloat radius, cpVect offset = cpv(0, 0));
void AddSquareShape(cpFloat width, cpFloat height, cpVect offset = cpv(0, 0));
void AddLineShape(cpVect start, cpVect end, cpFloat thickness = 1.0f);
void AddShape(int numVerts, cpVect *verts, cpVect offset = cpv(0, 0));

Re: Simulation differs after deleting and readding objects

Posted: Sat Feb 09, 2008 3:31 am
by slembcke
I think you want cpResetShapeIdCounter(). Looking at it now, the documentation is a bit vague, but basically shapes are given an ID that affects their hashing order. If the collisions are found in a different order, a simulation might run slightly differently. Reseting the ID counter ensures that the simulation will be deterministic if the objects are added in the same order.

That sounds like it would be the likely cause to me, though I haven't run the program yet.

Re: Simulation differs after deleting and readding objects

Posted: Sun Feb 10, 2008 3:12 am
by lucas
Added cpResetShapeIdCounter(); to the clear function with no effect.