Expand grammar and add CSG parity fixtures
This commit is contained in:
parent
d754cda94e
commit
cc4bbaa635
5 changed files with 94 additions and 1 deletions
|
|
@ -265,6 +265,12 @@ Algorithm migration steps:
|
|||
|
||||
## Acceptance Tests To Add
|
||||
|
||||
- Where `vg_csg` exposes the same behavior as public RealtimeCSG/demo APIs,
|
||||
maintain exact observable parity fixtures. These should compare public
|
||||
behavior such as category vocabulary, brush plane/polygon counts, split
|
||||
counts, visible/reversed semantics, bounds early-outs, and mesh output
|
||||
invariants. Do not use vague "looks right" tests where a public seam has a
|
||||
countable contract.
|
||||
- Two overlapping additive boxes produce no duplicate coplanar surface.
|
||||
- Subtraction is implemented as `!(!A || B)` and matches direct cases.
|
||||
- Intersection is implemented as `!(!A || !B)` and matches direct cases.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ pub enum BrushOp {
|
|||
Intersect,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum PolygonCategory {
|
||||
Inside,
|
||||
Outside,
|
||||
Aligned,
|
||||
ReverseAligned,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct Aabb {
|
||||
pub min: Vec3,
|
||||
|
|
|
|||
|
|
@ -330,6 +330,35 @@ fn polygon_normal(vertices: &[Vec3]) -> Vec3 {
|
|||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn assert_box_parity(solid: &ConvexSolid, material: MaterialId) {
|
||||
assert_eq!(solid.polygons.len(), 6);
|
||||
assert_eq!(solid.clip_planes.len(), 6);
|
||||
assert!(
|
||||
solid
|
||||
.polygons
|
||||
.iter()
|
||||
.all(|polygon| polygon.vertices.len() == 4)
|
||||
);
|
||||
assert!(
|
||||
solid
|
||||
.polygons
|
||||
.iter()
|
||||
.all(|polygon| polygon.material == material)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parity_box_brush_from_planes_has_six_quad_polygons() {
|
||||
let solid = ConvexSolid::box_from_center_size(
|
||||
Vec3::ZERO,
|
||||
Vec3::splat(2.0),
|
||||
Quat::IDENTITY,
|
||||
MaterialId(9),
|
||||
);
|
||||
|
||||
assert_box_parity(&solid, MaterialId(9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtract_center_box_emits_six_convex_fragments() {
|
||||
let source = ConvexSolid::box_from_center_size(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ mod mesh;
|
|||
mod primitives;
|
||||
|
||||
pub use assembler::{Assembler, BuildOutput, BuildReport, BuildWarning};
|
||||
pub use brush::{Aabb, Brush, BrushId, BrushOp, MaterialId, Primitive};
|
||||
pub use brush::{Aabb, Brush, BrushId, BrushOp, MaterialId, PolygonCategory, Primitive};
|
||||
pub use convex::{ConvexPolygon, ConvexSolid, Plane};
|
||||
pub use dsl::LevelDsl;
|
||||
pub use mesh::TriangleMesh;
|
||||
|
|
|
|||
50
tests/realtime_csg_parity.rs
Normal file
50
tests/realtime_csg_parity.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use bevy_math::{Quat, Vec3};
|
||||
use vg_csg::{Aabb, Assembler, ConvexSolid, MaterialId, PolygonCategory};
|
||||
|
||||
#[test]
|
||||
fn parity_polygon_category_vocabulary_matches_public_demo() {
|
||||
let categories = [
|
||||
PolygonCategory::Inside,
|
||||
PolygonCategory::Outside,
|
||||
PolygonCategory::Aligned,
|
||||
PolygonCategory::ReverseAligned,
|
||||
];
|
||||
|
||||
assert_eq!(categories.len(), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parity_box_brush_observable_counts_match_realtime_csg_demo() {
|
||||
let solid = ConvexSolid::box_from_center_size(
|
||||
Vec3::ZERO,
|
||||
Vec3::splat(2.0),
|
||||
Quat::IDENTITY,
|
||||
MaterialId(3),
|
||||
);
|
||||
|
||||
assert_eq!(solid.clip_planes.len(), 6);
|
||||
assert_eq!(solid.polygons.len(), 6);
|
||||
assert_eq!(
|
||||
solid
|
||||
.polygons
|
||||
.iter()
|
||||
.map(|polygon| polygon.vertices.len())
|
||||
.sum::<usize>(),
|
||||
24
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parity_center_box_subtraction_has_six_surviving_regions() {
|
||||
let mut asm = Assembler::new();
|
||||
asm.solid_box(
|
||||
"source",
|
||||
Aabb::from_center_size(Vec3::ZERO, Vec3::splat(4.0)),
|
||||
MaterialId(1),
|
||||
);
|
||||
asm.cut_box("void", Aabb::from_center_size(Vec3::ZERO, Vec3::splat(2.0)));
|
||||
|
||||
let output = asm.build();
|
||||
assert_eq!(output.report.emitted_convex_fragments, 6);
|
||||
assert_eq!(output.report.warnings.len(), 0);
|
||||
}
|
||||
Loading…
Reference in a new issue