mirror of https://github.com/AxioDL/metaforce.git
Finish CMetroidAreaCollider
This commit is contained in:
parent
ec7ac212ef
commit
ff15bfbec3
|
@ -1829,7 +1829,7 @@ void CStateManager::Update(float dt)
|
|||
|
||||
if (x904_gameState != EGameState::Paused)
|
||||
{
|
||||
PreThinkEffects(dt);
|
||||
PreThinkObjects(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)
|
||||
{
|
||||
|
@ -1974,7 +1974,7 @@ void CStateManager::PreThinkEffects(float dt)
|
|||
if (TCastToPtr<CScriptEffect> effect = ent)
|
||||
effect->PreThink(dt, *this);
|
||||
|
||||
for (CEntity* ent : GetCameraObjectList())
|
||||
for (CEntity* ent : GetAllObjectList())
|
||||
if (ent && !GetCameraObjectList().GetObjectById(ent->GetUniqueId()))
|
||||
ent->PreThink(dt, *this);
|
||||
}
|
||||
|
|
|
@ -354,7 +354,7 @@ public:
|
|||
void Update(float dt);
|
||||
void UpdateGameState();
|
||||
void UpdateHintState(float dt);
|
||||
void PreThinkEffects(float dt);
|
||||
void PreThinkObjects(float dt);
|
||||
void MovePlatforms(float dt);
|
||||
void MoveDoors(float dt);
|
||||
void CrossTouchActors();
|
||||
|
|
|
@ -140,7 +140,7 @@ public:
|
|||
u32 GetNumTriangles() const { return x40_polyCount; }
|
||||
CCollisionSurface GetMasterListTriangle(u16 idx) 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);
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ 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_DupPrimitiveCheckCount = 0;
|
||||
u16 CMetroidAreaCollider::g_DupVertexList[0x5000] = {};
|
||||
u16 CMetroidAreaCollider::g_DupEdgeList[0xC000] = {};
|
||||
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())
|
||||
{}
|
||||
|
||||
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)
|
||||
: 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()),
|
||||
|
@ -202,6 +212,9 @@ bool CMetroidAreaCollider::ConvexPolyCollision(const zeus::CPlane* planes, const
|
|||
{
|
||||
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[1]);
|
||||
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,
|
||||
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;
|
||||
}
|
||||
|
||||
bool CMetroidAreaCollider::SphereCollisionCheckBoolean(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
|
||||
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,
|
||||
|
@ -467,16 +540,114 @@ bool CMetroidAreaCollider::AABoxCollisionCheck(const CAreaOctTree& octTree, cons
|
|||
|
||||
bool CMetroidAreaCollider::SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
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,
|
||||
const zeus::CSphere& sphere, const CMaterialList& matList,
|
||||
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,
|
||||
|
@ -730,7 +901,185 @@ bool CMetroidAreaCollider::MovingSphereCollisionCheck_Cached(const COctreeLeafCa
|
|||
const zeus::CVector3f& dir, float mag, CCollisionInfo& infoOut,
|
||||
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()
|
||||
|
@ -739,7 +1088,7 @@ void CMetroidAreaCollider::ResetInternalCounters()
|
|||
g_RejectedByClip = 0;
|
||||
g_TrianglesProcessed = 0;
|
||||
g_DupTrianglesProcessed = 0;
|
||||
if (g_DupPrimitiveCheckCount == -1)
|
||||
if (g_DupPrimitiveCheckCount == 0xffff)
|
||||
{
|
||||
memset(g_DupVertexList, 0, 0x5000);
|
||||
memset(g_DupEdgeList, 0, 0xC000);
|
||||
|
|
|
@ -37,6 +37,30 @@ public:
|
|||
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
|
||||
{
|
||||
zeus::CLineSeg x0_seg;
|
||||
|
@ -64,7 +88,7 @@ class CMetroidAreaCollider
|
|||
static u32 g_RejectedByClip;
|
||||
static u32 g_TrianglesProcessed;
|
||||
static u32 g_DupTrianglesProcessed;
|
||||
static s16 g_DupPrimitiveCheckCount;
|
||||
static u16 g_DupPrimitiveCheckCount;
|
||||
static u16 g_DupVertexList[0x5000];
|
||||
static u16 g_DupEdgeList[0xC000];
|
||||
static u16 g_DupTriangleList[0x4000];
|
||||
|
@ -72,6 +96,12 @@ class CMetroidAreaCollider
|
|||
const CBooleanAABoxAreaCache& cache);
|
||||
static bool AABoxCollisionCheck_Internal(const CAreaOctTree::Node& node,
|
||||
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,
|
||||
const rstl::reserved_vector<u32, 8>& vertIndices,
|
||||
const zeus::CVector3f& dir, double& d,
|
||||
|
@ -100,10 +130,12 @@ public:
|
|||
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,
|
||||
const CMaterialFilter& filter);
|
||||
|
||||
static bool SphereCollisionCheckBoolean_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const zeus::CSphere& sphere, const CMaterialFilter& filter);
|
||||
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,
|
||||
const CMaterialFilter& filter, const CMaterialList& matList,
|
||||
CCollisionInfoList& list);
|
||||
|
||||
static bool SphereCollisionCheck_Cached(const COctreeLeafCache& leafCache, const zeus::CAABox& aabb,
|
||||
const zeus::CSphere& sphere, const CMaterialList& matList,
|
||||
const CMaterialFilter& filter, CCollisionInfoList& list);
|
||||
static bool SphereCollisionCheck(const CAreaOctTree& octTree, const zeus::CAABox& aabb,
|
||||
const zeus::CSphere& sphere, const CMaterialList& matList,
|
||||
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& dir, float mag, CCollisionInfo& infoOut,
|
||||
|
|
|
@ -212,9 +212,24 @@ u32 RayAABoxIntersection_Double(const zeus::CMRay& ray, const zeus::CAABox& aabb
|
|||
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,
|
||||
|
@ -502,5 +517,264 @@ bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxh
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace CollisionUtil
|
|||
bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, 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_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,
|
||||
|
@ -27,6 +27,15 @@ bool AABoxAABoxIntersection(const zeus::CAABox& aabb0, const zeus::CAABox& aabb1
|
|||
bool TriBoxOverlap(const zeus::CVector3f& boxcenter, const zeus::CVector3f& boxhalfsize,
|
||||
const zeus::CVector3f& trivert0, const zeus::CVector3f& trivert1,
|
||||
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__
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace urde
|
|||
CGuiModel::CGuiModel(const CGuiWidgetParms& parms, CSimplePool* sp, ResId modelId, u32 lightMask, bool flag)
|
||||
: 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)
|
||||
return;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ void CGuiTextSupport::CheckAndRebuildTextBuffer()
|
|||
g_TextExecuteBuf->AddColor(EColorType::Outline, x28_outlineColor);
|
||||
|
||||
std::u16string initStr;
|
||||
if ((x5c_fontId & 0xffff) != 0xffff)
|
||||
if (x5c_fontId != 0xffffffff)
|
||||
initStr = hecl::Char16Format(L"&font=%08X;", u32(x5c_fontId));
|
||||
initStr += x0_string;
|
||||
|
||||
|
|
2
specter
2
specter
|
@ -1 +1 @@
|
|||
Subproject commit 9ebeb21ade732a0f03542c4507e1d9a3f4040b23
|
||||
Subproject commit 79b00ed327c88c80bece7f7b58e1fc8d02ab52e1
|
Loading…
Reference in New Issue