Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
1574 lines
56 KiB
C++
1574 lines
56 KiB
C++
#include "StuffHeaders.hpp"
|
|
|
|
OBB OBB::Identity(LinearMatrix4D(0), Vector3D(0.0f, 0.0f, 0.0f), 0.0f);
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void OBB::TestInstance() const
|
|
{
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
int OBB::ComputeBounds(ReadOnlyArrayOf<Point3D> &points)
|
|
{
|
|
Check_Object(&points);
|
|
|
|
//
|
|
//----------------------------------------------------------
|
|
// Find the coordinate system the points would like to be in
|
|
//----------------------------------------------------------
|
|
//
|
|
localToParent.ComputeAxes(points);
|
|
LinearMatrix4D world_to_local;
|
|
world_to_local.Invert(localToParent);
|
|
int type = 1;
|
|
|
|
//
|
|
//----------------------------------------------------------------
|
|
// Find the extents of both the local and world bounds and use the
|
|
// smaller set
|
|
//----------------------------------------------------------------
|
|
//
|
|
DynamicArrayOf<Point3D> local_points(points.GetLength());
|
|
for (int i=0; i<points.GetLength(); ++i)
|
|
local_points[i].Multiply(points[i], world_to_local);
|
|
ExtentBox local_box;
|
|
ExtentBox box;
|
|
local_box.ComputeBounds(local_points);
|
|
box.ComputeBounds(points);
|
|
|
|
//
|
|
//----------------------------------------------------
|
|
// If we are using the world box reset localToParent
|
|
//----------------------------------------------------
|
|
//
|
|
Point3D center_in_world;
|
|
if (box.GetVolume() < local_box.GetVolume())
|
|
{
|
|
// Get center-in-world directly from world box
|
|
box.GetCenterpoint(¢er_in_world);
|
|
localToParent = LinearMatrix4D::Identity;
|
|
axisExtents.x = 0.5f * (box.maxX - box.minX) + SMALL;
|
|
axisExtents.y = 0.5f * (box.maxY - box.minY) + SMALL;
|
|
axisExtents.z = 0.5f * (box.maxZ - box.minZ) + SMALL;
|
|
type = 2;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// Else we are using the local box recompute the center-in-world
|
|
//--------------------------------------------------------------
|
|
//
|
|
else {
|
|
Point3D center;
|
|
local_box.GetCenterpoint(¢er);
|
|
center_in_world.Multiply(center, localToParent);
|
|
axisExtents.x = 0.5f * (local_box.maxX - local_box.minX) + SMALL;
|
|
axisExtents.y = 0.5f * (local_box.maxY - local_box.minY) + SMALL;
|
|
axisExtents.z = 0.5f * (local_box.maxZ - local_box.minZ) + SMALL;
|
|
}
|
|
|
|
localToParent(3,0) = center_in_world.x;
|
|
localToParent(3,1) = center_in_world.y;
|
|
localToParent(3,2) = center_in_world.z;
|
|
|
|
sphereRadius = axisExtents.GetLength();
|
|
return type;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
#if !defined(Spew)
|
|
void Spew(
|
|
const char* group,
|
|
const OBB &box
|
|
)
|
|
{
|
|
Check_Object(&box);
|
|
SPEW((group, ""));
|
|
SPEW((group, " Transform = +"));
|
|
Spew(group, box.localToParent);
|
|
SPEW((group, ""));
|
|
SPEW((
|
|
group,
|
|
" Extents = <%4f,%4f,%4f>, Radius = %4f+",
|
|
box.axisExtents.x,
|
|
box.axisExtents.y,
|
|
box.axisExtents.z,
|
|
box.sphereRadius
|
|
));
|
|
}
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
OBB& OBB::Multiply(
|
|
const OBB &obb,
|
|
const LinearMatrix4D &matrix
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&obb);
|
|
Check_Object(&matrix);
|
|
|
|
localToParent.Multiply(obb.localToParent, matrix);
|
|
axisExtents = obb.axisExtents;
|
|
sphereRadius = obb.sphereRadius;
|
|
return *this;
|
|
}
|
|
|
|
#if 0 // moved it into hpp-file
|
|
//
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
OBB& OBB::MultiplySphereOnly(
|
|
const OBB &obb,
|
|
const LinearMatrix4D &matrix
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&obb);
|
|
Check_Object(&matrix);
|
|
|
|
#if USE_ASSEMBLER_CODE
|
|
|
|
Scalar *f = localToParent.entries;
|
|
|
|
_asm {
|
|
mov edx, matrix
|
|
push esi
|
|
mov esi, obb.localToParent
|
|
|
|
mov eax, f
|
|
|
|
fld dword ptr [edx+4] // m[1][0]
|
|
fmul dword ptr [esi+01ch] // obb.localToParent(3,1)
|
|
|
|
fld dword ptr [edx+8] // m[2][0]
|
|
fmul dword ptr [esi+02Ch] // obb.localToParent(3,2)
|
|
|
|
fxch st(1)
|
|
fadd dword ptr [edx+0Ch] // m[3][0]
|
|
|
|
fld dword ptr [edx] // m[0][0]
|
|
fmul dword ptr [esi+0Ch] // obb.localToParent(3,0)
|
|
|
|
fxch st(2)
|
|
faddp st(1),st
|
|
|
|
fld dword ptr [edx+14h] // m[1][1]
|
|
fmul dword ptr [esi+01ch] // obb.localToParent(3,1)
|
|
|
|
fxch st(2)
|
|
faddp st(1),st
|
|
|
|
fld dword ptr [edx+18h] // m[2][1]
|
|
fmul dword ptr [esi+02ch] // obb.localToParent(3,2)
|
|
|
|
fxch st(1)
|
|
fstp dword ptr [eax+0ch] // localToParent(3,0)
|
|
|
|
fadd dword ptr [edx+1Ch] // m[3][1]
|
|
|
|
fld dword ptr [edx+10h] // m[0][1]
|
|
fmul dword ptr [esi+0ch] // obb.localToParent(3,0)
|
|
|
|
fxch st(2)
|
|
faddp st(1),st
|
|
|
|
fld dword ptr [edx+24h] // m[1][2]
|
|
fmul dword ptr [esi+01ch] // obb.localToParent(3,1)
|
|
|
|
fxch st(2)
|
|
faddp st(1),st
|
|
|
|
fld dword ptr [edx+28h] // m[2][2]
|
|
fmul dword ptr [esi+02ch] // obb.localToParent(3,2)
|
|
|
|
fxch st(1)
|
|
fstp dword ptr [eax+01ch] // localToParent(3,1)
|
|
|
|
fadd dword ptr [edx+2Ch] // m[3][2]
|
|
|
|
fld dword ptr [edx+20h] // m[0][2]
|
|
fmul dword ptr [esi+0ch] // obb.localToParent(3,0)
|
|
|
|
fxch st(2)
|
|
faddp st(1),st
|
|
|
|
pop esi
|
|
|
|
faddp st(1),st
|
|
|
|
fstp dword ptr [eax+02ch] // localToParent(3,2)
|
|
}
|
|
#else
|
|
localToParent(3,0) =
|
|
obb.localToParent(3,0)*matrix(0,0)
|
|
+ obb.localToParent(3,1)*matrix(1,0)
|
|
+ obb.localToParent(3,2)*matrix(2,0)
|
|
+ matrix(3,0);
|
|
localToParent(3,1) =
|
|
obb.localToParent(3,0)*matrix(0,1)
|
|
+ obb.localToParent(3,1)*matrix(1,1)
|
|
+ obb.localToParent(3,2)*matrix(2,1)
|
|
+ matrix(3,1);
|
|
localToParent(3,2) =
|
|
obb.localToParent(3,0)*matrix(0,2)
|
|
+ obb.localToParent(3,1)*matrix(1,2)
|
|
+ obb.localToParent(3,2)*matrix(2,2)
|
|
+ matrix(3,2);
|
|
#endif
|
|
|
|
sphereRadius = obb.sphereRadius;
|
|
return *this;
|
|
}
|
|
#endif
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
OBB::SeparatingAxis OBB::FindSeparatingAxis(const OBB& box) const
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(&box);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// The following routine is based on various simplifications of the
|
|
// following formula: If L represents a line in space, two OBBs (A and B)
|
|
// are separated by on that axis if (B-A)*L > sum of the projected radii.
|
|
// The projected radius of each OBB is equal to the sum of the three
|
|
// cardinal axes (in parent space) projected unto the line and multiplied
|
|
// by the OBBs extent size in that direction
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Verify(axisExtents.x >= 0.0f);
|
|
Verify(axisExtents.y >= 0.0f);
|
|
Verify(axisExtents.z >= 0.0f);
|
|
Verify(box.axisExtents.x >= 0.0f);
|
|
Verify(box.axisExtents.y >= 0.0f);
|
|
Verify(box.axisExtents.z >= 0.0f);
|
|
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Get the distance between the centerpoints. Both boxes are assumed to
|
|
// convert their local axes into a common parent space
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check_Object(&localToParent);
|
|
Check_Object(&box.localToParent);
|
|
Point3D
|
|
distance(
|
|
localToParent(3,0) - box.localToParent(3,0),
|
|
localToParent(3,1) - box.localToParent(3,1),
|
|
localToParent(3,2) - box.localToParent(3,2)
|
|
);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// The rows of the matrix encode the local axes in world space. The first
|
|
// separation axis we will be testing our x axis in world space, so
|
|
// project the other box's primary axes onto it, and store the results
|
|
// away for future reference
|
|
//
|
|
// The math for L = A0: (A0 is the X axis row of our matrix)
|
|
// Given: A0,A1, and B2 are orthogonal
|
|
// B0,B1, and B2 are orthogonal
|
|
// Ax, Ay, and Az >= 0
|
|
// Bx, By, and Bz >= 0
|
|
//
|
|
// projection = (B-A)*A0
|
|
// radius = |Ax*(A0*A0)| + |Ay*(A0*A1)| + |Az*(A0*A2)| + |Bx*(A0*B0)| + |By*(A0*B1)| + |Bz*(A0*B2)|
|
|
// = Ax + Bx*|A0*B0| + By*|A0*B1| + Bz*|A0*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
Scalar axis_projections[3][3];
|
|
axis_projections[X_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// The maximum distance the centerpoints can be away and still touch is
|
|
// equal to the sum of our x extent plus the other's extents, as modified
|
|
// by the projection values. If the boxes can't touch, return A0 as the
|
|
// separating plane
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Scalar radius =
|
|
axisExtents.x
|
|
+ box.axisExtents.x * axis_projections[X_Axis][0]
|
|
+ box.axisExtents.y * axis_projections[X_Axis][1]
|
|
+ box.axisExtents.z * axis_projections[X_Axis][2];
|
|
Scalar projection =
|
|
localToParent(X_Axis,0) * distance.x
|
|
+ localToParent(X_Axis,1) * distance.y
|
|
+ localToParent(X_Axis,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return A0;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Do the same check against our Y axis
|
|
//
|
|
// The math for L = A1:
|
|
//
|
|
// projection = (B-A)*A1
|
|
// radius = |Ax*(A1*A0)| + |Ay*(A1*A1)| + |Az*(A1*A2)| + |Bx*(A1*B0)| + |By*(A1*B1)| + |Bz*(A1*B2)|
|
|
// = Ay + Bx*|A1*B0| + By*|A1*B1| + Bz*|A1*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Y_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.y
|
|
+ box.axisExtents.x * axis_projections[1][0]
|
|
+ box.axisExtents.y * axis_projections[1][1]
|
|
+ box.axisExtents.z * axis_projections[1][2];
|
|
projection =
|
|
localToParent(1,0) * distance.x
|
|
+ localToParent(1,1) * distance.y
|
|
+ localToParent(1,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return A1;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check our z axis
|
|
//
|
|
// The math for L = A2:
|
|
//
|
|
// projection = (B-A)*A2
|
|
// radius = |Ax*(A2*A0)| + |Ay*(A2*A1)| + |Az*(A2*A2)| + |Bx*(A2*B0)| + |By*(A2*B1)| + |Bz*(A2*B2)|
|
|
// = Az + Bx*|A2*B0| + By*|A2*B1| + Bz*|A2*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Z_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.z
|
|
+ box.axisExtents.x * axis_projections[2][0]
|
|
+ box.axisExtents.y * axis_projections[2][1]
|
|
+ box.axisExtents.z * axis_projections[2][2];
|
|
projection =
|
|
localToParent(2,0) * distance.x
|
|
+ localToParent(2,1) * distance.y
|
|
+ localToParent(2,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return A2;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// See if the other box's X axis is a separator
|
|
//
|
|
// The math for L = B0:
|
|
//
|
|
// projection = (B-A)*B0
|
|
// radius = |Ax*(B0*A0)| + |Ay*(B0*A1)| + |Az*(B0*A2)| + |Bx*(B0*B0)| + |By*(B0*B1)| + |Bz*(B0*B2)|
|
|
// = Bx + Ax*|B0*A0| + Ay*|B0*A1| + Az*|B0*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.x
|
|
+ axisExtents.x * axis_projections[0][X_Axis]
|
|
+ axisExtents.y * axis_projections[1][X_Axis]
|
|
+ axisExtents.z * axis_projections[2][X_Axis];
|
|
projection =
|
|
box.localToParent(X_Axis,0) * distance.x
|
|
+ box.localToParent(X_Axis,1) * distance.y
|
|
+ box.localToParent(X_Axis,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return B0;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Y axis
|
|
//
|
|
// The math for L = B1:
|
|
//
|
|
// projection = (B-A)*B1
|
|
// radius = |Ax*(B1*A0)| + |Ay*(B1*A1)| + |Az*(B1*A2)| + |Bx*(B1*B0)| + |By*(B1*B1)| + |Bz*(B1*B2)|
|
|
// = By + Ax*|B1*A0| + Ay*|B1*A1| + Az*|B1*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.y
|
|
+ axisExtents.x * axis_projections[0][Y_Axis]
|
|
+ axisExtents.y * axis_projections[1][Y_Axis]
|
|
+ axisExtents.z * axis_projections[2][Y_Axis];
|
|
projection =
|
|
box.localToParent(Y_Axis,0) * distance.x
|
|
+ box.localToParent(Y_Axis,1) * distance.y
|
|
+ box.localToParent(Y_Axis,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return B1;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Z axis
|
|
//
|
|
// The math for L = B2:
|
|
//
|
|
// projection = (B-A)*B2
|
|
// radius = |Ax*(B2*A0)| + |Ay*(B2*A1)| + |Az*(B2*A2)| + |Bx*(B2*B0)| + |By*(B2*B1)| + |Bz*(B2*B2)|
|
|
// = Bz + Ax*|B2*A0| + Ay*|B2*A1| + Az*|B2*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.z
|
|
+ axisExtents.x * axis_projections[0][Z_Axis]
|
|
+ axisExtents.y * axis_projections[1][Z_Axis]
|
|
+ axisExtents.z * axis_projections[2][Z_Axis];
|
|
projection =
|
|
box.localToParent(Z_Axis,0) * distance.x
|
|
+ box.localToParent(Z_Axis,1) * distance.y
|
|
+ box.localToParent(Z_Axis,2) * distance.z;
|
|
if (projection > radius || projection < -radius)
|
|
return B2;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
// We have finished with the separation tests based upon the box faces. We
|
|
// now need to test with the edges, so make a matrix that converts the other
|
|
// box into our space, then recompute the distance vector (its just the
|
|
// other boxes's new origin)
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
LinearMatrix4D parent_to_local;
|
|
parent_to_local.Invert(localToParent);
|
|
LinearMatrix4D b;
|
|
b.Multiply(box.localToParent, parent_to_local);
|
|
distance = b;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The next 9 tests will create separation axes by crossing the 3 direction
|
|
// vectors of our box with the 3 direction vectors of the other box
|
|
//
|
|
// The math for L = A0xB0 or <1,0,0>xB0:
|
|
//
|
|
// projection = (B-A)*(A0xB0) = (B-A)*<0,-B(0,2),B(0,1)>
|
|
// radius = |Ax*((A0xB0)*A0)| + |Ay*((A0xB0)*A1)| + |Az*((A0xB0)*A2)|
|
|
// + |Bx*((A0xB0)*B0)| + |By*((A0xB0)*B1)| + |Bz*((A0xB0)*B2)|
|
|
// = Ay*|(A0xB0)*A1| + Az*|(A0xB0)*A2| + By*|(A0xB0)*B1| + Bz*|(A0xB0)*B2|
|
|
// = Ay*|(<1,0,0>xB0)*<0,1,0>| + Az*|(<1,0,0>xB0)*<0,0,1>|
|
|
// + By*|(<1,0,0>xB0)*B1| + Bz*|(<1,0,0>xB0)*B2|
|
|
// = Ay*|<0,-B(0,2),B(0,1)>*<0,1,0>| + Az*|<0,-B(0,2),B(0,1)>*<0,0,1>|
|
|
// + By*|<0,-B(0,2),B(0,1)>*B1| + Bz*|<0,-B(0,2),B(0,1)>*B2|
|
|
// = Ay*|-B(0,2)| + Az*|B(0,1)| + By*|<0,-B(0,2),B(0,1)>*B1| + Bz*|<0,-B(0,2),B(0,1)>*B2|
|
|
// = Ay*|B(0,2)| + Az*|B(0,1)|
|
|
// + By*|<0,-B(0,2),B(0,1)>*<B(1,0),B(1,1),B(1,2)>| + Bz*|<0,-B(0,2),B(0,1)>*<B(2,0),B(2,1),B(2,2)>|
|
|
// = Ay*|B(0,2)| + Az*|B(0,1)|
|
|
// + By*|<-B(0,2),B(0,1)>*<B(1,1),B(1,2)>| + Bz*|<-B(0,2),B(0,1)>*<B(2,1),B(2,2)>|
|
|
// = Ay*|B(0,2)| + Az*|B(0,1)|
|
|
// + By*|B(0,1)*B(1,2) - B(0,2)*<B(1,1)| + Bz*|B(0,1)*B(2,2) - B(0,2)*B(2,1)|
|
|
// = Ay*|B(0,2)| + Az*|B(0,1)| + By*dets(2,0) + Bz*dets(1,0)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
Scalar dets[3][3];
|
|
dets[1][0] = Fabs(b(0,1)*b(2,2) - b(2,1)*b(0,2));
|
|
dets[2][0] = Fabs(b(0,1)*b(1,2) - b(1,1)*b(0,2));
|
|
|
|
Scalar absolutes[3][3];
|
|
absolutes[0][1] = Fabs(b(0,1));
|
|
absolutes[0][2] = Fabs(b(0,2));
|
|
|
|
radius =
|
|
axisExtents.y*absolutes[0][2]
|
|
+ axisExtents.z*absolutes[0][1]
|
|
+ box.axisExtents.y*dets[2][0]
|
|
+ box.axisExtents.z*dets[1][0];
|
|
projection = distance.z*b(0,1) - distance.y*b(0,2);
|
|
if (projection > radius || projection < -radius)
|
|
return A0xB0;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A0xB1 or <1,0,0>xB1:
|
|
//
|
|
// dets absolutes
|
|
// ... .**
|
|
// *.. ...
|
|
// *.. ...
|
|
//
|
|
// projection = (B-A)*(A0xB1) = (B-A)*<0,-B(1,2),B(1,1)>
|
|
// radius = Ax*|((A0xB1)*A0)| + Ay*|((A0xB1)*A1)| + Az*|((A0xB1)*A2)|
|
|
// + Bx*|((A0xB1)*B0)| + By*|((A0xB1)*B1)| + Bz*|((A0xB1)*B2)|
|
|
// = Ay*|(A0xB1)*A1| + Az*|(A0xB1)*A2| + Bx*|(A0xB1)*B0| + Bz*|(A0xB1)*B2|
|
|
// = Ay*|(<1,0,0>xB1)*A1| + Az*|(<1,0,0>xB1)*A2| + Bx*|(<1,0,0>xB1)*B0| + Bz*|(<1,0,0>xB1)*B2|
|
|
// = Ay*|<0,-B(1,2),B(1,1)>*<0,1,0>| + Az*|<0,-B(1,2),B(1,1)>*<0,0,1>|
|
|
// + Bx*|<0,-B(1,2),B(1,1)>*B0| + Bz*|<0,-B(1,2),B(1,1)>*B2|
|
|
// = Ay*|-B(1,2)| + Az*|B(1,1)| + Bx*|<0,-B(1,2),B(1,1)>*B0| + Bz*|<0,-B(1,2),B(1,1)>*B2|
|
|
// = Ay*|B(1,2)| + Az*|B(1,1)|
|
|
// + Bx*|<0,-B(1,2),B(1,1)>*<B(0,0),B(0,1),B(0,2)>| + Bz*|<0,-B(1,2),B(1,1)>*<B(2,0),B(2,1),B(2,2)>|
|
|
// = Ay*|B(1,2)| + Az*|B(1,1)|
|
|
// + Bx*|<-B(1,2),B(1,1)>*<B(0,1),B(0,2)>| + Bz*|<-B(1,2),B(1,1)>*<B(2,1),B(2,2)>|
|
|
// = Ay*|B(1,2)| + Az*|B(1,1)|
|
|
// + Bx*|B(1,1)*B(0,2) - B(1,2)*B(0,1)| + Bz*|B(1,1)*B(2,2) - B(1,2)*B(2,1)|
|
|
// = Ay*|B(1,2)| + Az*|B(1,1)| + Bx*dets(2,0) + Bz*dets(0,0)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
dets[0][0] = Fabs(b(1,1)*b(2,2) - b(2,1)*b(1,2));
|
|
|
|
absolutes[1][1] = Fabs(b(1,1));
|
|
absolutes[1][2] = Fabs(b(1,2));
|
|
|
|
radius =
|
|
axisExtents.y*absolutes[1][2]
|
|
+ axisExtents.z*absolutes[1][1]
|
|
+ box.axisExtents.x*dets[2][0]
|
|
+ box.axisExtents.z*dets[0][0];
|
|
projection = distance.z*b(1,1) - distance.y*b(1,2);
|
|
if (projection > radius || projection < -radius)
|
|
return A0xB1;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A0xB2 or <1,0,0>xB2:
|
|
//
|
|
// dets absolutes
|
|
// *.. .**
|
|
// *.. .**
|
|
// *.. ...
|
|
//
|
|
// projection = (B-A)*(A0xB2) = (B-A)*<0,-B(2,2),B(2,1)>
|
|
// radius = Ax*|(A0xB2)*A0| + Ay*|(A0xB2)*A1| + Az*|(A0xB2)*A2|
|
|
// + Bx*|(A0xB2)*B0| + By*|(A0xB2)*B1| + Bz*|(A0xB2)*B2|
|
|
// = Ay*|(A0xB2)*A1| + Az*|(A0xB2)*A2| + Bx*|(A0xB2)*B0| + By*|(A0xB2)*B1|
|
|
// = Ay*|<0,-B(2,2),B(2,1)>*A1| + Az*|<0,-B(2,2),B(2,1)>*A2|
|
|
// + Bx*|<0,-B(2,2),B(2,1)>*B0| + By*|<0,-B(2,2),B(2,1)>*B1|
|
|
// = Ay*|<0,-B(2,2),B(2,1)>*<0,1,0>| + Az*|<0,-B(2,2),B(2,1)>*<0,0,1>|
|
|
// + Bx*|<0,-B(2,2),B(2,1)>*<B(0,0),B(0,1),B(0,2)>| + By*|<0,-B(2,2),B(2,1)>*<B(1,0),B(1,1),B(1,2)>|
|
|
// = Ay*|-B(2,2)| + Az*|B(2,1)|
|
|
// + Bx*|<-B(2,2),B(2,1)>*<B(0,1),B(0,2)>| + By*|<-B(2,2),B(2,1)>*<B(1,1),B(1,2)>|
|
|
// = Ay*|B(2,2)| + Az*|B(2,1)|
|
|
// + Bx*|B(2,1)*B(0,2) - B(2,2)*B(0,1)| + By*|B(2,1)*B(1,2) - B(2,2)*B(1,1)|
|
|
// = Ay*|B(2,2)| + Az*|B(2,1)| + Bx*dets(1,0) + By*dets(0,0)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
absolutes[2][1] = Fabs(b(2,1));
|
|
absolutes[2][2] = Fabs(b(2,2));
|
|
|
|
radius =
|
|
axisExtents.y*absolutes[2][2]
|
|
+ axisExtents.z*absolutes[2][1]
|
|
+ box.axisExtents.x*dets[1][0]
|
|
+ box.axisExtents.y*dets[0][0];
|
|
projection = distance.z*b(2,1) - distance.y*b(2,2);
|
|
if (projection > radius || projection < -radius)
|
|
return A0xB2;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A1xB0 or <0,1,0>xB0:
|
|
//
|
|
// dets absolutes
|
|
// *.. .**
|
|
// *.. .**
|
|
// *.. .**
|
|
//
|
|
// projection = (B-A)*(A1xB0) = (B-A)*<B(0,2),0,-B(0,0)>
|
|
// radius = Ax*|(A1xB0)*A0| + Ay*|(A1xB0)*A1| + Az*|(A1xB0)*A2|
|
|
// + Bx*|(A1xB0)*B0| + By*|(A1xB0)*B1| + Bz*|(A1xB0)*B2|
|
|
// = Ax*|(A1xB0)*A0| + Az*|(A1xB0)*A2| + By*|(A1xB0)*B1| + Bz*|(A1xB0)*B2|
|
|
// = Ax*|<B(0,2),0,-B(0,0)>*A0| + Az*|<B(0,2),0,-B(0,0)>*A2|
|
|
// + By*|<B(0,2),0,-B(0,0)>*B1| + Bz*|<B(0,2),0,-B(0,0)>*B2|
|
|
// = Ax*|<B(0,2),0,-B(0,0)>*<1,0,0>| + Az*|<B(0,2),0,-B(0,0)>*<0,0,1>|
|
|
// + By*|<B(0,2),0,-B(0,0)>*<B(1,0),B(1,1),B(1,2)>| + Bz*|<B(0,2),0,-B(0,0)>*<B(2,0),B(2,1),B(2,2)>|
|
|
// = Ax*|B(0,2)| + Az*|-B(0,0)|
|
|
// + By*|<B(0,2),-B(0,0)>*<B(1,0),B(1,2)>| + Bz*|<B(0,2),-B(0,0)>*<B(2,0),B(2,2)>|
|
|
// = Ax*|B(0,2)| + Az*|B(0,0)|
|
|
// + By*|B(0,2)*B(1,0) - B(0,0)*B(1,2)| + Bz*|B(0,2)*B(2,0) - B(0,0)*B(2,2)|
|
|
// = Ax*|B(0,2)| + Az*|B(0,0)| + By*dets(2,1) + Bz*dets(1,1)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
dets[2][1] = Fabs(b(0,2)*b(1,0) - b(0,0)*b(1,2));
|
|
dets[1][1] = Fabs(b(0,0)*b(2,2) - b(2,0)*b(0,2));
|
|
|
|
absolutes[0][0] = Fabs(b(0,0));
|
|
|
|
radius =
|
|
axisExtents.x*absolutes[0][2]
|
|
+ axisExtents.z*absolutes[0][0]
|
|
+ box.axisExtents.y*dets[2][1]
|
|
+ box.axisExtents.z*dets[1][1];
|
|
projection = distance.x*b(0,2) - distance.z*b(0,0);
|
|
if (projection > radius || projection < -radius)
|
|
return A1xB0;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A1xB1 or <0,1,0>xB1:
|
|
//
|
|
// dets absolutes
|
|
// *.. ***
|
|
// **. .**
|
|
// **. .**
|
|
//
|
|
// projection = (B-A)*(A1xB1) = (B-A)*<B(1,2),0,-B(1,0)>
|
|
// radius = Ax*|(A1xB1)*A0| + Ay*|(A1xB1)*A1| + Az*|(A1xB1)*A2|
|
|
// + Bx*|(A1xB1)*B0| + By*|(A1xB1)*B1| + Bz*|(A1xB1)*B2|
|
|
// = Ax*|(A1xB1)*A0| + Az*|(A1xB1)*A2| + Bx*|(A1xB1)*B0| + Bz*|(A1xB1)*B2|
|
|
// = Ax*|<B(1,2),0,-B(1,0)>*A0| + Az*|<B(1,2),0,-B(1,0)>*A2|
|
|
// + Bx*|<B(1,2),0,-B(1,0)>*B0| + Bz*|<B(1,2),0,-B(1,0)>*B2|
|
|
// = Ax*|<B(1,2),0,-B(1,0)>*<1,0,0>| + Az*|<B(1,2),0,-B(1,0)>*<0,0,1>|
|
|
// + Bx*|<B(1,2),0,-B(1,0)>*<B(0,0),B(0,1),B(0,2)>| + Bz*|<B(1,2),0,-B(1,0)>*B(2,0),B(2,1),B(2,2)|
|
|
// = Ax*|B(1,2)| + Az*|-B(1,0)|
|
|
// + Bx*|<B(1,2),-B(1,0)>*<B(0,0),B(0,2)>| + Bz*|<B(1,2),-B(1,0)>*B(2,0),B(2,2)>|
|
|
// = Ax*|B(1,2)| + Az*|B(1,0)|
|
|
// + Bx*|B(1,2)*<B(0,0) - B(1,0)*B(0,2)| + Bz*|B(1,2)*B(2,0) - B(1,0)*B(2,2)|
|
|
// = Ax*|B(1,2)| + Az*|B(1,0)| + Bx*dets(2,1) + Bz*dets(0,1)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
dets[0][1] = Fabs(b(1,2)*b(2,0) - b(1,0)*b(2,2));
|
|
|
|
absolutes[1][0] = Fabs(b(1,0));
|
|
|
|
radius =
|
|
axisExtents.x*absolutes[1][2]
|
|
+ axisExtents.z*absolutes[1][0]
|
|
+ box.axisExtents.x*dets[2][1]
|
|
+ box.axisExtents.z*dets[0][1];
|
|
projection = distance.x*b(1,2) - distance.z*b(1,0);
|
|
if (projection > radius || projection < -radius)
|
|
return A1xB1;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A1xB2 or <0,1,0>xB2:
|
|
//
|
|
// dets absolutes
|
|
// **. ***
|
|
// **. ***
|
|
// **. .**
|
|
//
|
|
// projection = (B-A)*(A1xB2) = (B-A)*<B(2,2),0,-B(2,0)>
|
|
// radius = Ax*|(A1xB2)*A0| + Ay*|(A1xB2)*A1| + Az*|(A1xB2)*A2|
|
|
// + Bx*|(A1xB2)*B0| + By*|(A1xB2)*B1| + Bz*|(A1xB2)*B2|
|
|
// = Ax*|(A1xB2)*A0| + Az*|(A1xB2)*A2| + Bx*|(A1xB2)*B0| + By*|(A1xB2)*B1|
|
|
// = Ax*|<B(2,2),0,-B(2,0)>*A0| + Az*|<B(2,2),0,-B(2,0)>*A2|
|
|
// + Bx*|<B(2,2),0,-B(2,0)>*B0| + By*|<B(2,2),0,-B(2,0)>*B1|
|
|
// = Ax*|<B(2,2),0,-B(2,0)>*<1,0,0>| + Az*|<B(2,2),0,-B(2,0)>*<0,0,1>|
|
|
// + Bx*|<B(2,2),0,-B(2,0)>*<B(0,0),B(0,1),B(0,2)>| + By*|<B(2,2),0,-B(2,0)>*<B(1,0),B(1,1),B(1,2)>|
|
|
// = Ax*|B(2,2)| + Az*|-B(2,0)|
|
|
// + Bx*|<B(2,2),-B(2,0)>*<B(0,0),B(0,2)>| + By*|<B(2,2),-B(2,0)>*<B(1,0),B(1,2)>|
|
|
// = Ax*|B(2,2)| + Az*|B(2,0)|
|
|
// + Bx*|B(2,2)*B(0,0) -B(2,0)*B(0,2)| + By*|B(2,2)*B(1,0) - B(2,0)*B(1,2)|
|
|
// = Ax*|B(2,2)| + Az*|B(2,0)| + Bx*dets(1,1) + By*dets(0,1)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
absolutes[2][0] = Fabs(b(2,0));
|
|
|
|
radius =
|
|
axisExtents.x*absolutes[2][2]
|
|
+ axisExtents.z*absolutes[2][0]
|
|
+ box.axisExtents.x*dets[1][1]
|
|
+ box.axisExtents.y*dets[0][1];
|
|
projection = distance.x*b(2,2) - distance.z*b(2,0);
|
|
if (projection > radius || projection < -radius)
|
|
return A1xB2;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A2xB0 or <0,0,1>xB0:
|
|
//
|
|
// dets absolutes
|
|
// **. ***
|
|
// **. ***
|
|
// **. ***
|
|
//
|
|
// projection = (B-A)*(A2xB0) = (B-A)*<-B(0,1),B(0,0),0>
|
|
// radius = Ax*|(A2xB0)*A0| + Ay*|(A2xB0)*A1| + Az*|(A2xB0)*A2|
|
|
// + Bx*|(A2xB0)*B0| + By*|(A2xB0)*B1| + Bz*|(A2xB0)*B2|
|
|
// = Ax*|(A2xB0)*A0| + Ay*|(A2xB0)*A1| + By*|(A2xB0)*B1| + Bz*|(A2xB0)*B2|
|
|
// = Ax*|<-B(0,1),B(0,0),0>*A0| + Ay*|<-B(0,1),B(0,0),0>*A1|
|
|
// + By*|<-B(0,1),B(0,0),0>*B1| + Bz*|<-B(0,1),B(0,0),0>*B2|
|
|
// = Ax*|<-B(0,1),B(0,0),0>*<1,0,0>| + Ay*|<-B(0,1),B(0,0),0>*<0,1,0>|
|
|
// + By*|<-B(0,1),B(0,0),0>*<B(1,0),B(1,1),B(1,2)>| + Bz*|<-B(0,1),B(0,0),0>*<B(2,0),B(2,1),B(2,2)>|
|
|
// = Ax*|-B(0,1)| + Ay*|B(0,0)|
|
|
// + By*|<-B(0,1),B(0,0)>*<B(1,0),B(1,1)>| + Bz*|<-B(0,1),B(0,0)>*<B(2,0),B(2,1)>|
|
|
// = Ax*|B(0,1)| + Ay*|B(0,0)|
|
|
// + By*|B(0,0)*B(1,1) -B(0,1)*B(1,0)| + Bz*|B(0,0)*B(2,1) - B(0,1)*B(2,0)|
|
|
// = Ax*|B(0,1)| + Ay*|B(0,0)| + By*dets(2,2) + Bz*dets(1,2)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
dets[2][2] = Fabs(b(1,1)*b(0,0) - b(0,1)*b(1,0));
|
|
dets[1][2] = Fabs(b(2,1)*b(0,0) - b(2,0)*b(0,1));
|
|
|
|
radius =
|
|
axisExtents.x*absolutes[0][1]
|
|
+ axisExtents.y*absolutes[0][0]
|
|
+ box.axisExtents.y*dets[2][2]
|
|
+ box.axisExtents.z*dets[1][2];
|
|
projection = distance.y*b(0,0) - distance.x*b(0,1);
|
|
if (projection > radius || projection < -radius)
|
|
return A2xB0;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A2xB1 or <0,0,1>xB1:
|
|
//
|
|
// dets absolutes
|
|
// **. ***
|
|
// *** ***
|
|
// *** ***
|
|
//
|
|
// projection = (B-A)*(A2xB1) = (B-A)*<-B(1,1),B(1,0),0>
|
|
// radius = Ax*|(A2xB1)*A0| + Ay*|(A2xB1)*A1| + Az*|(A2xB1)*A2|
|
|
// + Bx*|(A2xB1)*B0| + By*|(A2xB1)*B1| + Bz*|(A2xB1)*B2|
|
|
// = Ax*|(A2xB1)*A0| + Ay*|(A2xB1)*A1| + Bx*|(A2xB1)*B0| + Bz*|(A2xB1)*B2|
|
|
// = Ax*|<-B(1,1),B(1,0),0>*A0| + Ay*|<-B(1,1),B(1,0),0>*A1|
|
|
// + Bx*|<-B(1,1),B(1,0),0>*B0| + Bz*|<-B(1,1),B(1,0),0>*B2|
|
|
// = Ax*|<-B(1,1),B(1,0),0>*<1,0,0>| + Ay*|<-B(1,1),B(1,0),0>*<0,1,0>|
|
|
// + Bx*|<-B(1,1),B(1,0),0>*<B(0,0),B(0,1),B(0,2)>| + Bz*|<-B(1,1),B(1,0),0>*<B(2,0),B(2,1),B(2,2)>|
|
|
// = Ax*|-B(1,1)| + Ay*|B(1,0)|
|
|
// + Bx*|<-B(1,1),B(1,0)>*<B(0,0),B(0,1)>| + Bz*|<-B(1,1),B(1,0)>*<B(2,0),B(2,1)>|
|
|
// = Ax*|B(1,1)| + Ay*|B(1,0)|
|
|
// + Bx*|B(1,0)*B(0,1) - B(1,1)*B(0,0)| + Bz*|B(1,0)*B(2,1) - B(1,1)*B(2,0)|
|
|
// = Ax*|B(1,1)| + Ay*|B(1,0)| + Bx*dets(2,2) + Bz*dets(0,2)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
dets[0][2] = Fabs(b(1,0)*b(2,1) - b(2,0)*b(1,1));
|
|
|
|
radius =
|
|
axisExtents.x*absolutes[1][1]
|
|
+ axisExtents.y*absolutes[1][0]
|
|
+ box.axisExtents.x*dets[2][2]
|
|
+ box.axisExtents.z*dets[0][2];
|
|
projection = distance.y*b(1,0) - distance.x*b(1,1);
|
|
if (projection > radius || projection < -radius)
|
|
return A2xB1;
|
|
|
|
//
|
|
//------------------------------------------------------------------------------------------------------------
|
|
// The math for L = A2xB2 or <0,0,1>xB2:
|
|
//
|
|
// dets absolutes
|
|
// *** ***
|
|
// *** ***
|
|
// *** ***
|
|
//
|
|
// projection = (B-A)*(A2xB2) = (B-A)*<-B(2,1),B(2,0),0>
|
|
// radius = Ax*|(A2xB2)*A0| + Ay*|(A2xB2)*A1| + Az*|(A2xB2)*A2|
|
|
// + Bx*|(A2xB2)*B0| + By*|(A2xB2)*B1| + Bz*|(A2xB2)*B2|
|
|
// = Ax*|(A2xB2)*A0| + Ay*|(A2xB2)*A1| + Bx*|(A2xB2)*B0| + By*|(A2xB2)*B1|
|
|
// = Ax*|<-B(2,1),B(2,0),0>*A0| + Ay*|<-B(2,1),B(2,0),0>*A1|
|
|
// + Bx*|<-B(2,1),B(2,0),0>*B0| + By*|<-B(2,1),B(2,0),0>*B1|
|
|
// = Ax*|<-B(2,1),B(2,0),0>*<1,0,0>| + Ay*|<-B(2,1),B(2,0),0>*<0,1,0>|
|
|
// + Bx*|<-B(2,1),B(2,0),0>*<B(0,0),B(0,1),B(0,2)>| + By*|<-B(2,1),B(2,0),0>*<B(1,0),B(1,1),B(1,2)>|
|
|
// = Ax*|-B(2,1)| + Ay*|B(2,0)|
|
|
// + Bx*|<-B(2,1),B(2,0)>*<B(0,0),B(0,1)>| + By*|<-B(2,1),B(2,0)>*<B(1,0),B(1,1)>|
|
|
// = Ax*|B(2,1)| + Ay*|B(2,0)|
|
|
// + Bx*|B(2,0)*B(0,1) - B(2,1)*B(0,0)| + By*|B(2,0)*B(1,1) - B(2,1)*B(1,0)|
|
|
// = Ax*|B(2,1)| + Ay*|B(2,0)| + Bx*dets(1,2) + By*dets(0,2)
|
|
//------------------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
axisExtents.x*absolutes[2][1]
|
|
+ axisExtents.y*absolutes[2][0]
|
|
+ box.axisExtents.x*dets[1][2]
|
|
+ box.axisExtents.y*dets[0][2];
|
|
projection = distance.y*b(2,0) - distance.x*b(2,1);
|
|
if (projection > radius || projection < -radius)
|
|
return A2xB2;
|
|
|
|
return NoSeparation;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool OBB::Contains(const Point3D &point) const
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&point);
|
|
|
|
//
|
|
//-------------------------------------
|
|
// Translate the point into local space
|
|
//-------------------------------------
|
|
//
|
|
Point3D local;
|
|
local.MultiplyByInverse(point, localToParent);
|
|
|
|
//
|
|
//--------------------------
|
|
// Compare it to the extents
|
|
//--------------------------
|
|
//
|
|
return Fabs(local.x)<=axisExtents.x && Fabs(local.y)<=axisExtents.y && Fabs(local.z)<=axisExtents.z;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void OBB::Union(
|
|
const OBB &first,
|
|
const OBB &second
|
|
)
|
|
{
|
|
Check_Pointer(this);
|
|
Check_Object(&first);
|
|
Check_Object(&second);
|
|
|
|
//
|
|
//-------------------------------------------------
|
|
// Learn about the spheres surrounding the two OBBs
|
|
//-------------------------------------------------
|
|
//
|
|
Point3D c1(first.localToParent);
|
|
Point3D c2(second.localToParent);
|
|
Vector3D diff;
|
|
diff.Subtract(c2, c1);
|
|
Scalar len = diff.GetLength();
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// See if the first sphere is contained in the second
|
|
//---------------------------------------------------
|
|
//
|
|
if (len+first.sphereRadius <= second.sphereRadius || !first.sphereRadius)
|
|
{
|
|
if (this != &second)
|
|
*this = second;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//---------------------------------------------------
|
|
// See if the second sphere is contained in the first
|
|
//---------------------------------------------------
|
|
//
|
|
if (len+second.sphereRadius <= first.sphereRadius || !second.sphereRadius)
|
|
{
|
|
if (this != &first)
|
|
*this = first;
|
|
return;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------
|
|
// The new sphere will lie somewhere between the old ones
|
|
//-------------------------------------------------------
|
|
//
|
|
localToParent = LinearMatrix4D::Identity;
|
|
axisExtents = Vector3D::Identity;
|
|
c1.Lerp(c1, c2, (len + second.sphereRadius - first.sphereRadius) / (2.0f*len));
|
|
localToParent.BuildTranslation(c1);
|
|
sphereRadius = 0.5f * (len + first.sphereRadius + second.sphereRadius);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
OBB::SeparatingAxis OBB::CalculateSeparationVector(
|
|
Vector3D *vector,
|
|
const OBB &box
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(vector);
|
|
Check_Object(&box);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// We use the same logic as in detecting separation, but since we know
|
|
// the boxes are already intersecting, we will look to see which axis
|
|
// separates the boxes by the least space, then we will nudge this box by
|
|
// that amount. We will initially only concern ourselves with the axes
|
|
// based on the face normals
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Verify(axisExtents.x >= 0.0f);
|
|
Verify(axisExtents.y >= 0.0f);
|
|
Verify(axisExtents.z >= 0.0f);
|
|
Verify(box.axisExtents.x >= 0.0f);
|
|
Verify(box.axisExtents.y >= 0.0f);
|
|
Verify(box.axisExtents.z >= 0.0f);
|
|
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Get the distance between the centerpoints. Both boxes are assumed to
|
|
// convert their local axes into a common parent space
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check_Object(&localToParent);
|
|
Check_Object(&box.localToParent);
|
|
Point3D
|
|
distance(
|
|
localToParent(3,0) - box.localToParent(3,0),
|
|
localToParent(3,1) - box.localToParent(3,1),
|
|
localToParent(3,2) - box.localToParent(3,2)
|
|
);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// The rows of the matrix encode the local axes in world space. The first
|
|
// separation axis we will be testing our x axis in world space, so
|
|
// project the other box's primary axes onto it, and store the results
|
|
// away for future reference
|
|
//
|
|
// The math for L = A0: (A0 is the X axis row of our matrix)
|
|
// Given: A0,A1, and B2 are orthogonal
|
|
// B0,B1, and B2 are orthogonal
|
|
// Ax, Ay, and Az >= 0
|
|
// Bx, By, and Bz >= 0
|
|
//
|
|
// projection = (B-A)*A0
|
|
// radius = |Ax*(A0*A0)| + |Ay*(A0*A1)| + |Az*(A0*A2)| + |Bx*(A0*B0)| + |By*(A0*B1)| + |Bz*(A0*B2)|
|
|
// = Ax + Bx*|A0*B0| + By*|A0*B1| + Bz*|A0*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
Scalar axis_projections[3][3];
|
|
axis_projections[X_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// The maximum distance the centerpoints can be away and still touch is
|
|
// equal to the sum of our x extent plus the other's extents, as modified
|
|
// by the projection values. If the boxes can't touch, return A0 as the
|
|
// separating plane
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Scalar radius =
|
|
axisExtents.x
|
|
+ box.axisExtents.x * axis_projections[X_Axis][0]
|
|
+ box.axisExtents.y * axis_projections[X_Axis][1]
|
|
+ box.axisExtents.z * axis_projections[X_Axis][2];
|
|
Scalar projection =
|
|
localToParent(X_Axis,0) * distance.x
|
|
+ localToParent(X_Axis,1) * distance.y
|
|
+ localToParent(X_Axis,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
Scalar best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(0,0) * radius;
|
|
vector->y = localToParent(0,1) * radius;
|
|
vector->z = localToParent(0,2) * radius;
|
|
SeparatingAxis axis = A0;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Do the same check against our Y axis
|
|
//
|
|
// The math for L = A1:
|
|
//
|
|
// projection = (B-A)*A1
|
|
// radius = |Ax*(A1*A0)| + |Ay*(A1*A1)| + |Az*(A1*A2)| + |Bx*(A1*B0)| + |By*(A1*B1)| + |Bz*(A1*B2)|
|
|
// = Ay + Bx*|A1*B0| + By*|A1*B1| + Bz*|A1*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Y_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.y
|
|
+ box.axisExtents.x * axis_projections[1][0]
|
|
+ box.axisExtents.y * axis_projections[1][1]
|
|
+ box.axisExtents.z * axis_projections[1][2];
|
|
projection =
|
|
localToParent(1,0) * distance.x
|
|
+ localToParent(1,1) * distance.y
|
|
+ localToParent(1,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
if (radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(1,0) * radius;
|
|
vector->y = localToParent(1,1) * radius;
|
|
vector->z = localToParent(1,2) * radius;
|
|
axis = A1;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check our z axis
|
|
//
|
|
// The math for L = A2:
|
|
//
|
|
// projection = (B-A)*A2
|
|
// radius = |Ax*(A2*A0)| + |Ay*(A2*A1)| + |Az*(A2*A2)| + |Bx*(A2*B0)| + |By*(A2*B1)| + |Bz*(A2*B2)|
|
|
// = Az + Bx*|A2*B0| + By*|A2*B1| + Bz*|A2*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Z_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.z
|
|
+ box.axisExtents.x * axis_projections[2][0]
|
|
+ box.axisExtents.y * axis_projections[2][1]
|
|
+ box.axisExtents.z * axis_projections[2][2];
|
|
projection =
|
|
localToParent(2,0) * distance.x
|
|
+ localToParent(2,1) * distance.y
|
|
+ localToParent(2,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
if (radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(2,0) * radius;
|
|
vector->y = localToParent(2,1) * radius;
|
|
vector->z = localToParent(2,2) * radius;
|
|
axis = A2;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// See if the other box's X axis is a separator
|
|
//
|
|
// The math for L = B0:
|
|
//
|
|
// projection = (B-A)*B0
|
|
// radius = |Ax*(B0*A0)| + |Ay*(B0*A1)| + |Az*(B0*A2)| + |Bx*(B0*B0)| + |By*(B0*B1)| + |Bz*(B0*B2)|
|
|
// = Bx + Ax*|B0*A0| + Ay*|B0*A1| + Az*|B0*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.x
|
|
+ axisExtents.x * axis_projections[0][X_Axis]
|
|
+ axisExtents.y * axis_projections[1][X_Axis]
|
|
+ axisExtents.z * axis_projections[2][X_Axis];
|
|
projection =
|
|
box.localToParent(X_Axis,0) * distance.x
|
|
+ box.localToParent(X_Axis,1) * distance.y
|
|
+ box.localToParent(X_Axis,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
if (radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(0,0) * radius;
|
|
vector->y = box.localToParent(0,1) * radius;
|
|
vector->z = box.localToParent(0,2) * radius;
|
|
axis = B0;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Y axis
|
|
//
|
|
// The math for L = B1:
|
|
//
|
|
// projection = (B-A)*B1
|
|
// radius = |Ax*(B1*A0)| + |Ay*(B1*A1)| + |Az*(B1*A2)| + |Bx*(B1*B0)| + |By*(B1*B1)| + |Bz*(B1*B2)|
|
|
// = By + Ax*|B1*A0| + Ay*|B1*A1| + Az*|B1*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.y
|
|
+ axisExtents.x * axis_projections[0][Y_Axis]
|
|
+ axisExtents.y * axis_projections[1][Y_Axis]
|
|
+ axisExtents.z * axis_projections[2][Y_Axis];
|
|
projection =
|
|
box.localToParent(Y_Axis,0) * distance.x
|
|
+ box.localToParent(Y_Axis,1) * distance.y
|
|
+ box.localToParent(Y_Axis,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
if (radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(1,0) * radius;
|
|
vector->y = box.localToParent(1,1) * radius;
|
|
vector->z = box.localToParent(1,2) * radius;
|
|
axis = B1;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Z axis
|
|
//
|
|
// The math for L = B2:
|
|
//
|
|
// projection = (B-A)*B2
|
|
// radius = |Ax*(B2*A0)| + |Ay*(B2*A1)| + |Az*(B2*A2)| + |Bx*(B2*B0)| + |By*(B2*B1)| + |Bz*(B2*B2)|
|
|
// = Bz + Ax*|B2*A0| + Ay*|B2*A1| + Az*|B2*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.z
|
|
+ axisExtents.x * axis_projections[0][Z_Axis]
|
|
+ axisExtents.y * axis_projections[1][Z_Axis]
|
|
+ axisExtents.z * axis_projections[2][Z_Axis];
|
|
projection =
|
|
box.localToParent(Z_Axis,0) * distance.x
|
|
+ box.localToParent(Z_Axis,1) * distance.y
|
|
+ box.localToParent(Z_Axis,2) * distance.z;
|
|
|
|
radius -= Fabs(projection);
|
|
if (radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
Verify(radius > 0.0f);
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(2,0) * radius;
|
|
vector->y = box.localToParent(2,1) * radius;
|
|
vector->z = box.localToParent(2,2) * radius;
|
|
axis = B2;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void OBB::CalculateSecondarySeparationVector(
|
|
Vector3D *vector,
|
|
const OBB &box,
|
|
const UnitVector3D &primary
|
|
)
|
|
{
|
|
Check_Object(this);
|
|
Check_Pointer(vector);
|
|
Check_Object(&box);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// We use the same logic as in detecting separation, but since we know
|
|
// the boxes are already intersecting, we will look to see which axis
|
|
// separates the boxes by the least space, then we will nudge this box by
|
|
// that amount. We will initially only concern ourselves with the axes
|
|
// based on the face normals
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Verify(axisExtents.x >= 0.0f);
|
|
Verify(axisExtents.y >= 0.0f);
|
|
Verify(axisExtents.z >= 0.0f);
|
|
Verify(box.axisExtents.x >= 0.0f);
|
|
Verify(box.axisExtents.y >= 0.0f);
|
|
Verify(box.axisExtents.z >= 0.0f);
|
|
|
|
|
|
//
|
|
//----------------------------------------------------------------------
|
|
// Get the distance between the centerpoints. Both boxes are assumed to
|
|
// convert their local axes into a common parent space
|
|
//----------------------------------------------------------------------
|
|
//
|
|
Check_Object(&localToParent);
|
|
Check_Object(&box.localToParent);
|
|
Point3D
|
|
distance(
|
|
localToParent(3,0) - box.localToParent(3,0),
|
|
localToParent(3,1) - box.localToParent(3,1),
|
|
localToParent(3,2) - box.localToParent(3,2)
|
|
);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// The rows of the matrix encode the local axes in world space. The first
|
|
// separation axis we will be testing our x axis in world space, so
|
|
// project the other box's primary axes onto it, and store the results
|
|
// away for future reference
|
|
//
|
|
// The math for L = A0: (A0 is the X axis row of our matrix)
|
|
// Given: A0,A1, and B2 are orthogonal
|
|
// B0,B1, and B2 are orthogonal
|
|
// Ax, Ay, and Az >= 0
|
|
// Bx, By, and Bz >= 0
|
|
//
|
|
// projection = (B-A)*A0
|
|
// radius = |Ax*(A0*A0)| + |Ay*(A0*A1)| + |Az*(A0*A2)| + |Bx*(A0*B0)| + |By*(A0*B1)| + |Bz*(A0*B2)|
|
|
// = Ax + Bx*|A0*B0| + By*|A0*B1| + Bz*|A0*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
Scalar axis_projections[3][3];
|
|
axis_projections[X_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[X_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(X_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(X_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(X_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
|
|
//
|
|
//-----------------------------------------------------------------------
|
|
// The maximum distance the centerpoints can be away and still touch is
|
|
// equal to the sum of our x extent plus the other's extents, as modified
|
|
// by the projection values. If the boxes can't touch, return A0 as the
|
|
// separating plane
|
|
//-----------------------------------------------------------------------
|
|
//
|
|
Scalar radius =
|
|
axisExtents.x
|
|
+ box.axisExtents.x * axis_projections[X_Axis][0]
|
|
+ box.axisExtents.y * axis_projections[X_Axis][1]
|
|
+ box.axisExtents.z * axis_projections[X_Axis][2];
|
|
Scalar projection =
|
|
localToParent(X_Axis,0) * distance.x
|
|
+ localToParent(X_Axis,1) * distance.y
|
|
+ localToParent(X_Axis,2) * distance.z;
|
|
Scalar primary_dot =
|
|
Fabs(localToParent(X_Axis,0) * primary.x
|
|
+ localToParent(X_Axis,1) * primary.y
|
|
+ localToParent(X_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
Scalar best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(0,0) * radius;
|
|
vector->y = localToParent(0,1) * radius;
|
|
vector->z = localToParent(0,2) * radius;
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Do the same check against our Y axis
|
|
//
|
|
// The math for L = A1:
|
|
//
|
|
// projection = (B-A)*A1
|
|
// radius = |Ax*(A1*A0)| + |Ay*(A1*A1)| + |Az*(A1*A2)| + |Bx*(A1*B0)| + |By*(A1*B1)| + |Bz*(A1*B2)|
|
|
// = Ay + Bx*|A1*B0| + By*|A1*B1| + Bz*|A1*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Y_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Y_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Y_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Y_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Y_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.y
|
|
+ box.axisExtents.x * axis_projections[1][0]
|
|
+ box.axisExtents.y * axis_projections[1][1]
|
|
+ box.axisExtents.z * axis_projections[1][2];
|
|
projection =
|
|
localToParent(Y_Axis,0) * distance.x
|
|
+ localToParent(Y_Axis,1) * distance.y
|
|
+ localToParent(Y_Axis,2) * distance.z;
|
|
Scalar dot =
|
|
Fabs(localToParent(Y_Axis,0) * primary.x
|
|
+ localToParent(Y_Axis,1) * primary.y
|
|
+ localToParent(Y_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
if (dot<0.85f && (radius < best_radius || primary_dot<0.85f))
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(1,0) * radius;
|
|
vector->y = localToParent(1,1) * radius;
|
|
vector->z = localToParent(1,2) * radius;
|
|
}
|
|
else
|
|
Verify(primary_dot < 0.85f);
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check our z axis
|
|
//
|
|
// The math for L = A2:
|
|
//
|
|
// projection = (B-A)*A2
|
|
// radius = |Ax*(A2*A0)| + |Ay*(A2*A1)| + |Az*(A2*A2)| + |Bx*(A2*B0)| + |By*(A2*B1)| + |Bz*(A2*B2)|
|
|
// = Az + Bx*|A2*B0| + By*|A2*B1| + Bz*|A2*B2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
axis_projections[Z_Axis][X_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(X_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(X_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(X_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Y_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Y_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Y_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Y_Axis,2)
|
|
);
|
|
axis_projections[Z_Axis][Z_Axis] =
|
|
Fabs(
|
|
localToParent(Z_Axis,0) * box.localToParent(Z_Axis,0)
|
|
+ localToParent(Z_Axis,1) * box.localToParent(Z_Axis,1)
|
|
+ localToParent(Z_Axis,2) * box.localToParent(Z_Axis,2)
|
|
);
|
|
radius =
|
|
axisExtents.z
|
|
+ box.axisExtents.x * axis_projections[2][0]
|
|
+ box.axisExtents.y * axis_projections[2][1]
|
|
+ box.axisExtents.z * axis_projections[2][2];
|
|
projection =
|
|
localToParent(2,0) * distance.x
|
|
+ localToParent(2,1) * distance.y
|
|
+ localToParent(2,2) * distance.z;
|
|
dot =
|
|
Fabs(localToParent(Z_Axis,0) * primary.x
|
|
+ localToParent(Z_Axis,1) * primary.y
|
|
+ localToParent(Z_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
if (dot<0.85f && radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = localToParent(2,0) * radius;
|
|
vector->y = localToParent(2,1) * radius;
|
|
vector->z = localToParent(2,2) * radius;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// See if the other box's X axis is a separator
|
|
//
|
|
// The math for L = B0:
|
|
//
|
|
// projection = (B-A)*B0
|
|
// radius = |Ax*(B0*A0)| + |Ay*(B0*A1)| + |Az*(B0*A2)| + |Bx*(B0*B0)| + |By*(B0*B1)| + |Bz*(B0*B2)|
|
|
// = Bx + Ax*|B0*A0| + Ay*|B0*A1| + Az*|B0*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.x
|
|
+ axisExtents.x * axis_projections[0][X_Axis]
|
|
+ axisExtents.y * axis_projections[1][X_Axis]
|
|
+ axisExtents.z * axis_projections[2][X_Axis];
|
|
projection =
|
|
box.localToParent(X_Axis,0) * distance.x
|
|
+ box.localToParent(X_Axis,1) * distance.y
|
|
+ box.localToParent(X_Axis,2) * distance.z;
|
|
dot =
|
|
Fabs(box.localToParent(X_Axis,0) * primary.x
|
|
+ box.localToParent(X_Axis,1) * primary.y
|
|
+ box.localToParent(X_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
if (dot<0.85f && radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(0,0) * radius;
|
|
vector->y = box.localToParent(0,1) * radius;
|
|
vector->z = box.localToParent(0,2) * radius;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Y axis
|
|
//
|
|
// The math for L = B1:
|
|
//
|
|
// projection = (B-A)*B1
|
|
// radius = |Ax*(B1*A0)| + |Ay*(B1*A1)| + |Az*(B1*A2)| + |Bx*(B1*B0)| + |By*(B1*B1)| + |Bz*(B1*B2)|
|
|
// = By + Ax*|B1*A0| + Ay*|B1*A1| + Az*|B1*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.y
|
|
+ axisExtents.x * axis_projections[0][Y_Axis]
|
|
+ axisExtents.y * axis_projections[1][Y_Axis]
|
|
+ axisExtents.z * axis_projections[2][Y_Axis];
|
|
projection =
|
|
box.localToParent(Y_Axis,0) * distance.x
|
|
+ box.localToParent(Y_Axis,1) * distance.y
|
|
+ box.localToParent(Y_Axis,2) * distance.z;
|
|
dot =
|
|
Fabs(box.localToParent(Y_Axis,0) * primary.x
|
|
+ box.localToParent(Y_Axis,1) * primary.y
|
|
+ box.localToParent(Y_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
if (dot<0.85f && radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(1,0) * radius;
|
|
vector->y = box.localToParent(1,1) * radius;
|
|
vector->z = box.localToParent(1,2) * radius;
|
|
}
|
|
|
|
//
|
|
//--------------------------------------------------------------------------------------------------
|
|
// Check its Z axis
|
|
//
|
|
// The math for L = B2:
|
|
//
|
|
// projection = (B-A)*B2
|
|
// radius = |Ax*(B2*A0)| + |Ay*(B2*A1)| + |Az*(B2*A2)| + |Bx*(B2*B0)| + |By*(B2*B1)| + |Bz*(B2*B2)|
|
|
// = Bz + Ax*|B2*A0| + Ay*|B2*A1| + Az*|B2*A2|
|
|
//--------------------------------------------------------------------------------------------------
|
|
//
|
|
radius =
|
|
box.axisExtents.z
|
|
+ axisExtents.x * axis_projections[0][Z_Axis]
|
|
+ axisExtents.y * axis_projections[1][Z_Axis]
|
|
+ axisExtents.z * axis_projections[2][Z_Axis];
|
|
projection =
|
|
box.localToParent(Z_Axis,0) * distance.x
|
|
+ box.localToParent(Z_Axis,1) * distance.y
|
|
+ box.localToParent(Z_Axis,2) * distance.z;
|
|
dot =
|
|
Fabs(box.localToParent(Z_Axis,0) * primary.x
|
|
+ box.localToParent(Z_Axis,1) * primary.y
|
|
+ box.localToParent(Z_Axis,2) * primary.z);
|
|
|
|
radius -= Fabs(projection);
|
|
Verify(radius > 0.0f);
|
|
if (dot<0.85f && radius < best_radius)
|
|
{
|
|
best_radius = radius;
|
|
radius += SMALL;
|
|
if (projection<0.0f)
|
|
radius = -radius;
|
|
vector->x = box.localToParent(2,0) * radius;
|
|
vector->y = box.localToParent(2,1) * radius;
|
|
vector->z = box.localToParent(2,2) * radius;
|
|
}
|
|
}
|