Collision not detected

A place to discuss everything related to Newton Dynamics.

Moderators: Sascha Willems, walaber

Re: Collision not detected

Postby en51nm » Sun May 27, 2012 7:37 am

I don't have any newton bodies, this is a (supposedly!) really simple collision-detection-between-two-convex-hulls program, no dynamics involved.

I fixed the problem anyway... I hadn't put the NewtonCollisionForEachPolygonDo command inside the driver->Beginscene and driver->Endscene functions.

For some reason only one of the debug meshes is drawn...

Image

However, it seems clear what the problem is.. The collision mesh looks nothing like the rendered scene node! far too few tris to make the collision accurate.

Here is the code I use to produce the convex hull:

Code: Select all
//Function to create a NewtonCollision from irrlicht mesh
NewtonCollision *CreateCollisionFromMesh(NewtonWorld *nWorld,IMesh *mesh)
{
   //Get number of vertices
   u32 nVertices = 0, nMeshBuffer;
   for( nMeshBuffer = 0 ; nMeshBuffer < mesh->getMeshBufferCount(); ++nMeshBuffer)
   {
      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<f32> vertices;
   vertices.reallocate(nVertices * 3);

   //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.X);
            vertices.push_back(verts[v].Pos.Y);
            vertices.push_back(verts[v].Pos.Z);
         }
      }

      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.X);
            vertices.push_back(verts[v].Pos.Y);
            vertices.push_back(verts[v].Pos.Z);
         }
      }
      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.X);
            vertices.push_back(verts[v].Pos.Y);
            vertices.push_back(verts[v].Pos.Z);
         }
      }
      break;

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

   //Create Newton collision object
   return NewtonCreateConvexHull(nWorld, nVertices, &vertices[0], sizeof(f32)*3,0.1f,0,NULL);
}


This is called inside my int main function like so:

Code: Select all
//Create two Sobjects
   SObject Sobj1;
   SObject Sobj2;

   //Load mesh and create new irrlicht node
   Sobj1.irr_node = smgr->addMeshSceneNode(smgr->getMesh("sphere.3ds")->getMesh(0));
   Sobj2.irr_node = smgr->addMeshSceneNode(smgr->getMesh("sphere.3ds")->getMesh(0));
   Sobj1.irr_node->getMaterial(0).EmissiveColor.set(255,255,0,255);
   Sobj2.irr_node->getMaterial(0).EmissiveColor.set(255,0,255,255);
   Sobj1.irr_node->setDebugDataVisible(EDS_HALF_TRANSPARENCY | EDS_BBOX_ALL);
   Sobj2.irr_node->setDebugDataVisible(EDS_HALF_TRANSPARENCY | EDS_BBOX_ALL);
   
   //Now create collision mesh from irrlicht mesh
   Sobj1.nwtn_collision = CreateCollisionFromMesh(nWorld,Sobj1.irr_node->getMesh());
   Sobj2.nwtn_collision = CreateCollisionFromMesh(nWorld,Sobj2.irr_node->getMesh());

   //Set position
   Sobj1.irr_node->setPosition(vector3df(100,0,0));
   Sobj2.irr_node->setPosition(vector3df(0,0,0));


Sobject isjust a struct containing a newton collision and an irrlicht scene node:

Code: Select all
//Struct for collision object
struct SObject
{
   //Irrlicht scene node
   IMeshSceneNode *irr_node;

   //Newton collision object
   NewtonCollision *nwtn_collision;
};
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby Julio Jerez » Sun May 27, 2012 7:45 am

return NewtonCreateConvexHull(nWorld, nVertices, &vertices[0], sizeof(f32)*3, 0.1f ,0,NULL);
your tolerance is too big, try
return NewtonCreateConvexHull(nWorld, nVertices, &vertices[0], sizeof(f32)*3, 0.001f ,0,NULL);

and for teh debug display showing only one shape I belieb they are both in teh same place, you nee to pass the local for each shape in each call.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Collision not detected

Postby en51nm » Sun May 27, 2012 8:07 am

YESS!!!! Thanks you!! It works!!

Julio Jerez wrote:and for teh debug display showing only one shape I belieb they are both in teh same place, you nee to pass the local for each shape in each call.


I don't completely understand what you mean... can you explain a little more simply?
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby Julio Jerez » Sun May 27, 2012 8:59 am

I mean that if you pass teh same matrix to teh collsion shape, then it will be rendered in the same location.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Collision not detected

Postby en51nm » Sun May 27, 2012 9:18 am

But I create two different matrix, one for each collision object:

Code: Select all
dgMatrix matrix1, matrix2;
NewtonCollisionGetMatrix(Sobj1.nwtn_collision,&matrix1[0][0]);
NewtonCollisionGetMatrix(Sobj2.nwtn_collision,&matrix2[0][0]);


Then I pass a different matrix to each polygon function:

Code: Select all
NewtonCollisionForEachPolygonDo(Sobj1.nwtn_collision,&matrix1[0][0],DebugShowGeometryCollision,device);
NewtonCollisionForEachPolygonDo(Sobj2.nwtn_collision,&matrix2[0][0],DebugShowGeometryCollision,device);


???
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby Sweenie » Sun May 27, 2012 9:22 am

