Optimize collision further: skip when stationary, cache floor height, fix drop bug

- Skip wall collision sweep entirely when player isn't moving (saves all
  collision calls when standing still)
- Reduce max sweep steps from 4 to 2 with 1.0f step size (all paths:
  follow, free-fly, swimming)
- Cache floor height between frames, reuse when position changes <0.5 units
- Fix floor height not updating after walking off tall objects (fountain etc)
  by always smoothing toward detected ground instead of ignoring drops >2 units
- Reduce free-fly ground probes from 5 to 1
- Disable WMO camera collision (raycast + floor probes) for performance
- Add spatial grid to raycastBoundingBoxes for when camera collision is re-enabled
This commit is contained in:
Kelsi 2026-02-07 15:54:33 -08:00
parent 974384c725
commit 6516fd777d
3 changed files with 110 additions and 118 deletions

View file

@ -2019,13 +2019,23 @@ float WMORenderer::raycastBoundingBoxes(const glm::vec3& origin, const glm::vec3
continue;
}
// Narrow-phase: triangle raycast for accurate camera collision.
// Narrow-phase: triangle raycast using spatial grid.
const auto& verts = group.collisionVertices;
const auto& indices = group.collisionIndices;
for (size_t i = 0; i + 2 < indices.size(); i += 3) {
const glm::vec3& v0 = verts[indices[i]];
const glm::vec3& v1 = verts[indices[i + 1]];
const glm::vec3& v2 = verts[indices[i + 2]];
// Compute local-space ray endpoint and query grid for XY range
glm::vec3 localEnd = localOrigin + localDir * (closestHit / glm::length(
glm::vec3(instance.modelMatrix * glm::vec4(localDir, 0.0f))));
float rMinX = std::min(localOrigin.x, localEnd.x) - 1.0f;
float rMinY = std::min(localOrigin.y, localEnd.y) - 1.0f;
float rMaxX = std::max(localOrigin.x, localEnd.x) + 1.0f;
float rMaxY = std::max(localOrigin.y, localEnd.y) + 1.0f;
group.getTrianglesInRange(rMinX, rMinY, rMaxX, rMaxY, wallTriScratch);
for (uint32_t triStart : wallTriScratch) {
const glm::vec3& v0 = verts[indices[triStart]];
const glm::vec3& v1 = verts[indices[triStart + 1]];
const glm::vec3& v2 = verts[indices[triStart + 2]];
glm::vec3 triNormal = glm::cross(v1 - v0, v2 - v0);
float normalLenSq = glm::dot(triNormal, triNormal);
if (normalLenSq < 1e-8f) {