(C++) Using a Vertex Buffer to Create a Newton Convex Hull

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
Zeuss
Posts: 114
Joined: Mon Nov 08, 2004 9:02 pm
Location: Canberra - Australia
Contact:

(C++) Using a Vertex Buffer to Create a Newton Convex Hull

Post by Zeuss »

Adding Networking to my Car game is proving to be a headache. So as break. Here is my code to Create a Newton Convex Hull (for collision) from a Vertex Buffer.

Its not very long, but it works very well :), but there are limitations, as this is the mesh buffer, it does not take into account scaling, rotation and position. But then, you can get the matrix data from the node, and pass that directly into newton, via NewtonBodySetMatrix(body, NodesMatrix.M);

Code: Select all

scene::IMeshBuffer *pBuffer = smgr->getMesh("models/cone.3DS")->getMesh(0)->getMeshBuffer(0);
	
	int VertexCount = pBuffer->getVertexCount();

	
	video::S3DVertex *vertices = (video::S3DVertex *)pBuffer->getVertices();
	

	
	NewtonCollision *Collision = NewtonCreateConvexHull( nWorld, VertexCount, &vertices[0].Pos.X, 36, NULL );

	NewtonBody *Body = NewtonCreateBody( nWorld, Collision);
The 36 as the 4th Parameter specifies the byte stride. NewtonCreateConvexHull reads in the first 12 bytes (3 floats) of the vertices struct and then skips the other 24 bytes (so normals, texture coordinates etc). It must be pointed to the Pos.X position within the structure, as it appeared that the Pos was offset by inside the structure.

My car deformation uses this convex hull at its core, but the best part of this, is to allow more interesting shapes to interact with. Instead of boring bound boxes, spheres and such.
Help make Irrlicht even Better! Create and submit your own Irrlicht Extension
Want a Games Education? Try The Academy of Interactive Entertainment
noone88
Posts: 49
Joined: Sat May 27, 2006 3:28 pm

Post by noone88 »

you get the meshbuffer this way:

getMeshBuffer(0);

Is it impossible that there are more than one meshbuffer available? can somebody explain me why one mesh has several mesh buffers? Are they all important for newton?

From http://www.irrlicht3d.org/wiki/index.ph ... nDetection i found this code:

Code: Select all

//Function to create a NewtonCollision from irrlicht mesh
NewtonCollision *CreateCollisionFromMesh(NewtonWorld *nWorld, IMesh *irr_mesh )
{
int nMeshBuffer = 0; //Mesh Buffer count
IMeshBuffer *mesh_buffer = NULL;
float *vertices; //Array to store vertices

u32 nVertices = 0;

//Get number of vertices
for( nMeshBuffer=0 ; nMeshBuffer < irr_mesh->getMeshBufferCount() ; nMeshBuffer++ )
{
nVertices += irr_mesh->getMeshBuffer(nMeshBuffer)->getVertexCount();
}

//Get (irr_)mesh buffers and copy face vertices
for( nMeshBuffer=0 ; nMeshBuffer < irr_mesh->getMeshBufferCount() ; nMeshBuffer++ )
{
mesh_buffer = irr_mesh->getMeshBuffer(nMeshBuffer);

//Get pointer to vertices and indices
S3DVertex *S3vertices = (S3DVertex*)mesh_buffer->getVertices();

//create buffer for vertices
vertices = new float[nVertices * 3];
u32 tmpCounter = 0;

//copy vertices from mesh to buffer
for(int i=0; i<mesh_buffer->getVertexCount(); i++)
{
vertices[tmpCounter++] = S3vertices[i].Pos.X;
vertices[tmpCounter++] = S3vertices[i].Pos.Y;
vertices[tmpCounter++] = S3vertices[i].Pos.Z;
}
}

//Create Newton collision object
NewtonCollision *collision_obj = NewtonCreateConvexHull(nWorld,nVertices,vertices,sizeof(float)*3,NULL);

//delete vertices
delete [] vertices;

return collision_obj;

} 
Iam not the best in c++ but doesn't " vertices = new float[nVertices * 3];"
clear the vertices array? So for me the code makes no sense because nvertices will always only contain data from the last "meshbuffer-loop"

thx for your help
buhatkj
Posts: 444
Joined: Fri Dec 12, 2003 4:53 am
Contact:

Post by buhatkj »

actually i think it's just sort of poor style. there was no reason to continually re-allocate the array, since we determined the total # of vertices above. c/c++ doesn't necessarily clear a memory space when it's allocated, so it probably works anyway. Though, some compilers this might not be the behavior, so it might work on some but not others i think. i think however, there is a possibility this could create a memory leak? does anyone else know?
My irrlicht-based projects have gone underground for now, but if you want, check out my webcomic instead! http://brokenboomerang.net
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Yeah, that code is not good. It allocates enough vertices for the entire mesh, but it does it once for every mesh buffer. It will leak memory because it only deletes the last array of floats it allocates. It also passes garbage vertex data to the newton function because it allocates enough space for all of the vertices, but it only actually copies the ones from the current mesh buffer into the array. Not to mention that it only supports one of the 3 vertex types supported by Irrlicht.

