Implement builtin collider tests

This commit is contained in:
Jack Andersen 2017-06-30 17:23:49 -10:00
parent ff15bfbec3
commit 7063f2412d
6 changed files with 680 additions and 26 deletions

View File

@ -1,5 +1,7 @@
#include "CCollidableAABox.hpp"
#include "CollisionUtil.hpp"
#include "CCollidableSphere.hpp"
#include "CCollisionInfo.hpp"
namespace urde
{
@ -56,13 +58,46 @@ void CCollidableAABox::SetStaticTableIndex(u32 index)
sTableIndex = index;
}
bool CCollidableAABox::CollideMovingAABox(const CInternalCollisionStructure &, const zeus::CVector3f &, double &, CCollisionInfo &)
bool CCollidableAABox::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut)
{
const CCollidableAABox& p0 = static_cast<const CCollidableAABox&>(collision.GetLeft().GetPrim());
const CCollidableAABox& p1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
zeus::CAABox b0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform());
double d;
zeus::CVector3f point, normal;
if (CollisionUtil::AABox_AABox_Moving(b0, b1, dir, d, point, normal) && d > 0.0 && d < dOut)
{
dOut = d;
infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal, -normal);
return true;
}
return false;
}
bool CCollidableAABox::CollideMovingSphere(const CInternalCollisionStructure &, const zeus::CVector3f &, double &, CCollisionInfo &)
bool CCollidableAABox::CollideMovingSphere(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut)
{
const CCollidableAABox& p0 = static_cast<const CCollidableAABox&>(collision.GetLeft().GetPrim());
const CCollidableSphere& p1 = static_cast<const CCollidableSphere&>(collision.GetRight().GetPrim());
zeus::CAABox b0 = p0.CalculateAABox(collision.GetLeft().GetTransform());
zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform());
double d = dOut;
zeus::CVector3f point, normal;
if (CollisionUtil::MovingSphereAABox(s1, b0, -dir, d, point, normal) && d < dOut)
{
point = s1.position - s1.radius * normal;
dOut = d;
infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), -normal);
return true;
}
return false;
}

View File

