NewtonCollisionCalculateAABB() ignores original matrix

Report any bugs here and we'll post fixes

Moderators: Sascha Willems, Thomas

NewtonCollisionCalculateAABB() ignores original matrix

Postby agi_shi » Tue Apr 26, 2011 7:47 pm

Here is some example code I use to create a cylinder:
Code: Select all
                  case Type.CYLINDER:
                  {
                     // Newton cylinders are oriented along +X
                     // so we need to rotate them 90 degrees
                     float[] offsetMatrix =
                     {
                         0, 1, 0, 0,
                         -1, 0, 0, 0,
                         0, 0, 1, 0,
                         0, 0, 0, 1
                     };
                     collision = NewtonCreateCylinder(world, radius, height, 0, offsetMatrix);
                  }
                  break;

As you can see, I use a simple offset matrix so that my cylinders stand upright by default instead of laying sideways.

However, when I use NewtonCollisionCalculateAABB(), it seems that the AABB is based on the original "sideways configuration" (ignoring my offset matrix). For example:
Image

The same issue applies to cones and capsules because they also default to the "sideways configuration":
Image

Spheres and boxes do not have this issue (I provide an identity matrix to the CreateBox/CreateSphere functions):
Image

Is this a bug, or am I doing something wrong?
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby Julio Jerez » Tue Apr 26, 2011 10:32 pm

I believe you have to have a bug because for a cylinder this is the function

Code: Select all
void dgCollisionConvex::CalcAABB (const dgMatrix &matrix, dgVector& p0, dgVector& p1) const
{
   dgVector origin (matrix.TransformVector(m_boxOrigin));
   dgVector size (m_boxSize.m_x * dgAbsf(matrix[0][0]) + m_boxSize.m_y * dgAbsf(matrix[1][0]) + m_boxSize.m_z * dgAbsf(matrix[2][0]) + DG_MAX_COLLISION_PADDING, 
               m_boxSize.m_x * dgAbsf(matrix[0][1]) + m_boxSize.m_y * dgAbsf(matrix[1][1]) + m_boxSize.m_z * dgAbsf(matrix[2][1]) + DG_MAX_COLLISION_PADDING, 
               m_boxSize.m_x * dgAbsf(matrix[0][2]) + m_boxSize.m_y * dgAbsf(matrix[1][2]) + m_boxSize.m_z * dgAbsf(matrix[2][2]) + DG_MAX_COLLISION_PADDING,
               dgFloat32 (0.0f));

   p0 = origin - size;
   p1 = origin + size;

#ifdef DG_DEBUG_AABB
   dgInt32 i;
   dgVector q0;
   dgVector q1;
   dgMatrix trans (matrix.Transpose());
   for (i = 0; i < 3; i ++) {
      q0[i] = matrix.m_posit[i] + matrix.RotateVector (SupportVertex(trans[i].Scale (-dgFloat32 (1.0f))))[i];
      q1[i] = matrix.m_posit[i] + matrix.RotateVector (SupportVertex(trans[i]))[i];
   }

   dgVector err0 (p0 - q0);
   dgVector err1 (p1 - q1);
   dgFloat32 err;
   err = GetMax (size.m_x, size.m_y, size.m_z) * 0.5f;
   _ASSERTE ((err0 % err0) < err * err);
   _ASSERTE ((err1 % err1) < err * err);
#endif

}


if the function was wrong the the collision will fail not only on cylinder but all almost every shape.
can you set a break point on the function and see if it actually use the matrix

also if you want a tight AABB the best function is not AABB the best funtion is the support vertex.
viewtopic.php?f=15&t=5163
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby agi_shi » Wed Apr 27, 2011 5:34 pm

Sorry, perhaps I expressed myself ambiguously.

The matrix I pass into NewtonCollisionCalculateAABB() (the same matrix passed to dgCollisionConvex::CalcAABB) is used correctly (for every type of collision).

The issue is that the matrix I pass into NewtonCreateCylinder() seems to be ignored when calculating the AABB. That is, when I create a cylinder with a 90 degree rotation (see my example code), that original 90 degree rotation is ignored when calculating the AABB, but the cylinder itself is indeed rotated 90 degrees.

I did some of my own digging, and it seems that dgCollisionConvex::CalcAABB does not account for dgCollision::m_offset. Is this intended?
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby agi_shi » Wed Apr 27, 2011 5:50 pm

