Converting IMesh to Newton Convex Hull.

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Gothi[c]

Converting IMesh to Newton Convex Hull.

Post by Gothi[c] »

I made a function to make a newton Convex hull for collision, but it's causing some random crashes on collision.

For me most of the time it works, only sometimes it seems that the convex hull is too big, and other times it is too small, and other times it doesn't exist, but most of the time it works and it's accurate. But on my friends system it crashes often.

This leads me to believe that there is some nasty memory corruption in this function, maybe due to the way I pass the float array? Or maybe not enough or too much memory allocated? I'm running all out of ideas. If there is anyone out there that could point me to what's wrong with this function, I would greatly appriciate it!

Anyway, here's the function:

Code: Select all

  CollisionMesh CreateNewtonCollisionConvex(IAnimatedMesh *Mesh)
    {
    debugout << "Creating collision mesh.";

    // Check if the animated mesh passed exists.

    if (!Mesh)
      {
      debugout << "CreateNewtonCollision : error : mesh passed to the function does not exist.";
      }

    // get a mesh from the animated mesh. (default first frame)

    IMesh* MyMesh = Mesh->getMesh(0);

    // Init stuff

    int BufferCount = MyMesh->getMeshBufferCount();
    IMeshBuffer* mb = 0;
    NewtonBody* Body;
    NewtonCollision* Collision;
    float *varray = 0;

    debugout << "Passed the initialisation stuff.";

    // Loop through all vertices and add them to an array of float that newton wants.

    for (int bi = 0 ; bi < BufferCount ; bi++)
      {
      debugout << "Looping mesh buffer nr : " << bi;
      mb = MyMesh->getMeshBuffer(bi);
      debugout << "Pointer to mesh buffer : " << mb;
      varray = new float[mb->getVertexCount()*3];
      debugout << "Pointer to varray : " << varray;
      debugout << "sizeof(varray) : " << sizeof(varray);
      int VerticleCount = mb->getVertexCount();
      debugout << "VertexCount : " << VerticleCount;
      S3DVertex* Vertices = (S3DVertex*)mb->getVertices();
      for (int ii = 0 ; ii < mb->getVertexCount() ; ii += 3)
        {
        debugout << "Looping through verticle nr : " << ii;
        varray[ii] = Vertices[ii].Pos.X;
        varray[ii+1] = Vertices[ii].Pos.Y;
        varray[ii+2] = Vertices[ii].Pos.Z;
        }
      }

    // Finalize and return result.

    debugout << "Finalizing...";
    Collision = NewtonCreateConvexHull(nWorld,mb->getVertexCount(),(float*)varray,(sizeof(float)*3),NULL);
    Body = NewtonCreateBody(nWorld,Collision);
    CollisionMesh result;
    result.Body = Body;
    result.Collision = Collision;
    debugout << "Pointer to Body : " << Body;
    debugout << "Pointer to Collision : " << Collision;
    debugout << "Done.";
    return result;
    }
CollisionMesh is just a struct containing a NewtonBody and a NewtonCollision.
dhenton9000
Posts: 395
Joined: Fri Apr 08, 2005 8:46 pm

Post by dhenton9000 »

here are some thoughts, which may or may not be helpful. You are probably handling a bunch of these anyway:

where is varray deleted? Its created with new but not deleted. maybe its deleted via newton because you sent it in via createconvexhull?

any possibility that Mesh->getMesh(0) returns garbage?
what about MyMesh->getMeshBuffer(bi)? I've found that these return unexpected stuff depending on whether i load from .X or .obj

Don't know if that helps.
Gothi[c]
Posts: 8
Joined: Fri Mar 17, 2006 6:40 pm
Contact:

Post by Gothi[c] »

I am only handeling 2 of them for testing, both the same model!
Most of the time it works, sometimes it doesn't, on the same model files.

getMesh(0) should deffinitly return something, as the same file and the same mesh is loaded and it only sporadically fails.

getMeshBuffer(bi) would return something i'd think as it's based upon getMeshBufferCount()

I deleted the array after it's use now, but it doesn't make a difference.
Still random failiure.
Gothi[c]
Posts: 8
Joined: Fri Mar 17, 2006 6:40 pm
Contact:

Post by Gothi[c] »

Well, I found the problem that made my code crash,... it was rather obious, that loop was all wrong.

fix:

