// Turn ray into segment
Vector3 A = Origin;
Vector3 B = Origin + Direction * 1000.0f; // Max length of ray (can be reduced)
// Segment mid point
Vector3 m = (A + B) * 0.5f;
// Segment halflength vector
Vector3 d = A - m;
// Translate OBB and segment to origin
m = m - oBB.Centre;
// Project the segment onto the separating axes
float adx = Math.Abs(Vector3.Dot(oBB.Axis_X, d));
float ady = Math.Abs(Vector3.Dot(oBB.Axis_Y, d));
float adz = Math.Abs(Vector3.Dot(oBB.Axis_Z, d));
// Obb axes are othogonal
Console.WriteLine(Vector3.Cross(oBB.Axis_X, oBB.Axis_Y));
Console.WriteLine(oBB.Axis_Z);
// Try world coordinates as separating values
if (Math.Abs(m.X) > oBB.Extents.X + adx)
{
return false;
}
if (Math.Abs(m.Y) > oBB.Extents.Y + ady)
{
return false;
}
if (Math.Abs(m.Z) > oBB.Extents.Z + adz)
{
return false;
}
// Add in an epsilon term to counteract arithmetic errors when segment is (near parallel to a coordinate axis
adx += GameConstants.EPSILON;
ady += GameConstants.EPSILON;
adz += GameConstants.EPSILON;
// Try cross products of segment direction vector with coordinate axes
if (Math.Abs(m.Y * d.Z - m.Z * d.Y) > oBB.Extents.Y * adz + oBB.Extents.Z * ady)
{
return false;
}
if (Math.Abs(m.Z * d.X - m.X * d.Z) > oBB.Extents.X * adz + oBB.Extents.Z * adx)
{
return false;
}
if (Math.Abs(m.X * d.Y - m.Y * d.X) > oBB.Extents.X * ady + oBB.Extents.Y * adx)
{
return false;
}
return true;
[Solved] Problems when projecting segment onto OBB axis.
Here is the ray/intersection test I am using:
The problem is the intersection test is not returning true when the OBB rotation is anything but axis aligned (Matrix.Identity).
Have the following lines not projected the ray/segment onto the OBB axes correctly:
// Project the segment onto the separating axes
float adx = Math.Abs(Vector3.Dot(oBB.Axis_X, d));
float ady = Math.Abs(Vector3.Dot(oBB.Axis_Y, d));
float adz = Math.Abs(Vector3.Dot(oBB.Axis_Z, d));
Or have I made a different mistake entirely?
Thank you.
[Edited by - Spa8nky on November 10, 2009 9:41:44 AM]
Ok, I've now solved the problem but I have another:
When returning the surface normal of the OBB from a given point, is the following correct:
If not, then please feel free to scorn :)
Thanks
EDIT: The method above isn't correct :(
[Edited by - Spa8nky on November 9, 2009 7:47:55 PM]
When returning the surface normal of the OBB from a given point, is the following correct:
/// <summary> /// Return the surface normal for any given point on the OBB /// </summary> /// <param name="point"></param> /// <returns></returns> public Vector3 GetNormalFromPoint(Vector3 point) { Vector3 normal = Vector3.Zero; float min = float.MaxValue; float distance; point -= Centre; distance = Math.Abs(Extents.X - Math.Abs(point.X)); if (distance < min) { min = distance; normal = Math.Sign(point.X) * Axis_X; // Rotation.M11, Rotation.M12, Rotation.M13 } distance = Math.Abs(Extents.Y - Math.Abs(point.Y)); if (distance < min) { min = distance; normal = Math.Sign(point.Y) * Axis_Y; // Rotation.M21, Rotation.M22, Rotation.M23 } distance = Math.Abs(Extents.Z - Math.Abs(point.Z)); if (distance < min) { min = distance; normal = Math.Sign(point.Z) * Axis_Z; // Rotation.M31, Rotation.M32, Rotation.M33 } return normal; }
If not, then please feel free to scorn :)
Thanks
EDIT: The method above isn't correct :(
[Edited by - Spa8nky on November 9, 2009 7:47:55 PM]
I got it, woohoo!
Seems to work just fine! Any comments?
/// <summary> /// Return the surface normal for any given point on the OBB /// </summary> /// <param name="point"></param> /// <returns></returns> public Vector3 GetNormalFromPoint(Vector3 point) { Vector3 normal = Vector3.Zero; float min = float.MaxValue; float distance; point -= Centre; // Compute translation vector t Vector3 t = point - Centre; t.X = Vector3.Dot(point, Axis_X); t.Y = Vector3.Dot(point, Axis_Y); t.Z = Vector3.Dot(point, Axis_Z); distance = Math.Abs(Extents.X - Math.Abs(t.X)); if (distance < min) { min = distance; normal = Math.Sign(t.X) * Axis_X; // Rotation.M11, Rotation.M12, Rotation.M13 } distance = Math.Abs(Extents.Y - Math.Abs(t.Y)); if (distance < min) { min = distance; normal = Math.Sign(t.Y) * Axis_Y; // Rotation.M21, Rotation.M22, Rotation.M23 } distance = Math.Abs(Extents.Z - Math.Abs(t.Z)); if (distance < min) { min = distance; normal = Math.Sign(t.Z) * Axis_Z; // Rotation.M31, Rotation.M32, Rotation.M33 } return normal; }
Seems to work just fine! Any comments?
Just that
Vector3 t = point - Centre;
is overwritten immediately after that line. So I assume thatVector3 t;
would be already sufficient.
Oh yes, thank you.
The code now reads as follows:
I think this is about as straight forward as I can make this method. If I try simplifying it:
The code won't work as I am changing t each time.
The code now reads as follows:
/// <summary> /// Return the surface normal for any given point on the OBB /// </summary> /// <param name="point"></param> /// <returns></returns> public Vector3 GetNormalFromPoint(Vector3 point) { Vector3 normal = Vector3.Zero; float min = float.MaxValue; float distance; // Compute translation vector t point -= Centre; Vector3 t; // Bring translation into OBB's coordinate frame t.X = Vector3.Dot(point, Axis_X); t.Y = Vector3.Dot(point, Axis_Y); t.Z = Vector3.Dot(point, Axis_Z); distance = Math.Abs(Extents.X - Math.Abs(t.X)); if (distance < min) { min = distance; normal = Math.Sign(t.X) * Axis_X; // Rotation.M11, Rotation.M12, Rotation.M13 } distance = Math.Abs(Extents.Y - Math.Abs(t.Y)); if (distance < min) { min = distance; normal = Math.Sign(t.Y) * Axis_Y; // Rotation.M21, Rotation.M22, Rotation.M23 } distance = Math.Abs(Extents.Z - Math.Abs(t.Z)); if (distance < min) { min = distance; normal = Math.Sign(t.Z) * Axis_Z; // Rotation.M31, Rotation.M32, Rotation.M33 } return normal; }
I think this is about as straight forward as I can make this method. If I try simplifying it:
// Compute translation vector t Vector3 t = point - Centre; // Bring translation into OBB's coordinate frame t.X = Vector3.Dot(t, Axis_X); t.Y = Vector3.Dot(t, Axis_Y); t.Z = Vector3.Dot(t, Axis_Z);
The code won't work as I am changing t each time.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement