Finish CMetroidAreaCollider

This commit is contained in:
Jack Andersen 2017-06-29 15:39:34 -10:00
parent ec7ac212ef
commit ff15bfbec3
10 changed files with 685 additions and 19 deletions

View File

@ -1829,7 +1829,7 @@ void CStateManager::Update(float dt)
if (x904_gameState != EGameState::Paused) if (x904_gameState != EGameState::Paused)
{ {
PreThinkEffects(dt); PreThinkObjects(dt);
x87c_fluidPlaneManager->Update(dt); x87c_fluidPlaneManager->Update(dt);
} }
@ -1961,7 +1961,7 @@ void CStateManager::UpdateHintState(float dt)
} }
} }
void CStateManager::PreThinkEffects(float dt) void CStateManager::PreThinkObjects(float dt)
{ {
if (x84c_player->x9f4_deathTime > 0.f) if (x84c_player->x9f4_deathTime > 0.f)
{ {
@ -1974,7 +1974,7 @@ void CStateManager::PreThinkEffects(float dt)
if (TCastToPtr<CScriptEffect> effect = ent) if (TCastToPtr<CScriptEffect> effect = ent)
effect->PreThink(dt, *this); effect->PreThink(dt, *this);
for (CEntity* ent : GetCameraObjectList()) for (CEntity* ent : GetAllObjectList())
if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId())) if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId()))
ent->PreThink(dt, *this); ent->PreThink(dt, *this);
} }

View File

@ -354,7 +354,7 @@ public:
void Update(float dt); void Update(float dt);
void UpdateGameState(); void UpdateGameState();
void UpdateHintState(float dt); void UpdateHintState(float dt);
void PreThinkEffects(float dt); void PreThinkObjects(float dt);
void MovePlatforms(float dt); void MovePlatforms(float dt);
void MoveDoors(float dt); void MoveDoors(float dt);
void CrossTouchActors(); void CrossTouchActors();

View File

@ -140,7 +140,7 @@ public:
u32 GetNumTriangles() const { return x40_polyCount; } u32 GetNumTriangles() const { return x40_polyCount; }
CCollisionSurface GetMasterListTriangle(u16 idx) const; CCollisionSurface GetMasterListTriangle(u16 idx) const;
void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const; void GetTriangleVertexIndices(u16 idx, u16 indicesOut[3]) const;
const u16* GetTriangleEdgeIndices(u16 idx) const { return &x44_polyEdges[idx * 6]; } const u16* GetTriangleEdgeIndices(u16 idx) const { return &x44_polyEdges[idx * 3]; }
static std::unique_ptr<CAreaOctTree> MakeFromMemory(const u8* buf, unsigned int size); static std::unique_ptr<CAreaOctTree> MakeFromMemory(const u8* buf, unsigned int size);
}; };

View File

