Skip to main content

symbios_shape/
lib.rs

1//! # Symbios Shape
2//!
3//! **A Sovereign Derivation Engine for CGA Shape Grammars.**
4//!
5//! Symbios Shape is a pure-Rust engine for generating procedural geometry using
6//! Computer-Generated Architecture (CGA) Shape Grammars, as popularised by
7//! Esri CityEngine. It is designed for embedding in game engines (Bevy, Godot)
8//! and offline procedural pipelines where reliability and determinism are paramount.
9//!
10//! ## Key Features
11//!
12//! - **Lightweight**: Depends on `glam` (math), `nom` (parsing), `rand` (stochastic rules), `thiserror`, `serde`, and `symbios-genetics` — no engine or runtime required.
13//! - **CGA-Compatible Operations**: `Extrude`, `Split` (snap-aware, with `{ … }*` rhythm groups), `SplitArea`, `Fit`, `Repeat`, `Comp(Faces|Edges)`, `Taper`, `Scale`, `Size`, `Center`, `Translate`, `Rotate`, `Align`, `Mirror`, `Offset` (inset/outset), `ShapeL`/`ShapeU`, `Roof`, `Attach`, `Scatter`, `Polygon`, `RegSnap`, `Label`, `IfClear`/`IfOccluded`/`IfInside`/`IfTouches`, `Pick`, `I`, `Mat`, and the reserved `NIL` vanish rule.
14//! - **Expression Language**: every numeric argument accepts arithmetic, comparisons, logicals, `rand(min, max)` and friends, plus `scope.x/y/z`, `split.i`, `split.n`, `depth`, rule parameters, and `attr`/`const` names.
15//! - **Rules with Parameters and Guards**: `Spire(n) --> when(n == 0): … | else: …` alongside weighted stochastic variants (`70% A | else: B`).
16//! - **Per-Shape Seed Streams**: derivations are pure functions of `(grammar, root scope, seed)` — queue-order independent, and editing one subtree re-rolls only that subtree.
17//! - **Grammar Statements**: `attr` / `const` declarations and `style … extends …` override sets; hosts steer with [`Interpreter::set_attr`] / [`Interpreter::set_style`].
18//! - **15 Roof Types**: Pyramid, Shed, Gable, Hip, Flat, OpenGable, BoxGable, PyramidHip, Butterfly, MShaped, Gambrel, Mansard, Saltbox, Jerkinhead, DutchGable — with `height=`, `ridge=`, fascia bands, and Shed's `Back` northlight face.
19//! - **Rich Face Profiles**: [`FaceProfile`] describes each terminal's cross-section (Rectangle, Taper, Triangle, Trapezoid, Polygon).
20//! - **Mass Model**: [`Material`] `{ id, density }` + [`MassProperties`] `{ mass, centroid, inertia }` computed on [`Terminal`] for physics / LOD / IK consumers.
21//! - **Snap-Lines + Occlusion Queries**: `RegSnap` records face planes; `Split(snap=...)` aligns to them. The occlusion conditionals gate sub-rules on (optionally labelled) OBB relations with already-emitted terminals; the same overlap test is exposed at runtime via [`ShapeModel::query`] → [`TerminalQuery`] and the free function [`obb_overlap`].
22//! - **Genetic Evolution**: [`genetics::ShapeGenotype`] wraps the rule table for `symbios-genetics` algorithms (literal-leaf Gaussian mutation, BLX-α crossover).
23//! - **Bevy-Ready Output**: [`ShapeModel`] containing [`Terminal`] nodes with scope, mesh_id, face_profile, material, mass_properties, and occlusion label.
24//!
25//! ## Example
26//!
27//! ```rust
28//! use symbios_shape::{Interpreter, Scope, Vec3, Quat};
29//! use symbios_shape::grammar::parse_ops;
30//!
31//! let mut interp = Interpreter::new();
32//!
33//! // A simple 3-storey building
34//! interp.add_rule("Lot", parse_ops("Extrude(12) Split(Y) { 3: Ground | ~1: Upper | 2: Roof }").unwrap());
35//! interp.add_rule("Ground", parse_ops(r#"I("GroundFloor")"#).unwrap());
36//! interp.add_rule("Upper",  parse_ops(r#"I("Floor")"#).unwrap());
37//! interp.add_rule("Roof",   parse_ops(r#"Taper(0.8) I("Roof")"#).unwrap());
38//!
39//! let footprint = Scope::new(Vec3::ZERO, Quat::IDENTITY, Vec3::new(10.0, 0.0, 10.0));
40//! let model = interp.derive(footprint, "Lot").unwrap();
41//!
42//! assert_eq!(model.len(), 3);
43//! assert_eq!(model.terminals[0].mesh_id, "GroundFloor");
44//! assert_eq!(model.terminals[2].mesh_id, "Roof");
45//! assert!(matches!(model.terminals[2].face_profile, symbios_shape::FaceProfile::Taper(t) if (t - 0.8).abs() < 1e-9));
46//! ```
47
48pub mod error;
49pub mod expr;
50pub mod genetics;
51pub mod grammar;
52pub mod interpreter;
53pub mod model;
54pub mod ops;
55pub mod query;
56pub mod scope;
57
58pub use error::ShapeError;
59pub use interpreter::Interpreter;
60pub use model::{FaceProfile, MassProperties, Material, ShapeModel, SnapPlane, Terminal};
61pub use ops::{
62    AttachCase, AttachSelector, Axis, CompTarget, FaceSelector, OffsetCase, OffsetSelector,
63    RoofCase, RoofConfig, RoofFaceSelector, RoofType, ShapeOp, SnapBinding, SplitSize, SplitSlot,
64};
65pub use query::{TerminalQuery, obb_overlap};
66pub use scope::{Quat, Scope, Vec3};