From 6f9e6712ce7e2426d0ad7e116f8e403a4f344930 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Mon, 3 Jul 2017 19:03:11 -1000 Subject: [PATCH] Implement final dynamic collision tests --- Runtime/Collision/CCollidableAABox.cpp | 22 ++++++++++++-- Runtime/Collision/CCollidableOBBTree.cpp | 2 +- Runtime/Collision/CCollidableSphere.cpp | 36 ++++++++++++++++++++--- Runtime/Collision/CCollisionPrimitive.cpp | 32 ++++++++++++++++++-- Runtime/Collision/CCollisionPrimitive.hpp | 4 ++- 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/Runtime/Collision/CCollidableAABox.cpp b/Runtime/Collision/CCollidableAABox.cpp index 45f5dd9e8..48b2cecaa 100644 --- a/Runtime/Collision/CCollidableAABox.cpp +++ b/Runtime/Collision/CCollidableAABox.cpp @@ -2,6 +2,7 @@ #include "CollisionUtil.hpp" #include "CCollidableSphere.hpp" #include "CCollisionInfo.hpp" +#include "CInternalRayCastStructure.hpp" namespace urde { @@ -43,9 +44,26 @@ FourCC CCollidableAABox::GetPrimType() const return SBIG('AABX'); } -CRayCastResult CCollidableAABox::CastRayInternal(const CInternalRayCastStructure &) const +CRayCastResult CCollidableAABox::CastRayInternal(const CInternalRayCastStructure& rayCast) const { - return {}; + if (!rayCast.GetFilter().Passes(GetMaterial())) + return {}; + zeus::CTransform rayCastXfInv = rayCast.GetTransform().inverse(); + zeus::CVector3f localRayStart = rayCastXfInv * rayCast.GetRay().start; + zeus::CVector3f localRayDir = rayCastXfInv.rotate(rayCast.GetRay().dir); + float tMin, tMax; + int axis; + bool sign; + if (!CollisionUtil::BoxLineTest(x10_aabox, localRayStart, localRayDir, tMin, tMax, axis, sign) || + tMin < 0.f || (rayCast.GetMaxTime() > 0.f && tMin > rayCast.GetMaxTime())) + return {}; + + zeus::CVector3f planeNormal; + planeNormal[axis] = sign ? 1.f : -1.f; + float planeD = axis ? x10_aabox.min[axis] : -x10_aabox.max[axis]; + CRayCastResult result(tMin, localRayStart + tMin * localRayDir, zeus::CPlane(planeNormal, planeD), GetMaterial()); + result.Transform(rayCast.GetTransform()); + return result; } const CCollisionPrimitive::Type& CCollidableAABox::GetType() diff --git a/Runtime/Collision/CCollidableOBBTree.cpp b/Runtime/Collision/CCollidableOBBTree.cpp index 786a72b4e..7fbfd65dd 100644 --- a/Runtime/Collision/CCollidableOBBTree.cpp +++ b/Runtime/Collision/CCollidableOBBTree.cpp @@ -26,7 +26,7 @@ bool CCollidableOBBTree::LineIntersectsLeaf(const COBBTree::CLeafData& leaf, CRa if (CollisionUtil::RayTriangleIntersection(info.GetRay().start, info.GetRay().dir, surface.GetVerts(), info.Magnitude())) { - intersectIdx = i; + intersectIdx = surfIdx; ret = true; } } diff --git a/Runtime/Collision/CCollidableSphere.cpp b/Runtime/Collision/CCollidableSphere.cpp index 5763d4227..0e838a6aa 100644 --- a/Runtime/Collision/CCollidableSphere.cpp +++ b/Runtime/Collision/CCollidableSphere.cpp @@ -2,6 +2,7 @@ #include "CCollisionInfoList.hpp" #include "CCollidableAABox.hpp" #include "CollisionUtil.hpp" +#include "CInternalRayCastStructure.hpp" namespace urde { @@ -211,7 +212,7 @@ const zeus::CSphere& CCollidableSphere::GetSphere() const { return x10_sphere; } void CCollidableSphere::SetSphereCenter(const zeus::CVector3f&) { - + /* Remove me? */ } zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const @@ -221,13 +222,40 @@ zeus::CSphere CCollidableSphere::Transform(const zeus::CTransform& xf) const u32 CCollidableSphere::GetTableIndex() const { return sTableIndex; } -zeus::CAABox CCollidableSphere::CalculateAABox(const zeus::CTransform&) const { return {}; } +zeus::CAABox CCollidableSphere::CalculateAABox(const zeus::CTransform& xf) const +{ + zeus::CVector3f xfPos = xf * x10_sphere.position; + return {xfPos - x10_sphere.radius, xfPos + x10_sphere.radius}; +} -zeus::CAABox CCollidableSphere::CalculateLocalAABox() const { return {}; } +zeus::CAABox CCollidableSphere::CalculateLocalAABox() const +{ + return {x10_sphere.position - x10_sphere.radius, x10_sphere.position + x10_sphere.radius}; +} FourCC CCollidableSphere::GetPrimType() const { return SBIG('SPHR'); } -CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructure&) const { return {}; } +CRayCastResult CCollidableSphere::CastRayInternal(const CInternalRayCastStructure& rayCast) const +{ + if (!rayCast.GetFilter().Passes(GetMaterial())) + return {}; + + zeus::CSphere xfSphere = Transform(rayCast.GetTransform()); + float t = 0.f; + zeus::CVector3f point; + if (CollisionUtil::RaySphereIntersection(xfSphere, rayCast.GetRay().start, rayCast.GetRay().dir, + rayCast.GetMaxTime(), t, point)) + { + zeus::CVector3f delta = point - xfSphere.position; + float deltaMag = delta.magnitude(); + zeus::CUnitVector3f planeNormal = + (deltaMag > 0.01f) ? delta * (1.f / deltaMag) : rayCast.GetRay().dir; + float planeD = point.dot(planeNormal); + return CRayCastResult(t, point, zeus::CPlane(planeNormal, planeD), GetMaterial()); + } + + return {}; +} const CCollisionPrimitive::Type& CCollidableSphere::GetType() { return sType; } diff --git a/Runtime/Collision/CCollisionPrimitive.cpp b/Runtime/Collision/CCollisionPrimitive.cpp index e6c7b50cc..e8b1744ed 100644 --- a/Runtime/Collision/CCollisionPrimitive.cpp +++ b/Runtime/Collision/CCollisionPrimitive.cpp @@ -144,14 +144,42 @@ bool CCollisionPrimitive::CollideBoolean(CInternalCollisionStructure::CPrimDesc& return InternalCollideBoolean({prim0, prim1}); } +bool CCollisionPrimitive::InternalCollideMoving(const CInternalCollisionStructure& collision, + const zeus::CVector3f& dir, + double& dOut, CCollisionInfo& infoOut) +{ + u32 idx0 = collision.GetLeft().GetPrim().GetTableIndex(); + u32 idx1 = collision.GetRight().GetPrim().GetTableIndex(); + + MovingComparisonFunc func; + if (idx0 == -1 || idx1 == -1) + { + sNullMovingCollider = nullptr; + func = sNullMovingCollider; + } + else + { + func = (*sTableOfMovingCollidables)[sNumTypes * idx1 + idx0]; + } + + if (func) + { + if (!collision.GetLeft().GetFilter().Passes(collision.GetRight().GetPrim().GetMaterial()) || + !collision.GetRight().GetFilter().Passes(collision.GetLeft().GetPrim().GetMaterial())) + return false; + return func(collision, dir, dOut, infoOut); + } + + return false; +} + bool CCollisionPrimitive::CollideMoving(CInternalCollisionStructure::CPrimDesc& prim0, CInternalCollisionStructure::CPrimDesc& prim1, const zeus::CVector3f& dir, double& dOut, CCollisionInfo& infoOut) { - // TODO: Finish - return false; + return InternalCollideMoving({prim0, prim1}, dir, dOut, infoOut); } void CCollisionPrimitive::InitBeginTypes() diff --git a/Runtime/Collision/CCollisionPrimitive.hpp b/Runtime/Collision/CCollisionPrimitive.hpp index 629c973df..57766e6ce 100644 --- a/Runtime/Collision/CCollisionPrimitive.hpp +++ b/Runtime/Collision/CCollisionPrimitive.hpp @@ -133,6 +133,8 @@ private: static bool InternalCollide(const CInternalCollisionStructure& collision, CCollisionInfoList& list); static bool InternalCollideBoolean(const CInternalCollisionStructure& collision); + static bool InternalCollideMoving(const CInternalCollisionStructure& collision, const zeus::CVector3f& dir, + double& dOut, CCollisionInfo& infoOut); public: CCollisionPrimitive() = default; @@ -155,7 +157,7 @@ public: CInternalCollisionStructure::CPrimDesc& prim1); static bool CollideMoving(CInternalCollisionStructure::CPrimDesc& prim0, CInternalCollisionStructure::CPrimDesc& prim1, - const zeus::CVector3f& vec, + const zeus::CVector3f& dir, double& dOut, CCollisionInfo& infoOut);