calculateLocalInertia crash with only btConvexHullShape

Post Reply
Badytheprogram
Posts: 9
Joined: Mon Dec 31, 2018 1:00 am

calculateLocalInertia crash with only btConvexHullShape

Post by Badytheprogram » Mon Dec 31, 2018 1:42 am

Hi.

I am working on my gamesystem, rewriting it to a better shape to be exact, and now I have a problem with the convex shape.
fortunately there is no problem with the other shapes, but if I want to build a btConvexHullShape, a lots of time it crash when it reach the

Code: Select all

"collisionshape->calculateLocalInertia(mass, localinertia); "
line with this error message:
Unhandled exception at 0x00A6C2FE in PlayGround.exe: 0xC0000005: Access violation reading location 0xFFFFFFFF. occurred
But if it not crash, it work like a charm, without any problem, however it never crash with other shapes.

So here is the initial code(the collisionshape definition is in the header, so I can reach it globally inside the class) :

Code: Select all

	string shapetype = "box";
	if (functions.searchinvector("hitboxtype", configuration, tablecoord)) shapetype = configuration[tablecoord + 1];
	
	size = Ogre::Vector3(1, 1, 1);
	position = itemnode->_getDerivedPosition();
	quaternion = itemnode->_getDerivedOrientation();
	mass = 0;
	localinertia = btVector3(0, 0, 0);
	radius = 1;
	if (functions.searchinvector("radsize", configuration, tablecoord))radius = functions.converttodouble(configuration[tablecoord + 1]);
	if (functions.searchinvector("size", configuration, tablecoord))
	{
		size.x = functions.converttodouble(configuration[tablecoord + 1]);
		size.y = functions.converttodouble(configuration[tablecoord + 2]);
		size.z = functions.converttodouble(configuration[tablecoord + 3]);
	}
	
	if (functions.searchinvector("mass", configuration, tablecoord)) mass = functions.converttofloat(configuration[tablecoord + 1]);

	if (functions.searchinvector("localinertia", configuration, tablecoord))
	{
		localinertia.setX(btScalar(functions.converttofloat(configuration[tablecoord + 1])));
		localinertia.setY(btScalar(functions.converttofloat(configuration[tablecoord + 2])));
		localinertia.setZ(btScalar(functions.converttofloat(configuration[tablecoord + 3])));
	}

	

	btTransform transform; transform.setIdentity();
	transform.setOrigin(btVector3(btScalar(position.x), btScalar(position.y), btScalar(position.z)));//position
	transform.setRotation(btQuaternion(btScalar(quaternion.x), btScalar(quaternion.y), btScalar(quaternion.z), btScalar(quaternion.w)));


	btDefaultMotionState *motionstate = new btDefaultMotionState(transform);
	_setcollisionshape(shapetype);//here I call the shape functions
	
	functions.log("after _setcollisionshape "+functions.converttostring(mass)+" - " + functions.converttostring(localinertia.getX()));
	int stupidname = collisionshape->getShapeType();
	functions.log("name: "+functions.converttostring(stupidname));
	collisionshape->calculateLocalInertia(mass, localinertia);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, motionstate, collisionshape, localinertia);
and here is the code what is build up the convex shape:

Code: Select all