I did some of my own digging, and if we make the following change to dgCollisionConvex::CalcAABB:
Code: Select all
// rename matrix to matrixPtr
void dgCollisionConvex::CalcAABB (const dgMatrix &matrixPtr, dgVector& p0, dgVector& p1) const
{
   // calculate the proper matrix
   dgMatrix matrix(GetOffsetMatrix() * matrixPtr);

   // [...]

Then the bounding box is correct, even when I pass an offset matrix to NewtonCreateCylinder()
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby agi_shi » Wed Apr 27, 2011 6:00 pm

That said, NewtonCollisionCalculateAABB() still returns an incorrect result when used on a convex hull modifier which contains such a rotated cylinder. I believe this is because dgCollisionConvexModifer has its own CalcAABB() function which is based on SupportVertex(). I don't know how to fix this issue, I think the bug is within SupportVertex().
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby Julio Jerez » Wed Apr 27, 2011 10:22 pm

agi_shi wrote:I did some of my own digging, and it seems that dgCollisionConvex::CalcAABB does not account for dgCollision::m_offset. Is this intended?


This is correct,
Like I said Calculate support Vertex is the best way to calculate the AABB
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby Julio Jerez » Wed Apr 27, 2011 10:59 pm

This is support Vertex function

Code: Select all
void NewtonCollisionSupportVertex(const NewtonCollision* collisionPtr, const dFloat* const dir, dFloat* const vertex)
{
   dgCollisionConvex* collision;
   

   TRACE_FUNTION(__FUNCTION__);

   collision = (dgCollisionConvex*) collisionPtr;
//   _ASSERTE (collision->IsType (dgCollision::dgConvexCollision_RTTI));

   const dgMatrix& matrix = collision->GetOffsetMatrix ();
   dgVector searchDir (matrix.UnrotateVector(dgVector (dir[0], dir[1], dir[2], dgFloat32 (0.0f))));
   searchDir = searchDir.Scale (dgRsqrt (searchDir % searchDir));

   dgVector vertexOut (matrix.TransformVector(collision->SupportVertex(searchDir)));

   vertex[0] = vertexOut[0];
   vertex[1] = vertexOut[1];
   vertex[2] = vertexOut[2];
   
}



As you can see it does uses the offset Matrix: const dgMatrix& matrix = collision->GetOffsetMatrix ();

Belive me supportvertex is used for everything collison related in the engine.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby Julio Jerez » Thu Apr 28, 2011 8:59 am

Agi, your sugestion to change the CalcAABB is a good one, but it may break the engine in lots of other places.
a better solution will be to modify NewtonCollisionCalculateAABB like this
Code: Select all
void NewtonCollisionCalculateAABB(const NewtonCollision* collisionPtr, const dFloat* const offsetMatrix, dFloat* const p0, dFloat* const p1)
{
   dgCollision* collision;
   collision = (dgCollision*) collisionPtr;

//   const dgMatrix& matrix = *((dgMatrix*) offsetMatrix);
              dgMatrix matrix = collision->GetOfssetMtarix () * (*((dgMatrix*) offsetMatrix));

   dgVector q0;
   dgVector q1;

   TRACE_FUNTION(__FUNCTION__);
   collision->CalcAABB (matrix, q0, q1);
   p0[0] = q0.m_x;
   p0[1] = q0.m_y;
   p0[2] = q0.m_z;

   p1[0] = q1.m_x;
   p1[1] = q1.m_y;
   p1[2] = q1.m_z;
}


and the problem will be solved for everything without modifying the internals of the collision system
does that make sence to you?

if it does I checked in that conversion, if you sync to SVN you can test it and see if it works.
Julio Jerez
Moderator
Moderator
 
Posts: 12249
Joined: Sun Sep 14, 2003 2:18 pm
Location: Los Angeles

Re: NewtonCollisionCalculateAABB() ignores original matrix

Postby agi_shi » Thu Apr 28, 2011 11:03 am

:shock: So NewtonCollisionSupportVertex() uses GetOffsetMatrix(), not the internal dgCollisionConvex::SupportVertex() function. Therefore, it makes perfect sense to use GetOffsetMatrix() in NewtonCollisionCalculateAABB() rather than the internal dgCollisionConvex::CalcAABB() function.

I'm completely confident that your suggested fix will completely fix my issue without affecting any of the internals of the engine, like you said :mrgreen: I'll update to SVN HEAD when I get home.
agi_shi
 
Posts: 263
Joined: Fri Aug 17, 2007 6:54 pm


Return to Bugs and Fixes

Who is online

Users browsing this forum: No registered users and 6 guests

cron