@ -10,7 +10,7 @@ u32 CMetroidAreaCollider::g_CalledClip = 0;
u32 CMetroidAreaCollider::g_RejectedByClip = 0; u32 CMetroidAreaCollider::g_RejectedByClip = 0;
u32 CMetroidAreaCollider::g_TrianglesProcessed = 0; u32 CMetroidAreaCollider::g_TrianglesProcessed = 0;
u32 CMetroidAreaCollider::g_DupTrianglesProcessed = 0; u32 CMetroidAreaCollider::g_DupTrianglesProcessed = 0;
s16 CMetroidAreaCollider::g_DupPrimitiveCheckCount = 0; u16 CMetroidAreaCollider::g_DupPrimitiveCheckCount = 0;
u16 CMetroidAreaCollider::g_DupVertexList[0x5000] = {}; u16 CMetroidAreaCollider::g_DupVertexList[0x5000] = {};
u16 CMetroidAreaCollider::g_DupEdgeList[0xC000] = {}; u16 CMetroidAreaCollider::g_DupEdgeList[0xC000] = {};
u16 CMetroidAreaCollider::g_DupTriangleList[0x4000] = {}; u16 CMetroidAreaCollider::g_DupTriangleList[0x4000] = {};
@ -25,6 +25,16 @@ CBooleanAABoxAreaCache::CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const C
: x0_aabb(aabb), x4_filter(filter), x8_center(aabb.center()), x14_halfExtent(aabb.extents()) : x0_aabb(aabb), x4_filter(filter), x8_center(aabb.center()), x14_halfExtent(aabb.extents())
{} {}
CSphereAreaCache::CSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter,
const CMaterialList& material, CCollisionInfoList& collisionList)
: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter), xc_material(material), x10_collisionList(collisionList)
{}
CBooleanSphereAreaCache::CBooleanSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere,
const CMaterialFilter& filter)
: x0_aabb(aabb), x4_sphere(sphere), x8_filter(filter)
{}
SBoxEdge::SBoxEdge(const zeus::CAABox& aabb, int idx, const zeus::CVector3f& dir) 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), : 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()), x58_start(x40_end - x28_dir), x70_coDir(x58_start.cross(dir).asNormalized()),
@ -202,6 +212,9 @@ bool CMetroidAreaCollider::ConvexPolyCollision(const zeus::CPlane* planes, const
{ {
rstl::reserved_vector<zeus::CVector3f, 20> vecs[2]; rstl::reserved_vector<zeus::CVector3f, 20> vecs[2];
g_CalledClip += 1;
g_RejectedByClip -= 1;
vecs[0].push_back(verts[0]); vecs[0].push_back(verts[0]);
vecs[0].push_back(verts[1]); vecs[0].push_back(verts[1]);
vecs[0].push_back(verts[2]); vecs[0].push_back(verts[2]);
@ -313,13 +326,73 @@ bool CMetroidAreaCollider::AABoxCollisionCheckBoolean(const CAreaOctTree& octTre
bool CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, bool CMetroidAreaCollider::SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter) const zeus::CSphere& sphere, const CMaterialFilter& filter)
{ {
CBooleanSphereAreaCache cache(aabb, sphere, 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.x8_filter.Passes(CMaterialList(surf.GetSurfaceFlags())))
{
if (CollisionUtil::TriSphereOverlap(cache.x4_sphere,
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
return true;
}
}
}
}
return false;
}
bool CMetroidAreaCollider::SphereCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node,
const CBooleanSphereAreaCache& cache)
{
for (int i=0 ; i<8 ; ++i)
{
CAreaOctTree::Node::ETreeType type = node.GetChildType(i);
if (type != CAreaOctTree::Node::ETreeType::Invalid)
{
CAreaOctTree::Node ch = node.GetChild(i);
if (cache.x0_aabb.intersects(ch.GetBoundingBox()))
{
if (type == CAreaOctTree::Node::ETreeType::Leaf)
{
CAreaOctTree::TriListReference list = ch.GetTriangleArray();
for (int j=0 ; j<list.GetSize() ; ++j)
{
++g_TrianglesProcessed;
CCollisionSurface surf = ch.GetOwner().GetMasterListTriangle(list.GetAt(j));
if (cache.x8_filter.Passes(CMaterialList(surf.GetSurfaceFlags())))
{
if (CollisionUtil::TriSphereOverlap(cache.x4_sphere,
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2)))
return true;
}
}
}
else
{
if (SphereCollisionCheckBoolean_Internal(ch, cache))
return true;
}
}
}
}
return false; return false;
} }
bool CMetroidAreaCollider::SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, bool CMetroidAreaCollider::SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter) const zeus::CSphere& sphere, const CMaterialFilter& filter)
{ {
return false; CAreaOctTree::Node node = octTree.GetRootNode();
CBooleanSphereAreaCache cache(aabb, sphere, filter);
return SphereCollisionCheckBoolean_Internal(node, cache);
} }
bool CMetroidAreaCollider::AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, bool CMetroidAreaCollider::AABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
@ -467,16 +540,114 @@ bool CMetroidAreaCollider::AABoxCollisionCheck(const CAreaOctTree& octTree, cons
bool CMetroidAreaCollider::SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, bool CMetroidAreaCollider::SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList, const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list) const CMaterialFilter& filter, CCollisionInfoList& clist)
{ {
return false; ResetInternalCounters();
bool ret = false;
zeus::CVector3f point, normal;
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 (filter.Passes(material))
{
if (CollisionUtil::TriSphereIntersection(sphere,
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2),
point, normal))
{
CCollisionInfo collision(point, matList, material, normal);
clist.Add(collision, false);
ret = true;
}
}
}
}
}
}
return ret;
}
bool CMetroidAreaCollider::SphereCollisionCheck_Internal(const CAreaOctTree::Node& node,
const CSphereAreaCache& cache)
{
bool ret = false;
zeus::CVector3f point, normal;
for (int i=0 ; i<8 ; ++i)
{
CAreaOctTree::Node::ETreeType chTp = node.GetChildType(i);
if (chTp != CAreaOctTree::Node::ETreeType::Invalid)
{
CAreaOctTree::Node ch = node.GetChild(i);
if (cache.x0_aabb.intersects(ch.GetBoundingBox()))
{
if (chTp == CAreaOctTree::Node::ETreeType::Leaf)
{
CAreaOctTree::TriListReference list = ch.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 = ch.GetOwner().GetMasterListTriangle(triIdx);
CMaterialList material(surf.GetSurfaceFlags());
if (cache.x8_filter.Passes(material))
{
if (CollisionUtil::TriSphereIntersection(cache.x4_sphere,
surf.GetVert(0), surf.GetVert(1), surf.GetVert(2),
point, normal))
{
CCollisionInfo collision(point, cache.xc_material, material, normal);
cache.x10_collisionList.Add(collision, false);
ret = true;
}
}
}
}
}
else
{
if (SphereCollisionCheck_Internal(ch, cache))
ret = true;
}
}
}
}
return ret;
} }
bool CMetroidAreaCollider::SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, bool CMetroidAreaCollider::SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList, const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list) const CMaterialFilter& filter, CCollisionInfoList& list)
{ {
return false; CSphereAreaCache cache(aabb, sphere, filter, matList, list);
ResetInternalCounters();
CAreaOctTree::Node node = octTree.GetRootNode();
return SphereCollisionCheck_Internal(node, cache);
} }
bool CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb, bool CMetroidAreaCollider::MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb,
@ -730,7 +901,185 @@ bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCa
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
double& dOut) double& dOut)
{ {
return false; bool ret = false;
ResetInternalCounters();
dOut = mag;
zeus::CAABox movedAABB = 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();
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)))
{
zeus::CVector3f surfNormal = surf.GetNormal();
if ((sphere.position + moveVec - surf.GetVert(0)).dot(surfNormal) <= sphere.radius)
{
bool triRet = false;
float mag = (sphere.radius - (sphere.position - surf.GetVert(0)).dot(surfNormal)) / dir.dot(surfNormal);
zeus::CVector3f intersectPoint = sphere.position + mag * dir;
bool outsideEdges[] =
{(intersectPoint - surf.GetVert(0)).dot((surf.GetVert(1) - surf.GetVert(0)).cross(surfNormal)) < 0.f,
(intersectPoint - surf.GetVert(1)).dot((surf.GetVert(2) - surf.GetVert(1)).cross(surfNormal)) < 0.f,
(intersectPoint - surf.GetVert(2)).dot((surf.GetVert(0) - surf.GetVert(2)).cross(surfNormal)) < 0.f};
if (mag >= 0.f && !outsideEdges[0] && !outsideEdges[1] && !outsideEdges[2] && mag < dOut)
{
infoOut = CCollisionInfo(intersectPoint - sphere.radius * surfNormal, matList, triMat, surfNormal);
dOut = mag;
triRet = true;
ret = true;
}
bool intersects = (sphere.position - surf.GetVert(0)).dot(surfNormal) <= sphere.radius;
bool x49c[] = {true, true, true};
const u16* edgeIndices = node.GetOwner().GetTriangleEdgeIndices(triIdx);
for (int k=0 ; k<3 ; ++k)
{
if (intersects || outsideEdges[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))
{
int nextIdx = (k + 1) % 3;
zeus::CVector3f edgeVec = surf.GetVert(nextIdx) - surf.GetVert(k);
float edgeVecMag = edgeVec.magnitude();
edgeVec *= (1.f / edgeVecMag);
float dirDotEdge = dir.dot(edgeVec);
zeus::CVector3f edgeRej = dir - dirDotEdge * edgeVec;
float edgeRejMagSq = edgeRej.magSquared();
zeus::CVector3f vertToSphere = sphere.position - surf.GetVert(k);
float vtsDotEdge = vertToSphere.dot(edgeVec);
zeus::CVector3f vtsRej = vertToSphere - vtsDotEdge * edgeVec;
if (edgeRejMagSq > 0.f)
{
float tmp = 2.f * vtsRej.dot(edgeRej);
float tmp2 = 4.f * edgeRejMagSq *
(vtsRej.magSquared() - sphere.radius * sphere.radius) - tmp * tmp;
if (tmp2 >= 0.f)
{
float mag = 0.5f / edgeRejMagSq * (-tmp - std::sqrt(tmp2));
if (mag >= 0.f)
{
float t = mag * dirDotEdge + vtsDotEdge;
if (t >= 0.f && t <= edgeVecMag && mag < dOut)
{
zeus::CVector3f point = surf.GetVert(k) + t * edgeVec;
infoOut = CCollisionInfo(point, matList, edgeMat,
(sphere.position + mag * dir - point).normalized());
dOut = mag;
triRet = true;
ret = true;
x49c[k] = false;
x49c[nextIdx] = false;
}
else if (t < -sphere.radius && dirDotEdge <= 0.f)
{
x49c[k] = false;
}
else if (t > edgeVecMag + sphere.radius && dirDotEdge >= 0.0)
{
x49c[nextIdx] = false;
}
}
}
else
{
x49c[k] = false;
x49c[nextIdx] = false;
}
}
}
}
}
}
for (int k=0 ; k<3 ; ++k)
{
u16 vertIdx = vertIndices[k];
if (x49c[k])
{
if (g_DupPrimitiveCheckCount != g_DupVertexList[vertIdx])
{
g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount;
double d = dOut;
if (CollisionUtil::RaySphereIntersection_Double(zeus::CSphere(surf.GetVert(k), sphere.radius),
sphere.position, dir, d) && d >= 0.0)
{
infoOut = CCollisionInfo(surf.GetVert(k), matList, node.GetOwner().GetVertMaterial(vertIdx),
(sphere.position + dir * d - surf.GetVert(k)).normalized());
dOut = d;
triRet = true;
ret = true;
}
}
}
else
{
g_DupVertexList[vertIdx] = g_DupPrimitiveCheckCount;
}
}
if (triRet)
{
moveVec = float(dOut) * dir;
movedAABB = 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;
} }
void CMetroidAreaCollider::ResetInternalCounters() void CMetroidAreaCollider::ResetInternalCounters()
@ -739,7 +1088,7 @@ void CMetroidAreaCollider::ResetInternalCounters()
g_RejectedByClip = 0; g_RejectedByClip = 0;
g_TrianglesProcessed = 0; g_TrianglesProcessed = 0;
g_DupTrianglesProcessed = 0; g_DupTrianglesProcessed = 0;
if (g_DupPrimitiveCheckCount == -1) if (g_DupPrimitiveCheckCount == 0xffff)
{ {
memset(g_DupVertexList, 0, 0x5000); memset(g_DupVertexList, 0, 0x5000);
memset(g_DupEdgeList, 0, 0xC000); memset(g_DupEdgeList, 0, 0xC000);

View File

@ -37,6 +37,30 @@ public:
CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter); CBooleanAABoxAreaCache(const zeus::CAABox& aabb, const CMaterialFilter& filter);
}; };
class CSphereAreaCache
{
friend class CMetroidAreaCollider;
const zeus::CAABox& x0_aabb;
const zeus::CSphere& x4_sphere;
const CMaterialFilter& x8_filter;
const CMaterialList& xc_material;
CCollisionInfoList& x10_collisionList;
public:
CSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere, const CMaterialFilter& filter,
const CMaterialList& material, CCollisionInfoList& collisionList);
};
class CBooleanSphereAreaCache
{
friend class CMetroidAreaCollider;
const zeus::CAABox& x0_aabb;
const zeus::CSphere& x4_sphere;
const CMaterialFilter& x8_filter;
public:
CBooleanSphereAreaCache(const zeus::CAABox& aabb, const zeus::CSphere& sphere,
const CMaterialFilter& filter);
};
struct SBoxEdge struct SBoxEdge
{ {
zeus::CLineSeg x0_seg; zeus::CLineSeg x0_seg;
@ -64,7 +88,7 @@ class CMetroidAreaCollider
static u32 g_RejectedByClip; static u32 g_RejectedByClip;
static u32 g_TrianglesProcessed; static u32 g_TrianglesProcessed;
static u32 g_DupTrianglesProcessed; static u32 g_DupTrianglesProcessed;
static s16 g_DupPrimitiveCheckCount; static u16 g_DupPrimitiveCheckCount;
static u16 g_DupVertexList[0x5000]; static u16 g_DupVertexList[0x5000];
static u16 g_DupEdgeList[0xC000]; static u16 g_DupEdgeList[0xC000];
static u16 g_DupTriangleList[0x4000]; static u16 g_DupTriangleList[0x4000];
@ -72,6 +96,12 @@ class CMetroidAreaCollider
const CBooleanAABoxAreaCache& cache); const CBooleanAABoxAreaCache& cache);
static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node, static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node,
const CAABoxAreaCache& cache); const CAABoxAreaCache& cache);
static bool SphereCollisionCheckBoolean_Internal(const CAreaOctTree::Node& node,
const CBooleanSphereAreaCache& cache);
static bool SphereCollisionCheck_Internal(const CAreaOctTree::Node& node,
const CSphereAreaCache& cache);
static bool MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb, static bool MovingAABoxCollisionCheck_BoxVertexTri(const CCollisionSurface& surf, const zeus::CAABox& aabb,
const rstl::reserved_vector<u32, 8>& vertIndices, const rstl::reserved_vector<u32, 8>& vertIndices,
const zeus::CVector3f& dir, double& d, const zeus::CVector3f& dir, double& d,
@ -100,10 +130,12 @@ public:
CMetroidAreaCollider::COctreeLeafCache& cache); CMetroidAreaCollider::COctreeLeafCache& cache);
static bool ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts, static bool ConvexPolyCollision(const zeus::CPlane* planes, const zeus::CVector3f* verts,
zeus::CAABox& aabb); zeus::CAABox& aabb);
static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, static bool AABoxCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter); const CMaterialFilter& filter);
static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, static bool AABoxCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter); const CMaterialFilter& filter);
static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialFilter& filter); const zeus::CSphere& sphere, const CMaterialFilter& filter);
static bool SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb, static bool SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
@ -115,12 +147,14 @@ public:
static bool AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, static bool AABoxCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList, const CMaterialFilter& filter, const CMaterialList& matList,
CCollisionInfoList& list); CCollisionInfoList& list);
static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList, const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list); const CMaterialFilter& filter, CCollisionInfoList& list);
static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb, static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
const zeus::CSphere& sphere, const CMaterialList& matList, const zeus::CSphere& sphere, const CMaterialList& matList,
const CMaterialFilter& filter, CCollisionInfoList& list); const CMaterialFilter& filter, CCollisionInfoList& list);
static bool MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb, static bool MovingAABoxCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
const CMaterialFilter& filter, const CMaterialList& matList, const CMaterialFilter& filter, const CMaterialList& matList,
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut, const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,

