mirror of https://github.com/AxioDL/metaforce.git
Finish AABB area colliders
This commit is contained in:
parent
458cde358c
commit
ec7ac212ef
|
@ -1492,7 +1492,8 @@ bool CStateManager::TestRayDamage(const zeus::CVector3f& pos, const CActor& dama
|
|||
return false;
|
||||
|
||||
float depth;
|
||||
u32 count = CollisionUtil::RayAABoxIntersection(ray, *bounds, zeus::CVector3f::skZero, depth);
|
||||
zeus::CVector3f norm;
|
||||
u32 count = CollisionUtil::RayAABoxIntersection(ray, *bounds, norm, depth);
|
||||
if (count == 0 || count == 1)
|
||||
return true;
|
||||
|
||||
|
|
|
@ -662,4 +662,25 @@ CCollisionSurface CAreaOctTree::GetMasterListTriangle(u16 idx) const
|
|||
GetVert(vert2), material);
|
||||
}
|
||||
|
||||
void CAreaOctTree::GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const
|
||||
{
|
||||
const CCollisionEdge& e0 = x3c_edges[x44_polyEdges[idx*3]];
|
||||
const CCollisionEdge& e1 = x3c_edges[x44_polyEdges[idx*3+1]];
|
||||
indicesOut[2] =
|
||||
(e1.GetVertIndex1() != e0.GetVertIndex1() && e1.GetVertIndex1() != e0.GetVertIndex2()) ?
|
||||
e1.GetVertIndex1() : e1.GetVertIndex2();
|
||||
|
||||
u32 material = x28_materials[x34_polyMats[idx]];
|
||||
if (material & 0x2000000)
|
||||
{
|
||||
indicesOut[0] = e0.GetVertIndex2();
|
||||
indicesOut[1] = e0.GetVertIndex1();
|
||||
}
|
||||
else
|
||||
{
|
||||
indicesOut[0] = e0.GetVertIndex1();
|
||||
indicesOut[1] = e0.GetVertIndex2();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ public:
|
|||
u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges,
|
||||
u32 vertCount, const float* verts);
|
||||
|
||||
const zeus::CAABox& GetAABB() const { return x0_aabb; }
|
||||
Node GetRootNode() const { return Node(x20_treeBuf, x0_aabb, *this, x18_treeType); }
|
||||
const u8* GetTreeMemory() const { return x20_treeBuf; }
|
||||
zeus::CVector3f GetVert(int idx) const
|
||||
|
@ -131,14 +132,15 @@ public:
|
|||
return zeus::CVector3f(vert[0], vert[1], vert[2]);
|
||||
}
|
||||
const CCollisionEdge& GetEdge(int idx) const { return x3c_edges[idx]; }
|
||||
u32 GetVertMaterial(int idx) const { return x28_materials[x2c_vertMats[idx]]; }
|
||||
u32 GetEdgeMaterial(int idx) const { return x28_materials[x30_edgeMats[idx]]; }
|
||||
u32 GetTriangleMaterial(int idx) const { return x28_materials[x34_polyMats[idx]]; }
|
||||
u32 GetNumEdges() const { return x38_edgeCount; }
|
||||
u32 GetNumVerts() const { return x48_vertCount; }
|
||||
u32 GetNumTriangles() const { return x40_polyCount; }
|
||||
CCollisionSurface GetMasterListTriangle(u16 idx) const;
|
||||
const u16* GetTriangleVertexIndices(u16 idx) const;
|
||||
const u16* GetTriangleEdgeIndices(u16 idx) const;
|
||||
void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const;
|
||||
const u16* GetTriangleEdgeIndices(u16 idx) const { return &x44_polyEdges[idx * 6]; }
|
||||
|
||||
static std::unique_ptr<CAreaOctTree> MakeFromMemory(const u8* buf, unsigned int size);
|
||||
};
|
||||
|
|
|
@ -146,7 +146,7 @@ bool CCollisionPrimitive::CollideBoolean(CInternalCollisionStructure::CPrimDesc&
|
|||
|
||||
bool CCollisionPrimitive::CollideMoving(CInternalCollisionStructure::CPrimDesc& prim0,
|
||||
CInternalCollisionStructure::CPrimDesc& prim1,
|
||||
const zeus::CVector3f& vec,
|
||||
const zeus::CVector3f& dir,
|
||||
double& dOut,
|
||||
CCollisionInfo& infoOut)
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
|
||||
zeus::CVector3f GetNormal() const;
|
||||
const zeus::CVector3f& GetVert(s32 idx) const { return (&x0_a)[idx]; }
|
||||
const zeus::CVector3f* GetVerts() const { return &x0_a; }
|
||||
zeus::CVector3f GetPoint(s32) const;
|
||||
zeus::CPlane GetPlane() const;
|
||||
u32 GetSurfaceFlags() const { return x24_flags; }
|
||||
|
|
|
@ -570,17 +570,17 @@ bool CGameCollision::DetectCollision_Cached_Moving(CStateManager& mgr, CAreaColl
|
|||
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||
const CMaterialFilter& filter,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const zeus::CVector3f& vec,
|
||||
const zeus::CVector3f& dir,
|
||||
TUniqueId& idOut, CCollisionInfo& infoOut, double& d)
|
||||
{
|
||||
idOut = kInvalidUniqueId;
|
||||
if (!filter.GetExcludeList().HasMaterial(EMaterialTypes::StaticCollision))
|
||||
{
|
||||
if (CGameCollision::DetectStaticCollision_Cached_Moving(mgr, cache, prim, xf, filter, vec, infoOut, d))
|
||||
if (CGameCollision::DetectStaticCollision_Cached_Moving(mgr, cache, prim, xf, filter, dir, infoOut, d))
|
||||
return true;
|
||||
}
|
||||
|
||||
return CGameCollision::DetectDynamicCollisionMoving(prim, xf, nearList, vec, idOut, infoOut, d, mgr);
|
||||
return CGameCollision::DetectDynamicCollisionMoving(prim, xf, nearList, dir, idOut, infoOut, d, mgr);
|
||||
}
|
||||
|
||||
bool CGameCollision::DetectStaticCollision(CStateManager& mgr, const CCollisionPrimitive& prim,
|
||||
|
@ -667,13 +667,13 @@ bool CGameCollision::DetectStaticCollision_Cached(CStateManager& mgr, CAreaColli
|
|||
|
||||
bool CGameCollision::DetectStaticCollision_Cached_Moving(CStateManager& mgr, CAreaCollisionCache& cache,
|
||||
const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||
const CMaterialFilter& filter, const zeus::CVector3f& vec,
|
||||
const CMaterialFilter& filter, const zeus::CVector3f& dir,
|
||||
CCollisionInfo& infoOut, double& dOut)
|
||||
{
|
||||
if (prim.GetPrimType() == FOURCC('OBTG'))
|
||||
return false;
|
||||
|
||||
zeus::CVector3f offset = float(dOut) * vec;
|
||||
zeus::CVector3f offset = float(dOut) * dir;
|
||||
zeus::CAABox aabb = prim.CalculateAABox(xf);
|
||||
zeus::CAABox offsetAABB = aabb;
|
||||
offsetAABB.accumulateBounds(offset + offsetAABB.min);
|
||||
|
@ -694,7 +694,7 @@ bool CGameCollision::DetectStaticCollision_Cached_Moving(CStateManager& mgr, CAr
|
|||
CCollisionInfo info;
|
||||
double d = dOut;
|
||||
if (CMetroidAreaCollider::MovingAABoxCollisionCheck_Cached(leafCache, aabb, filter,
|
||||
CMaterialList(EMaterialTypes::Solid), vec,
|
||||
CMaterialList(EMaterialTypes::Solid), dir,
|
||||
dOut, info, d) && d < dOut)
|
||||
{
|
||||
infoOut = info;
|
||||
|
@ -711,7 +711,7 @@ bool CGameCollision::DetectStaticCollision_Cached_Moving(CStateManager& mgr, CAr
|
|||
CCollisionInfo info;
|
||||
double d = dOut;
|
||||
if (CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(leafCache, aabb, xfSphere, filter,
|
||||
CMaterialList(EMaterialTypes::Solid), vec,
|
||||
CMaterialList(EMaterialTypes::Solid), dir,
|
||||
dOut, info, d) && d < dOut)
|
||||
{
|
||||
infoOut = info;
|
||||
|
@ -748,7 +748,7 @@ bool CGameCollision::DetectDynamicCollision(const CCollisionPrimitive& prim, con
|
|||
|
||||
bool CGameCollision::DetectDynamicCollisionMoving(const CCollisionPrimitive& prim, const zeus::CTransform& xf,
|
||||
const rstl::reserved_vector<TUniqueId, 1024>& nearList,
|
||||
const zeus::CVector3f& vec, TUniqueId& idOut,
|
||||
const zeus::CVector3f& dir, TUniqueId& idOut,
|
||||
CCollisionInfo& infoOut, double& dOut, CStateManager& mgr)
|
||||
{
|
||||
bool ret = false;
|
||||
|
@ -762,7 +762,7 @@ bool CGameCollision::DetectDynamicCollisionMoving(const CCollisionPrimitive& pri
|
|||
CInternalCollisionStructure::CPrimDesc p1(*actor->GetCollisionPrimitive(),
|
||||
CMaterialFilter::skPassEverything,
|
||||
actor->GetPrimitiveTransform());
|
||||
if (CCollisionPrimitive::CollideMoving(p0, p1, vec, d, info) && d < dOut)
|
||||
if (CCollisionPrimitive::CollideMoving(p0, p1, dir, d, info) && d < dOut)
|
||||
{
|
||||
ret = true;
|
||||
infoOut = info;
|
||||
|
|
|
@ -100,6 +100,8 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
u64 GetValue() const { return x0_list; }
|
||||
|
||||
static s32 BitPosition(u64 flag)
|
||||
{
|
||||
for (u32 i = 0; i < 63; ++i)
|
||||
|
|
|
@ -1,16 +1,159 @@
|
|||
#include "CMetroidAreaCollider.hpp"
|
||||
#include "CMaterialFilter.hpp"
|
||||
#include "CollisionUtil.hpp"
|
||||
#include "CCollisionInfoList.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
u32 CMetroidAreaCollider::g_CalledClip = 0;
|
||||
u32 CMetroidAreaCollider::g_RejectedByClip = 0;
|
||||
u32 CMetroidAreaCollider::g_TrianglesProcessed = 0;
|
||||
u32 CMetroidAreaCollider::g_DupTrianglesProcessed = 0;
|
||||
s16 CMetroidAreaCollider::g_DupPrimitiveCheckCount = 0;
|
||||
u16 CMetroidAreaCollider::g_DupVertexList[0x5000] = {};
|
||||
u16 CMetroidAreaCollider::g_DupEdgeList[0xC000] = {};
|
||||
u16 CMetroidAreaCollider::g_DupTriangleList[0x4000] = {};
|
||||
|
||||
CAABoxAreaCache::CAABoxAreaCache(const zeus::CAABox& aabb, const zeus::CPlane* pl, const CMaterialFilter& filter,
|
||||
const CMaterialList& material, CCollisionInfoList& collisionList)
|
||||
: x0_aabb(aabb), x4_planes(pl), x8_filter(filter), xc_material(material), x10_collisionList(collisionList),
|
||||
x14_center(aabb.center()), x20_halfExtent(aabb.extents())
|
||||
{}
|
||||
|
||||
CBooleanAABoxAreaCache::CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter)
|
||||
: x0_aabb(aabb), x4_filter(filter), x8_center(aabb.center()), x14_halfExtent(aabb.extents())
|
||||
{}
|
||||
|
||||
SBoxEdge::SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir)
|
||||
: x0_seg(aabb.getEdge(zeus::CAABox::EBoxEdgeId(idx))), x28_dir(x0_seg.dir), x40_end(x0_seg.end),
|
||||
x58_start(x40_end - x28_dir), x70_coDir(x58_start.cross(dir).asNormalized()),
|
||||
x88_dirCoDirDot(x28_dir.dot(x70_coDir))
|
||||
{}
|
||||
|
||||
static void FlagEdgeIndicesForFace(int face, bool edgeFlags[12])
|
||||
{
|
||||
switch (face)
|
||||
{
|
||||
case 0:
|
||||
edgeFlags[10] = true;
|
||||
edgeFlags[11] = true;
|
||||
edgeFlags[2] = true;
|
||||
edgeFlags[4] = true;
|
||||
return;
|
||||
case 1:
|
||||
edgeFlags[8] = true;
|
||||
edgeFlags[9] = true;
|
||||
edgeFlags[0] = true;
|
||||
edgeFlags[6] = true;
|
||||
return;
|
||||
case 2:
|
||||
edgeFlags[4] = true;
|
||||
edgeFlags[5] = true;
|
||||
edgeFlags[6] = true;
|
||||
edgeFlags[7] = true;
|
||||
return;
|
||||
case 3:
|
||||
edgeFlags[0] = true;
|
||||
edgeFlags[1] = true;
|
||||
edgeFlags[2] = true;
|
||||
edgeFlags[3] = true;
|
||||
return;
|
||||
case 4:
|
||||
edgeFlags[7] = true;
|
||||
edgeFlags[8] = true;
|
||||
edgeFlags[3] = true;
|
||||
edgeFlags[11] = true;
|
||||
return;
|
||||
case 5:
|
||||
edgeFlags[1] = true;
|
||||
edgeFlags[5] = true;
|
||||
edgeFlags[9] = true;
|
||||
edgeFlags[10] = true;
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FlagVertexIndicesForFace(int face, bool vertFlags[8])
|
||||
{
|
||||
switch (face)
|
||||
{
|
||||
case 0:
|
||||
vertFlags[1] = true;
|
||||
vertFlags[3] = true;
|
||||
vertFlags[5] = true;
|
||||
vertFlags[7] = true;
|
||||
return;
|
||||
case 1:
|
||||
vertFlags[0] = true;
|
||||
vertFlags[2] = true;
|
||||
vertFlags[4] = true;
|
||||
vertFlags[6] = true;
|
||||
return;
|
||||
case 2:
|
||||
vertFlags[2] = true;
|
||||
vertFlags[3] = true;
|
||||
vertFlags[6] = true;
|
||||
vertFlags[7] = true;
|
||||
return;
|
||||
case 3:
|
||||
vertFlags[0] = true;
|
||||
vertFlags[1] = true;
|
||||
vertFlags[4] = true;
|
||||
vertFlags[5] = true;
|
||||
return;
|
||||
case 4:
|
||||
vertFlags[4] = true;
|
||||
vertFlags[5] = true;
|
||||
vertFlags[6] = true;
|
||||
vertFlags[7] = true;
|
||||
return;
|
||||
case 5:
|
||||
vertFlags[0] = true;
|
||||
vertFlags[1] = true;
|
||||
vertFlags[2] = true;
|
||||
vertFlags[3] = true;
|
||||
return;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
CMovingAABoxComponents::CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir)
|
||||
: x6e8_aabb(aabb)
|
||||
{
|
||||
bool edgeFlags[12] = {};
|
||||
bool vertFlags[8] = {};
|
||||
int useFaces = 0;
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (dir[i] != 0.f)
|
||||
{
|
||||
int face = i * 2 + (dir[i] < 0.f);
|
||||
FlagEdgeIndicesForFace(face, edgeFlags);
|
||||
FlagVertexIndicesForFace(face, vertFlags);
|
||||
useFaces += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0 ; i<12 ; ++i)
|
||||
x0_edges.push_back(SBoxEdge(aabb, i, dir));
|
||||
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
if (vertFlags[i])
|
||||
x6c4_vertIdxs.push_back(i);
|
||||
|
||||
if (useFaces == 1)
|
||||
{
|
||||
x6e8_aabb = zeus::CAABox::skInvertedBox;
|
||||
x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[0]));
|
||||
x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[1]));
|
||||
x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[2]));
|
||||
x6e8_aabb.accumulateBounds(aabb.getPoint(x6c4_vertIdxs[3]));
|
||||
}
|
||||
}
|
||||
|
||||
CMetroidAreaCollider::COctreeLeafCache::COctreeLeafCache(const CAreaOctTree& octTree)
|
||||
: x0_octTree(octTree)
|
||||
{
|
||||
|
@ -48,9 +191,78 @@ void CMetroidAreaCollider::BuildOctreeLeafCache(const CAreaOctTree::Node& node,
|
|||
}
|
||||
}
|
||||
|
||||
static zeus::CVector3f ClipRayToPlane(const zeus::CVector3f& a, const zeus::CVector3f& b,
|
||||
const zeus::CPlane& plane)
|
||||
{
|
||||
return (1.f - -plane.pointToPlaneDist(a) / (b - a).dot(plane.vec)) * (a - b) + b;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts,
|
||||
zeus::CAABox& aabb)
|
||||
{
|
||||
rstl::reserved_vector<zeus::CVector3f, 20> vecs[2];
|
||||
|
||||
vecs[0].push_back(verts[0]);
|
||||
vecs[0].push_back(verts[1]);
|
||||
vecs[0].push_back(verts[2]);
|
||||
|
||||
int vecIdx = 0;
|
||||
int otherVecIdx = 1;
|
||||
for (int i=0 ; i<6 ; ++i)
|
||||
{
|
||||
rstl::reserved_vector<zeus::CVector3f, 20>& vec = vecs[vecIdx];
|
||||
rstl::reserved_vector<zeus::CVector3f, 20>& otherVec = vecs[otherVecIdx];
|
||||
otherVec.clear();
|
||||
|
||||
bool inFrontOf = planes[i].pointToPlaneDist(vec.front()) >= 0.f;
|
||||
for (int j=0 ; j<vec.size() ; ++j)
|
||||
{
|
||||
const zeus::CVector3f& b = vec[(j + 1) % vec.size()];
|
||||
if (inFrontOf)
|
||||
otherVec.push_back(vec[j]);
|
||||
if ((planes[i].pointToPlaneDist(b) >= 0.f) ^ inFrontOf)
|
||||
otherVec.push_back(ClipRayToPlane(vec[j], b, planes[i]));
|
||||
}
|
||||
|
||||
if (otherVec.empty())
|
||||
return false;
|
||||
|
||||
vecIdx ^= 1;
|
||||
otherVecIdx ^= 1;
|
||||
}
|
||||
|
||||
rstl::reserved_vector<zeus::CVector3f, 20>& accumVec = vecs[otherVecIdx ^ 1];
|
||||
for (const zeus::CVector3f& point : accumVec)
|
||||
aabb.accumulateBounds(point);
|
||||
|
||||
g_RejectedByClip -= 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter)
|
||||
{
|
||||
CBooleanAABoxAreaCache cache(aabb, filter);
|
||||
|
||||
for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache)
|
||||
{
|
||||
if (cache.x0_aabb.intersects(node.GetBoundingBox()))
|
||||
{
|
||||
CAreaOctTree::TriListReference list = node.GetTriangleArray();
|
||||
for (int j=0 ; j<list.GetSize() ; ++j)
|
||||
{
|
||||
++g_TrianglesProcessed;
|
||||
CCollisionSurface surf = node.GetOwner().GetMasterListTriangle(list.GetAt(j));
|
||||
if (cache.x4_filter.Passes(CMaterialList(surf.GetSurfaceFlags())))
|
||||
{
|
||||
if (CollisionUtil::TriBoxOverlap(cache.x8_center, cache.x14_halfExtent,
|
||||
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -114,14 +326,143 @@ bool CMetroidAreaCollider::AABoxCollisionCheck_Cached(const COctreeLeafCache& le
|
|||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
CCollisionInfoList& list)
|
||||
{
|
||||
return false;
|
||||
bool ret = false;
|
||||
zeus::CPlane planes[] =
|
||||
{
|
||||
{zeus::CVector3f::skRight, aabb.min.dot(zeus::CVector3f::skRight)},
|
||||
{zeus::CVector3f::skLeft, aabb.max.dot(zeus::CVector3f::skLeft)},
|
||||
{zeus::CVector3f::skForward, aabb.min.dot(zeus::CVector3f::skForward)},
|
||||
{zeus::CVector3f::skBack, aabb.max.dot(zeus::CVector3f::skBack)},
|
||||
{zeus::CVector3f::skUp, aabb.min.dot(zeus::CVector3f::skUp)},
|
||||
{zeus::CVector3f::skDown, aabb.max.dot(zeus::CVector3f::skDown)}
|
||||
};
|
||||
CAABoxAreaCache cache(aabb, planes, filter, matList, list);
|
||||
|
||||
ResetInternalCounters();
|
||||
|
||||
for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache)
|
||||
{
|
||||
if (aabb.intersects(node.GetBoundingBox()))
|
||||
{
|
||||
CAreaOctTree::TriListReference list = node.GetTriangleArray();
|
||||
for (int j=0 ; j<list.GetSize() ; ++j)
|
||||
{
|
||||
++g_TrianglesProcessed;
|
||||
u16 triIdx = list.GetAt(j);
|
||||
if (g_DupPrimitiveCheckCount == g_DupTriangleList[triIdx])
|
||||
{
|
||||
g_DupTrianglesProcessed += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_DupTriangleList[triIdx] = g_DupPrimitiveCheckCount;
|
||||
CCollisionSurface surf = node.GetOwner().GetMasterListTriangle(triIdx);
|
||||
CMaterialList material(surf.GetSurfaceFlags());
|
||||
if (cache.x8_filter.Passes(material))
|
||||
{
|
||||
if (CollisionUtil::TriBoxOverlap(cache.x14_center, cache.x20_halfExtent,
|
||||
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
|
||||
{
|
||||
zeus::CAABox aabb = zeus::CAABox::skInvertedBox;
|
||||
if (ConvexPolyCollision(cache.x4_planes, surf.GetVerts(), aabb))
|
||||
{
|
||||
zeus::CPlane plane = surf.GetPlane();
|
||||
CCollisionInfo collision(aabb, cache.xc_material, material,
|
||||
plane.normal(), -plane.normal());
|
||||
cache.x10_collisionList.Add(collision, false);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node,
|
||||
const CAABoxAreaCache& cache)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
switch (node.GetTreeType())
|
||||
{
|
||||
case CAreaOctTree::Node::ETreeType::Invalid:
|
||||
return false;
|
||||
case CAreaOctTree::Node::ETreeType::Branch:
|
||||
{
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
{
|
||||
CAreaOctTree::Node ch = node.GetChild(i);
|
||||
if (ch.GetBoundingBox().intersects(cache.x0_aabb))
|
||||
if (AABoxCollisionCheck_Internal(ch, cache))
|
||||
ret = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAreaOctTree::Node::ETreeType::Leaf:
|
||||
{
|
||||
CAreaOctTree::TriListReference list = node.GetTriangleArray();
|
||||
for (int j=0 ; j<list.GetSize() ; ++j)
|
||||
{
|
||||
++g_TrianglesProcessed;
|
||||
u16 triIdx = list.GetAt(j);
|
||||
if (g_DupPrimitiveCheckCount == g_DupTriangleList[triIdx])
|
||||
{
|
||||
g_DupTrianglesProcessed += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_DupTriangleList[triIdx] = g_DupPrimitiveCheckCount;
|
||||
CCollisionSurface surf = node.GetOwner().GetMasterListTriangle(triIdx);
|
||||
CMaterialList material(surf.GetSurfaceFlags());
|
||||
if (cache.x8_filter.Passes(material))
|
||||
{
|
||||
if (CollisionUtil::TriBoxOverlap(cache.x14_center, cache.x20_halfExtent,
|
||||
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
|
||||
{
|
||||
zeus::CAABox aabb = zeus::CAABox::skInvertedBox;
|
||||
if (ConvexPolyCollision(cache.x4_planes, surf.GetVerts(), aabb))
|
||||
{
|
||||
zeus::CPlane plane = surf.GetPlane();
|
||||
CCollisionInfo collision(aabb, cache.xc_material, material,
|
||||
plane.normal(), -plane.normal());
|
||||
cache.x10_collisionList.Add(collision, false);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
CCollisionInfoList& list)
|
||||
{
|
||||
return false;
|
||||
zeus::CPlane planes[] =
|
||||
{
|
||||
{zeus::CVector3f::skRight, aabb.min.dot(zeus::CVector3f::skRight)},
|
||||
{zeus::CVector3f::skLeft, aabb.max.dot(zeus::CVector3f::skLeft)},
|
||||
{zeus::CVector3f::skForward, aabb.min.dot(zeus::CVector3f::skForward)},
|
||||
{zeus::CVector3f::skBack, aabb.max.dot(zeus::CVector3f::skBack)},
|
||||
{zeus::CVector3f::skUp, aabb.min.dot(zeus::CVector3f::skUp)},
|
||||
{zeus::CVector3f::skDown, aabb.max.dot(zeus::CVector3f::skDown)}
|
||||
};
|
||||
CAABoxAreaCache cache(aabb, planes, filter, matList, list);
|
||||
|
||||
ResetInternalCounters();
|
||||
|
||||
CAreaOctTree::Node node = octTree.GetRootNode();
|
||||
return AABoxCollisionCheck_Internal(node, cache);
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
|
@ -138,23 +479,276 @@ bool CMetroidAreaCollider::SphereCollisionCheck(const CAreaOctTree& octTree, con
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb,
|
||||
const rstl::reserved_vector<u32, 8>& vertIndices,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point)
|
||||
{
|
||||
bool ret = false;
|
||||
for (u32 idx : vertIndices)
|
||||
{
|
||||
zeus::CVector3f point = aabb.getPoint(idx);
|
||||
if (CollisionUtil::RayTriangleIntersection_Double(point, dir, surf.GetVerts(), d))
|
||||
{
|
||||
point = float(d) * dir + point;
|
||||
normal = surf.GetNormal();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::MovingAABoxCollisionCheck_TriVertexBox(const zeus::CVector3f& vert, const zeus::CAABox& aabb,
|
||||
const zeus::CVector3f& dir, double& dOut,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point)
|
||||
{
|
||||
zeus::CMRay ray(vert, -dir, dOut);
|
||||
zeus::CVector3f norm;
|
||||
double d;
|
||||
if (CollisionUtil::RayAABoxIntersection_Double(ray, aabb, norm, d) == 2)
|
||||
{
|
||||
d *= dOut;
|
||||
if (d < dOut)
|
||||
{
|
||||
normal = -norm;
|
||||
dOut = d;
|
||||
point = vert;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::MovingAABoxCollisionCheck_Edge(const zeus::CVector3f& ev0, const zeus::CVector3f& ev1,
|
||||
const rstl::reserved_vector<SBoxEdge, 12>& edges,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
for (const SBoxEdge& edge : edges)
|
||||
{
|
||||
zeus::CVector3d ev0d = ev0;
|
||||
zeus::CVector3d ev1d = ev1;
|
||||
if ((edge.x70_coDir.dot(ev0d) >= edge.x88_dirCoDirDot) !=
|
||||
(edge.x70_coDir.dot(ev1d) >= edge.x88_dirCoDirDot))
|
||||
{
|
||||
zeus::CVector3d delta = ev0d - ev1d;
|
||||
zeus::CVector3d cross0 = edge.x58_start.cross(delta);
|
||||
if (cross0.magSquared() > DBL_EPSILON)
|
||||
{
|
||||
zeus::CVector3d cross0Norm = cross0.asNormalized();
|
||||
if (cross0Norm.dot(dir) >= 0.0)
|
||||
{
|
||||
ev1d = ev0;
|
||||
ev0d = ev1;
|
||||
delta = ev0d - ev1d;
|
||||
cross0Norm = edge.x58_start.cross(delta).asNormalized();
|
||||
}
|
||||
|
||||
zeus::CVector3d clipped = ev0d + -(ev0d.dot(edge.x70_coDir) - edge.x88_dirCoDirDot) /
|
||||
delta.dot(edge.x70_coDir) * delta;
|
||||
int maxCompIdx = (std::fabs(edge.x70_coDir.x) > std::fabs(edge.x70_coDir.y)) ? 0 : 1;
|
||||
if (std::fabs(edge.x70_coDir[maxCompIdx]) < std::fabs(edge.x70_coDir.z))
|
||||
maxCompIdx = 2;
|
||||
|
||||
int ci0, ci1;
|
||||
switch (maxCompIdx)
|
||||
{
|
||||
case 0:
|
||||
ci0 = 1;
|
||||
ci1 = 2;
|
||||
break;
|
||||
case 1:
|
||||
ci0 = 0;
|
||||
ci1 = 2;
|
||||
break;
|
||||
default:
|
||||
ci0 = 0;
|
||||
ci1 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
double mag = edge.x58_start[ci0] * (clipped[ci1] - edge.x28_dir[ci1]) -
|
||||
edge.x58_start[ci1] * (clipped[ci0] - edge.x28_dir[ci0]) /
|
||||
edge.x58_start[ci0] * dir[ci1] - edge.x58_start[ci1] * dir[ci0];
|
||||
if (mag > 0.0 && mag < d)
|
||||
{
|
||||
zeus::CVector3d clippedMag = clipped - mag * zeus::CVector3d(dir);
|
||||
if ((edge.x28_dir.x - clippedMag).dot(edge.x40_end.x - clippedMag) < 0.0)
|
||||
{
|
||||
normal = cross0Norm.asCVector3f();
|
||||
point = clipped.asCVector3f();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
const zeus::CVector3f& vec, float mag, CCollisionInfo& infoOut,
|
||||
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
|
||||
double& dOut)
|
||||
{
|
||||
return false;
|
||||
bool ret = false;
|
||||
ResetInternalCounters();
|
||||
dOut = mag;
|
||||
|
||||
CMovingAABoxComponents components(aabb, dir);
|
||||
|
||||
zeus::CAABox movedAABB = components.x6e8_aabb;
|
||||
zeus::CVector3f moveVec = mag * dir;
|
||||
movedAABB.accumulateBounds(aabb.min + moveVec);
|
||||
movedAABB.accumulateBounds(aabb.max + moveVec);
|
||||
|
||||
zeus::CVector3f center = movedAABB.center();
|
||||
zeus::CVector3f extent = movedAABB.extents();
|
||||
|
||||
zeus::CVector3f normal, point;
|
||||
|
||||
for (const CAreaOctTree::Node& node : leafCache.x4_nodeCache)
|
||||
{
|
||||
if (movedAABB.intersects(node.GetBoundingBox()))
|
||||
{
|
||||
CAreaOctTree::TriListReference list = node.GetTriangleArray();
|
||||
for (int j=0 ; j<list.GetSize() ; ++j)
|
||||
{
|
||||
u16 triIdx = list.GetAt(j);
|
||||
if (g_DupPrimitiveCheckCount != g_DupTriangleList[triIdx])
|
||||
{
|
||||
g_TrianglesProcessed += 1;
|
||||
g_DupTriangleList[triIdx] = g_DupPrimitiveCheckCount;
|
||||
CMaterialList triMat(node.GetOwner().GetTriangleMaterial(triIdx));
|
||||
if (filter.Passes(triMat))
|
||||
{
|
||||
u16 vertIndices[3];
|
||||
node.GetOwner().GetTriangleVertexIndices(triIdx, vertIndices);
|
||||
CCollisionSurface surf(node.GetOwner().GetVert(vertIndices[0]),
|
||||
node.GetOwner().GetVert(vertIndices[1]),
|
||||
node.GetOwner().GetVert(vertIndices[2]),
|
||||
triMat.GetValue());
|
||||
|
||||
if (CollisionUtil::TriBoxOverlap(center, extent,
|
||||
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
|
||||
{
|
||||
bool triRet = false;
|
||||
double d = dOut;
|
||||
if (MovingAABoxCollisionCheck_BoxVertexTri(surf, aabb, components.x6c4_vertIdxs,
|
||||
dir, d, normal, point) && d < dOut)
|
||||
{
|
||||
triRet = true;
|
||||
ret = true;
|
||||
infoOut = CCollisionInfo(point, matList, triMat, normal);
|
||||
dOut = d;
|
||||
}
|
||||
|
||||
for (int k=0 ; k<3 ; ++k)
|
||||
{
|
||||
u16 vertIdx = vertIndices[k];
|
||||
zeus::CVector3f point = node.GetOwner().GetVert(vertIdx);
|
||||
if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx])
|
||||
{
|
||||
g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount;
|
||||
if (movedAABB.pointInside(point))
|
||||
{
|
||||
d = dOut;
|
||||
if (MovingAABoxCollisionCheck_TriVertexBox(point, aabb, dir, d,
|
||||
normal, point) && d < dOut)
|
||||
{
|
||||
CMaterialList vertMat(node.GetOwner().GetVertMaterial(vertIdx));
|
||||
triRet = true;
|
||||
ret = true;
|
||||
infoOut = CCollisionInfo(point, matList, vertMat, normal);
|
||||
dOut = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx);
|
||||
for (int k=0 ; k<3 ; ++k)
|
||||
{
|
||||
u16 edgeIdx = edgeIndices[k];
|
||||
if (g_DupPrimitiveCheckCount != g_DupEdgeList[edgeIdx])
|
||||
{
|
||||
g_DupEdgeList[edgeIdx] = g_DupPrimitiveCheckCount;
|
||||
CMaterialList edgeMat(node.GetOwner().GetEdgeMaterial(edgeIdx));
|
||||
if (!edgeMat.HasMaterial(EMaterialTypes::TwentyFour))
|
||||
{
|
||||
d = dOut;
|
||||
const CCollisionEdge& edge = node.GetOwner().GetEdge(edgeIdx);
|
||||
if (MovingAABoxCollisionCheck_Edge(node.GetOwner().GetVert(edge.GetVertIndex1()),
|
||||
node.GetOwner().GetVert(edge.GetVertIndex2()),
|
||||
components.x0_edges, dir, d, normal, point) &&
|
||||
d < dOut)
|
||||
{
|
||||
triRet = true;
|
||||
ret = true;
|
||||
infoOut = CCollisionInfo(point, matList, edgeMat, normal);
|
||||
dOut = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (triRet)
|
||||
{
|
||||
moveVec = float(dOut) * dir;
|
||||
movedAABB = components.x6e8_aabb;
|
||||
movedAABB.accumulateBounds(aabb.min + moveVec);
|
||||
movedAABB.accumulateBounds(aabb.max + moveVec);
|
||||
center = movedAABB.center();
|
||||
extent = movedAABB.extents();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx);
|
||||
g_DupEdgeList[edgeIndices[0]] = g_DupPrimitiveCheckCount;
|
||||
g_DupEdgeList[edgeIndices[1]] = g_DupPrimitiveCheckCount;
|
||||
g_DupEdgeList[edgeIndices[2]] = g_DupPrimitiveCheckCount;
|
||||
g_DupVertexList[vertIndices[0]] = g_DupPrimitiveCheckCount;
|
||||
g_DupVertexList[vertIndices[1]] = g_DupPrimitiveCheckCount;
|
||||
g_DupVertexList[vertIndices[2]] = g_DupPrimitiveCheckCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const zeus::CSphere& sphere,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
const zeus::CVector3f& vec, float mag, CCollisionInfo& infoOut,
|
||||
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
|
||||
double& dOut)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void CMetroidAreaCollider::ResetInternalCounters()
|
||||
{
|
||||
g_CalledClip = 0;
|
||||
g_RejectedByClip = 0;
|
||||
g_TrianglesProcessed = 0;
|
||||
g_DupTrianglesProcessed = 0;
|
||||
if (g_DupPrimitiveCheckCount == -1)
|
||||
{
|
||||
memset(g_DupVertexList, 0, 0x5000);
|
||||
memset(g_DupEdgeList, 0, 0xC000);
|
||||
memset(g_DupTriangleList, 0, 0x8000);
|
||||
g_DupPrimitiveCheckCount += 1;
|
||||
}
|
||||
g_DupPrimitiveCheckCount += 1;
|
||||
}
|
||||
|
||||
void CAreaCollisionCache::ClearCache()
|
||||
{
|
||||
x18_leafCaches.clear();
|
||||
|
|
|
@ -11,6 +11,21 @@ class CCollisionInfoList;
|
|||
class CCollisionInfo;
|
||||
class CMaterialList;
|
||||
|
||||
class CAABoxAreaCache
|
||||
{
|
||||
friend class CMetroidAreaCollider;
|
||||
const zeus::CAABox& x0_aabb;
|
||||
const zeus::CPlane* x4_planes;
|
||||
const CMaterialFilter& x8_filter;
|
||||
const CMaterialList& xc_material;
|
||||
CCollisionInfoList& x10_collisionList;
|
||||
zeus::CVector3f x14_center;
|
||||
zeus::CVector3f x20_halfExtent;
|
||||
public:
|
||||
CAABoxAreaCache(const zeus::CAABox& aabb, const zeus::CPlane* pl, const CMaterialFilter& filter,
|
||||
const CMaterialList& material, CCollisionInfoList& collisionList);
|
||||
};
|
||||
|
||||
class CBooleanAABoxAreaCache
|
||||
{
|
||||
friend class CMetroidAreaCollider;
|
||||
|
@ -22,14 +37,56 @@ public:
|
|||
CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter);
|
||||
};
|
||||
|
||||
struct SBoxEdge
|
||||
{
|
||||
zeus::CLineSeg x0_seg;
|
||||
zeus::CVector3d x28_dir;
|
||||
zeus::CVector3d x40_end;
|
||||
zeus::CVector3d x58_start;
|
||||
zeus::CVector3d x70_coDir;
|
||||
double x88_dirCoDirDot;
|
||||
SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir);
|
||||
};
|
||||
|
||||
class CMovingAABoxComponents
|
||||
{
|
||||
friend class CMetroidAreaCollider;
|
||||
rstl::reserved_vector<SBoxEdge, 12> x0_edges;
|
||||
rstl::reserved_vector<u32, 8> x6c4_vertIdxs;
|
||||
zeus::CAABox x6e8_aabb;
|
||||
public:
|
||||
CMovingAABoxComponents(const zeus::CAABox& aabb, const zeus::CVector3f& dir);
|
||||
};
|
||||
|
||||
class CMetroidAreaCollider
|
||||
{
|
||||
static u32 g_CalledClip;
|
||||
static u32 g_RejectedByClip;
|
||||
static u32 g_TrianglesProcessed;
|
||||
static u32 g_DupTrianglesProcessed;
|
||||
static s16 g_DupPrimitiveCheckCount;
|
||||
static u16 g_DupVertexList[0x5000];
|
||||
static u16 g_DupEdgeList[0xC000];
|
||||
static u16 g_DupTriangleList[0x4000];
|
||||
static bool AABoxCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node,
|
||||
const CBooleanAABoxAreaCache& cache);
|
||||
static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node,
|
||||
const CAABoxAreaCache& cache);
|
||||
static bool MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb,
|
||||
const rstl::reserved_vector<u32, 8>& vertIndices,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point);
|
||||
static bool MovingAABoxCollisionCheck_TriVertexBox(const zeus::CVector3f& vert, const zeus::CAABox& aabb,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point);
|
||||
static bool MovingAABoxCollisionCheck_Edge(const zeus::CVector3f& ev0, const zeus::CVector3f& ev1,
|
||||
const rstl::reserved_vector<SBoxEdge, 12>& edges,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
zeus::CVector3f& normal, zeus::CVector3f& point);
|
||||
public:
|
||||
class COctreeLeafCache
|
||||
{
|
||||
friend class CMetroidAreaCollider;
|
||||
const CAreaOctTree& x0_octTree;
|
||||
rstl::reserved_vector<CAreaOctTree::Node, 64> x4_nodeCache;
|
||||
bool x908_24_overflow : 1;
|
||||
|
@ -41,6 +98,8 @@ public:
|
|||
};
|
||||
static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb,
|
||||
CMetroidAreaCollider::COctreeLeafCache& cache);
|
||||
static bool ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts,
|
||||
zeus::CAABox& aabb);
|
||||
static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter);
|
||||
static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
|
||||
|
@ -64,13 +123,14 @@ public:
|
|||
const CMaterialFilter& filter, CCollisionInfoList& list);
|
||||
static bool MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
const zeus::CVector3f& vec, float mag, CCollisionInfo& infoOut,
|
||||
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
|
||||
double& dOut);
|
||||
static bool MovingSphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const zeus::CSphere& sphere,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
const zeus::CVector3f& vec, float mag, CCollisionInfo& infoOut,
|
||||
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
|
||||
double& dOut);
|
||||
static void ResetInternalCounters();
|
||||
};
|
||||
|
||||
class CAreaCollisionCache
|
||||
|
|
|
@ -9,15 +9,207 @@ namespace CollisionUtil
|
|||
|
||||
bool LineIntersectsOBBox(const zeus::COBBox& obb, const zeus::CMRay& ray, float& d)
|
||||
{
|
||||
const zeus::CVector3f transXf = obb.transform.toMatrix4f().vec[0].toVec3f();
|
||||
zeus::CVector3f norm;
|
||||
return RayAABoxIntersection(ray.getInvUnscaledTransformRay(obb.transform), {-obb.extents, obb.extents},
|
||||
transXf, d);
|
||||
norm, d);
|
||||
}
|
||||
|
||||
u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& box, const zeus::CVector3f&, float& d)
|
||||
u32 RayAABoxIntersection(const zeus::CMRay& ray, const zeus::CAABox& aabb,
|
||||
zeus::CVector3f& norm, float& d)
|
||||
{
|
||||
int sign[] = {2, 2, 2};
|
||||
bool bad = true;
|
||||
zeus::CVector3f rayStart = ray.start;
|
||||
zeus::CVector3f rayDelta = ray.delta;
|
||||
zeus::CVector3f aabbMin = aabb.min;
|
||||
zeus::CVector3f aabbMax = aabb.max;
|
||||
|
||||
return 0;
|
||||
zeus::CVector3f vec0 = {-1.f, -1.f, -1.f};
|
||||
zeus::CVector3f vec1;
|
||||
|
||||
if (rayDelta.x != 0.f && rayDelta.y != 0.f && rayDelta.z != 0.f)
|
||||
{
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (rayStart[i] < aabbMin[i])
|
||||
{
|
||||
sign[i] = 1;
|
||||
bad = false;
|
||||
vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
else if (rayStart[i] > aabbMax[i])
|
||||
{
|
||||
sign[i] = 0;
|
||||
bad = false;
|
||||
vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (bad)
|
||||
{
|
||||
d = 0.f;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zeus::CVector3f end;
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (rayStart[i] < aabbMin[i])
|
||||
{
|
||||
sign[i] = 1;
|
||||
bad = false;
|
||||
end[i] = aabbMin[i];
|
||||
}
|
||||
else if (rayStart[i] > aabbMax[i])
|
||||
{
|
||||
sign[i] = 0;
|
||||
bad = false;
|
||||
end[i] = aabbMax[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (bad)
|
||||
{
|
||||
d = 0.f;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
if (sign[i] != 2 && rayDelta[i] != 0.f)
|
||||
vec0[i] = (end[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
|
||||
float maxComp = vec0.x;
|
||||
int maxCompIdx = 0;
|
||||
if (maxComp < vec0.y)
|
||||
{
|
||||
maxComp = vec0.y;
|
||||
maxCompIdx = 1;
|
||||
}
|
||||
if (maxComp < vec0.z)
|
||||
{
|
||||
maxComp = vec0.z;
|
||||
maxCompIdx = 2;
|
||||
}
|
||||
|
||||
if (maxComp < 0.f || maxComp > 1.f)
|
||||
return 0;
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (maxCompIdx != i)
|
||||
{
|
||||
vec1[i] = maxComp * rayDelta[i] + rayStart[i];
|
||||
if (vec1[i] > aabbMax[i])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
d = maxComp;
|
||||
norm = zeus::CVector3f::skZero;
|
||||
norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.f : 1.f;
|
||||
return 2;
|
||||
}
|
||||
|
||||
u32 RayAABoxIntersection_Double(const zeus::CMRay& ray, const zeus::CAABox& aabb,
|
||||
zeus::CVector3f& norm, double& d)
|
||||
{
|
||||
int sign[] = {2, 2, 2};
|
||||
bool bad = true;
|
||||
zeus::CVector3d rayStart = ray.start;
|
||||
zeus::CVector3d rayDelta = ray.delta;
|
||||
zeus::CVector3d aabbMin = aabb.min;
|
||||
zeus::CVector3d aabbMax = aabb.max;
|
||||
|
||||
zeus::CVector3d vec0 = {-1.0, -1.0, -1.0};
|
||||
zeus::CVector3d vec1;
|
||||
|
||||
if (rayDelta.x != 0.0 && rayDelta.y != 0.0 && rayDelta.z != 0.0)
|
||||
{
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (rayStart[i] < aabbMin[i])
|
||||
{
|
||||
sign[i] = 1;
|
||||
bad = false;
|
||||
vec0[i] = (aabbMin[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
else if (rayStart[i] > aabbMax[i])
|
||||
{
|
||||
sign[i] = 0;
|
||||
bad = false;
|
||||
vec0[i] = (aabbMax[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (bad)
|
||||
{
|
||||
d = 0.0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
zeus::CVector3d end;
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (rayStart[i] < aabbMin[i])
|
||||
{
|
||||
sign[i] = 1;
|
||||
bad = false;
|
||||
end[i] = aabbMin[i];
|
||||
}
|
||||
else if (rayStart[i] > aabbMax[i])
|
||||
{
|
||||
sign[i] = 0;
|
||||
bad = false;
|
||||
end[i] = aabbMax[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (bad)
|
||||
{
|
||||
d = 0.0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
if (sign[i] != 2 && rayDelta[i] != 0.0)
|
||||
vec0[i] = (end[i] - rayStart[i]) / rayDelta[i];
|
||||
}
|
||||
|
||||
double maxComp = vec0.x;
|
||||
int maxCompIdx = 0;
|
||||
if (maxComp < vec0.y)
|
||||
{
|
||||
maxComp = vec0.y;
|
||||
maxCompIdx = 1;
|
||||
}
|
||||
if (maxComp < vec0.z)
|
||||
{
|
||||
maxComp = vec0.z;
|
||||
maxCompIdx = 2;
|
||||
}
|
||||
|
||||
if (maxComp < 0.0 || maxComp > 1.0)
|
||||
return 0;
|
||||
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
{
|
||||
if (maxCompIdx != i)
|
||||
{
|
||||
vec1[i] = maxComp * rayDelta[i] + rayStart[i];
|
||||
if (vec1[i] > aabbMax[i])
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
d = maxComp;
|
||||
norm = zeus::CVector3f::skZero;
|
||||
norm[maxCompIdx] = (sign[maxCompIdx] == 1) ? -1.0 : 1.0;
|
||||
return 2;
|
||||
}
|
||||
|
||||
u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f &, const zeus::CVector3f &, double &)
|
||||
|
@ -46,6 +238,30 @@ bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& p
|
|||
return false;
|
||||
}
|
||||
|
||||
bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir,
|
||||
const zeus::CVector3f* verts, double& d)
|
||||
{
|
||||
zeus::CVector3d v0tov1 = verts[1] - verts[0];
|
||||
zeus::CVector3d v0tov2 = verts[2] - verts[0];
|
||||
zeus::CVector3d cross0 = zeus::CVector3d(dir).cross(v0tov2);
|
||||
double dot0 = v0tov1.dot(cross0);
|
||||
if (dot0 < DBL_EPSILON)
|
||||
return false;
|
||||
zeus::CVector3d v0toPoint = point - verts[0];
|
||||
double dot1 = v0toPoint.dot(cross0);
|
||||
if (dot1 < 0.0 || dot1 > dot0)
|
||||
return false;
|
||||
zeus::CVector3d cross1 = v0toPoint.cross(v0tov1);
|
||||
double dot2 = cross1.dot(dir);
|
||||
if (dot2 < 0.0 || dot1 + dot2 > dot0)
|
||||
return false;
|
||||
double final = 1.0 / dot0 * cross1.dot(v0tov2);
|
||||
if (final < 0.0 || final >= d)
|
||||
return false;
|
||||
d = final;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out)
|
||||
{
|
||||
if (vec.canBeNormalized())
|
||||
|
|
|
@ -11,10 +11,13 @@ class CCollisionInfoList;
|
|||
namespace CollisionUtil
|
||||
{
|
||||
bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&);
|
||||
u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, const zeus::CVector3f&, float&);
|
||||
u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, zeus::CVector3f&, float&);
|
||||
u32 RayAABoxIntersection_Double(const zeus::CMRay&, const zeus::CAABox&, zeus::CVector3f&, double&);
|
||||
u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, double&);
|
||||
bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||
float mag, float& T, zeus::CVector3f& point);
|
||||
bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir,
|
||||
const zeus::CVector3f* verts, double& d);
|
||||
void FilterOutBackfaces(const zeus::CVector3f& vec, const CCollisionInfoList& in, CCollisionInfoList& out);
|
||||
void FilterByClosestNormal(const zeus::CVector3f& norm, const CCollisionInfoList& in, CCollisionInfoList& out);
|
||||
bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const CMaterialList& list0,
|
||||
|
|
2
specter
2
specter
|
@ -1 +1 @@
|
|||
Subproject commit 05b504a639d9b8e2d332403cec0c634c642095ea
|
||||
Subproject commit 9ebeb21ade732a0f03542c4507e1d9a3f4040b23
|
Loading…
Reference in New Issue