Ok, no bodies.
Then get the world transform matrix from irr_node instead.
Sweenie
 
Posts: 503
Joined: Mon Jan 24, 2005 7:59 am
Location: Sweden

Re: Collision not detected

Postby en51nm » Tue May 29, 2012 5:54 am

I'm not sure how to typecast irrlicht's matix4 to newton's dgMatrix. At the moment I'm getting a compiler error:

Code: Select all
//Get collision matrix
dgMatrix matrix1 = Sobj1.irr_node->getAbsoluteTransformation();

//Pass to debug drawer
NewtonCollisionForEachPolygonDo(Sobj1.nwtn_collision,&matrix1[0][0],DebugShowGeometryCollision,device);


I don't understand how this works, though, surely the matrix I need is the one from the newton collision object, not from the irrlicht scene node...?

EDIT: Just to get accross the problem I'm having more visually, I've uploaded a video of the program in action
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby Julio Jerez » Tue May 29, 2012 8:38 am

the matrix is a simpel array of 4 x 4 float, you can write a utility funtion that copy the elements from one to the other member by menber.
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Collision not detected

Postby en51nm » Tue May 29, 2012 9:24 am

But why does it work correctly for the cylinder (see video example in my last post) but not for the sphere? And why does the cylinder move the sphere's mesh. I get exactly the same result if I pass an identity matrix to both NewtonCollisionForEachPolygonDo functions:

Code: Select all
//dgMatrix matrix = dgGetIdentityMatrix();

NewtonCollisionForEachPolygonDo(Sobj1.nwtn_collision,&matrix[0][0],DebugShowGeometryCollision,device);
NewtonCollisionForEachPolygonDo(Sobj2.nwtn_collision,&matrix[0][0],DebugShowGeometryCollision,device);
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby Julio Jerez » Tue May 29, 2012 10:26 am

I do not know, it soudl work for both.

make sure the matrix is a correct 4 x 4, meaning the last element of the three rows is zero, and the last element of the forth row is 1.0
Julio Jerez
Moderator
Moderator
 
Posts: 12426
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: Collision detected!

Postby en51nm » Wed May 30, 2012 5:03 am

Right... I think I'm starting to get somewhere.

Both collision meshes now display properly by using this function:

Code: Select all
driver->setTransform(video::ETS_WORLD, core::matrix4());


but they now remain in the correct initial position, but don't move when I update the position of the nodes. Despite this, the collision detection still works, until I rotate the objects using:

Code: Select all
irr_node->setRotation(vector3df(X,Y,Z));


Here you can see a collision has occurred, despite there clearly not being a collision:

Image

Is this something to do with irrlicht doing rotation in Euler angle and newton using Quaternions? If so, how can I fix it? I have made another video to help visualise my problem.
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Re: Collision not detected

Postby JoeJ » Wed May 30, 2012 6:21 am

Looking at your CheckForCollision function, i see that you give newton a matrix that only contains translation info.
Orientation is left as identity - that explains why rotation is ignored.

driver->setTransform(video::ETS_WORLD, core::matrix4());
This sets the 3D Api Modelview Matrix to identity, because core::matrix4() generates Identity?
Note that if this is set to something different, it may transform all or parts of your Nodes AND/OR DebugVisualisation Renderings.
This may be wanted OR not by you (Explaines why things move with other things).


It seems that you really have problem keeping that 3 things in sync: Irr-Nodes, DebugVisualisation, physical collision mesh.
I'd recommend to try:

1. Use driver->setTransform(video::ETS_WORLD, core::matrix4()) to eliminate one source of error - do this after each drawing, maybe irrlicht modifies that for rendering.
2. See if Irrlicht supports irr_node->setTransform(matrix4 *m) or something similar to feed it with conventional matrices that also work for newton.
Avoid that the 2nd mesh is a child of the first (!) - use root node as parent for both, and root should be set to identity too.
3. Build your test matrices:

float xform1[16] = [
1,0,0,0
0,1,0,0
0,0,1,0
x,y,x,0]; // x,y,z = translation - leave rotation as is for now

matrix4 *mat_irr1 = (matrix4*)&xform1;
dMatrix *mat_nwt1 = (dMatrix*)&xform1;

... similar with a second matrix for second mesh;


4. Now give all 3 things the same matrix and see if it works.

5. If not maybe irrlicht uses the swapped matrix format (But i'm sure someone would have mentioned that):
float xform1Swp[16] = [
1,0,0,x,
0,1,0,y,
0,0,1,z,
0,0,0,1];

6. If that works, you can replace the matrix by something you use usually, maybe *mat_irr1 = irr_node1->getTransform(), and check for rotation too.
User avatar
JoeJ
 
Posts: 1489
Joined: Tue Dec 21, 2010 6:18 pm

Re: Collision not detected

Postby en51nm » Wed May 30, 2012 6:30 am

Just figured it out. Needed to pass the scene nodes absolute transform to the driver-> setTransform function. The rotation wasn't working because I needed to irr_node->setRotaionDegrees in my collision check function!! All works correctly now!!
en51nm
 
Posts: 27
Joined: Thu May 17, 2012 3:20 pm

Previous

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 1 guest

cron