Jump to content


Trying to create collision detection for levels using PhysX, NxConvexTriangleDesc


20 replies to this topic

#1 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 20 July 2007 - 02:54 PM

This is really killing me, I've looked over the numbers and Iknow what I'm feeding the following function is right:

NxActor* PhysX::GenerateTriangleMeshFromDXMesh(ID3DXMesh* Mesh, NxVec3 pos, short* indices, float* vertices)

{

	//dump indices:

	std::ofstream out(L"out.txt");

	//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[i].x = vertices[ii]/2;

		verts[i].y = vertices[++ii]/2;

		verts[i].z = vertices[++ii]/2;

	}


	//Create pointer for indices

	NxU32 *tris = new NxU32[NumTriangles * 3];


	IndexBufferStruct *DXMeshIBPtr;


	ii = 0;

	for(int NumInd = 0; NumInd < NumTriangles * 3; NumInd++)

	{

		tris[NumInd] = indices[ii];

		out<<indices[ii]<<"\n";

		NumInd++;

		tris[NumInd] = indices[++ii];

		out<<indices[ii]<<"\n";

		NumInd++;

		tris[NumInd] = indices[++ii];

		out<<indices[ii]<<"\n";

		++ii;

	}


	NxU16* tri = new NxU16[NumTriangles];


	// Build physical model

	NxTriangleMeshDesc TriMeshDesc;

	TriMeshDesc.numVertices = NumVerticies;

	TriMeshDesc.numTriangles = NumTriangles;

	TriMeshDesc.pointStrideBytes = sizeof(NxVec3);

	TriMeshDesc.triangleStrideBytes = 3*sizeof(NxU16);

	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); //<-- status always fails

		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;

}


However I keep getting null pointer errors at the point where it's supposed to cook a triangle mesh (NxCookTriangleMesh(trimeshdesc, buf); I don't understand why, I've looked over the SDK and some physx tutorials to no avail.

#2 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 907 posts

Posted 20 July 2007 - 04:57 PM

You are supplying 32-bit indices to NxCookTriangleMesh, but the NxTriangleMeshDesc is set up to use 16-bit indices.
"Stupid bug! You go squish now!!" - Homer Simpson

#3 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 21 July 2007 - 04:40 AM

Kenneth Gorking said:

You are supplying 32-bit indices to NxCookTriangleMesh, but the NxTriangleMeshDesc is set up to use 16-bit indices.

It doesn't matter if I'm using NxU32 or NxU16, same difference.

#4 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 907 posts

Posted 21 July 2007 - 08:55 AM

Have you tried calling the isValid() function on the NxTriangleMeshDesc structure? If it fails there, single-stepping into it is easy and it will show you the error. If it succeeds, the error may be in the vertex/triangle data provided.
"Stupid bug! You go squish now!!" - Homer Simpson

#5 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 21 July 2007 - 01:32 PM

Kenneth Gorking said:

Have you tried calling the isValid() function on the NxTriangleMeshDesc structure? If it fails there, single-stepping into it is easy and it will show you the error. If it succeeds, the error may be in the vertex/triangle data provided.

Yeah it succeeded, I don't see what could be wrong with the vertices/indices I provide to it, worked fine with convex meshes,


Where model is an ID3DXMesh,

This is how I get vertices:

float* vertices = (float*)malloc(model->GetNumVertices() * sizeof(D3DXVECTOR3));


	DWORD stride =  D3DXGetFVFVertexSize(model->GetFVF());

	BYTE* vbptr = NULL;

	model->LockVertexBuffer(0, (LPVOID*)&vbptr);


	int ii = -1;

	for(int i = 0; i < model->GetNumVertices(); i++)

	{

		ii++;

		D3DXVECTOR3* pos = (D3DXVECTOR3*)vbptr;

		vertices[ii] = pos->x;

		vertices[++ii] = pos->y;

		vertices[++ii] = pos->z;


		vbptr += stride;

	}

	model->UnlockVertexBuffer();


	return vertices;

and indices:

std::ofstream c(L"indices2.txt");

	LPVOID * ppData;

	DWORD stride = sizeof(short);

	BYTE* ibptr = NULL;


	short* indices = new short[model->GetNumFaces() * 3];


	model->LockIndexBuffer(0, (LPVOID*)&indices);


	for(int i = 0; i < model->GetNumFaces() * 3; i++)

	{

		c<<indices[i]<<"\n";

	}


	model->UnlockIndexBuffer();


	return indices;


the ofstreams are kind of old actually, from when i was verifying the function swere working correctly. I'm very sure they are.

#6 Nicholas Christopher

    Member

  • Members
  • PipPip
  • 77 posts

Posted 21 July 2007 - 01:38 PM

Hi,

maybe this line:

Quote

for(int NumInd = 0; NumInd < NumTriangles * 3; NumInd++)

should be this:

Quote

for(int NumInd = 0; NumInd < NumTriangles ; NumInd++)

taken from code from this link:

http://www.gamedev.n...page=1