I believe this code will work better.

Code: Select all

//Function to create a NewtonCollision from irrlicht mesh
NewtonCollision *CreateCollisionFromMesh(NewtonWorld *nWorld, scene::IMesh *mesh)
{
  //Get number of vertices
  u32 nVertices = 0, nMeshBuffer;
  for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
  {
    scene::IMeshBuffer *buffer = mesh->getMeshBuffer(nMeshBuffer);
    nVertices += buffer->getVertexCount();
  }

  // allocate block for positions of every vertex in mesh, no need to delete
  // anything, the array cleans up for us.
  core::array<core::vector3df> vertices;
  vertices.reallocate(nVertices);

  //Get mesh buffers and copy face vertices
  for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
  {
    scene::IMeshBuffer *buffer = mesh->getMeshBuffer(nMeshBuffer);

    // handle the irrlicht supported vertex types
    switch(buffer->getVertexType())
    {
    case video::EVT_STANDARD:
      {
        video::S3DVertex* verts = (video::S3DVertex*)buffer->getVertices();
        for(u32 v = 0; v < buffer->getVertexCount(); ++v)
          vertices.push_back(verts[v].Pos);
      }
      break;

    case video::EVT_2TCOORDS:
      {
        video::S3DVertex2TCoords* verts = (video::S3DVertex2TCoords*)buffer->getVertices();
        for(u32 v = 0; v < buffer->getVertexCount(); ++v)
          vertices.push_back(verts[v].Pos);
      }
      break;

    case video::EVT_TANGENTS:
      {
        video::S3DVertexTangents* verts = (video::S3DVertexTangents*)buffer->getVertices();
        for(u32 v = 0; v < buffer->getVertexCount(); ++v)
          vertices.push_back(verts[v].Pos);
      }
      break;

    default:
      return 0; // don't know vertex type! bail.
    }
  }

  //Create Newton collision object
  return NewtonCreateConvexHull(nWorld, nVertices, &vertices[0].X, sizeof(core::vector3df), NULL);
}
Last edited by vitek on Sat Apr 14, 2007 3:36 am, edited 3 times in total.
buhatkj
Posts: 444
Joined: Fri Dec 12, 2003 4:53 am
Contact:

Post by buhatkj »

yeh vitek has it right, though im almost curious what would happen in the tmpcounter didnt get reset each pass. would it preserve the earlier data in the array?
My irrlicht-based projects have gone underground for now, but if you want, check out my webcomic instead! http://brokenboomerang.net
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

No. If tmpcounter didn't get reset, the only thing that would change is where the valid data would get stored in the vertices array. Right now the valid vertex data is always at the front of the array. If tmpcounter was declared and initialized outside the loop then the valid data would be offset from the front of the buffer by tmpcounter * 3 floats.

All in all, the code on the wiki is evil.
noone88
Posts: 49
Joined: Sat May 27, 2006 3:28 pm

Post by noone88 »

perfect vitek - thank you :D
JonLT
Posts: 152
Joined: Thu Mar 15, 2007 5:47 pm
Location: Denmark

Post by JonLT »

I get this

Code: Select all

cannot convert `irr::core::vector3df*' to `const dFloat*' for argument `3' to `NewtonCollision* NewtonCreateConvexHull(const NewtonWorld*, int, const dFloat*, int, const dFloat*)' 
do i need to make a float[3] for every intry in vertices?
agi_shi
Posts: 122
Joined: Mon Feb 26, 2007 12:46 am

Post by agi_shi »

JonLT wrote:I get this

Code: Select all

cannot convert `irr::core::vector3df*' to `const dFloat*' for argument `3' to `NewtonCollision* NewtonCreateConvexHull(const NewtonWorld*, int, const dFloat*, int, const dFloat*)' 
do i need to make a float[3] for every intry in vertices?
/methinks it should be &vertices[0].X ;)
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Yeah, it should be &vertices[0].X. Either that, or the array should created like this...

Code: Select all

core::array<f32> vertices;
vertices.reallocate(nVertices * 3);

// each loop should be updated...
for(u32 v = 0; v < buffer->getVertexCount(); ++v) 
{
  vertices.push_back(verts[v].Pos.X);
  vertices.push_back(verts[v].Pos.Y);
  vertices.push_back(verts[v].Pos.Z);
}

// this should be passed to the convex hull function
return NewtonCreateConvexHull(nWorld, nVertices, &vertices[0], sizeof(f32 * 3), NULL);
JonLT
Posts: 152
Joined: Thu Mar 15, 2007 5:47 pm
Location: Denmark

Post by JonLT »

thanks!
Post Reply