Report any bugs here and we'll post fixes
Moderators: Sascha Willems, Thomas
by 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:
The same issue applies to cones and capsules because they also default to the "sideways configuration":
Spheres and boxes do not have this issue (I provide an identity matrix to the CreateBox/CreateSphere functions):
Is this a bug, or am I doing something wrong?
-
agi_shi
-
- Posts: 263
- Joined: Fri Aug 17, 2007 6:54 pm
by 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
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by 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
by 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
by 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
by 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
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by 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
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by 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
-
- Posts: 12249
- Joined: Sun Sep 14, 2003 2:18 pm
- Location: Los Angeles
-
by agi_shi » Thu Apr 28, 2011 11:03 am
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
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