🔍 Module Scanned
libs/zig-math/ (engine-math re-exports from this library)
📝 Summary
The intersectsChunkRelative function computes a bounding sphere for frustum culling with an incorrect center calculation. The center.y formula uses -cam_y which places the sphere near the camera position instead of at the chunk's center, causing chunks to be incorrectly culled when the camera is above the chunk bottom.
📍 Location
- File:
libs/zig-math/frustum.zig:118-135
- Function/Scope:
intersectsChunkRelative
🔴 Severity: High
- Critical: Crashes, data corruption, security vulnerabilities, GPU device loss
- High: Memory leaks, race conditions, incorrect rendering, broken features
- Medium: Performance degradation, missing error handling, suboptimal patterns
- Low: Code style, dead code, minor improvements
💥 Impact
When the camera is positioned above chunk bottom (e.g., cam_y=80 in a chunk spanning y=0 to y=256), the bounding sphere center is placed at y=48 instead of y=128. With radius=144, the sphere only covers y=-96 to y=192, missing the top portion of the chunk (y=192 to y=256). This causes chunks to be incorrectly culled, resulting in missing terrain rendering.
🔎 Evidence
pub fn intersectsChunkRelative(self: Frustum, chunk_x: i32, chunk_z: i32, cam_x: f32, cam_y: f32, cam_z: f32) bool {
const CHUNK_SIZE_X: f32 = 16.0;
const CHUNK_SIZE_Y: f32 = 256.0;
const CHUNK_SIZE_Z: f32 = 16.0;
const world_x: f32 = @as(f32, @floatFromInt(chunk_x * 16)) - cam_x;
const world_z: f32 = @as(f32, @floatFromInt(chunk_z * 16)) - cam_z;
const world_y: f32 = -cam_y; // <-- BUG: This is camera height, not chunk position
const center = Vec3.init(
world_x + CHUNK_SIZE_X * 0.5,
world_y + CHUNK_SIZE_Y * 0.5, // center.y = -cam_y + 128, should be chunk center y=128
world_z + CHUNK_SIZE_Z * 0.5,
);
const radius: f32 = CHUNK_SIZE_Y * 0.5 + CHUNK_SIZE_X; // 144, not true circumscribed radius
return self.intersectsSphere(center, radius);
}
Example with cam_y=80:
- Current: center.y = -80 + 128 = 48, sphere covers y=[-96, 192]
- Expected: center.y = 128, sphere covers y=[-16, 272]
- Chunk spans y=[0, 256]
- Top ~64 units of chunk are outside the sphere, causing incorrect culling
🛠️ Proposed Fix
The center calculation needs to account for the chunk's vertical position in world space. Since the function lacks a chunk_y parameter, the sphere should be centered at the middle of a standard chunk column (y=128):
const world_y: f32 = CHUNK_SIZE_Y * 0.5 - cam_y; // chunk center (128) minus camera offset
Alternatively, if the intent is to have the sphere follow the camera vertically while spanning the chunk column, the center should be explicitly:
const center = Vec3.init(
world_x + CHUNK_SIZE_X * 0.5,
CHUNK_SIZE_Y * 0.5 - cam_y, // Place at chunk vertical center, offset by camera
world_z + CHUNK_SIZE_Z * 0.5,
);
The radius should also be corrected to the true circumscribed radius:
const radius: f32 = std.math.sqrt(
std.math.pow(f32, CHUNK_SIZE_X * 0.5, 2) +
std.math.pow(f32, CHUNK_SIZE_Y * 0.5, 2) +
std.math.pow(f32, CHUNK_SIZE_Z * 0.5, 2)
); // ~128.25 instead of 144
✅ Acceptance Criteria
📚 References
🔍 Module Scanned
libs/zig-math/(engine-math re-exports from this library)📝 Summary
The
intersectsChunkRelativefunction computes a bounding sphere for frustum culling with an incorrect center calculation. The center.y formula uses-cam_ywhich places the sphere near the camera position instead of at the chunk's center, causing chunks to be incorrectly culled when the camera is above the chunk bottom.📍 Location
libs/zig-math/frustum.zig:118-135intersectsChunkRelative🔴 Severity: High
💥 Impact
When the camera is positioned above chunk bottom (e.g., cam_y=80 in a chunk spanning y=0 to y=256), the bounding sphere center is placed at y=48 instead of y=128. With radius=144, the sphere only covers y=-96 to y=192, missing the top portion of the chunk (y=192 to y=256). This causes chunks to be incorrectly culled, resulting in missing terrain rendering.
🔎 Evidence
Example with cam_y=80:
🛠️ Proposed Fix
The center calculation needs to account for the chunk's vertical position in world space. Since the function lacks a chunk_y parameter, the sphere should be centered at the middle of a standard chunk column (y=128):
Alternatively, if the intent is to have the sphere follow the camera vertically while spanning the chunk column, the center should be explicitly:
The radius should also be corrected to the true circumscribed radius:
✅ Acceptance Criteria
intersectsChunkRelativecorrectly culls chunks when camera is at various heights (y=0, y=80, y=200, y=256)nix develop --command zig build test📚 References
radius = sqrt((w/2)^2 + (h/2)^2 + (d/2)^2)