Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
vabold committed Jan 25, 2024
1 parent 5357037 commit c153cdf
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 81 deletions.
248 changes: 168 additions & 80 deletions source/game/field/RKGndCol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ RKGndCol::RKGndCol(const void *file) {

// TODO: This makes an assumption that m_blockData is allocated immediately after
// m_prisms=m_prismData+1
m_prismCount = ((uintptr_t)m_blockData - (uintptr_t)m_prisms) / sizeof(KCollisionPrism);
m_prismCount =
(reinterpret_cast<uintptr_t>(m_blockData) - reinterpret_cast<uintptr_t>(m_prisms + 1)) /
sizeof(KCollisionPrism);

computeBBox();
}
Expand All @@ -69,14 +71,13 @@ void RKGndCol::computeBBox() {
const KCollisionPrism prism = getPrism(i);

const EGG::Vector3f fnrm = getNrm(prism.fnrm_i);
// TODO: Why are the variables backwards?
const EGG::Vector3f enrm3 = getNrm(prism.enrm1_i);
const EGG::Vector3f enrm1 = getNrm(prism.enrm1_i);
const EGG::Vector3f enrm2 = getNrm(prism.enrm2_i);
const EGG::Vector3f enrm1 = getNrm(prism.enrm3_i);
const EGG::Vector3f enrm3 = getNrm(prism.enrm3_i);
const EGG::Vector3f vtx1 = getPos(prism.pos_i);

const EGG::Vector3f vtx3 = GetVertex(prism.height, vtx1, fnrm, enrm1, enrm3);
const EGG::Vector3f vtx2 = GetVertex(prism.height, vtx1, fnrm, enrm1, enrm2);
const EGG::Vector3f vtx3 = GetVertex(prism.height, vtx1, fnrm, enrm3, enrm1);
const EGG::Vector3f vtx2 = GetVertex(prism.height, vtx1, fnrm, enrm3, enrm2);

m_bbox.mMin = m_bbox.mMin.minimize(vtx1);
m_bbox.mMin = m_bbox.mMin.minimize(vtx2);
Expand Down Expand Up @@ -158,12 +159,9 @@ const u16 *RKGndCol::searchBlock(const EGG::Vector3f &point) {

/* 807c2410 - checkCollision */
bool RKGndCol::checkSphereCollision(float *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut) {
if (std::isfinite(m_prevPos.y)) {
; // return checkSphereMovement(distOut, fnrmOut, flagsOut);
} else {
return checkSphere(distOut, fnrmOut, flagsOut);
}
return false;
return std::isfinite(m_prevPos.y) ?
false /* checkSphereMovement(distOut, fnrmOut, flagsOut) */ :
checkSphere(distOut, fnrmOut, flagsOut);
}

/*bool RKGndCol::LAB_807c19ec(float &planeDist, f32 real_sq_dist) {
Expand Down Expand Up @@ -212,8 +210,9 @@ bool RKGndCol::scaleNormalsAndUpdatePlaneDist(f32 dot, f32 dist1, f32 dist2,
return LAB_807c19d0(planeDist, sq_dist);
}*/

bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG::Vector3f *fnrmOut,
u16 *flagsOut) {
// Returns whether or not there are still triangles to check
bool RKGndCol::checkSphereTriCollision(const KCollisionPrism &prism, f32 *distOut,
EGG::Vector3f *fnrmOut, u16 *flagsOut) {
// Responsible for updating the output params
auto out = [&](float dist) {
if (distOut) {
Expand All @@ -236,9 +235,10 @@ bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG

const EGG::Vector3f vert = m_pos - getPos(prism.pos_i);

// Edge normals point outside the triangle
const EGG::Vector3f enrm1 = getNrm(prism.enrm1_i);
f32 dist_ac = vert.ps_dot(enrm1);
if (m_radius <= dist_ac) {
f32 dist_ca = vert.ps_dot(enrm1);
if (m_radius <= dist_ca) {
return false;
}

Expand All @@ -261,17 +261,95 @@ bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG
return false;
}

auto LAB_807c19ec = [&](f32 real_sq_dist) {
// Originally part of the edge searching, but moved out for simplicity
// If these are all zero, then we're inside the triangle
if (dist_ab <= 0.0f && dist_bc <= 0.0f && dist_ca <= 0.0f) {
return out(dist_in_plane);
}

EGG::Vector3f edge_nor, other_edge_nor;
f32 edge_dist, other_edge_dist;
// NOTE (vabold): > means further, < means closer, = means same distance
if (dist_ab >= dist_ca && dist_ab > dist_bc) {
// AB is the furthest edge
edge_nor = enrm2;
edge_dist = dist_ab;
if (dist_ca >= dist_bc) {
// CA is the second furthest edge
other_edge_nor = enrm1;
other_edge_dist = dist_ca;
} else {
// BC is the second furthest edge
other_edge_nor = enrm3;
other_edge_dist = dist_bc;
}
} else if (dist_bc >= dist_ca) {
// BC is the furthest edge
edge_nor = enrm3;
edge_dist = dist_bc;
if (dist_ab >= dist_ca) {
// AB is the second furthest edge
other_edge_nor = enrm2;
other_edge_dist = dist_ab;
} else {
// CA is the second furthest edge
other_edge_nor = enrm1;
other_edge_dist = dist_ca;
}
} else {
// CA is the furthest edge
edge_nor = enrm1;
edge_dist = dist_ca;
if (dist_bc >= dist_ab) {
// BC is the second furthest edge
other_edge_nor = enrm3;
other_edge_dist = dist_bc;
} else {
// AB is the second furthest edge
other_edge_nor = enrm2;
other_edge_dist = dist_ab;
}
}

f32 cos = edge_nor.ps_dot(other_edge_nor);
f32 sq_dist;
if (cos * edge_dist > other_edge_dist) {
if (edge_dist > plane_dist) {
return false;
}

sq_dist = m_radius * m_radius - edge_dist * edge_dist;
} else {
f32 t = (cos * edge_dist - other_edge_dist) / (cos * cos - 1.0f);
f32 s = edge_dist - t * cos;
const EGG::Vector3f corner_pos = edge_nor * s + other_edge_nor * t;
f32 corner_sq_dist = corner_pos.dot();

if (corner_sq_dist > plane_dist * plane_dist) {
return false;
}

sq_dist = m_radius * m_radius - corner_sq_dist;
}

if (sq_dist < plane_dist * plane_dist || sq_dist < 0.0f) {
return false;
}

f32 dist = EGG::Mathf::sqrt(sq_dist) - plane_dist;
if (dist <= 0.0f) {
return false;
}

return out(dist);

/*auto LAB_807c19ec = [&](f32 real_sq_dist) {
u32 temp = (((0 <= real_sq_dist) << 1) << 0x1c) >> 0x1d;
if (real_sq_dist < plane_dist * plane_dist || temp == 0) {
return false;
}
f32 distToPlanePlusRadius = 0.0f;
if (real_sq_dist > 0) {
distToPlanePlusRadius = EGG::Mathf::frsqrt(real_sq_dist) * real_sq_dist;
}
distToPlanePlusRadius -= plane_dist;
f32 distToPlanePlusRadius = EGG::Mathf::sqrt(real_sq_dist) - plane_dist;
if (distToPlanePlusRadius <= 0) {
return false;
}
Expand All @@ -288,11 +366,11 @@ bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG
return LAB_807c19ec(real_sq_dist);
};
auto scaleAndCombineNormals = [&](f32 dot, f32 dist1, f32 dist2, const EGG::Vector3f &nrm1,
auto scaleAndCombineNormals = [&](f32 cos, f32 dist1, f32 dist2, const EGG::Vector3f &nrm1,
const EGG::Vector3f &nrm2) {
f32 dVar7 = (dot * dist1 - dist2) / (dot * dot - 1);
f32 fVar1 = dist1 - dVar7 * dot;
EGG::Vector3f combined = nrm1 * dVar7 + nrm2 * fVar1;
f32 t = (cos * dist1 - dist2) / (cos * cos - 1);
f32 s = dist1 - t * cos;
EGG::Vector3f combined = nrm1 * s + nrm2 * t;
return LAB_807c19d0(combined.ps_dot(combined));
};
Expand All @@ -301,38 +379,38 @@ bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG
bool bDotCheck;
auto dotAndScale = [&](const EGG::Vector3f &vec1, const EGG::Vector3f &vec2, f32 dist1,
f32 dist2) {
f32 dist2) -> bool {
f32 dot = vec1.ps_dot(vec2);
bDotCheck = dot * dist1 <= dist2;
return bDotCheck ? scaleAndCombineNormals(dot, dist1, dist2, vec1, vec2) : false;
};
f32 radius_sq = m_radius * m_radius;
EGG::Vector3f vec1, vec2;
f32 dist1, dist2;
if (dist_ac <= dist_ab) {
if (dist_ca <= dist_ab) {
if (dist_ab <= dist_bc) {
if (dist_bc <= 0) {
return out(dist_in_plane);
}
bool bRet = dotAndScale(enrm2, enrm3, dist_bc, dist_ab);
if (bDotCheck) {
return bRet;
}
}
if (dist_ab <= 0) {
return out(dist_in_plane);
}
if (dist_bc <= dist_ac) {
bool bRet = dotAndScale(enrm1, enrm2, dist_ab, dist_ac);
if (bDotCheck) {
return bRet;
}
vec1 = enrm2;
vec2 = enrm3;
dist1 = dist_bc;
dist2 = dist_ab;
} else if (dist_bc <= dist_ca) {
vec1 = enrm1;
vec2 = enrm2;
dist1 = dist_ab;
dist2 = dist_ca;
} else {
bool bRet = dotAndScale(enrm2, enrm3, dist_ab, dist_bc);
if (bDotCheck) {
return bRet;
}
vec1 = enrm2;
vec2 = enrm3;
dist1 = dist_ab;
dist2 = dist_bc;
}
bool bRet = dotAndScale(vec1, vec2, dist1, dist2);
if (bDotCheck) {
return bRet;
}
if (plane_dist < dist_ab) {
return false;
}
Expand All @@ -341,66 +419,76 @@ bool RKGndCol::checkTriCollision(const KCollisionPrism &prism, f32 *distOut, EGG
return LAB_807c19ec(real_sq_dist);
}
if (dist_ac <= dist_bc) {
if (dist_bc <= 0.0f) {
return out(dist_in_plane);
}
if (dist_ac <= dist_ab) {
bool bRet = dotAndScale(enrm2, enrm3, dist_bc, dist_ab);
if (bDotCheck) {
return bRet;
}
if (dist_ca <= dist_bc) {
bool bScale = false;
if (dist_ca <= dist_ab) {
vec1 = enrm2;
vec2 = enrm3;
dist1 = dist_bc;
dist2 = dist_ab;
} else {
bool bRet = dotAndScale(enrm3, enrm1, dist_ac, dist_bc);
if (bDotCheck) {
return bRet;
}
vec1 = enrm3;
vec2 = enrm1;
dist1 = dist_ca;
dist2 = dist_bc;
}
bool bRet = dotAndScale(vec1, vec2, dist1, dist2);
if (bDotCheck) {
return bRet;
}
if (plane_dist < dist_bc) {
return false;
}
f32 real_sq_dist = radius_sq - dist_bc * dist_bc;
return LAB_807c19ec(real_sq_dist);
}
if (dist_ac <= 0.0f) {
return out(dist_in_plane);
}
// LAB_807c170c
if (dist_ab <= dist_bc) {
f32 dot = enrm1.ps_dot(enrm3);
if (dist_bc < dot * dist_ac) {
if (dist_ac <= dist_in_plane) {
f32 real_sq_dist = radius_sq - dist_ac * dist_ac;
return LAB_807c19ec(real_sq_dist);
if (dist_bc < dot * dist_ca) {
// GOTO LAB_807c1830
if (dist_in_plane < dist_ca) {
return false;
}
return false;
} else {
return scaleAndCombineNormals(dot, dist_ac, dist_bc, enrm3, enrm1);
f32 real_sq_dist = radius_sq - dist_ca * dist_ca;
return LAB_807c19ec(real_sq_dist);
}
return scaleAndCombineNormals(dot, dist_ca, dist_bc, enrm3, enrm1);
} else {
f32 dot = enrm1.ps_dot(enrm2);
if (dist_ab < dot * dist_ac) {
if (dist_ac <= plane_dist) {
f32 real_sq_dist = radius_sq - dist_ac * dist_ac;
if (dist_ab < dot * dist_ca) {
if (dist_ca <= plane_dist) {
f32 real_sq_dist = radius_sq - dist_ca * dist_ca;
return LAB_807c19ec(real_sq_dist);
}
return false;
}
return scaleAndCombineNormals(dot, dist_ab, dist_ac, enrm1, enrm2);
}
return scaleAndCombineNormals(dot, dist_ab, dist_ca, enrm1, enrm2);
}*/
}

bool RKGndCol::checkSphere(float *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut) {
bool RKGndCol::checkSphere(f32 *distOut, EGG::Vector3f *fnrmOut, u16 *flagsOut) {
// If there's no list of triangles to check, there's no collision
if (!m_prismIter) {
return false;
}

// Check collision for all triangles, and continuously call the function until we're out
while (*++m_prismIter != 0) {
KCollisionPrism prism = getPrism(*m_prismIter);
if (checkTriCollision(prism, distOut, fnrmOut, flagsOut)) {
const KCollisionPrism prism = getPrism(*m_prismIter);
if (checkSphereTriCollision(prism, distOut, fnrmOut, flagsOut)) {
return true;
}
}

// We're out of triangles to check - another list must be prepared for subsequent calls
m_prismIter = nullptr;
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion source/game/field/RKGndCol.hh
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public:
KCollisionPrism getPrism(u16 prismIdx) const;

private:
bool checkTriCollision(const KCollisionPrism &prism, float *distOut, EGG::Vector3f *fnrmOut,
bool checkSphereTriCollision(const KCollisionPrism &prism, float *distOut, EGG::Vector3f *fnrmOut,
u16 *flagsOut);
/*bool LAB_807c19d0(float &planeDist, f32 sq_dist);
bool LAB_807c19ec(float &planeDist, f32 real_sq_dist);
Expand Down

0 comments on commit c153cdf

Please sign in to comment.