From a569a41a4f3e32c48a4ea388202b486ce6ef5ba9 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 7 Apr 2024 17:31:04 -0400 Subject: [PATCH 1/2] Fix handling of waveset bounding boxes. See CWE's `plGeometrySpans::AdjustBounds()` for the source of this change. Wavesets are flattened at runtime to the water height and are perturbed along the world Z axis. The input mesh, OTOH, conforms to the bottom of the pool. This means that if we simply spit out the bounding box of the input mesh, the resulting bounding box will be too deep in the -Z direction and not contain any of the +Z displacement needed. This means that the waveset could vanish due to culling. --- core/PRP/Geometry/plDrawableSpans.cpp | 38 ++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/core/PRP/Geometry/plDrawableSpans.cpp b/core/PRP/Geometry/plDrawableSpans.cpp index d1a1d237..6eb36dcf 100644 --- a/core/PRP/Geometry/plDrawableSpans.cpp +++ b/core/PRP/Geometry/plDrawableSpans.cpp @@ -531,14 +531,38 @@ void plDrawableSpans::calcBounds() hsBounds3Ext world; world.setFlags(hsBounds3Ext::kAxisAligned); - auto localPoints = std::make_unique(verts.size()); - auto worldPoints = std::make_unique(verts.size()); - for (size_t j = 0; j < verts.size(); j++) { - localPoints[j] = verts[j].fPos; - worldPoints[j] = fIcicles[i]->getLocalToWorld().multPoint(verts[j].fPos); + if (fIcicles[i]->getProps() & plSpan::kWaterHeight) { + constexpr float kMaxWaveHeight = 5.f; + + auto localPoints = std::make_unique(verts.size()); + for (size_t j = 0; j < verts.size(); j++) + localPoints[j] = verts[j].fPos; + loc.setFromPoints(verts.size(), localPoints.get()); + + // Water is flattened at runtime to the water height Z + // coordinate. The bounding box needs to be bloated out + // a bit, though, to account for the maximum possible geometry + // waves. + hsVector3 reboundPts[]{ loc.getMins(), loc.getMaxs() }; + for (hsVector3& pt : reboundPts) + pt = fIcicles[i]->getLocalToWorld().multPoint(pt); + reboundPts[0].Z = fIcicles[i]->getWaterHeight() - kMaxWaveHeight; + reboundPts[1].Z = fIcicles[i]->getWaterHeight() + kMaxWaveHeight; + + world.setFromPoints(std::size(reboundPts), reboundPts); + for (hsVector3& pt : reboundPts) + pt = fIcicles[i]->getWorldToLocal().multPoint(pt); + loc.setFromPoints(std::size(reboundPts), reboundPts); + } else { + auto localPoints = std::make_unique(verts.size()); + auto worldPoints = std::make_unique(verts.size()); + for (size_t j = 0; j < verts.size(); j++) { + localPoints[j] = verts[j].fPos; + worldPoints[j] = fIcicles[i]->getLocalToWorld().multPoint(verts[j].fPos); + } + loc.setFromPoints(verts.size(), localPoints.get()); + world.setFromPoints(verts.size(), worldPoints.get()); } - loc.setFromPoints(verts.size(), localPoints.get()); - world.setFromPoints(verts.size(), worldPoints.get()); loc.unalign(); fIcicles[i]->setLocalBounds(loc); From 1571eb462569fc437f0e359db3efa0d6e0a675ba Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Sun, 7 Apr 2024 17:33:31 -0400 Subject: [PATCH 2/2] D'oh! This is C++14. Don't use `std::size()`. --- core/PRP/Geometry/plDrawableSpans.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/PRP/Geometry/plDrawableSpans.cpp b/core/PRP/Geometry/plDrawableSpans.cpp index 6eb36dcf..b084c957 100644 --- a/core/PRP/Geometry/plDrawableSpans.cpp +++ b/core/PRP/Geometry/plDrawableSpans.cpp @@ -549,10 +549,10 @@ void plDrawableSpans::calcBounds() reboundPts[0].Z = fIcicles[i]->getWaterHeight() - kMaxWaveHeight; reboundPts[1].Z = fIcicles[i]->getWaterHeight() + kMaxWaveHeight; - world.setFromPoints(std::size(reboundPts), reboundPts); + world.setFromPoints(2, reboundPts); for (hsVector3& pt : reboundPts) pt = fIcicles[i]->getWorldToLocal().multPoint(pt); - loc.setFromPoints(std::size(reboundPts), reboundPts); + loc.setFromPoints(2, reboundPts); } else { auto localPoints = std::make_unique(verts.size()); auto worldPoints = std::make_unique(verts.size());