collisionshape = new btConvexHullShape();

	for (size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
	{
		posElem->baseVertexPointerToElement(vertex, &pReal);
		Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
		functions.log("pt["+ functions.converttostring(j)+"]: x: " + functions.converttostring(pReal[0]) + " y: " + functions.converttostring(pReal[1]) + "z: " + functions.converttostring(pReal[2]));
		
		btVector3 btv = btVector3(pReal[0], pReal[1], pReal[2]);
		((btConvexHullShape*)collisionshape)->addPoint(btv);			
	}
The points what I give to the shape it's valid, and the objects are convex, simple boxes.
Some log for proof:

Code: Select all

02:12:49: before _setcollisionshape
02:12:49: the Convex one
02:12:49: pt[0]: x: 0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[1]: x: 0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[2]: x: -0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[3]: x: -0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[4]: x: 0.5 y: 0.5z: -0.499999
02:12:49: ______________________________________________
02:12:49: pt[5]: x: -0.5 y: 0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[6]: x: -0.5 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[7]: x: 0.499999 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[8]: x: 0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[9]: x: 0.5 y: 0.5z: -0.499999
02:12:49: ______________________________________________
02:12:49: pt[10]: x: 0.499999 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[11]: x: 0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[12]: x: 0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[13]: x: 0.499999 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[14]: x: -0.5 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[15]: x: -0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[16]: x: -0.5 y: -0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[17]: x: -0.5 y: 0.5z: 0.494248
02:12:49: ______________________________________________
02:12:49: pt[18]: x: -0.5 y: 0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[19]: x: -0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[20]: x: 0.5 y: 0.5z: -0.499999
02:12:49: ______________________________________________
02:12:49: pt[21]: x: 0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[22]: x: -0.5 y: -0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: pt[23]: x: -0.5 y: 0.5z: -0.5
02:12:49: ______________________________________________
02:12:49: vertex_count: 24
02:12:49: after _setcollisionshape mass: 1 - localinertiax: 0
02:12:49: shapetype: 4
Maybe important information, the class is abstact.
I use Visual studio 2017 with Ogre 1.9 and the Bulletphysics version is 2.83.7

Badytheprogram
Posts: 9
Joined: Mon Dec 31, 2018 1:00 am

Re: calculateLocalInertia crash with only btConvexHullShape

Post by Badytheprogram » Wed Jan 02, 2019 5:53 pm

I go trought all the posts with "btConvexHullShape" here and I didn't found anything. Compared it to a lot of tutorials what I found and all the codes seems good to me. I tried other objects, and tried all the "get" functions in the collisionshapes and they all did return valid data, It didn't seems nullpointer at all. I tried several definitions, and nothing. It crash, without any usefull infomation because the debugger didn't show where it crash inside the btPolyhedralConvexShape::calculateLocalInertia calss(not accessible) so I officially run out if ideas and options. :'(

User avatar
drleviathan
Posts: 486
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: calculateLocalInertia crash with only btConvexHullShape

Post by drleviathan » Thu Jan 03, 2019 4:45 pm

When I look at your code I see one weirdness. This part here:

Code: Select all

	        localinertia.setX(btScalar(functions.converttofloat(configuration[tablecoord + 1])));
		localinertia.setY(btScalar(functions.converttofloat(configuration[tablecoord + 2])));
		localinertia.setZ(btScalar(functions.converttofloat(configuration[tablecoord + 3])));
Usually the first component would be at tablecoord + 0 rather than tablecoord + 1 however it is not clear to me what tablecoord really points to. It may be you have not provided enough info and I would need ALL of your code and the content you're loading to really figure it out.

Meanwhile, I think I've seen calculateLocalInertia() crash on invalid pointer when given NaN input, so I recommend you sanity check all the data you are feeding to the btRigidBodyConstructionInfo.

Badytheprogram
Posts: 9
Joined: Mon Dec 31, 2018 1:00 am

Re: calculateLocalInertia crash with only btConvexHullShape

Post by Badytheprogram » Thu Jan 03, 2019 7:45 pm

Thanks for answering:

In the configuration initial table looks like this:
basic,testobj,platform1,entity,platform1node,basiccube.mesh,material,climbertexture,position,0,0,11,
rotation,0,0,0,scale,1,1,1,showboundingbox,true,force,physics01,mass,1,activationtype,alwayson,restitution,1,hitboxtype,convexmesh:own
The bulletspecific configuration starts after the "force" but the initial use the whole list.

the seachinvector function simply search in this list, and return the position of the word. so if you search the word "hitboxtype" then the tablecord+1 will be the "convexmesh:own"
I know I could write it more elegantly, but it's a several years old function, I used it all over the program and it works pretty good, plus I still have a bunch of work with the system, this one have low priority.

I checked all of the input data and it looks pretty valid to me(maybe I forgot something?):

Code: Select all

20:16:20: the konvex one
20:16:20: pt[0]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[1]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[2]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[3]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[4]: x: 0.5 y: 0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[5]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[6]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[7]: x: 0.499999 y: 0.5z: 0.499999
20:16:20: ______________________________________________
20:16:20: pt[8]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[9]: x: 0.5 y: 0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[10]: x: 0.499999 y: 0.5z: 0.499999
20:16:20: ______________________________________________
20:16:20: pt[11]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[12]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[13]: x: 0.499999 y: 0.5z: 0.499999
20:16:20: ______________________________________________
20:16:20: pt[14]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[15]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[16]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[17]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[18]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[19]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[20]: x: 0.5 y: 0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[21]: x: 0.5 y: -0.5z: 0.5
20:16:20: ______________________________________________
20:16:20: pt[22]: x: -0.5 y: -0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: pt[23]: x: -0.5 y: 0.5z: -0.5
20:16:20: ______________________________________________
20:16:20: concave: false
20:16:20: vertex_count: 24
20:16:20: shapetype: 4
20:16:20: mass: 1
20:16:20: margin: 0.1
20:16:20: LocalScaling 1 - 1 - 1
20:16:20: localinertia 0 - 0 - 0
20:16:20: aabbmin -0.64 - -0.64 - -11.64
20:16:20: aabbmax 0.64 - 0.64 - -10.3658
20:16:20: position: 0 - 0 - -11
20:16:20: quaternion: 0 - 0 - 0 - 1
Here is the whole algorithm of the convexshape generator, I show only the passing part last time:

Code: Select all

void Rigidbody::entitytoconvexshape3(Ogre::Entity *Entity)
{
	//unsigned int ticket = threadogre.GetPlaceHolder();
	functions.log("the konvex one");
	// Each entity added need to reset size and radius
		// next time getRadius and getSize are asked, they're computed.

	bool added_shared = false;
	size_t vertex_count = 0, index_count = 0;
	size_t current_offset = 0;
	size_t shared_offset = 0;

	Ogre::MeshPtr mesh = Entity->getMesh();
	Ogre::Node* nNode = Entity->getParentNode();

	//ettm.mTransform = transform;
	Ogre::Vector3 mScale = nNode ? nNode->getScale() : Ogre::Vector3(1, 1, 1);

	for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::SubMesh* submesh = mesh->getSubMesh(i);
		// We only need to add the shared vertices once
		if (submesh->useSharedVertices)
		{
			if (!added_shared)
			{
				vertex_count += mesh->sharedVertexData->vertexCount;
				added_shared = true;
			}
		}
		else
		{
			vertex_count += submesh->vertexData->vertexCount;
		}
		// Add the indices
		index_count += submesh->indexData->indexCount;
	}

	Ogre::Vector3* vertices = new Ogre::Vector3[vertex_count];
	added_shared = false;

	btTriangleMesh *mTriMesh = new btTriangleMesh();
	for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
	{
		Ogre::SubMesh* submesh = mesh->getSubMesh(i);

		Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData;

		if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared))
		{
			if (submesh->useSharedVertices)
			{
				added_shared = true;
				shared_offset = current_offset;
			}


			const Ogre::VertexElement* posElem =
				vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);

			Ogre::HardwareVertexBufferSharedPtr vbuf =
				vertex_data->vertexBufferBinding->getBuffer(posElem->getSource());

			unsigned char* vertex =
				static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));

			// There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double
			//  as second argument. So make it float, to avoid trouble when Ogre::Real will
			//  be comiled/typedefed as double:
			//Ogre::Real* pReal;
			float* pReal;
			int endj = 0;
			//collisionshape = new btBoxShape(btVector3(btScalar(1), btScalar(1), btScalar(1)));
			//return;
			collisionshape = new btConvexHullShape();

			for (size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize())
			{
				posElem->baseVertexPointerToElement(vertex, &pReal);
				btVector3 pt(pReal[0], pReal[1], pReal[2]);
				functions.log("pt["+ functions.converttostring(j)+"]: x: " + functions.converttostring(pt.getX()) + " y: " + functions.converttostring(pt.getY()) + "z: " + functions.converttostring(pt.getX()));
				functions.log("______________________________________________");
				((btConvexHullShape*)collisionshape)->addPoint(pt);
			}
			collisionshape->calculateSerializeBufferSize();
			functions.log("concave: "+functions.converttostring(collisionshape->isConcave(),""));
			collisionshape->setMargin(0.1f);
			functions.log("vertex_count: " + functions.converttostring(vertex_count));
			vbuf->unlock();
			//next_offset += vertex_data->vertexCount;
		}
	}
}
and here is the full initial code:

Code: Select all

bool Rigidbody::initial(int index, Ogre::Node *node,Ogre::Entity *&Entity, vector<string> configuration)
{
	name = configuration[2];
	itemindex = index;
	itemnode = node;
	string shapetype = "box";
	
	if (Entity != nullptr)
	{
		entity = Entity;
		entityisvalid = true;
	}
	int tablecoord = -1;
	if (functions.searchinvector("hitboxtype", configuration, tablecoord)) shapetype = configuration[tablecoord + 1];
	
	size = Ogre::Vector3(1, 1, 1);
	position = itemnode->_getDerivedPosition();
	quaternion = itemnode->_getDerivedOrientation();
	mass = 0;
	localinertia = btVector3(0, 0, 0);
	radius = 1;
	

	//ha gömb, akkor a rádiusz még az element definíciójában lessz hozzáadva radsize,value szerkezettel
	if (functions.searchinvector("radsize", configuration, tablecoord))radius = functions.converttodouble(configuration[tablecoord + 1]);

	if (functions.searchinvector("size", configuration, tablecoord))
	{
		size.x = functions.converttodouble(configuration[tablecoord + 1]);
		size.y = functions.converttodouble(configuration[tablecoord + 2]);
		size.z = functions.converttodouble(configuration[tablecoord + 3]);
	}
	
	if (functions.searchinvector("mass", configuration, tablecoord)) mass = functions.converttofloat(configuration[tablecoord + 1]);

	if (functions.searchinvector("localinertia", configuration, tablecoord))
	{
		localinertia.setX(btScalar(functions.converttofloat(configuration[tablecoord + 1])));
		localinertia.setY(btScalar(functions.converttofloat(configuration[tablecoord + 2])));
		localinertia.setZ(btScalar(functions.converttofloat(configuration[tablecoord + 3])));
	}

	

	btTransform transform; transform.setIdentity();
	transform.setOrigin(btVector3(btScalar(position.x), btScalar(position.y), btScalar(position.z)));//position
	transform.setRotation(btQuaternion(btScalar(quaternion.x), btScalar(quaternion.y), btScalar(quaternion.z), btScalar(quaternion.w)));


	btDefaultMotionState *motionstate = new btDefaultMotionState(transform);
	
	_setcollisionshape(shapetype);
	
	
	int shapenumber = collisionshape->getShapeType();

	
	btVector3 aabbmin,aabbmax,scaaling;
	collisionshape->getAabb(transform,aabbmin, aabbmax);
	

	scaaling=collisionshape->getLocalScaling();

	functions.log("shapetype: " + functions.converttostring(shapenumber));
	functions.log("mass: " + functions.converttostring(mass));
	functions.log("margin: "+ functions.converttostring(collisionshape->getMargin()));
	functions.log("LocalScaling " + functions.converttostring(scaaling.getX()) + " - " + functions.converttostring(scaaling.getY()) + " - " + functions.converttostring(scaaling.getZ()));
	functions.log("localinertia " + functions.converttostring(localinertia.getX()) + " - " + functions.converttostring(localinertia.getY()) + " - " + functions.converttostring(localinertia.getZ()));
	functions.log("aabbmin " + functions.converttostring(aabbmin.getX()) + " - " + functions.converttostring(aabbmin.getY()) + " - " + functions.converttostring(aabbmin.getZ()));
	functions.log("aabbmax " + functions.converttostring(aabbmax.getX()) + " - " + functions.converttostring(aabbmax.getY()) + " - " + functions.converttostring(aabbmax.getZ()));

	functions.log("position: " + functions.converttostring(position.x) + " - " + functions.converttostring(position.y) + " - " + functions.converttostring(position.z));
	functions.log("quaternion: " + functions.converttostring(quaternion.x) + " - " + functions.converttostring(quaternion.y) + " - " + functions.converttostring(quaternion.z) + " - " + functions.converttostring(quaternion.w));

	

	btVector3 ascale(btScalar(1), btScalar(1), btScalar(1));
	collisionshape->setLocalScaling(ascale);

	collisionshape->calculateLocalInertia(mass, localinertia);

	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, motionstate, collisionshape, localinertia);
	

	
	double friction = 1, rollingfriction = 0.5;
	if (functions.searchinvector("friction", configuration, tablecoord)) friction = functions.converttodouble(configuration[tablecoord + 1]);

	if (functions.searchinvector("rollingfriction", configuration, tablecoord)) rollingfriction == functions.converttodouble(configuration[tablecoord + 1]);

	rbInfo.m_friction = btScalar(friction);
	rbInfo.m_rollingFriction = btScalar(rollingfriction);
	body = new btRigidBody(rbInfo);

	body->setUserPointer(itemnode);
	body->setUserIndex(index);
	
	if (functions.searchinvector("activationtype", configuration, tablecoord))
	{
		setactivationtype(configuration[tablecoord + 1]);
	}

	float restitution = 0;
	if (functions.searchinvector("restitution", configuration, tablecoord)) restitution = functions.converttofloat(configuration[tablecoord + 1]);
	setrestitution(restitution);

	bool anctive = true;
	bool nedforce = true;
	data::boolvector3 nedforces = data::boolvector3(true, true, true);
	bool nedroll = true;
	data::boolvector3 nedrolls = data::boolvector3(true, true, true);
	//bool active = true;

	//if (functions.searchinvector("active", configuration, tablecoord)) active = functions.converttobool(configuration[tablecoord + 1]);
	if (functions.searchinvector("active", configuration, tablecoord)) anctive = functions.converttobool(configuration[tablecoord + 1]);
	if (functions.searchinvector("needforce", configuration, tablecoord)) nedforce = functions.converttobool(configuration[tablecoord + 1]);
	if (functions.searchinvector("activeforcedirection", configuration, tablecoord))
	{
		nedforces.x = functions.converttobool(configuration[tablecoord + 1]);
		nedforces.y = functions.converttobool(configuration[tablecoord + 2]);
		nedforces.z = functions.converttobool(configuration[tablecoord + 3]);
	}
	if (functions.searchinvector("needroll", configuration, tablecoord))nedroll = functions.converttobool(configuration[tablecoord + 1]);
	if (functions.searchinvector("activerolldirection", configuration, tablecoord))
	{
		nedrolls.x = functions.converttobool(configuration[tablecoord + 1]);
		nedrolls.y = functions.converttobool(configuration[tablecoord + 2]);
		nedrolls.z = functions.converttobool(configuration[tablecoord + 3]);
	}


	setactive(anctive);
	needmove(nedforce);
	setactivemovedirections(nedforces);
	needroll(nedroll);
	setactiverollingdirections(nedrolls);

	if (functions.searchinvector("hitboxscale", configuration, tablecoord))
	{
		data::vector3 scale(functions.converttofloat(configuration[tablecoord + 1]),functions.converttofloat(configuration[tablecoord + 2]), functions.converttofloat(configuration[tablecoord + 3]));
		sethitboxscale(scale);
	}

	if (functions.searchinvector("flags", configuration, tablecoord))
	{
		vector<string> flags = functions.getvectorline(configuration, "flags", "flags:end");

		for (int i = 0; i < flags.size(); i++)
		{
			setcollisionflag(flags[i]);
		}
	}

	return true;
}
There is a functions between the initial and the entitytoconvexshape3, but it's like the same if you call it directly from the initial function, nothing extra in there, just some if functions:

Code: Select all

bool Rigidbody::_setcollisionshape(string shapetype)
{

	if (shapetype == "box")
	{

		collisionshape = new btBoxShape(btVector3(btScalar(size.x), btScalar(size.y), btScalar(size.z)));
		return true;
	}

	if (shapetype == "capsule")
	{
		collisionshape = new btCapsuleShape(btScalar(size.x / 2), btScalar(size.y));
		return true;
	}

	if (shapetype == "cylinder")
	{
		collisionshape = new btCylinderShape(btVector3(btScalar(size.x), btScalar(size.y), btScalar(size.z)));
		return true;
	}

	if (shapetype == "plane")
	{

		collisionshape = new btBoxShape(btVector3(btScalar(size.x), btScalar(0), btScalar(size.z)));
		return true;

	}

	if (shapetype == "sphere")
	{
		collisionshape = new btSphereShape(btScalar(radius));
		return true;
	}

	if (functions.Getstringbefore(shapetype, ":", false) == "convexmesh")
	{
		string entityname = functions.Getstringafter(shapetype, ":", false);
		if (entityname == "own")
		{

			if (entityisvalid)
			{
				//collisionshape = new btConvexHullShape();
				//collisionshape = entitytoconvexshape3(entity);
				entitytoconvexshape3(entity);
				return true;
			}
		}
		else if (entityname != "")
		{
			Resultelement parent = gamesets.getelement(entityname);
			if (parent.exist && parent.element->gettype() == "entity")
			{
				Ogre::Entity *entity;
				parent.element->getentity(entity);
				collisionshape = new btConvexHullShape();
				//btConvexHullShape *convexshape = entitytoconvexshape(entity);
				//collisionshape = new btConvexTriangleMeshShape(entitytoconvexshape(entity));
				//collisionshape = ;
				return true;
			}
		}
	}

	if (functions.Getstringbefore(shapetype, ":", false) == "statictrianglemesh")
	{
		string entityname = functions.Getstringafter(shapetype, ":", false);
		if (entityname == "own")
		{
			if (entityisvalid)
			{

				functions.log("entity name: "+entity->getName());
				btTriangleMesh* btrianglemesh = entitytobtTriangleMesh(entity);
				functions.log("got the trianglemesh.");
				collisionshape = new btBvhTriangleMeshShape(btrianglemesh, true);
				return true;
			}
		}
		else if (entityname != "")
		{
			Resultelement parent = gamesets.getelement(entityname);
			if (parent.exist && parent.element->gettype() == "entity")
			{
				Ogre::Entity *entity;
				parent.element->getentity(entity);
				btTriangleMesh* btrianglemesh = new btTriangleMesh();
				btrianglemesh = entitytobtTriangleMesh(entity);
				collisionshape = new btBvhTriangleMeshShape(btrianglemesh, true);
				return true;
			}
		}
	}

	return false;
}