Code: Select all

  CollisionMesh CreateNewtonCollisionConvex(IAnimatedMesh *Mesh)
    {

    // Check if the animated mesh passed exists.

    if (!Mesh)
      {
      debugout << "CreateNewtonCollision : error : mesh passed to the function does not exist.";
      }

    // get a mesh from the animated mesh. (default first frame)

    IMesh* MyMesh = Mesh->getMesh(0);

    // Init stuff

    int BufferCount = MyMesh->getMeshBufferCount();
    IMeshBuffer* mb = 0;
    NewtonBody* Body;
    NewtonCollision* Collision;
    float *varray = 0;

    // Loop through all vertices and add them to an array of float that newton wants.

    for (int bi = 0 ; bi < BufferCount ; bi++)
      {
      mb = MyMesh->getMeshBuffer(bi);
      int VerticleCount = mb->getVertexCount();
      debugout << "VertexCount : " << VerticleCount;
      varray = new float[VerticleCount*3];
      S3DVertex* Vertices = (S3DVertex*)mb->getVertices();
      for (int ii = 0 ; ii < VerticleCount ; ii++)
        {
        varray[(ii*3)] = Vertices[ii].Pos.X;
        varray[(ii*3)+1] = Vertices[ii].Pos.Y;
        varray[(ii*3)+2] = Vertices[ii].Pos.Z;
        }
      }

    // Finalize and return result.

    Collision = NewtonCreateConvexHull(nWorld,mb->getVertexCount(),(float*)varray,(sizeof(float)*3),NULL);
    delete varray;
    Body = NewtonCreateBody(nWorld,Collision);
    CollisionMesh result;
    result.Collision = Collision;
    result.Body = Body;
    return result;
    }
But now, like you said, i'm getting a garbage mesh buffer, regardless weither or not i load a .3ds or .obj or whatever. i tried loading a cube with 8 vertices, and mb->getVertexCount() returns 12, another time it returned 170 and another time 260, on the same model, never changing the filename.
WTF it's not supposed to do that!

how am I ever supposed to process a mesh if it behaves like that ?!
how do i make the difference between garbage data and valid data ?!

I tried eliminating the meshbuffer loop and just use ->getMeshBuffer(0) but that didn't make any difference at all, as it normally only loops through one meshbuffer anyway....

ARGH!

what am I doing wrong?!
Gothi[c]
Posts: 8
Joined: Fri Mar 17, 2006 6:40 pm
Contact:

Post by Gothi[c] »

Fixed it now with the help of bitplane (thanks).

Code: Select all

  CollisionMesh CreateNewtonCollisionConvex(IAnimatedMesh *Mesh)
    {

    // Check if the animated mesh passed exists.

    if (!Mesh)
      {
      debugout << "CreateNewtonCollision : error : mesh passed to the function does not exist.";
      }

    // get a mesh from the animated mesh. (default first frame)

    IMesh* MyMesh = Mesh->getMesh(0);

    // Init stuff

    int BufferCount = MyMesh->getMeshBufferCount();
    IMeshBuffer* mb = 0;
    NewtonBody* Body;
    NewtonCollision* Collision;
    float *varray = 0;

    // Loop through all vertices and add them to an array of float that newton wants.

    for (int bi = 0 ; bi < BufferCount ; bi++)
      {
      mb = MyMesh->getMeshBuffer(bi);
      int VerticleCount = mb->getVertexCount();
      debugout << "VertexCount : " << VerticleCount;
      varray = new float[VerticleCount*3];
      switch(mb->getVertexType())
        {
        case EVT_STANDARD:
          {
          S3DVertex* Vertices = (S3DVertex*)mb->getVertices();
          for (int ii = 0 ; ii < VerticleCount ; ii++)
            {
            varray[(ii*3)] = Vertices[ii].Pos.X;
            varray[(ii*3)+1] = Vertices[ii].Pos.Y;
            varray[(ii*3)+2] = Vertices[ii].Pos.Z;
            }
            break;
          }
        case EVT_2TCOORDS:
          {
          S3DVertex2TCoords* Vertices = (S3DVertex2TCoords*)mb->getVertices();
          for (int ii = 0 ; ii < VerticleCount ; ii++)
            {
            varray[(ii*3)] = Vertices[ii].Pos.X;
            varray[(ii*3)+1] = Vertices[ii].Pos.Y;
            varray[(ii*3)+2] = Vertices[ii].Pos.Z;
            }
            break;
          }
        }
      }

    // Finalize and return result.

    Collision = NewtonCreateConvexHull(nWorld,mb->getVertexCount(),(float*)varray,(sizeof(float)*3),NULL);
    delete varray;
    Body = NewtonCreateBody(nWorld,Collision);
    CollisionMesh result;
    result.Collision = Collision;
    result.Body = Body;
    return result;
    }
[/img]
Post Reply