@ -1,4 +1,7 @@
#include "CCollidableSphere.hpp"
#include "CCollisionInfoList.hpp"
#include "CCollidableAABox.hpp"
#include "CollisionUtil.hpp"
namespace urde
{
@ -8,16 +11,195 @@ u32 CCollidableSphere::sTableIndex = -1;
namespace Collide
{
bool Sphere_AABox(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; }
bool Sphere_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableAABox& p1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
bool Sphere_AABox_Bool(const CInternalCollisionStructure&)
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform());
float distSq = 0.f;
int flags = 0;
for (int i=0 ; i<3 ; ++i)
{
if (s0.position[i] < b1.min[i])
{
if (s0.position[i] + s0.radius >= b1.min[i])
{
float dist = s0.position[i] - b1.min[i];
distSq += dist * dist;
flags |= 1 << (2 * i);
}
else
{
return false;
}
}
else if (s0.position[i] > b1.max[i])
{
if (s0.position[i] - s0.radius <= b1.max[i])
{
float dist = s0.position[i] - b1.max[i];
distSq += dist * dist;
flags |= 1 << (2 * i + 1);
}
else
{
return false;
}
}
}
bool Sphere_Sphere(const CInternalCollisionStructure&, CCollisionInfoList&) { return false; }
if (!flags)
{
zeus::CVector3f normal = (s0.position - b1.center()).normalized();
zeus::CVector3f point = s0.position + normal * s0.radius;
CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), normal);
list.Add(info, false);
return true;
}
if (distSq > s0.radius * s0.radius)
return false;
zeus::CVector3f point;
switch (flags)
{
case 0x1a:
point = zeus::CVector3f(b1.max.x, b1.max.y, b1.min.z);
break;
case 0x19:
point = zeus::CVector3f(b1.min.x, b1.max.y, b1.min.z);
break;
case 0x16:
point = zeus::CVector3f(b1.max.x, b1.min.y, b1.min.z);
break;
case 0x15:
point = zeus::CVector3f(b1.min.x, b1.min.y, b1.min.z);
break;
case 0x2a:
point = zeus::CVector3f(b1.max.x, b1.max.y, b1.max.z);
break;
case 0x29:
point = zeus::CVector3f(b1.min.x, b1.max.y, b1.max.z);
break;
case 0x26:
point = zeus::CVector3f(b1.max.x, b1.min.y, b1.max.z);
break;
case 0x25:
point = zeus::CVector3f(b1.min.x, b1.min.y, b1.max.z);
break;
case 0x11:
point = zeus::CVector3f(b1.min.x, s0.position.y, b1.min.z);
break;
case 0x12:
point = zeus::CVector3f(b1.max.x, s0.position.y, b1.min.z);
break;
case 0x14:
point = zeus::CVector3f(s0.position.x, b1.min.y, b1.min.z);
break;
case 0x18:
point = zeus::CVector3f(s0.position.x, b1.max.y, b1.min.z);
break;
case 0x5:
point = zeus::CVector3f(b1.min.x, b1.min.y, s0.position.z);
break;
case 0x6:
point = zeus::CVector3f(b1.max.x, b1.min.y, s0.position.z);
break;
case 0x9:
point = zeus::CVector3f(b1.min.x, b1.max.y, s0.position.z);
break;
case 0xa:
point = zeus::CVector3f(b1.max.x, b1.max.y, s0.position.z);
break;
case 0x21:
point = zeus::CVector3f(b1.min.x, s0.position.y, b1.max.z);
break;
case 0x22:
point = zeus::CVector3f(b1.max.x, s0.position.y, b1.max.z);
break;
case 0x24:
point = zeus::CVector3f(s0.position.x, b1.min.y, b1.max.z);
break;
case 0x28:
point = zeus::CVector3f(s0.position.x, b1.max.y, b1.max.z);
break;
case 0x1:
point = zeus::CVector3f(b1.min.x, s0.position.y, s0.position.z);
break;
case 0x2:
point = zeus::CVector3f(b1.max.x, s0.position.y, s0.position.z);
break;
case 0x4:
point = zeus::CVector3f(s0.position.x, b1.min.y, s0.position.z);
break;
case 0x8:
point = zeus::CVector3f(s0.position.x, b1.max.y, s0.position.z);
break;
case 0x10:
point = zeus::CVector3f(s0.position.x, s0.position.y, b1.min.z);
break;
case 0x20:
point = zeus::CVector3f(s0.position.x, s0.position.y, b1.max.z);
break;
default: break;
}
CCollisionInfo info(point, p0.GetMaterial(), p1.GetMaterial(), (s0.position - point).normalized());
list.Add(info, false);
return true;
}
bool Sphere_AABox_Bool(const CInternalCollisionStructure& collision)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableAABox& p1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox b1 = p1.Transform(collision.GetRight().GetTransform());
return CCollidableSphere::Sphere_AABox_Bool(s0, b1);
}
bool Sphere_Sphere(const CInternalCollisionStructure& collision, CCollisionInfoList& list)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableSphere& p1 = static_cast<const CCollidableSphere&>(collision.GetRight().GetPrim());
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform());
float radiusSum = s0.radius + s1.radius;
zeus::CVector3f delta = s0.position - s1.position;
float deltaMagSq = delta.magSquared();
if (deltaMagSq <= radiusSum * radiusSum)
{
zeus::CVector3f deltaNorm = delta.canBeNormalized() ?
(1.f / std::sqrt(deltaMagSq)) * delta : zeus::CVector3f::skRight;
zeus::CVector3f collisionPoint = deltaNorm * s1.radius + s1.position;
CCollisionInfo info(collisionPoint, p0.GetMaterial(), p1.GetMaterial(), deltaNorm);
list.Add(info, false);
return true;
}
return false;
}
bool Sphere_Sphere_Bool(const CInternalCollisionStructure& collision)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableSphere& p1 = static_cast<const CCollidableSphere&>(collision.GetRight().GetPrim());
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform());
float radiusSum = s0.radius + s1.radius;
return (s0.position - s1.position).magSquared() <= radiusSum * radiusSum;
}
bool Sphere_Sphere_Bool(const CInternalCollisionStructure&) { return false; }
}
CCollidableSphere::CCollidableSphere(const zeus::CSphere& sphere, const CMaterialList& list)
@ -51,15 +233,46 @@ const CCollisionPrimitive::Type& CCollidableSphere::GetType() { return sType; }
void CCollidableSphere::SetStaticTableIndex(u32 index) { sTableIndex = index; }
bool CCollidableSphere::CollideMovingAABox(const CInternalCollisionStructure&, const zeus::CVector3f&, double&,
CCollisionInfo&)
bool CCollidableSphere::CollideMovingAABox(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableAABox& p1 = static_cast<const CCollidableAABox&>(collision.GetRight().GetPrim());
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CAABox b1 = p1.CalculateAABox(collision.GetRight().GetTransform());
double d = dOut;
zeus::CVector3f point, normal;
if (CollisionUtil::MovingSphereAABox(s0, b1, dir, d, point, normal) && d < dOut)
{
dOut = d;
infoOut = CCollisionInfo(point, p0.GetMaterial(), p1.GetMaterial(), normal);
return true;
}
return false;
}
bool CCollidableSphere::CollideMovingSphere(const CInternalCollisionStructure&, const zeus::CVector3f&, double&,
CCollisionInfo&)
bool CCollidableSphere::CollideMovingSphere(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir,
double& dOut, CCollisionInfo& infoOut)
{
const CCollidableSphere& p0 = static_cast<const CCollidableSphere&>(collision.GetLeft().GetPrim());
const CCollidableSphere& p1 = static_cast<const CCollidableSphere&>(collision.GetRight().GetPrim());
zeus::CSphere s0 = p0.Transform(collision.GetLeft().GetTransform());
zeus::CSphere s1 = p1.Transform(collision.GetRight().GetTransform());
double d = dOut;
if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(s1.position, s0.radius + s1.radius),
s0.position, dir, d) && d >= 0.0 && d < dOut)
{
dOut = d;
zeus::CVector3f normal = (s0.position + float(d) * dir - s1.position).normalized();
infoOut = CCollisionInfo(s1.position + s1.radius * normal, p0.GetMaterial(), p1.GetMaterial(), normal);
return true;
}
return false;
}