User avatar
drleviathan
Posts: 486
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: calculateLocalInertia crash with only btConvexHullShape

Post by drleviathan » Thu Jan 03, 2019 10:11 pm

I just looked at the Bullet implementation of btConvexHullShape::calculateLocalInertia(). It turns out it uses the method implemented in its base class btPolyhedralConvexShape::calculateLocalInertia() which just computes the inertia of the bounding box. I don't see how that code could possibly crash unless there has been very mysterious data corruption somewhere. The fact that it only happens sometimes already suggests that this is either an uninitialized memory problem or a race condition breaking multithreading (do you use it?). Which makes me want to ask the obvious question: "Are you sure your collisionshape pointer is valid?".

To investigate further you're going to have to level up your debugging skills. Here is one way to do it:

(1) Derive MyConvexHullShape from btConvexHullShape and use that instead. In that class: override the calculateLocalInertia() method which would be a straight copy of the implementation in btPolyhedralConvexShape. Do that first: it is effectively a no-op but: get that done and make sure you can compile an run. If you're still getting crashes then you should at least have a better callstack since you'd be using your own class for which VS should have full debug info.

(2) If necessary: instrument MyConvexHullShape::calculateLocalInertia() to sanity check each step of the calculation so you can narrow down on where Bad Stuff gets in. As I said: I really don't see any way that code could fail unless maybe getAABB() itself is crashing, but your fresh callstack from (1) should reveal if that is the case or not.

