Path: blob/master/thirdparty/jolt_physics/Jolt/Geometry/OrientedBox.cpp
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#include <Jolt/Jolt.h>56#include <Jolt/Geometry/OrientedBox.h>7#include <Jolt/Geometry/AABox.h>89JPH_NAMESPACE_BEGIN1011bool OrientedBox::Overlaps(const AABox &inBox, float inEpsilon) const12{13// Taken from: Real Time Collision Detection - Christer Ericson14// Chapter 4.4.1, page 103-105.15// Note that the code is swapped around: A is the aabox and B is the oriented box (this saves us from having to invert the orientation of the oriented box)1617// Convert AABox to center / extent representation18Vec3 a_center = inBox.GetCenter();19Vec3 a_half_extents = inBox.GetExtent();2021// Compute rotation matrix expressing b in a's coordinate frame22Mat44 rot(mOrientation.GetColumn4(0), mOrientation.GetColumn4(1), mOrientation.GetColumn4(2), mOrientation.GetColumn4(3) - Vec4(a_center, 0));2324// Compute common subexpressions. Add in an epsilon term to25// counteract arithmetic errors when two edges are parallel and26// their cross product is (near) null (see text for details)27Vec3 epsilon = Vec3::sReplicate(inEpsilon);28Vec3 abs_r[3] { rot.GetAxisX().Abs() + epsilon, rot.GetAxisY().Abs() + epsilon, rot.GetAxisZ().Abs() + epsilon };2930// Test axes L = A0, L = A1, L = A231float ra, rb;32for (int i = 0; i < 3; i++)33{34ra = a_half_extents[i];35rb = mHalfExtents[0] * abs_r[0][i] + mHalfExtents[1] * abs_r[1][i] + mHalfExtents[2] * abs_r[2][i];36if (abs(rot(i, 3)) > ra + rb) return false;37}3839// Test axes L = B0, L = B1, L = B240for (int i = 0; i < 3; i++)41{42ra = a_half_extents.Dot(abs_r[i]);43rb = mHalfExtents[i];44if (abs(rot.GetTranslation().Dot(rot.GetColumn3(i))) > ra + rb) return false;45}4647// Test axis L = A0 x B048ra = a_half_extents[1] * abs_r[0][2] + a_half_extents[2] * abs_r[0][1];49rb = mHalfExtents[1] * abs_r[2][0] + mHalfExtents[2] * abs_r[1][0];50if (abs(rot(2, 3) * rot(1, 0) - rot(1, 3) * rot(2, 0)) > ra + rb) return false;5152// Test axis L = A0 x B153ra = a_half_extents[1] * abs_r[1][2] + a_half_extents[2] * abs_r[1][1];54rb = mHalfExtents[0] * abs_r[2][0] + mHalfExtents[2] * abs_r[0][0];55if (abs(rot(2, 3) * rot(1, 1) - rot(1, 3) * rot(2, 1)) > ra + rb) return false;5657// Test axis L = A0 x B258ra = a_half_extents[1] * abs_r[2][2] + a_half_extents[2] * abs_r[2][1];59rb = mHalfExtents[0] * abs_r[1][0] + mHalfExtents[1] * abs_r[0][0];60if (abs(rot(2, 3) * rot(1, 2) - rot(1, 3) * rot(2, 2)) > ra + rb) return false;6162// Test axis L = A1 x B063ra = a_half_extents[0] * abs_r[0][2] + a_half_extents[2] * abs_r[0][0];64rb = mHalfExtents[1] * abs_r[2][1] + mHalfExtents[2] * abs_r[1][1];65if (abs(rot(0, 3) * rot(2, 0) - rot(2, 3) * rot(0, 0)) > ra + rb) return false;6667// Test axis L = A1 x B168ra = a_half_extents[0] * abs_r[1][2] + a_half_extents[2] * abs_r[1][0];69rb = mHalfExtents[0] * abs_r[2][1] + mHalfExtents[2] * abs_r[0][1];70if (abs(rot(0, 3) * rot(2, 1) - rot(2, 3) * rot(0, 1)) > ra + rb) return false;7172// Test axis L = A1 x B273ra = a_half_extents[0] * abs_r[2][2] + a_half_extents[2] * abs_r[2][0];74rb = mHalfExtents[0] * abs_r[1][1] + mHalfExtents[1] * abs_r[0][1];75if (abs(rot(0, 3) * rot(2, 2) - rot(2, 3) * rot(0, 2)) > ra + rb) return false;7677// Test axis L = A2 x B078ra = a_half_extents[0] * abs_r[0][1] + a_half_extents[1] * abs_r[0][0];79rb = mHalfExtents[1] * abs_r[2][2] + mHalfExtents[2] * abs_r[1][2];80if (abs(rot(1, 3) * rot(0, 0) - rot(0, 3) * rot(1, 0)) > ra + rb) return false;8182// Test axis L = A2 x B183ra = a_half_extents[0] * abs_r[1][1] + a_half_extents[1] * abs_r[1][0];84rb = mHalfExtents[0] * abs_r[2][2] + mHalfExtents[2] * abs_r[0][2];85if (abs(rot(1, 3) * rot(0, 1) - rot(0, 3) * rot(1, 1)) > ra + rb) return false;8687// Test axis L = A2 x B288ra = a_half_extents[0] * abs_r[2][1] + a_half_extents[1] * abs_r[2][0];89rb = mHalfExtents[0] * abs_r[1][2] + mHalfExtents[1] * abs_r[0][2];90if (abs(rot(1, 3) * rot(0, 2) - rot(0, 3) * rot(1, 2)) > ra + rb) return false;9192// Since no separating axis is found, the OBB and AAB must be intersecting93return true;94}9596bool OrientedBox::Overlaps(const OrientedBox &inBox, float inEpsilon) const97{98// Taken from: Real Time Collision Detection - Christer Ericson99// Chapter 4.4.1, page 103-105.100// Note that A is this, B is inBox101102// Compute rotation matrix expressing b in a's coordinate frame103Mat44 rot = mOrientation.InversedRotationTranslation() * inBox.mOrientation;104105// Compute common subexpressions. Add in an epsilon term to106// counteract arithmetic errors when two edges are parallel and107// their cross product is (near) null (see text for details)108Vec3 epsilon = Vec3::sReplicate(inEpsilon);109Vec3 abs_r[3] { rot.GetAxisX().Abs() + epsilon, rot.GetAxisY().Abs() + epsilon, rot.GetAxisZ().Abs() + epsilon };110111// Test axes L = A0, L = A1, L = A2112float ra, rb;113for (int i = 0; i < 3; i++)114{115ra = mHalfExtents[i];116rb = inBox.mHalfExtents[0] * abs_r[0][i] + inBox.mHalfExtents[1] * abs_r[1][i] + inBox.mHalfExtents[2] * abs_r[2][i];117if (abs(rot(i, 3)) > ra + rb) return false;118}119120// Test axes L = B0, L = B1, L = B2121for (int i = 0; i < 3; i++)122{123ra = mHalfExtents.Dot(abs_r[i]);124rb = inBox.mHalfExtents[i];125if (abs(rot.GetTranslation().Dot(rot.GetColumn3(i))) > ra + rb) return false;126}127128// Test axis L = A0 x B0129ra = mHalfExtents[1] * abs_r[0][2] + mHalfExtents[2] * abs_r[0][1];130rb = inBox.mHalfExtents[1] * abs_r[2][0] + inBox.mHalfExtents[2] * abs_r[1][0];131if (abs(rot(2, 3) * rot(1, 0) - rot(1, 3) * rot(2, 0)) > ra + rb) return false;132133// Test axis L = A0 x B1134ra = mHalfExtents[1] * abs_r[1][2] + mHalfExtents[2] * abs_r[1][1];135rb = inBox.mHalfExtents[0] * abs_r[2][0] + inBox.mHalfExtents[2] * abs_r[0][0];136if (abs(rot(2, 3) * rot(1, 1) - rot(1, 3) * rot(2, 1)) > ra + rb) return false;137138// Test axis L = A0 x B2139ra = mHalfExtents[1] * abs_r[2][2] + mHalfExtents[2] * abs_r[2][1];140rb = inBox.mHalfExtents[0] * abs_r[1][0] + inBox.mHalfExtents[1] * abs_r[0][0];141if (abs(rot(2, 3) * rot(1, 2) - rot(1, 3) * rot(2, 2)) > ra + rb) return false;142143// Test axis L = A1 x B0144ra = mHalfExtents[0] * abs_r[0][2] + mHalfExtents[2] * abs_r[0][0];145rb = inBox.mHalfExtents[1] * abs_r[2][1] + inBox.mHalfExtents[2] * abs_r[1][1];146if (abs(rot(0, 3) * rot(2, 0) - rot(2, 3) * rot(0, 0)) > ra + rb) return false;147148// Test axis L = A1 x B1149ra = mHalfExtents[0] * abs_r[1][2] + mHalfExtents[2] * abs_r[1][0];150rb = inBox.mHalfExtents[0] * abs_r[2][1] + inBox.mHalfExtents[2] * abs_r[0][1];151if (abs(rot(0, 3) * rot(2, 1) - rot(2, 3) * rot(0, 1)) > ra + rb) return false;152153// Test axis L = A1 x B2154ra = mHalfExtents[0] * abs_r[2][2] + mHalfExtents[2] * abs_r[2][0];155rb = inBox.mHalfExtents[0] * abs_r[1][1] + inBox.mHalfExtents[1] * abs_r[0][1];156if (abs(rot(0, 3) * rot(2, 2) - rot(2, 3) * rot(0, 2)) > ra + rb) return false;157158// Test axis L = A2 x B0159ra = mHalfExtents[0] * abs_r[0][1] + mHalfExtents[1] * abs_r[0][0];160rb = inBox.mHalfExtents[1] * abs_r[2][2] + inBox.mHalfExtents[2] * abs_r[1][2];161if (abs(rot(1, 3) * rot(0, 0) - rot(0, 3) * rot(1, 0)) > ra + rb) return false;162163// Test axis L = A2 x B1164ra = mHalfExtents[0] * abs_r[1][1] + mHalfExtents[1] * abs_r[1][0];165rb = inBox.mHalfExtents[0] * abs_r[2][2] + inBox.mHalfExtents[2] * abs_r[0][2];166if (abs(rot(1, 3) * rot(0, 1) - rot(0, 3) * rot(1, 1)) > ra + rb) return false;167168// Test axis L = A2 x B2169ra = mHalfExtents[0] * abs_r[2][1] + mHalfExtents[1] * abs_r[2][0];170rb = inBox.mHalfExtents[0] * abs_r[1][2] + inBox.mHalfExtents[1] * abs_r[0][2];171if (abs(rot(1, 3) * rot(0, 2) - rot(0, 3) * rot(1, 2)) > ra + rb) return false;172173// Since no separating axis is found, the OBBs must be intersecting174return true;175}176177JPH_NAMESPACE_END178179180