#region CPL License
/*
Nuclex Framework
Copyright (C) 2002-2009 Nuclex Development Labs
This library is free software; you can redistribute it and/or
modify it under the terms of the IBM Common Public License as
published by the IBM Corporation; either version 1.0 of the
License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
IBM Common Public License for more details.
You should have received a copy of the IBM Common Public
License along with this library
*/
#endregion
using System;
using Microsoft.Xna.Framework;
namespace Nuclex.Geometry.Volumes.Collisions {
/// Contains all Aabb-to-Obb interference detection code
public static class AabbObbCollider {
/// Checks an AABB for intersection with an OBB
/// Extents of the AABB
/// Orientation and position of the OBB
/// Extents of the OBB
/// True if the two boxes are overlapping
///
///
/// This method is a helper method for the other intersection checks. It assumes the
/// AABB is sitting right in the center of the coordinate frame. In other words,
/// that the OBB has been transformed into the AABB's local coordinate frame.
///
///
/// Idea taken from the "Simple Intersection Tests for Games" article
/// on gamasutra by Gomez. The algorithm uses the separating axis test for
/// all 15 potential separating axes. If a separating axis can not be found,
/// the two boxes are overlapping.
/// (http://www.gamasutra.com/features/19991018/Gomez_1.htm)
///
///
public static bool CheckContact(
Vector3 aabbExtents, Matrix obbTransform, Vector3 obbExtents
) {
double ra, rb, t;
// A's basis vectors
for(int i = 0; i < 3; ++i) {
ra = VectorHelper.Get(ref aabbExtents, i);
rb =
obbExtents.X * Math.Abs(MatrixHelper.Get(ref obbTransform, i, 0)) +
obbExtents.Y * Math.Abs(MatrixHelper.Get(ref obbTransform, i, 1)) +
obbExtents.Z * Math.Abs(MatrixHelper.Get(ref obbTransform, i, 2));
//t = Math.Abs(VectorHelper.Get(ref obbPosition, i));
t = Math.Abs(MatrixHelper.Get(ref obbTransform, 3, i));
if(t > ra + rb)
return false;
}
// B's basis vectors
for(int k = 0; k < 3; ++k) {
ra =
aabbExtents.X * Math.Abs(MatrixHelper.Get(ref obbTransform, 0, k)) +
aabbExtents.Y * Math.Abs(MatrixHelper.Get(ref obbTransform, 1, k)) +
aabbExtents.Z * Math.Abs(MatrixHelper.Get(ref obbTransform, 2, k));
rb = VectorHelper.Get(ref obbExtents, k);
t = Math.Abs(
obbTransform.M41 * MatrixHelper.Get(ref obbTransform, 0, k) +
obbTransform.M42 * MatrixHelper.Get(ref obbTransform, 1, k) +
obbTransform.M43 * MatrixHelper.Get(ref obbTransform, 2, k)
);
if(t > ra + rb)
return false;
}
// L = A0 x B0
ra =
aabbExtents.Y * Math.Abs(obbTransform.M31) +
aabbExtents.Z * Math.Abs(obbTransform.M21);
rb =
obbExtents.Y * Math.Abs(obbTransform.M13) +
obbExtents.Z * Math.Abs(obbTransform.M12);
t = Math.Abs(
obbTransform.M43 * obbTransform.M21 - obbTransform.M42 * obbTransform.M31
);
if(t > ra + rb)
return false;
// L = A0 x B1
ra =
aabbExtents.Y * Math.Abs(obbTransform.M32) +
aabbExtents.Z * Math.Abs(obbTransform.M22);
rb =
obbExtents.X * Math.Abs(obbTransform.M13) +
obbExtents.Z * Math.Abs(obbTransform.M11);
t = Math.Abs(
obbTransform.M43 * obbTransform.M22 - obbTransform.M42 * obbTransform.M32
);
if(t > ra + rb)
return false;
// L = A0 x B2
ra =
aabbExtents.Y * Math.Abs(obbTransform.M33) +
aabbExtents.Z * Math.Abs(obbTransform.M23);
rb =
obbExtents.X * Math.Abs(obbTransform.M12) +
obbExtents.Y * Math.Abs(obbTransform.M11);
t = Math.Abs(
obbTransform.M43 * obbTransform.M23 - obbTransform.M42 * obbTransform.M33
);
if(t > ra + rb)
return false;
// L = A1 x B0
ra =
aabbExtents.X * Math.Abs(obbTransform.M31) +
aabbExtents.Z * Math.Abs(obbTransform.M11);
rb =
obbExtents.Y * Math.Abs(obbTransform.M23) +
obbExtents.Z * Math.Abs(obbTransform.M22);
t = Math.Abs(
obbTransform.M41 * obbTransform.M31 - obbTransform.M43 * obbTransform.M11
);
if(t > ra + rb)
return false;
// L = A1 x B1
ra =
aabbExtents.X * Math.Abs(obbTransform.M32) +
aabbExtents.Z * Math.Abs(obbTransform.M12);
rb =
obbExtents.X * Math.Abs(obbTransform.M23) +
obbExtents.Z * Math.Abs(obbTransform.M21);
t = Math.Abs(
obbTransform.M41 * obbTransform.M32 - obbTransform.M43 * obbTransform.M12
);
if(t > ra + rb)
return false;
// L = A1 x B2
ra =
aabbExtents.X * Math.Abs(obbTransform.M33) +
aabbExtents.Z * Math.Abs(obbTransform.M13);
rb =
obbExtents.X * Math.Abs(obbTransform.M22) +
obbExtents.Y * Math.Abs(obbTransform.M21);
t = Math.Abs(
obbTransform.M41 * obbTransform.M33 - obbTransform.M43 * obbTransform.M13
);
if(t > ra + rb)
return false;
// L = A2 x B0
ra =
aabbExtents.X * Math.Abs(obbTransform.M21) +
aabbExtents.Y * Math.Abs(obbTransform.M11);
rb =
obbExtents.Y * Math.Abs(obbTransform.M33) +
obbExtents.Z * Math.Abs(obbTransform.M32);
t = Math.Abs(
obbTransform.M42 * obbTransform.M11 - obbTransform.M41 * obbTransform.M21
);
if(t > ra + rb)
return false;
// L = A2 x B1
ra =
aabbExtents.X * Math.Abs(obbTransform.M22) +
aabbExtents.Y * Math.Abs(obbTransform.M12);
rb =
obbExtents.X * Math.Abs(obbTransform.M33) +
obbExtents.Z * Math.Abs(obbTransform.M31);
t = Math.Abs(
obbTransform.M42 * obbTransform.M12 - obbTransform.M41 * obbTransform.M22
);
if(t > ra + rb)
return false;
// L = A2 x B2
ra =
aabbExtents.X * Math.Abs(obbTransform.M23) +
aabbExtents.Y * Math.Abs(obbTransform.M13);
rb =
obbExtents.X * Math.Abs(obbTransform.M32) +
obbExtents.Y * Math.Abs(obbTransform.M31);
t = Math.Abs(
obbTransform.M42 * obbTransform.M13 - obbTransform.M41 * obbTransform.M23
);
if(t > ra + rb)
return false;
// No separating axis found, the two boxes overlap
return true;
}
/// Find the contact location between an AABB and an OBB
/// Minimum coordinates of the AABB
/// Maximum coordinates of the AABB
/// Orientation and position of the OBB
/// Extents of the OBB
/// A contact location if the axis aligned box touches the mesh
public static Vector3? FindContact(
Vector3 aabbMin, Vector3 aabbMax, Matrix obbTransform, Vector3 obbExtents
) {
throw new NotImplementedException("Not implemented yet");
}
}
} // namespace Nuclex.Geometry.Volumes.Collisions