world advance issue when objects are present

Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

world advance issue when objects are present

Post by Capilleary »

Hi
I've managed to create a wrapper class based on the Bullet Demos (mainly the "Hello World" demo from Bullet, as it is fairly simple, didn't have to search for code in a lot of files).
Everything worked fine, the application had output in text form. I thought the class was "Working" and was good for improvement. But right after I passed from text output to glut, the program crashed on the line "m_World->stepSimulation(timeStep,maxSubSteps);" (timeStep=1/60; maxSubSteps=10).
The "Step into" option of the debugger took me to line 201 from btCollisionObject.h ("return m_internalType;")

Code: Select all

///reserved for Bullet internal usage
	int	getInternalType() const
	{
		return m_internalType;
	}
the exception text is
Unhandled exception at 0x00430d46 in physics.exe: 0xC0000005: Access violation reading location 0xfeeeffba.
That simulation steps once, but the second time it has to step I get this exception.
here's the code executed when the body is added to the simulation (before the exception is thrown)

Code: Select all

	//create a dynamic rigidbody
/*01*/	btCollisionShape* colShape = new btSphereShape(Radius);
/*02*/	colShape->setUserPointer(new PS_Sphere(Radius));
/*03*/	m_CollisionShapes.push_back(colShape);

	/// Create Dynamic Objects
/*04*/	btTransform startTransform;
/*05*/	startTransform.setIdentity();

/*06*/	btScalar mass(1.f);

	//rigidbody is dynamic if and only if mass is non zero, otherwise static
/*07*/	bool isDynamic = (mass != 0.f);

/*08*/	btVector3 localInertia(0,0,0);
/*09*/	if (isDynamic)
/*10*/		colShape->calculateLocalInertia(mass,localInertia);

/*11*/	startTransform.setOrigin(btVector3(2,10,0));
		
	//using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
/*12*/	btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);
/*13*/	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,myMotionState,colShape,localInertia);
/*14*/	btRigidBody* body = new btRigidBody(rbInfo);

/*15*/	m_World->addRigidBody(body);
(this is the part that adds a sphere, it remained simplified, copied exactly from the demo, I numbered the rows containing code to make it easier to be provided help on this one :) )

and the class members:

Code: Select all

	btAlignedObjectArray<btCollisionShape*> m_CollisionShapes;
	btDiscreteDynamicsWorld* m_World;
	btSequentialImpulseConstraintSolver* m_Solver;
	btAxisSweep3* m_OverlappingPairCache;
	btCollisionDispatcher* m_Dispatcher;
	btDefaultCollisionConfiguration* m_CollisionConfiguration;
the class constructor:

Code: Select all

Physics::Physics(btVector3 gravity)
{
	///collision configuration contains default setup for memory, collision setup. Advanced users can create their own configuration.
	m_CollisionConfiguration = new btDefaultCollisionConfiguration();

	///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
	m_Dispatcher = new btCollisionDispatcher(m_CollisionConfiguration);
	
	///the maximum size of the collision world. Make sure objects stay within these boundaries
	///Don't make the world AABB size too large, it will harm simulation quality and performance
	btVector3 worldAabbMin(-10000,-10000,-10000);
	btVector3 worldAabbMax(10000,10000,10000);
	int	maxProxies = 1024;
	m_OverlappingPairCache = new btAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

	///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
	m_Solver = new btSequentialImpulseConstraintSolver;

	m_World = new btDiscreteDynamicsWorld(m_Dispatcher,m_OverlappingPairCache,m_Solver,m_CollisionConfiguration);

	m_World->setGravity(gravity);
}
(again, just like in the demo)

Why would this exception be thrown?
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

I tried again to solve the problem. Rewrote piece by piece some minimalistic code that does exactly what the HelloWorld demo does. All I did was include all the code sequences from the main() function into separate methods of a class. The simulation works fine when there are no objects. As soon as one gets added, the stepSimulation can execute only once, and the second time it crashes with 0x00000005 exception. Here's a shot of the debugging process taking place in btRigidBody.h just before it enters the method where the exception is thrown. The colObj has non-null members each time, but this time practicly all members are null. So eventually, the getInternalType() method throws the exception.

sorry I missed important details in the last post:

OS: Microsoft Windows XP Home Edition SP2 (updated when new updates are availible)