View File

@ -212,9 +212,24 @@ u32 RayAABoxIntersection_Double(const zeus::CMRay& ray, const zeus::CAABox& aabb
return 2; return 2;
} }
u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f &, const zeus::CVector3f &, double &) bool RaySphereIntersection_Double(const zeus::CSphere& sphere, const zeus::CVector3f& pos,
const zeus::CVector3f& dir, double& T)
{ {
return 0; zeus::CVector3d sPosD = sphere.position;
zeus::CVector3d posD = pos;
zeus::CVector3d sphereToPos = posD - sPosD;
double f30 = sphereToPos.dot(zeus::CVector3d(dir)) * 2.0;
double f1 = f30 * f30 - 4.0 * (sphereToPos.magSquared() - sphere.radius * sphere.radius);
if (f1 >= 0.0)
{
double intersectT = 0.5 * (-f30 - std::sqrt(f1));
if (T == 0 || intersectT < T)
{
T = intersectT;
return true;
}
}
return false;
} }
bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
@ -502,5 +517,264 @@ bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxh
return true; /* box and triangle overlaps */ return true; /* box and triangle overlaps */
} }
double TriPointSqrDist(const zeus::CVector3f& point,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2, float* baryX, float* baryY)
{
zeus::CVector3d A = trivert0 - point;
zeus::CVector3d B = trivert1 - trivert0;
zeus::CVector3d C = trivert2 - trivert0;
double bMag = B.magSquared();
double cMag = C.magSquared();
double bDotC = B.dot(C);
double aDotB = A.dot(B);
double aDotC = A.dot(C);
double ret = A.magSquared();
double rej = std::fabs(bMag * cMag - bDotC * bDotC);
double retB = bDotC * aDotC - cMag * aDotB;
double retA = bDotC * aDotB - bMag * aDotC;
if (retB + retA <= rej)
{
if (retB < 0.0)
{
if (retA < 0.0)
{
if (aDotB < 0.0)
{
retA = 0.0;
if (-aDotB >= bMag)
{
retB = 1.0;
ret += 2.0 * aDotB + bMag;
}
else
{
retB = -aDotB / bMag;
ret += aDotB * retB;
}
}
else
{
retB = 0.0;
if (aDotC >= 0.0)
{
retA = 0.0;
}
else if (-aDotC >= cMag)
{
retA = 1.0;
ret += 2.0 * aDotC + cMag;
}
else
{
retA = -aDotC / cMag;
ret += aDotC * retA;
}
}
}
else
{
retB = 0.0;
if (aDotC >= 0.0)
{
retA = 0.0;
}
else if (-aDotC >= cMag)
{
retA = 1.0;
ret += 2.0 * aDotC + cMag;
}
else
{
retA = -aDotC / cMag;
ret += aDotC * retA;
}
}
}
else if (retA < 0.0)
{
retA = 0.0;
if (aDotB >= 0.0)
{
retB = 0.0;
}
else if (-aDotB >= bMag)
{
retB = 1.0;
ret += 2.0 * aDotB + bMag;
}
else
{
retB = -aDotB / bMag;
ret += aDotB * retB;
}
}
else
{
float f3 = 1.0 / rej;
retA *= f3;
retB *= f3;
ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) +
retA * (2.0 * aDotC + (bDotC * retB + cMag * retA));
}
}
else if (retB < 0.0)
{
retB = bDotC + aDotB;
retA = cMag + aDotC;
if (retA > retB)
{
retA -= retB;
retB = bMag - 2.0 * bDotC;
retB += cMag;
if (retA >= retB)
{
retB = 1.0;
retA = 0.0;
ret += 2.0 * aDotB + bMag;
}
else
{
retB = retA / retB;
retA = 1.0 - retB;
ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) +
retA * (2.0 * aDotC + (bDotC * retB + cMag * retA));
}
}
else
{
retB = 0.0;
if (retA <= 0.0)
{
retA = 1.0;
ret += 2.0 * aDotC + cMag;
}
else if (aDotC >= 0.0)
{
retA = 0.0;
}
else
{
retA = -aDotC / cMag;
ret += aDotC * retA;
}
}
}
else
{
if (retA < 0.0)
{
retB = bDotC + aDotC;
retA = bMag + aDotB;
if (retA > retB)
{
retA -= retB;
retB = bMag - 2.0 * bDotC;
retB += cMag;
if (retA >= retB)
{
retA = 1.0;
retB = 0.0;
ret += 2.0 * aDotC + cMag;
}
else
{
retA /= retB;
retB = 1.0 - retA;
ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) +
retA * (2.0 * aDotC + (bDotC * retB + cMag * retA));
}
}
else
{
retA = 0.0;
if (retA <= 0.0)
{
retB = 1.0;
ret += 2.0 * aDotB + bMag;
}
else if (aDotB >= 0.0)
{
retB = 0.0;
}
else
{
retB = -aDotB / bMag;
ret += aDotB * retB;
}
}
}
else
{
retB = cMag + aDotC;
retB -= bDotC;
retA = retB - aDotB;
if (retA <= 0.0)
{
retB = 0.0;
retA = 1.0;
ret += 2.0 * aDotC + cMag;
}
else
{
retB = bMag - 2.0 * bDotC;
retB += cMag;
if (retA >= retB)
{
retB = 1.0;
retA = 0.0;
ret += 2.0 * aDotB + bMag;
}
else
{
retB = retA / retB;
retA = 1.0 - retB;
ret += retB * (2.0 * aDotB + (bMag * retB + bDotC * retA)) +
retA * (2.0 * aDotC + (bDotC * retB + cMag * retA));
}
}
}
}
if (baryX)
*baryX = retA;
if (baryY)
*baryY = retB;
return ret;
}
bool TriSphereOverlap(const zeus::CSphere& sphere,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2)
{
return TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, nullptr, nullptr) <=
sphere.radius * sphere.radius;
}
bool TriSphereIntersection(const zeus::CSphere& sphere,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2, zeus::CVector3f& point, zeus::CVector3f& normal)
{
float baryX, baryY;
if (TriPointSqrDist(sphere.position, trivert0, trivert1, trivert2, &baryX, &baryY) >
sphere.radius * sphere.radius)
return false;
zeus::CVector3f barys(baryX, baryY, 1.f - (baryX + baryY));
point = zeus::baryToWorld(trivert2, trivert1, trivert0, barys);
if (baryX == 0.f || baryX == 1.f || baryY == 0.f || baryY == 1.f ||
barys.z == 0.f || barys.z == 1.f)
normal = -sphere.getSurfaceNormal(point);
else
normal = (trivert1 - trivert0).cross(trivert2 - trivert0).normalized();
return true;
}
} }
} }