after edit... seems that its your own post.. maybe its wrong also. ;)
Nicholas Christopher
Architecture software development, and modeling
http:\\www.arconovum.com

#7 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 21 July 2007 - 03:46 PM

Nicholas Christopher said:

Hi,

maybe this line:


should be this:



taken from code from this link:

http://www.gamedev.n...page=1


after edit... seems that its your own post.. maybe its wrong also. ;)

haha, yeah, I've been asking around, I've been stuck here for waaaay too long, I almost gave up because of it.

#8 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 907 posts

Posted 22 July 2007 - 12:22 PM

You are not copying the indices you lock. :) There is no garantee that the pointer to the indices will remain valid after the call to UnlockIndexBuffer(). You should also call GetOptions() on the mesh and check for the D3DXMESH_32BIT flag to see if the indices are really stored as 16-bit integers.

Btw, the memory you are allocating is also leaked, because the pointer is overwritten by the call to LockIndexBuffer(). If you somewhere are deleting the 'indices' pointer being returned (which you should), you will actually be deleting the pointer to the ID3DXMesh's index data, which in turn may or may not be valid, which will most likely chrash you program. Should you get lucky and have a valid pointer, your program will still chrash when the mesh is released :)
"Stupid bug! You go squish now!!" - Homer Simpson

#9 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 23 July 2007 - 06:25 AM

oh ok, I'm not *absoloutely* sure I understand what you mean. I changed the getindices return from a short pointer to a vector pointer,

std::vector<short> mesh::GetIndices()

{

	std::ofstream c(L"indices1.txt");

	LPVOID * ppData;

	DWORD stride = sizeof(short);

	BYTE* ibptr = NULL;


	short* indices = new short[model->GetNumFaces() * 3];


	std::vector<short> copy;


	model->LockIndexBuffer(0, (LPVOID*)&indices);


	for(int i = 0; i < model->GetNumFaces() * 3; i++)

	{

		copy.push_back(indices[i]);

	}


	model->UnlockIndexBuffer();


	for(int i = 0; i < model->GetNumFaces() * 3; i++)

	{

		c<<copy[i]<<"\n";

	}


	delete indices;

	return copy;

}

and modified the physx function to accept the vector and move it over to an NxU16 array:

NxActor* PhysX::GenerateTriangleMeshFromDXMesh(ID3DXMesh* Mesh, NxVec3 pos, std::vector<short> indices, float* vertices)

{

	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[i].x = vertices[ii]/2;

		verts[i].y = vertices[++ii]/2;

		verts[i].z = vertices[++ii]/2;

	}

	//Create pointer for indices

	NxU16 *tris = new NxU16[NumTriangles * 3];


	ii = 0;

	for(int NumInd = 0; NumInd < NumTriangles * 3; NumInd++)

	{

		tris[NumInd] = indices[ii];

		NumInd++;

		tris[NumInd] = indices[++ii];

		NumInd++;

		tris[NumInd] = indices[++ii];

		++ii;

	}


	NxU16* tri = new NxU16[NumTriangles];


	// Build physical model

	NxTriangleMeshDesc TriMeshDesc;

	TriMeshDesc.numVertices = NumVerticies;

	TriMeshDesc.numTriangles = NumTriangles;

	TriMeshDesc.pointStrideBytes = sizeof(NxVec3);

	TriMeshDesc.triangleStrideBytes = 3*sizeof(NxU16);

	TriMeshDesc.points = verts;

	TriMeshDesc.triangles = tris;

	TriMeshDesc.flags = NX_MF_16_BIT_INDICES;

	

	if(TriMeshDesc.isValid())

	{

		::MessageBox(0, L"Is valid", 0, 0);

	}

	

	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); //<-- status always fails

		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;

}

umm, it stil doesn't work, I even checked some of the values randomly from the NxU16 array using a message box and if block.

Crashes on the same place.

Could the fact I declare gPhysicsSDK and gScene without static have something to do with it? In the tutorials it's always static NxPhysicsSDK* gPhysicsSDK but mine does'thave the static part. When I do try to change it to static in the header file I get a link 2019 error, I did try to change it to static during runtime like so:

static NxPhysicsSDK* temp = gPhysicsSDK

It worked but still same error, so the problem probably isn't with the static thing.

#10 Retro_J

    New Member

  • Members
  • Pip
  • 7 posts

Posted 23 July 2007 - 07:38 AM

Not seeing all your code it's difficult to see how you've set your cooking up. But have you called NxInitCooking() ?

#11 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 23 July 2007 - 10:21 AM

Retro_J said:

Not seeing all your code it's difficult to see how you've set your cooking up. But have you called NxInitCooking() ?

Well i'm hardly a pro-programmer (nothing I got to hide that will revolutionaze realtime physics :P) so whatever of my code you wanna see just ask and I'll upload it.

Anyways, I finally got it working.

After seeing Retro_J ask about the whole NxInitCooking it struck me, I hadn't put that in (unlike all the other cook functions I had before, only this one didn't have the NxInitcooking, dunno how I forgot. It didn't work though :O then it turned out it was because of the short array passing thingamob :8 fixed that and everything works great now :)