C++: Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Installed Edition: VC Express

CPU: AMD Sempron 3000+


Here: I can even share the code that seems to be correct:
header:

Code: Select all

#ifndef __PHYSICS_HPP_ 
#define __PHYSICS_HPP_ 
#include "btBulletDynamicsCommon.h"

static const double PI=3.141592653589;

class Physics
{
private:
	btAlignedObjectArray<btCollisionShape*> m_CollisionShapes;
	btDiscreteDynamicsWorld* m_World;
	btSequentialImpulseConstraintSolver* m_Solver;
	bt32BitAxisSweep3* m_OverlappingPairCache;
	btCollisionDispatcher* m_Dispatcher;
	btDefaultCollisionConfiguration* m_CollisionConfiguration;
public:
	btRigidBody* createBox(btVector3 BoxHalfExtents, btVector3 Position, btScalar mass, btVector3 LinearVelocity=btVector3(0.0f,0.0f,0.0f), btVector3 Inertia=btVector3(0.0f,0.0f,0.0f));
	void createSphere(btScalar Radius);
	void Advance(btScalar timeStep = 1.0f/60.0f, int maxSteps = 10);
	btCollisionObjectArray getObjects();
	int getObjectsCount();
	Physics(btVector3 Gravity);
	~Physics();
};
#endif // __PHYSICS_HPP_
and the definition

Code: Select all

#include "physics.hpp"
#include "physics_shape.hpp"  // class for managing data about the shape, for rendering, etc.

Physics::Physics(btVector3 gravity)
{
	m_CollisionConfiguration = new btDefaultCollisionConfiguration();

	m_Dispatcher = new btCollisionDispatcher(m_CollisionConfiguration);
	
	btVector3 worldAabbMin(-10000,-10000,-10000);
	btVector3 worldAabbMax(10000,10000,10000);
	int	maxProxies = 1024;
	m_OverlappingPairCache = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax,maxProxies);

	m_Solver = new btSequentialImpulseConstraintSolver;

	m_World = new btDiscreteDynamicsWorld(m_Dispatcher,m_OverlappingPairCache,m_Solver,m_CollisionConfiguration);

	m_World->setGravity(gravity);
}

Physics::~Physics()
{
	for (int i=m_World->getNumCollisionObjects()-1; i>=0 ;i--)
	{
		btCollisionObject* obj = m_World->getCollisionObjectArray()[i];
		btRigidBody* body = btRigidBody::upcast(obj);
		if (body && body->getMotionState())
		{
			delete body->getMotionState();
		}
		m_World->removeCollisionObject( obj );
		delete obj;
	}

	for (int j=0;j<m_CollisionShapes.size();j++)
	{
		btCollisionShape* shape = m_CollisionShapes[j];
		m_CollisionShapes[j] = 0;
		delete shape;
	}

	delete m_World;

	delete m_Solver;

	delete m_OverlappingPairCache;

	delete m_Dispatcher;

	delete m_CollisionConfiguration;

	m_CollisionShapes.clear();
}

btRigidBody* Physics::createBox(btVector3 BoxHalfExtents, btVector3 Position, btScalar mass, btVector3 LinearVelocity, btVector3 Inertia)
{
	///create shape
	btCollisionShape* Shape = new btBoxShape(BoxHalfExtents);
	m_CollisionShapes.push_back(Shape);

	//create motion state
	btTransform Transform;
	Transform.setIdentity();
	Transform.setOrigin(Position);
	btMotionState* motionState = new btDefaultMotionState(Transform,Transform);

	if (mass != 0.0f)
		Shape->calculateLocalInertia(mass,Inertia);

	btRigidBody* body = new btRigidBody(mass,motionState,Shape,Inertia);

	body->setLinearVelocity(LinearVelocity);

	//add the body to the dynamics world
	m_World->addRigidBody(body);
	return body;
}

void Physics::createSphere(btScalar Radius)
{

}

void Physics::Advance(btScalar timeStep, int maxSubSteps)
{
	m_World->stepSimulation(timeStep,maxSubSteps);
}

btCollisionObjectArray Physics::getObjects()
{
	return Physics::m_World->getCollisionObjectArray();
}

int Physics::getObjectsCount()
{
	return Physics::m_World->getNumCollisionObjects();
}
I planned it to be simple, like this:

