#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 &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 local_points(points.GetLength()); for (int i=0; i, 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)>*| + Bz*|<0,-B(0,2),B(0,1)>*| // = Ay*|B(0,2)| + Az*|B(0,1)| // + By*|<-B(0,2),B(0,1)>*| + Bz*|<-B(0,2),B(0,1)>*| // = Ay*|B(0,2)| + Az*|B(0,1)| // + By*|B(0,1)*B(1,2) - B(0,2)* 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)>*| + Bz*|<0,-B(1,2),B(1,1)>*| // = Ay*|B(1,2)| + Az*|B(1,1)| // + Bx*|<-B(1,2),B(1,1)>*| + Bz*|<-B(1,2),B(1,1)>*| // = 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)>*| + By*|<0,-B(2,2),B(2,1)>*| // = Ay*|-B(2,2)| + Az*|B(2,1)| // + Bx*|<-B(2,2),B(2,1)>*| + By*|<-B(2,2),B(2,1)>*| // = 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)* // 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*|*A0| + Az*|*A2| // + By*|*B1| + Bz*|*B2| // = Ax*|*<1,0,0>| + Az*|*<0,0,1>| // + By*|*| + Bz*|*| // = Ax*|B(0,2)| + Az*|-B(0,0)| // + By*|*| + Bz*|*| // = 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)* // 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*|*A0| + Az*|*A2| // + Bx*|*B0| + Bz*|*B2| // = Ax*|*<1,0,0>| + Az*|*<0,0,1>| // + Bx*|*| + Bz*|*B(2,0),B(2,1),B(2,2)| // = Ax*|B(1,2)| + Az*|-B(1,0)| // + Bx*|*| + Bz*|*B(2,0),B(2,2)>| // = Ax*|B(1,2)| + Az*|B(1,0)| // + Bx*|B(1,2)* radius || projection < -radius) return A1xB1; // //------------------------------------------------------------------------------------------------------------ // The math for L = A1xB2 or <0,1,0>xB2: // // dets absolutes // **. *** // **. *** // **. .** // // projection = (B-A)*(A1xB2) = (B-A)* // 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*|*A0| + Az*|*A2| // + Bx*|*B0| + By*|*B1| // = Ax*|*<1,0,0>| + Az*|*<0,0,1>| // + Bx*|*| + By*|*| // = Ax*|B(2,2)| + Az*|-B(2,0)| // + Bx*|*| + By*|*| // = 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>*| + Bz*|<-B(0,1),B(0,0),0>*| // = Ax*|-B(0,1)| + Ay*|B(0,0)| // + By*|<-B(0,1),B(0,0)>*| + Bz*|<-B(0,1),B(0,0)>*| // = 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>*| + Bz*|<-B(1,1),B(1,0),0>*| // = Ax*|-B(1,1)| + Ay*|B(1,0)| // + Bx*|<-B(1,1),B(1,0)>*| + Bz*|<-B(1,1),B(1,0)>*| // = 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>*| + By*|<-B(2,1),B(2,0),0>*| // = Ax*|-B(2,1)| + Ay*|B(2,0)| // + Bx*|<-B(2,1),B(2,0)>*| + By*|<-B(2,1),B(2,0)>*| // = 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; } }