Erm, except one thing, everytime the FPS rate goes below 300 (yes, 300 is insanely high but I don't have much going on screen) NxActor::addForce stops working. collions still work fine but whenever I try to add a force it doesn't work, somewhere from 400 to 300 the addforce becomes less and less effective.

Basically it seems like the physics is being affected by the framerate O_O, any suggestions how I can fix this up?

I think the only relevent code is as follows:


bool Display(float timeDelta)

{

     box->addForce(...) //<-- add a force to NxActor

     

     StartPhysics(timeDelta);

     gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);

}


...


void PhysX::StartPhysics(NxReal time)

{

	// Update the time step

	//gDeltaTime = time;


	NxReal deltaTime = 1.0f/6.0f;


	// Start collision and dynamics for delta time since the last frame

	gScene->simulate(time);

	gScene->flushStream();

}


It's kind of an odd problem, I think I can figure it out soon enough (I hope).

#12 Retro_J

    New Member

  • Members
  • Pip
  • 7 posts

Posted 23 July 2007 - 12:00 PM

Are you applying the force to the TraingleMesh ? If so, don't forget that they can only be static and not dynamic.

#13 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 24 July 2007 - 07:03 AM

Retro_J said:

Are you applying the force to the TraingleMesh ? If so, don't forget that they can only be static and not dynamic.

oh yes it is dynamic, it works fine right up until the framerate goes below 400 and stops working when it's going at ~300fps. It's like theres abit of force still being applied when a force is applied but bby and large it isn't working right.

I don't get it, looks like different things are happening based on the framerate :8

#14 Retro_J

    New Member

  • Members
  • Pip
  • 7 posts

Posted 24 July 2007 - 10:48 AM

You cannot use NxTriangleMesh as a dynamic actor, hence the problems you are having.

You can either use an NxConvexMesh, but they are limited to 256 polys, or decompose your geometry into multiple convex mesh shapes.

#15 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 25 July 2007 - 12:50 AM

Retro_J said:

You cannot use NxTriangleMesh as a dynamic actor, hence the problems you are having.

You can either use an NxConvexMesh, but they are limited to 256 polys, or decompose your geometry into multiple convex mesh shapes.

Thats what I'm doing.

I have a convex mesh (albeit just a box) and I apply a force to it. Works fine right up to a point where the framerate goes below 400 then everything starts flipping out, collision detection works but the force won't apply properly anymore.

#16 Retro_J

    New Member

  • Members
  • Pip
  • 7 posts

Posted 25 July 2007 - 09:56 AM

Have you tried playing around with your timestep sizes and switching between fixed and variable ?

Try NX_TIMESTEP_FIXED and

NxReal deltaTime = 1.0f/60.0f;

Also have you worked through; Lesson 112 – Local Forces and Force Modes ?

#17 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 27 July 2007 - 10:23 AM

Retro_J said:

Have you tried playing around with your timestep sizes and switching between fixed and variable ?

Try NX_TIMESTEP_FIXED and

NxReal deltaTime = 1.0f/60.0f;

Also have you worked through; Lesson 112 – Local Forces and Force Modes ?

tried all that already, no help :8 I've read through 112, doesn't have much to do with it.

The physics is fps dependent, it goes very slow when the fps is 200 and very fast when above that, camera motion and all of that (not physics related) works fine. So it's probably the way I pass the change in time or something. I did try fixed, but it wasn't much help when it was 1/60 and the fps was below 200 (I changed it to 1/600 and it worked fine but not very smoothely), at 500fps the whole thing ran fine and smooth.

I'm probably going to have to lock the framerate at 60fps so I can get the physics to synch, I don't know how to do it with a variable framerate.

#18 Reedbeta

    DevMaster Staff

  • Administrators
  • 4782 posts
  • LocationBellevue, WA

Posted 27 July 2007 - 05:19 PM

You can run multiple physics updates in one frame if the framerate is high enough...you should be using fixed-timestep physics anyway just for reproducibility.
reedbeta.com - developer blog, OpenGL demos, and other projects

#19 chillypacman

    New Member

  • Members
  • PipPip
  • 24 posts

Posted 29 July 2007 - 09:18 AM

Well I've locked the framerate at 60fps now and am using a fixed timestep to go with it.

I found that the physics are fps dependent, if I have a time step of 1/100 at 60fps it means I should have a timestep of 1/200 at 120fps, basically there has to be a physics/fps ratio maintained. I'll have to figure out an algorithm for this later on or just keep the fps locked at 60fps (which I'll probably do).

#20 Kenneth Gorking

    Senior Member

  • Members
  • PipPipPipPip
  • 907 posts

Posted 29 July 2007 - 03:58 PM

Locking the framerate seems a bit hackish, especially seeing as you appear to be the only PhysX user experiencing this problem. Perhaps you are doing something wrong? Also, using a fixed timestep means that it will automatically make multiple calls to advance the simulation, if enough time has passed.
"Stupid bug! You go squish now!!" - Homer Simpson





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users