Code: Select all

Physics* world = new Physics(btVector3(0,0,0));
world->createBox(.........);
while(!exit)
{
world->Advance();
/*code for rendering*/
}
what am I doing wrong?
You do not have the required permissions to view the files attached to this post.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: world advance issue when objects are present

Post by sparkprime »

This looks like a build problem, can you verify the hello world program works?

I just wrote a hello world tutorial for the wiki:

http://www.bulletphysics.com/mediawiki- ... ello_World
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

thanx. reading it now. Hope it helps :).
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

it seems I am the only one experiencing this problem. At other workstations my changed code works just fine. Strange, because on my station it's the first and only time this happens, and it doesn't explain why the changed code doesn't work when the original does.

Anyway, thanx a lot for your attention and patience.
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: world advance issue when objects are present

Post by sparkprime »

This is sounding more and more like a build problem, or something else (virus scanner?) that has interfered with the binaries in some manner.
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

I am starting to feel nervous.

I tried the code listed here: http://www.bulletphysics.com/mediawiki- ... ello_World
basicly it's the same as the Hello World demo. Yes, it works fine, it outputs the same results as seen on the site. But as soon as I divide the functionality in some methods like InitWorld() AddObjects() Simulate() DestroyWorld(), I get the same exception, in the same place. No classes this time, just some functions being called from main().

I am beginning to ask stupid questions like:
what machines are you working on? What CPUs, what operating systems, what compilers? what compiler options? are there some specific settings that differ from the defaults that I should set?

I just can't get this thing working like I want it to in MSVC9, no matter how much I try.

I am starting each paragraph with "I". There! I did it again!
sparkprime
Posts: 508
Joined: Fri May 30, 2008 2:51 am
Location: Ossining, New York

Re: world advance issue when objects are present

Post by sparkprime »

I haven't used msvc for a month or two but when I did use it, I don't remember it being too fussy about compiler flags. I would recomend just wiping everything bullet related, downloading it all again, recompiling, and continuing where you left off.
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

I god too confused when figuring out where the error might be. I assumed that it wasn't important that I have tried also to implement a graphical interface for the simulation. I guess that is the problem, and not the code divided in different methods.

I included the glut library, and here's how it goes:
The simulation runs fine without objects.
First object(s) is(are) added. When the application is idle, it performs the first stepSimulation since objects are added. Everything works fine, the simulation is stepped, the results are displayed. So the second time the idleCallback function is called by the glut, and this time all collision objects are null.

Please, if someone could reproduce this bug and give me an ideea of what to do I'll be grateful. Here's the full sources (I just can't run it).

I've done everything I was advised to do here, nothing helped.
You do not have the required permissions to view the files attached to this post.
Capilleary
Posts: 7
Joined: Thu Aug 21, 2008 2:06 pm
Location: Chisinau, Republic of Moldova

Re: world advance issue when objects are present

Post by Capilleary »

ah, don't bother. it's a known issue
http://www.bulletphysics.com/Bullet/php ... &view=next

thanx and sorry :)

(although it does somehow differ in my case, as I am using a 32 bit OS and the demos run fine)
JamesH
Posts: 19
Joined: Mon Oct 16, 2006 6:19 pm

Re: world advance issue when objects are present

Post by JamesH »

I get the same error to your first post if I use the line

Code: Select all

btCollisionObjectArray collisionObjects = dynamicsWorld->getCollisionObjectArray();
I was using it to iterate through the rigidbodies to ::activate() the ones that are sleeping if I change the gravity.

As a workaround I now cache the rigidbodies as I create them and iterate through them.
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA

Re: world advance issue when objects are present

Post by Erwin Coumans »

JamesH wrote:

Code: Select all

btCollisionObjectArray collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
This makes a copy of the entire array. Secondly, you discovered a problem with the array copy, it corrupts memory when the array goes out of scope. This will be fixed, but you shouldn't copy the array like this.

Instead, use a reference, btCollisionObjectArray&

Code: Select all

btCollisionObjectArray& collisionObjects = m_dynamicsWorld->getCollisionObjectArray();
Hope this helps,
Erwin
JamesH
Posts: 19
Joined: Mon Oct 16, 2006 6:19 pm

Re: world advance issue when objects are present

Post by JamesH »

Darn, missed that one - thanks Erwin