🔍 Module Scanned
libs/zig-math/ (engine-math module re-exports)
📝 Summary
The AABB.contains method uses inclusive <= comparisons for all axes, treating points exactly at the max boundary as contained within the AABB. When AABBs represent voxel/block regions using the common pattern AABB.init(Vec3.init(x, y, z), Vec3.init(x+1, y+1, z+1)), this creates a half-open interval [min, max) in mathematical terms, but the implementation treats it as fully closed [min, max]. This can cause subtle off-by-one errors in collision detection, especially when checking if a player or entity is "on the ground" versus one block too high.
📍 Location
- File:
libs/zig-math/aabb.zig:27-31
- Function/Scope:
AABB.contains
🔴 Severity: Medium
- 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 checking if a point is within a voxel AABB, a point at the max boundary (e.g., a player's feet at y=1.0 when standing on a block at y=0..1) is incorrectly reported as inside the AABB. This can cause:
- Incorrect collision responses at block boundaries
- Entities appearing to collide with blocks they're standing adjacent to rather than on top of
- Subtle physics glitches where players can't climb single-block steps they're standing on
The same issue affects intersects which relies on comparisons that assume inclusive boundaries.
🔎 Evidence
pub fn contains(self: AABB, point: Vec3) bool {
return point.x >= self.min.x and point.x <= self.max.x and
point.y >= self.min.y and point.y <= self.max.y and
point.z >= self.z and point.z <= self.max.z;
}
The use of <= instead of < means the point at max is contained. In a typical voxel AABB like AABB.init(Vec3.init(0,0,0), Vec3.init(1,1,1)) representing a block at origin, a point at (1, 1, 1) would be reported as contained even though it's at the exclusive upper boundary of the block volume.
🛠️ Proposed Fix
For collision-focused AABBs representing voxel volumes, the contains method should use exclusive upper bounds (< instead of <=) to properly implement the half-open interval semantics expected in voxel engines:
pub fn contains(self: AABB, point: Vec3) bool {
return point.x >= self.min.x and point.x < self.max.x and
point.y >= self.min.y and point.y < self.max.y and
point.z >= self.min.z and point.z < self.max.z;
}
Note: This change should be verified against all callers to ensure the new semantics are correct for their use case. Some callers (like UI rect containment) may intentionally want inclusive boundaries.
An alternative is to add a containsExclusive variant and deprecate the current contains behavior, or add a parameter to control boundary behavior.
✅ Acceptance Criteria
📚 References
🔍 Module Scanned
libs/zig-math/(engine-math module re-exports)📝 Summary
The
AABB.containsmethod uses inclusive<=comparisons for all axes, treating points exactly at the max boundary as contained within the AABB. When AABBs represent voxel/block regions using the common patternAABB.init(Vec3.init(x, y, z), Vec3.init(x+1, y+1, z+1)), this creates a half-open interval [min, max) in mathematical terms, but the implementation treats it as fully closed [min, max]. This can cause subtle off-by-one errors in collision detection, especially when checking if a player or entity is "on the ground" versus one block too high.📍 Location
libs/zig-math/aabb.zig:27-31AABB.contains🔴 Severity: Medium
💥 Impact
When checking if a point is within a voxel AABB, a point at the max boundary (e.g., a player's feet at y=1.0 when standing on a block at y=0..1) is incorrectly reported as inside the AABB. This can cause:
The same issue affects
intersectswhich relies on comparisons that assume inclusive boundaries.🔎 Evidence
The use of
<=instead of<means the point atmaxis contained. In a typical voxel AABB likeAABB.init(Vec3.init(0,0,0), Vec3.init(1,1,1))representing a block at origin, a point at(1, 1, 1)would be reported as contained even though it's at the exclusive upper boundary of the block volume.🛠️ Proposed Fix
For collision-focused AABBs representing voxel volumes, the
containsmethod should use exclusive upper bounds (<instead of<=) to properly implement the half-open interval semantics expected in voxel engines:Note: This change should be verified against all callers to ensure the new semantics are correct for their use case. Some callers (like UI rect containment) may intentionally want inclusive boundaries.
An alternative is to add a
containsExclusivevariant and deprecate the currentcontainsbehavior, or add a parameter to control boundary behavior.✅ Acceptance Criteria
isOnGroundfunction in collision.zig correctly detects ground at block boundaries📚 References