Good luck.

Badytheprogram
Posts: 9
Joined: Mon Dec 31, 2018 1:00 am

Re: calculateLocalInertia crash with only btConvexHullShape

Post by Badytheprogram » Fri Jan 04, 2019 4:55 pm

Actually I use multithreading, with the SDL 2.0 thread library. This is one of the reasons why I rewrite my whole system. I didn't tought, this would be the problem, I read somewhere the Bt is threadsafe. I think I need to make some further research. You saved me a lot of headache, Thank you.

Thanks for the debugging tips too, it's looks really helpfull, I will probably use it sometimes.

Badytheprogram
Posts: 9
Joined: Mon Dec 31, 2018 1:00 am

Re: calculateLocalInertia crash with only btConvexHullShape

Post by Badytheprogram » Mon Jan 14, 2019 3:52 pm

drleviathan wrote:
Thu Jan 03, 2019 10:11 pm
To investigate further you're going to have to level up your debugging skills. Here is one way to do it:

(1) Derive MyConvexHullShape from btConvexHullShape and use that instead. In that class: override the calculateLocalInertia() method which would be a straight copy of the implementation in btPolyhedralConvexShape. Do that first: it is effectively a no-op but: get that done and make sure you can compile an run. If you're still getting crashes then you should at least have a better callstack since you'd be using your own class for which VS should have full debug info.

(2) If necessary: instrument MyConvexHullShape::calculateLocalInertia() to sanity check each step of the calculation so you can narrow down on where Bad Stuff gets in. As I said: I really don't see any way that code could fail unless maybe getAABB() itself is crashing, but your fresh callstack from (1) should reveal if that is the case or not.

Good luck.
Here some update:

I first tought it was threadproblem, but when I put it on the main thread, it still crashed, so I tried your debug method and the problem with it: it just didn't crash at all. It built all of the shapes, and even working pretty good. I have no idea, what cause the problem in the original calculateLocalInertia() function.

I will do some test with it, but I am pretty sure all of the data is valid.

Post Reply