View File

@ -13,7 +13,7 @@ namespace CollisionUtil
bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&); bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&);
u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, 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 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_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, bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
float mag, float& T, zeus::CVector3f& point); float mag, float& T, zeus::CVector3f& point);
bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir, bool RayTriangleIntersection_Double(const zeus::CVector3f& point, const zeus::CVector3f& dir,
@ -27,6 +27,15 @@ bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1
bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxhalfsize, bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxhalfsize,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1, const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2); const zeus::CVector3f& trivert2);
double TriPointSqrDist(const zeus::CVector3f& point,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2, float* baryX, float* baryY);
bool TriSphereOverlap(const zeus::CSphere& sphere,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2);
bool TriSphereIntersection(const zeus::CSphere& sphere,
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
const zeus::CVector3f& trivert2, zeus::CVector3f& point, zeus::CVector3f& normal);
} }
} }
#endif // __URDE_COLLISIONUTIL_HPP__ #endif // __URDE_COLLISIONUTIL_HPP__

View File

@ -11,7 +11,7 @@ namespace urde
CGuiModel::CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, ResId modelId, u32 lightMask, bool flag) CGuiModel::CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, ResId modelId, u32 lightMask, bool flag)
: CGuiWidget(parms), x108_modelId(modelId), x10c_lightMask(lightMask) : CGuiWidget(parms), x108_modelId(modelId), x10c_lightMask(lightMask)
{ {
if (!flag || (modelId & 0xffff) == 0xffff || if (!flag || modelId == 0xffffffff ||
parms.x0_frame->GetGuiSys().GetUsageMode() == CGuiSys::EUsageMode::Two) parms.x0_frame->GetGuiSys().GetUsageMode() == CGuiSys::EUsageMode::Two)
return; return;

View File

@ -144,7 +144,7 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer()
g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor); g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor);
std::u16string initStr; std::u16string initStr;
if ((x5c_fontId & 0xffff) != 0xffff) if (x5c_fontId != 0xffffffff)
initStr = hecl::Char16Format(L"&font=%08X;", u32(x5c_fontId)); initStr = hecl::Char16Format(L"&font=%08X;", u32(x5c_fontId));
initStr += x0_string; initStr += x0_string;

@ -1 +1 @@
Subproject commit 9ebeb21ade732a0f03542c4507e1d9a3f4040b23 Subproject commit 79b00ed327c88c80bece7f7b58e1fc8d02ab52e1