Skip to main content
gamedev.net
🔒 Locked

Collision detection for triangle meshes in physx?

Started by chillypacman 3 replies 5.1k views
Original Post
chillypacman
chillypacman
I'm trying to find a good way of creating collision detection for triangle meshes. My major problem is that pmaps aren't a very good option (support for it may soon be dropped) and there are no tutorials on using NxTriangleMeshShape (no idea why). I did try using the InitBunny function in the documentation (re-adapted) but what it produces is a very, very bouncy object that doesn't want to stay still (even if I apply a massive force to it, just ignores it):
NxActor* PhysX::InitBunny(const NxVec3& pos, float* vertices, const NxReal density, NxTriangleMeshDesc& cmd, int numVertices, int numFaces)
{
	NxActorDesc actorDesc;
	NxBodyDesc bodyDesc;
	NxTriangleMesh  *triangleMesh;


	NxVec3* verts = new NxVec3[numVertices];

	int ii = -1;
	for(int i = 0; i < numVertices; i++)
	{
		++ii;
		verts.x = vertices[ii]/2;
		verts.y = vertices[++ii]/2;
		verts.z = vertices[++ii]/2;
	}

	std::ofstream c(L"nxvec3.txt");
	ii = -1;
	for(int i = 0; i < numVertices; i++)
	{
		++ii;
		c<<vertices[ii]/2<<", "<<vertices[++ii]/2<<", "<<vertices[++ii]/2<<"\n";
	}

	NxTriangleMeshDesc bunnyDesc;

	bunnyDesc.numVertices = numVertices; 
	bunnyDesc.numTriangles = numFaces;
	bunnyDesc.pointStrideBytes = sizeof(NxVec3);
	bunnyDesc.triangleStrideBytes = 3*sizeof(NxU32);
	bunnyDesc.points = verts;
	//bunnyDesc.triangles = verts;
	bunnyDesc.flags = 0;

	gCooking->NxCookTriangleMesh(bunnyDesc, UserStream("c:\\cooked.bin", false));

	NxTriangleMeshShapeDesc bunnyShapeDesc;
	bunnyShapeDesc.localPose.t = NxVec3(0, 0, 0);

	NxInitCooking();
	// Cooking from memory
	MemoryWriteBuffer buf;
	bool status = NxCookTriangleMesh(bunnyDesc, buf);
	triangleMesh = gPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data)); //<-- hello
	

	bunnyShapeDesc.meshData= triangleMesh;
	NxActor* newActor = gScene->createActor(actorDesc);

	if (bunnyShapeDesc.meshData)
	{
		NxActorDesc actorDesc;
		actorDesc.shapes.pushBack(&bunnyShapeDesc); 
		if (density)
		{
			actorDesc.body= &bodyDesc;  
			actorDesc.density= density;
		}
		else
		{
			actorDesc.body = NULL;
		}

		actorDesc.globalPose.t  = pos;
		NxActor* actor = gScene->createActor(actorDesc);

		// Attach drawable mesh to mesh shape's user data
		NxShape*const* shapes = actor->getShapes();
		shapes[0]->isTriangleMesh()->getTriangleMesh().saveToDesc(cmd);
		shapes[0]->userData = (void*)&cmd;

		return actor;
		//      gPhysicsSDK->releaseConvexMesh(*convexShapeDesc.meshData);
	}

	return NULL;
}

Right now my major worry with it is that I don't know what it wants when it asks for bunnyDesc.triangles, I tried using verts but it produced an error, so I commented it out. Therse no help anywhere about it which is really frustrating.
chillypacman
chillypacman
Thanks, but the code there gives me some sort of runtime error.

I did try using it though but to no avail:

NxActor* GenerateTriangleMeshFromDXMesh(ID3DXMesh* Mesh, NxVec3 pos, short* indices, float* vertices){	//Used to copy indices	typedef struct {		int IBNumber[3];	} IndexBufferStruct;	int NumVerticies = Mesh->GetNumVertices();	int NumTriangles = Mesh->GetNumFaces();	DWORD FVFSize = D3DXGetFVFVertexSize(Mesh->GetFVF());	//Create pointer for vertices	NxVec3* verts = new NxVec3[Mesh->GetNumVertices()];	int ii = -1;	for(int i = 0; i < Mesh->GetNumVertices(); i++)	{		++ii;		verts.x = vertices[ii]/2;		verts.y = vertices[++ii]/2;		verts.z = vertices[++ii]/2;	}	//Create pointer for indices	IndexBufferStruct *tris = new IndexBufferStruct[NumTriangles];	IndexBufferStruct *DXMeshIBPtr;	ii = 0;	for(int NumInd = 0; NumInd < NumTriangles; NumInd++)	{		tris[NumInd].IBNumber[0] = indices[ii];		tris[NumInd].IBNumber[1] = indices[++ii];		tris[NumInd].IBNumber[2] = indices[++ii];		++ii;	}	// Build physical model	NxTriangleMeshDesc TriMeshDesc;	TriMeshDesc.numVertices = NumVerticies;	TriMeshDesc.numTriangles = NumTriangles;	TriMeshDesc.pointStrideBytes = sizeof(NxVec3);	TriMeshDesc.triangleStrideBytes = 3*sizeof(short);	TriMeshDesc.points = verts;	TriMeshDesc.triangles = tris;	TriMeshDesc.flags = NX_MF_16_BIT_INDICES;		NxTriangleMeshShapeDesc ShapeDesc;	if(0)	{		// Cooking from file		bool status = NxCookTriangleMesh(TriMeshDesc, UserStream("c:\\tmp.bin", false));		ShapeDesc.meshData = gPhysicsSDK->createTriangleMesh(UserStream("c:\\tmp.bin", true));	}	else	{		// Cooking from memory		MemoryWriteBuffer buf;		bool status = NxCookTriangleMesh(TriMeshDesc, buf);		ShapeDesc.meshData = gPhysicsSDK->createTriangleMesh(MemoryReadBuffer(buf.data)); //<-- null pointer error here	}		NxActorDesc actorDesc;	actorDesc.shapes.pushBack(&ShapeDesc);	actorDesc.globalPose.t = pos;	NxActor* PhysXActor = gScene->createActor(actorDesc);	PhysXActor->userData = (void*)1;	delete[] verts;	delete[] tris;	return PhysXActor;}


short* indices isn't used though float* vertices is, the numbers are accurate (I'm pretty sure of it) so the error isn't caused by the numbers being fed into it.

Whats interesting is that the sample source code crashes with an error about the exe, however running it in my code it crashes with an unhandled exception. My code is based on physx 2.7, the sample is on 2.6 so that could be the difference.
experiment
experiment
I have the same problem with "GenerateTriangleMeshFromDXMesh()"

It breaks in MemoryReadBuffer::readByte() funnction (#stream.cpp)

at line 182: memcpy(&b, buffer, sizeof(NxU8));
Add
Add
(Yes, I do know this is an old thread, however, as I've found this thread several times while looking for an answer to the discussed problem, this information may be of use to somebody else.)

When "It breaks in MemoryReadBuffer::readByte() funnction (#stream.cpp)" it's usually due to a null pointer in the MemoryWriteBuffer structure, where your cooked vertex data should reside.

If you go back to the NxCookTriangleMesh function and check for a result you will probably find that the result of this function call is false. It is well worth sticking some handling code (or an assert) on this to make sure the function is returning true.

If the function is returning false, you'll also find that the MemoryWriteBuffer (buf) is not being populated, and so when you come to read from the buffer you get your null pointer read error.

The solution... go back and check your NxTriangleMeshDesc structure.
Ensure all stated vertex positions and indecies are defined, double check all of the values going into the structure.

Hope this helps someone.

Regards,
Adam
"The FFT - an algorithm the whole family can use" ... and for my next joke...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.