mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-09 21:53:40 +00:00
ifcviewer: move cullModelCpuCompute + cullModelCpuUpload into ViewportCore (#84-p)
CPU cull (frustum + contribution + LOD + opaque/transparent partition) and its companion GPU-upload step now live in ViewportCore. The HiZ occlusion test stays in VW — the pyramid + async readback machinery hasn't migrated yet — and is plumbed through a ViewportCore::HizOccludedFn callback the render path binds when HiZ is enabled-and-fresh. Null callback means "no occlusion test", which keeps the cull path host-agnostic. extractFrustumPlanes + aabbInFrustum moved up into CameraMath.h so both VW's render() (where the planes are extracted) and core's cull (where they're tested) can share without one #including the other. LOD-debug counters (lod1_dbg_count_, lod0_dbg_eligible_count_, lod0_dbg_no_lod1_count_, lod1_dbg_tris_saved_) moved to core too — they're written by cull and read/reset by VW's still-here per-frame [frame] heartbeat through reference aliases.
This commit is contained in:
@@ -82,4 +82,55 @@ inline bool tryInvert4f(const Eigen::Matrix4f& M, Eigen::Matrix4f& out) {
|
||||
return invertible;
|
||||
}
|
||||
|
||||
// Frustum-plane extraction from a column-major view-projection matrix
|
||||
// (Qt convention: element [c*4 + r] is column c, row r). Plane format
|
||||
// is (a, b, c, d) with `a*x + b*y + c*z + d >= 0` meaning the point is
|
||||
// inside. The clip-space convention is WebGPU's z ∈ [0, 1] (near is
|
||||
// `r2`, not `r3 + r2`); matches the projection matrices produced by
|
||||
// the GL-clip → WebGPU z-remap further down the pipeline.
|
||||
inline void extractFrustumPlanes(const float vp[16], float planes[6][4]) {
|
||||
auto rowVec = [&](int row, float out[4]) {
|
||||
out[0] = vp[0 * 4 + row];
|
||||
out[1] = vp[1 * 4 + row];
|
||||
out[2] = vp[2 * 4 + row];
|
||||
out[3] = vp[3 * 4 + row];
|
||||
};
|
||||
auto normalize = [](float p[4]) {
|
||||
const float len = std::sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2]);
|
||||
if (len > 0.0f) {
|
||||
const float inv = 1.0f / len;
|
||||
p[0] *= inv; p[1] *= inv; p[2] *= inv; p[3] *= inv;
|
||||
}
|
||||
};
|
||||
float r0[4], r1[4], r2[4], r3[4];
|
||||
rowVec(0, r0); rowVec(1, r1); rowVec(2, r2); rowVec(3, r3);
|
||||
// left, right, bottom, top, near (z >= 0), far
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
planes[0][i] = r3[i] + r0[i];
|
||||
planes[1][i] = r3[i] - r0[i];
|
||||
planes[2][i] = r3[i] + r1[i];
|
||||
planes[3][i] = r3[i] - r1[i];
|
||||
planes[4][i] = r2[i];
|
||||
planes[5][i] = r3[i] - r2[i];
|
||||
}
|
||||
for (int p = 0; p < 6; ++p) normalize(planes[p]);
|
||||
}
|
||||
|
||||
// Returns false iff the AABB is fully outside any one plane (early-
|
||||
// rejects trivially-invisible instances). May return true for boxes
|
||||
// that straddle the frustum — those still need to draw.
|
||||
inline bool aabbInFrustum(const float mn[3], const float mx[3],
|
||||
const float planes[6][4]) {
|
||||
for (int p = 0; p < 6; ++p) {
|
||||
const float a = planes[p][0], b = planes[p][1];
|
||||
const float c = planes[p][2], d = planes[p][3];
|
||||
// p-vertex: the AABB corner furthest along the plane normal.
|
||||
const float px = (a >= 0.0f) ? mx[0] : mn[0];
|
||||
const float py = (b >= 0.0f) ? mx[1] : mn[1];
|
||||
const float pz = (c >= 0.0f) ? mx[2] : mn[2];
|
||||
if (a * px + b * py + c * pz + d < 0.0f) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // CAMERAMATH_H
|
||||
|
||||
Reference in New Issue
Block a user