View File

@ -960,7 +960,7 @@ bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCa
}
bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius;
bool x49c[] = {true, true, true};
bool testVert[] = {true, true, true};
const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx);
for (int k=0 ; k<3 ; ++k)
{
@ -1002,23 +1002,23 @@ bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCa
dOut = mag;
triRet = true;
ret = true;
x49c[k] = false;
x49c[nextIdx] = false;
testVert[k] = false;
testVert[nextIdx] = false;
}
else if (t < -sphere.radius && dirDotEdge <= 0.f)
{
x49c[k] = false;
testVert[k] = false;
}
else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0)
{
x49c[nextIdx] = false;
testVert[nextIdx] = false;
}
}
}
else
{
x49c[k] = false;
x49c[nextIdx] = false;
testVert[k] = false;
testVert[nextIdx] = false;
}
}
}
@ -1029,7 +1029,7 @@ bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCa
for (int k=0 ; k<3 ; ++k)
{
u16 vertIdx = vertIndices[k];
if (x49c[k])
if (testVert[k])
{
if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx])
{

View File

@ -328,16 +328,65 @@ bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list
const zeus::CAABox& aabb1, const CMaterialList& list1,
CCollisionInfoList& infoList)
{
zeus::CAABox boolAABB = aabb0.booleanIntersection(aabb1);
if (boolAABB.invalid())
zeus::CVector3f maxOfMin(std::max(aabb0.min.x, aabb1.min.x),
std::max(aabb0.min.y, aabb1.min.y),
std::max(aabb0.min.z, aabb1.min.z));
zeus::CVector3f minOfMax(std::min(aabb0.max.x, aabb1.max.x),
std::min(aabb0.max.y, aabb1.max.y),
std::min(aabb0.max.z, aabb1.max.z));
if (maxOfMin.x >= minOfMax.x || maxOfMin.y >= minOfMax.y || maxOfMin.z >= minOfMax.z)
return false;
/* TODO: Finish */
zeus::CAABox boolAABB(maxOfMin, minOfMax);
if (!infoList.GetCount())
int ineqFlags[] =
{
infoList.Add(CCollisionInfo(boolAABB, list0, list1, AABBNormalTable[4], -AABBNormalTable[4]), false);
infoList.Add(CCollisionInfo(boolAABB, list0, list1, AABBNormalTable[5], -AABBNormalTable[5]), false);
(aabb0.min.x <= aabb1.min.x ? 1 << 0 : 0) |
(aabb0.min.x <= aabb1.max.x ? 1 << 1 : 0) |
(aabb0.max.x <= aabb1.min.x ? 1 << 2 : 0) |
(aabb0.max.x <= aabb1.max.x ? 1 << 3 : 0),
(aabb0.min.y <= aabb1.min.y ? 1 << 0 : 0) |
(aabb0.min.y <= aabb1.max.y ? 1 << 1 : 0) |
(aabb0.max.y <= aabb1.min.y ? 1 << 2 : 0) |
(aabb0.max.y <= aabb1.max.y ? 1 << 3 : 0),
(aabb0.min.z <= aabb1.min.z ? 1 << 0 : 0) |
(aabb0.min.z <= aabb1.max.z ? 1 << 1 : 0) |
(aabb0.max.z <= aabb1.min.z ? 1 << 2 : 0) |
(aabb0.max.z <= aabb1.max.z ? 1 << 3 : 0),
};
for (int i=0 ; i<3 ; ++i)
{
switch (ineqFlags[i])
{
case 0x2: // aabb0.min <= aabb1.max
{
CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i*2+1], -AABBNormalTable[i*2+1]);
infoList.Add(info, false);
break;
}
case 0xB: // aabb0.min <= aabb1.min && aabb0.max <= aabb1.min && aabb0.max <= aabb1.max
{
CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[i*2], -AABBNormalTable[i*2]);
infoList.Add(info, false);
break;
}
default: break;
}
}
if (infoList.GetCount())
return true;
{
CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[4], -AABBNormalTable[4]);
infoList.Add(info, false);
}
{
CCollisionInfo info(boolAABB, list0, list1, AABBNormalTable[5], -AABBNormalTable[5]);
infoList.Add(info, false);
}
return true;
@ -776,5 +825,354 @@ bool TriSphereIntersection(const zeus::CSphere& sphere,
return true;
}
bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir,
float& tMin, float& tMax, int& axis, bool& sign)
{
tMin = -999999.f;
tMax = 999999.f;
for (int i=0 ; i<3 ; ++i)
{
if (dir[i] == 0.f)
if (point[i] < aabb.min[i] || point[i] > aabb.max[i])
return false;
float dirRecip = 1.f / dir[i];
float tmpMin, tmpMax;
if (dir[i] < 0.f)
{
tmpMin = (aabb.max[i] - point[i]) * dirRecip;
tmpMax = (aabb.min[i] - point[i]) * dirRecip;
}
else
{
tmpMin = (aabb.min[i] - point[i]) * dirRecip;
tmpMax = (aabb.max[i] - point[i]) * dirRecip;
}
if (tmpMin > tMin)
{
sign = dir[i] < 0.f;
axis = i;
tMin = tmpMin;
}
if (tmpMax < tMax)
tMax = tmpMax;
}
return tMin <= tMax;
}
bool LineCircleIntersection2d(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CSphere& sphere,
int axis1, int axis2, float& d)
{
zeus::CVector3f delta = sphere.position - point;
zeus::CVector2f deltaVec(delta[axis1], delta[axis2]);
zeus::CVector2f dirVec(dir[axis1], dir[axis2]);
float dirVecMag = dirVec.magnitude();
if (dirVecMag < FLT_EPSILON)
return false;
float deltaVecDot = deltaVec.dot(dirVec / dirVecMag);
float deltaVecMagSq = deltaVec.magSquared();
float sphereRadSq = sphere.radius * sphere.radius;
if (deltaVecDot < 0.f && deltaVecMagSq > sphereRadSq)
return false;
float tSq = sphereRadSq - (deltaVecMagSq - deltaVecDot * deltaVecDot);
if (tSq < 0.f)
return false;
float t = std::sqrt(tSq);
d = (deltaVecMagSq > sphereRadSq) ? deltaVecDot - t : deltaVecDot + t;
d /= dirVecMag;
return true;
}
bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir,
double& dOut, zeus::CVector3f& point, zeus::CVector3f& normal)
{
zeus::CAABox expAABB(aabb.min - sphere.radius, aabb.max + sphere.radius);
float tMin, tMax;
int axis;
bool sign;
if (!BoxLineTest(expAABB, sphere.position, dir, tMin, tMax, axis, sign))
return false;
point = sphere.position + tMin * dir;
int nextAxis1 = (axis+1) % 3; // r0
int nextAxis2 = (axis+2) % 3; // r5
bool inMin1 = point[nextAxis1] >= aabb.min[nextAxis1]; // r6
bool inMax1 = point[nextAxis1] <= aabb.max[nextAxis1]; // r8
bool inBounds1 = inMin1 && inMax1; // r9
bool inMin2 = point[nextAxis2] >= aabb.min[nextAxis2]; // r7
bool inMax2 = point[nextAxis2] <= aabb.max[nextAxis2]; // r4
bool inBounds2 = inMin2 && inMax2; // r8
if (inBounds1 && inBounds2)
{
if (tMin < 0.f || tMin > dOut)
return false;
normal[axis] = sign ? 1.f : -1.f;
dOut = tMin;
point -= normal * sphere.radius;
return true;
}
else if (!inBounds1 && !inBounds2)
{
int pointFlags = (1 << axis) * sign | (1 << nextAxis1) * inMin1 | (1 << nextAxis2) * inMin2;
zeus::CVector3f aabbPoint = aabb.getPoint(pointFlags);
float d;
if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint, sphere.radius),
sphere.position, dir, dOut, d, point))
{
int useAxis = -1;
for (int i=0 ; i<3 ; ++i)
{
if ((pointFlags & (1 << i)) ? aabbPoint[i] > point[i] : aabbPoint[i] < point[i])
{
useAxis = i;
break;
}
}
if (useAxis == -1)
{
normal = (point - aabbPoint).normalized();
point -= sphere.radius * normal;
return true;
}
int useAxisNext1 = (useAxis+1) % 3;
int useAxisNext2 = (useAxis+2) % 3;
float d;
if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius),
useAxisNext1, useAxisNext2, d) && d > 0.f && d < dOut)
{
if (point[useAxis] > aabb.max[useAxis])
{
int useAxisBit = 1 << useAxis;
if (pointFlags & useAxisBit)
return false;
zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags | useAxisBit);
if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius),
sphere.position, dir, dOut, d, point))
{
dOut = d;
normal = (point - aabbPoint1).normalized();
point -= normal * sphere.radius;
return true;
}
else
{
return false;
}
}
else if (point[useAxis] < aabb.min[useAxis])
{
int useAxisBit = 1 << useAxis;
if (!(pointFlags & useAxisBit))
return false;
zeus::CVector3f aabbPoint1 = aabb.getPoint(pointFlags ^ useAxisBit);
if (CollisionUtil::RaySphereIntersection(zeus::CSphere(aabbPoint1, sphere.radius),
sphere.position, dir, dOut, d, point))
{
dOut = d;
normal = (point - aabbPoint1).normalized();
point -= normal * sphere.radius;
return true;
}
else
{
return false;
}
}
else
{
normal = point - aabbPoint;
normal.normalize();
point -= normal * sphere.radius;
return true;
}
}
}
else
{
int reverseCount = 0;
float dMin = 1.0e10f;
int minAxis = 0;
for (int i=0 ; i<3 ; ++i)
{
if (std::fabs(dir[i]) > FLT_EPSILON)
{
bool pointMax = pointFlags & (1 << i);
if (pointMax != dir[i] > 0.f)
{
++reverseCount;
float d = 1.f / dir[i] * ((pointMax ? aabb.max[i] : aabb.min[i]) - sphere.position[i]);
if (d < 0.f)
return false;
if (d < dMin)
{
dMin = d;
minAxis = i;
}
}
}
}
if (reverseCount < 2)
return false;
int useAxisNext1 = (minAxis+1) % 3;
int useAxisNext2 = (minAxis+2) % 3;
float d;
if (CollisionUtil::LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint, sphere.radius),
useAxisNext1, useAxisNext2, d) && d > 0.f && d < dOut)
{
point = sphere.position + d * dir;
if (point[minAxis] > aabb.max[minAxis])
return false;
if (point[minAxis] < aabb.min[minAxis])
return false;
dOut = d;
normal = point - aabbPoint;
normal.normalize();
point -= sphere.radius * normal;
return true;
}
else
{
return false;
}
}
}
bool useNextAxis1 = inBounds1 ? nextAxis2 : nextAxis1;
bool useNextAxis2 = inBounds1 ? nextAxis1 : nextAxis2;
int pointFlags = ((1 << useNextAxis1) * (inBounds1 ? inMin2 : inMin1)) | ((1 << axis) * sign);
zeus::CVector3f aabbPoint2 = aabb.getPoint(pointFlags);
float d;
if (LineCircleIntersection2d(sphere.position, dir, zeus::CSphere(aabbPoint2, sphere.radius),
axis, useNextAxis1, d) && d > 0.f && d < dOut)
{
point = sphere.position + d * dir;
if (point[useNextAxis2] > aabb.max[useNextAxis2])
{
zeus::CVector3f aabbPoint3 = aabb.getPoint(pointFlags | (1 << useNextAxis2));
if (point[useNextAxis2] < expAABB.max[useNextAxis2])
{
if (RaySphereIntersection(zeus::CSphere(aabbPoint3, sphere.radius),
sphere.position, dir, dOut, d, point))
{
dOut = d;
normal = (point - aabbPoint3).normalized();
point -= sphere.radius * normal;
return true;
}
}
return false;
}
else if (point[useNextAxis2] < aabb.min[useNextAxis2])
{
if (point[useNextAxis2] > expAABB.min[useNextAxis2])
{
if (RaySphereIntersection(zeus::CSphere(aabbPoint2, sphere.radius),
sphere.position, dir, dOut, d, point))
{
dOut = d;
normal = (point - aabbPoint2).normalized();
point -= sphere.radius * normal;
return true;
}
}
return false;
}
else
{
dOut = d;
normal = point - aabbPoint2;
normal.normalize();
point -= sphere.radius * normal;
return true;
}
}
return false;
}
bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir,
double& d, zeus::CVector3f& point, zeus::CVector3f& normal)
{
zeus::CVector3d vecMin(DBL_MIN);
zeus::CVector3d vecMax(DBL_MAX);
for (int i=0 ; i<3 ; ++i)
{
if (std::fabs(dir[i]) < FLT_EPSILON)
{
if (aabb0.min[i] >= aabb1.min[i] && aabb0.min[i] <= aabb1.max[i])
continue;
if (aabb0.max[i] >= aabb1.min[i] && aabb0.max[i] <= aabb1.max[i])
continue;
if (aabb0.min[i] < aabb1.min[i] && aabb0.max[i] > aabb1.max[i])
continue;
return false;
}
else
{
if (aabb0.max[i] < aabb1.min[i] && dir[i] > 0.f)
vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i];
else if (aabb1.max[i] < aabb0.min[i] && dir[i] < 0.f)
vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i];
else if (aabb1.max[i] > aabb0.min[i] && dir[i] < 0.f)
vecMin[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i];
else if (aabb0.max[i] > aabb1.min[i] && dir[i] > 0.f)
vecMin[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i];
if (aabb1.max[i] > aabb0.min[i] && dir[i] > 0.f)
vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i];
else if (aabb0.max[i] > aabb1.min[i] && dir[i] < 0.f)
vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i];
else if (aabb0.max[i] < aabb1.min[i] && dir[i] < 0.f)
vecMax[i] = (aabb1.min[i] - aabb0.max[i]) / dir[i];
else if (aabb1.max[i] < aabb0.min[i] && dir[i] > 0.f)
vecMax[i] = (aabb1.max[i] - aabb0.min[i]) / dir[i];
}
}
int maxAxis = 0;
if (vecMin[1] > vecMin[0])
maxAxis = 1;
if (vecMin[2] > vecMin[maxAxis])
maxAxis = 2;
float minMax = std::min(std::min(vecMax[2], vecMax[1]), vecMax[0]);
if (vecMin[maxAxis] > minMax)
return false;
d = minMax;
normal = zeus::CVector3f::skZero;
normal[maxAxis] = dir[maxAxis] > 0.f ? -1.f : 1.f;
for (int i=0 ; i<3 ; ++i)
point[i] = dir[i] > 0.f ? aabb0.max[i] : aabb0.min[i];
point += float(d) * dir;
return true;
}
}
}

View File

@ -36,6 +36,14 @@ bool TriSphereOverlap(const zeus::CSphere& sphere,
bool TriSphereIntersection(const zeus::CSphere& sphere,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2, zeus::CVector3f& point, zeus::CVector3f& normal);
bool BoxLineTest(const zeus::CAABox& aabb, const zeus::CVector3f& point, const zeus::CVector3f& dir,
float& tMin, float& tMax, int& axis, bool& sign);
bool LineCircleIntersection2d(const zeus::CVector3f& point, const zeus::CVector3f& dir, const zeus::CSphere& sphere,
int axis1, int axis2, float& d);
bool MovingSphereAABox(const zeus::CSphere& sphere, const zeus::CAABox& aabb, const zeus::CVector3f& dir,
double& d, zeus::CVector3f& point, zeus::CVector3f& normal);
bool AABox_AABox_Moving(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1, const zeus::CVector3f& dir,
double& d, zeus::CVector3f& point, zeus::CVector3f& normal);
}
}
#endif // __URDE_COLLISIONUTIL_HPP__

@ -1 +1 @@
Subproject commit 79b00ed327c88c80bece7f7b58e1fc8d02ab52e1
Subproject commit 1c17a28648e33d52a0eaea1e272da49ac6a940dd