Add Dream Machine grammar layer
This commit is contained in:
parent
efe1558e29
commit
3cb2bd56bc
13 changed files with 564 additions and 53 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -807,6 +807,14 @@ dependencies = [
|
|||
"bevy_math",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vg_grammar"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bevy_math",
|
||||
"vg_csg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.3+wasi-0.2.9"
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
[workspace]
|
||||
members = ["crates/vg_csg"]
|
||||
members = ["crates/vg_csg", "crates/vg_grammar"]
|
||||
resolver = "3"
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ Currently present:
|
|||
- starter architecture notes for the Blender scene-generation pipeline
|
||||
- a small `vibegeometry/` helper library for coordinate frames, deterministic
|
||||
fields, batching, Blender object/material/camera helpers, and verifier checks
|
||||
- experimental Rust crates: `vg_csg` for Bevy-math brush assembly and
|
||||
`vg_grammar` for semantic procedural claims feeding the CSG tree
|
||||
- a repo structure for schemas, prompts, examples, experiments, scripts, tools,
|
||||
notes, and durable state
|
||||
- small state inspection and pre-compaction helpers
|
||||
|
|
|
|||
10
crates/vg_grammar/Cargo.toml
Normal file
10
crates/vg_grammar/Cargo.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "vg_grammar"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
description = "Procedural grammar layer that emits semantic CSG claims for VibeGeometry"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
bevy_math = "0.17"
|
||||
vg_csg = { path = "../vg_csg" }
|
||||
30
crates/vg_grammar/examples/dream_room.rs
Normal file
30
crates/vg_grammar/examples/dream_room.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
use bevy_math::Vec3;
|
||||
use vg_grammar::{ClaimTree, CorridorSpec, DoorSpec, GrammarContext, RoomSpec, Rule};
|
||||
|
||||
fn main() {
|
||||
let ctx = GrammarContext::new(7);
|
||||
let mut tree = ClaimTree::new();
|
||||
|
||||
RoomSpec::new("dream gallery", Vec3::ZERO, Vec3::new(6.0, 5.0, 3.0)).emit(&ctx, &mut tree);
|
||||
CorridorSpec::along_x("east artery", Vec3::new(5.0, 0.0, 0.0), 5.0).emit(&ctx, &mut tree);
|
||||
DoorSpec::new(
|
||||
"gallery to artery",
|
||||
Vec3::new(3.0, 0.0, 1.1),
|
||||
Vec3::new(0.7, 1.4, 2.2),
|
||||
)
|
||||
.emit(&ctx, &mut tree);
|
||||
|
||||
let compiled = tree.compile();
|
||||
let output = compiled.assembler.build();
|
||||
|
||||
println!(
|
||||
"claims={} solids={} voids={} brushes={} vertices={} triangles={} warnings={}",
|
||||
tree.claims().len(),
|
||||
compiled.solid_claims,
|
||||
compiled.void_claims,
|
||||
compiled.brush_ids.len(),
|
||||
output.mesh.vertex_count(),
|
||||
output.mesh.triangle_count(),
|
||||
output.report.warnings.len()
|
||||
);
|
||||
}
|
||||
154
crates/vg_grammar/src/claim.rs
Normal file
154
crates/vg_grammar/src/claim.rs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
use bevy_math::Vec3;
|
||||
use vg_csg::{Assembler, BrushId, MaterialId};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ClaimTag(pub String);
|
||||
|
||||
impl ClaimTag {
|
||||
pub fn new(value: impl Into<String>) -> Self {
|
||||
Self(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum ClaimKind {
|
||||
Solid,
|
||||
Void,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Claim {
|
||||
pub name: String,
|
||||
pub kind: ClaimKind,
|
||||
pub center: Vec3,
|
||||
pub size: Vec3,
|
||||
pub material: MaterialId,
|
||||
pub tags: Vec<ClaimTag>,
|
||||
}
|
||||
|
||||
impl Claim {
|
||||
pub fn solid_box(
|
||||
name: impl Into<String>,
|
||||
center: Vec3,
|
||||
size: Vec3,
|
||||
material: MaterialId,
|
||||
) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
kind: ClaimKind::Solid,
|
||||
center,
|
||||
size,
|
||||
material,
|
||||
tags: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn void_box(name: impl Into<String>, center: Vec3, size: Vec3) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
kind: ClaimKind::Void,
|
||||
center,
|
||||
size,
|
||||
material: MaterialId::default(),
|
||||
tags: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tagged(mut self, tag: impl Into<String>) -> Self {
|
||||
self.tags.push(ClaimTag::new(tag));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ClaimTree {
|
||||
claims: Vec<Claim>,
|
||||
}
|
||||
|
||||
impl ClaimTree {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, claim: Claim) {
|
||||
self.claims.push(claim);
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, claims: impl IntoIterator<Item = Claim>) {
|
||||
self.claims.extend(claims);
|
||||
}
|
||||
|
||||
pub fn claims(&self) -> &[Claim] {
|
||||
&self.claims
|
||||
}
|
||||
|
||||
pub fn count_kind(&self, kind: ClaimKind) -> usize {
|
||||
self.claims
|
||||
.iter()
|
||||
.filter(|claim| claim.kind == kind)
|
||||
.count()
|
||||
}
|
||||
|
||||
pub fn compile(&self) -> CompileReport {
|
||||
let mut assembler = Assembler::new();
|
||||
let mut brush_ids = Vec::with_capacity(self.claims.len());
|
||||
for claim in &self.claims {
|
||||
let brush_id = match claim.kind {
|
||||
ClaimKind::Solid => assembler.solid_box(
|
||||
&claim.name,
|
||||
vg_csg::Aabb::from_center_size(claim.center, claim.size),
|
||||
claim.material,
|
||||
),
|
||||
ClaimKind::Void => assembler.cut_box(
|
||||
&claim.name,
|
||||
vg_csg::Aabb::from_center_size(claim.center, claim.size),
|
||||
),
|
||||
};
|
||||
brush_ids.push(brush_id);
|
||||
}
|
||||
|
||||
CompileReport {
|
||||
assembler,
|
||||
brush_ids,
|
||||
solid_claims: self.count_kind(ClaimKind::Solid),
|
||||
void_claims: self.count_kind(ClaimKind::Void),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CompileReport {
|
||||
pub assembler: Assembler,
|
||||
pub brush_ids: Vec<BrushId>,
|
||||
pub solid_claims: usize,
|
||||
pub void_claims: usize,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bevy_math::Vec3;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn claim_tree_compiles_solids_and_voids_to_brushes() {
|
||||
let mut tree = ClaimTree::new();
|
||||
tree.push(Claim::solid_box(
|
||||
"wall",
|
||||
Vec3::ZERO,
|
||||
Vec3::new(4.0, 0.25, 3.0),
|
||||
MaterialId(1),
|
||||
));
|
||||
tree.push(Claim::void_box(
|
||||
"door",
|
||||
Vec3::new(0.0, 0.0, -0.25),
|
||||
Vec3::new(1.0, 0.5, 1.5),
|
||||
));
|
||||
|
||||
let report = tree.compile();
|
||||
assert_eq!(report.solid_claims, 1);
|
||||
assert_eq!(report.void_claims, 1);
|
||||
assert_eq!(report.brush_ids.len(), 2);
|
||||
assert_eq!(report.assembler.brushes().len(), 2);
|
||||
}
|
||||
}
|
||||
43
crates/vg_grammar/src/context.rs
Normal file
43
crates/vg_grammar/src/context.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
use vg_csg::MaterialId;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Materials {
|
||||
pub wall: MaterialId,
|
||||
pub floor: MaterialId,
|
||||
pub ceiling: MaterialId,
|
||||
pub trim: MaterialId,
|
||||
}
|
||||
|
||||
impl Default for Materials {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
wall: MaterialId(1),
|
||||
floor: MaterialId(2),
|
||||
ceiling: MaterialId(3),
|
||||
trim: MaterialId(4),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GrammarContext {
|
||||
pub seed: u64,
|
||||
pub materials: Materials,
|
||||
pub world_scale: f32,
|
||||
}
|
||||
|
||||
impl GrammarContext {
|
||||
pub fn new(seed: u64) -> Self {
|
||||
Self {
|
||||
seed,
|
||||
materials: Materials::default(),
|
||||
world_scale: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GrammarContext {
|
||||
fn default() -> Self {
|
||||
Self::new(0)
|
||||
}
|
||||
}
|
||||
12
crates/vg_grammar/src/lib.rs
Normal file
12
crates/vg_grammar/src/lib.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//! Procedural grammar for emitting semantic CSG claims.
|
||||
//!
|
||||
//! `vg_grammar` is the authoring layer above `vg_csg`: rules describe why
|
||||
//! space exists, then compile into solid and void brush claims.
|
||||
|
||||
mod claim;
|
||||
mod context;
|
||||
mod rules;
|
||||
|
||||
pub use claim::{Claim, ClaimKind, ClaimTag, ClaimTree, CompileReport};
|
||||
pub use context::{GrammarContext, Materials};
|
||||
pub use rules::{CorridorSpec, DoorSpec, RoomSpec, Rule};
|
||||
237
crates/vg_grammar/src/rules.rs
Normal file
237
crates/vg_grammar/src/rules.rs
Normal file
|
|
@ -0,0 +1,237 @@
|
|||
use bevy_math::Vec3;
|
||||
|
||||
use crate::{Claim, ClaimTree, GrammarContext};
|
||||
|
||||
pub trait Rule {
|
||||
fn emit(&self, ctx: &GrammarContext, tree: &mut ClaimTree);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RoomSpec {
|
||||
pub name: String,
|
||||
pub center: Vec3,
|
||||
pub size: Vec3,
|
||||
pub wall_thickness: f32,
|
||||
}
|
||||
|
||||
impl RoomSpec {
|
||||
pub fn new(name: impl Into<String>, center: Vec3, size: Vec3) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
center,
|
||||
size,
|
||||
wall_thickness: 0.25,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule for RoomSpec {
|
||||
fn emit(&self, ctx: &GrammarContext, tree: &mut ClaimTree) {
|
||||
let half = self.size * 0.5;
|
||||
let t = self.wall_thickness;
|
||||
let wall_height = self.size.z;
|
||||
let wall_z = self.center.z + wall_height * 0.5;
|
||||
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} floor", self.name),
|
||||
self.center + Vec3::new(0.0, 0.0, -t * 0.5),
|
||||
Vec3::new(self.size.x, self.size.y, t),
|
||||
ctx.materials.floor,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("floor"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} ceiling", self.name),
|
||||
self.center + Vec3::new(0.0, 0.0, wall_height + t * 0.5),
|
||||
Vec3::new(self.size.x, self.size.y, t),
|
||||
ctx.materials.ceiling,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("ceiling"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} north wall", self.name),
|
||||
Vec3::new(self.center.x, self.center.y + half.y, wall_z),
|
||||
Vec3::new(self.size.x, t, wall_height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("wall"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} south wall", self.name),
|
||||
Vec3::new(self.center.x, self.center.y - half.y, wall_z),
|
||||
Vec3::new(self.size.x, t, wall_height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("wall"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} east wall", self.name),
|
||||
Vec3::new(self.center.x + half.x, self.center.y, wall_z),
|
||||
Vec3::new(t, self.size.y, wall_height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("wall"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} west wall", self.name),
|
||||
Vec3::new(self.center.x - half.x, self.center.y, wall_z),
|
||||
Vec3::new(t, self.size.y, wall_height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("room")
|
||||
.tagged("wall"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct CorridorSpec {
|
||||
pub name: String,
|
||||
pub center: Vec3,
|
||||
pub length: f32,
|
||||
pub width: f32,
|
||||
pub height: f32,
|
||||
pub wall_thickness: f32,
|
||||
}
|
||||
|
||||
impl CorridorSpec {
|
||||
pub fn along_x(name: impl Into<String>, center: Vec3, length: f32) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
center,
|
||||
length,
|
||||
width: 2.0,
|
||||
height: 2.6,
|
||||
wall_thickness: 0.2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule for CorridorSpec {
|
||||
fn emit(&self, ctx: &GrammarContext, tree: &mut ClaimTree) {
|
||||
let t = self.wall_thickness;
|
||||
let z = self.center.z + self.height * 0.5;
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} floor", self.name),
|
||||
self.center + Vec3::new(0.0, 0.0, -t * 0.5),
|
||||
Vec3::new(self.length, self.width, t),
|
||||
ctx.materials.floor,
|
||||
)
|
||||
.tagged("corridor")
|
||||
.tagged("floor"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} left wall", self.name),
|
||||
Vec3::new(self.center.x, self.center.y + self.width * 0.5, z),
|
||||
Vec3::new(self.length, t, self.height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("corridor")
|
||||
.tagged("wall"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} right wall", self.name),
|
||||
Vec3::new(self.center.x, self.center.y - self.width * 0.5, z),
|
||||
Vec3::new(self.length, t, self.height),
|
||||
ctx.materials.wall,
|
||||
)
|
||||
.tagged("corridor")
|
||||
.tagged("wall"),
|
||||
);
|
||||
tree.push(
|
||||
Claim::solid_box(
|
||||
format!("{} ceiling", self.name),
|
||||
self.center + Vec3::new(0.0, 0.0, self.height + t * 0.5),
|
||||
Vec3::new(self.length, self.width, t),
|
||||
ctx.materials.ceiling,
|
||||
)
|
||||
.tagged("corridor")
|
||||
.tagged("ceiling"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DoorSpec {
|
||||
pub name: String,
|
||||
pub center: Vec3,
|
||||
pub size: Vec3,
|
||||
}
|
||||
|
||||
impl DoorSpec {
|
||||
pub fn new(name: impl Into<String>, center: Vec3, size: Vec3) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
center,
|
||||
size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rule for DoorSpec {
|
||||
fn emit(&self, _ctx: &GrammarContext, tree: &mut ClaimTree) {
|
||||
tree.push(
|
||||
Claim::void_box(&self.name, self.center, self.size)
|
||||
.tagged("door")
|
||||
.tagged("void"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use vg_csg::Aabb;
|
||||
|
||||
use super::*;
|
||||
use crate::ClaimKind;
|
||||
|
||||
#[test]
|
||||
fn room_corridor_door_grammar_emits_semantic_claims_and_mesh() {
|
||||
let ctx = GrammarContext::new(42);
|
||||
let mut tree = ClaimTree::new();
|
||||
RoomSpec::new("gallery", Vec3::ZERO, Vec3::new(6.0, 5.0, 3.0)).emit(&ctx, &mut tree);
|
||||
CorridorSpec::along_x("artery", Vec3::new(5.0, 0.0, 0.0), 5.0).emit(&ctx, &mut tree);
|
||||
DoorSpec::new(
|
||||
"gallery east doorway",
|
||||
Vec3::new(3.0, 0.0, 1.1),
|
||||
Vec3::new(0.7, 1.4, 2.2),
|
||||
)
|
||||
.emit(&ctx, &mut tree);
|
||||
|
||||
assert_eq!(tree.count_kind(ClaimKind::Solid), 10);
|
||||
assert_eq!(tree.count_kind(ClaimKind::Void), 1);
|
||||
assert!(
|
||||
tree.claims()
|
||||
.iter()
|
||||
.any(|claim| claim.tags.iter().any(|tag| tag.0 == "door"))
|
||||
);
|
||||
|
||||
let report = tree.compile();
|
||||
let output = report.assembler.build();
|
||||
let door_void = Aabb::from_center_size(Vec3::new(3.0, 0.0, 1.1), Vec3::new(0.7, 1.4, 2.2));
|
||||
|
||||
assert!(output.mesh.triangle_count() > 60);
|
||||
assert!(output.report.warnings.is_empty());
|
||||
for tri in output.mesh.indices.chunks_exact(3) {
|
||||
let center = (output.mesh.positions[tri[0] as usize]
|
||||
+ output.mesh.positions[tri[1] as usize]
|
||||
+ output.mesh.positions[tri[2] as usize])
|
||||
/ 3.0;
|
||||
assert!(!door_void.contains_point_strict(center, 1.0e-4));
|
||||
}
|
||||
}
|
||||
}
|
||||
35
docs/research/dream-machine-grammar.md
Normal file
35
docs/research/dream-machine-grammar.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Dream Machine Grammar
|
||||
|
||||
The grammar layer is the authoring mind above CSG.
|
||||
|
||||
```text
|
||||
brief / lore / level intent
|
||||
-> procedural grammar rules
|
||||
-> semantic solid and void claims
|
||||
-> CSG tree classification
|
||||
-> visible polygon set
|
||||
-> Bevy mesh cache
|
||||
-> inspection loop
|
||||
```
|
||||
|
||||
`crates/vg_grammar` starts this layer. It deliberately emits claims before
|
||||
geometry:
|
||||
|
||||
- `Solid` claims say matter exists.
|
||||
- `Void` claims say space must stay empty.
|
||||
- tags preserve why the claim exists: `room`, `corridor`, `door`, `wall`,
|
||||
`floor`, `ceiling`.
|
||||
|
||||
The first rules are small on purpose:
|
||||
|
||||
- `RoomSpec`
|
||||
- `CorridorSpec`
|
||||
- `DoorSpec`
|
||||
|
||||
They prove the shape of the pipeline: grammar emits semantic claims, claims
|
||||
compile into `vg_csg` brushes, and the CSG assembler produces the mesh verdict.
|
||||
|
||||
The rule is simple: future procedural generators should feed CSG with authored
|
||||
space claims instead of bypassing the tree with final triangles. Cities,
|
||||
habitats, corridors, and districts can grow from fields and grammars, but hard
|
||||
architectural legality belongs in the CSG tree.
|
||||
|
|
@ -22,44 +22,23 @@ git log --oneline -5
|
|||
|
||||
## Current State
|
||||
|
||||
VibeGeometry is an incubation scaffold with persistence, graph-translation
|
||||
corpus notes, repo-local Geometry Script tooling, verifiers, doctrine, a Python
|
||||
helper library, and now a first Rust CSG assembler. Artifact schemas are still
|
||||
pending.
|
||||
VibeGeometry now has three live implementation organs:
|
||||
|
||||
Corpus inventory, graph maps, verification notes, and doctrine live in
|
||||
`docs/research/`; this handoff is not the ledger. Accepted corpus families
|
||||
include local Shriinivas samples, Quellenform `CurveToMeshUV`, official Blender
|
||||
demos, and IRCSS French Houses footholds. IRCSS blockers remain repeat-zone
|
||||
feedback, repeat `Top` outputs, foreach zones, gizmo nodes, and the rejected
|
||||
empty-output `WindowBeams` harness.
|
||||
- `vibegeometry/`: Python helpers for Blender coordinate frames, deterministic
|
||||
fields, batching, object/material/camera setup, and verifier checks.
|
||||
- `crates/vg_csg`: Rust/Bevy-math CSG brush assembler.
|
||||
- `crates/vg_grammar`: Dream Machine grammar layer emitting semantic solid/void
|
||||
claims into `vg_csg`.
|
||||
|
||||
From-scratch story-bound builds live in `examples/geometry_script/`:
|
||||
|
||||
- `aetheria_bloom_habitat.py`: whole Bloom study with explicit lore coordinate
|
||||
frames, cylindrical/endcap attachment, golden-angle transfer curves,
|
||||
deterministic settlement noise, batched dense detail, and inspection cameras.
|
||||
- `lucent_tether_habitat.py`: Ghostlight/Lucent tether habitat with orthogonal
|
||||
spin-gravity city plane, flat-cut dome base, street-field city, shader work,
|
||||
tether attachment, and exterior Citadel-scale solar/radiator florets.
|
||||
|
||||
Build notes and verifiers:
|
||||
|
||||
- `docs/research/builds/aetheria-bloom-habitat.md`
|
||||
- `docs/research/builds/lucent-tether-habitat.md`
|
||||
- `tools/verify_aetheria_bloom_habitat.py`
|
||||
- `tools/verify_lucent_tether_habitat.py`
|
||||
Corpus maps, story-bound builds, translation notes, RealtimeCSG doctrine, and
|
||||
procedural doctrine live under `docs/research/`; this handoff is not the ledger.
|
||||
Artifact schemas are still pending.
|
||||
|
||||
Current authoring prior: use the full Python stack. Python structures intent,
|
||||
tables, loops, variants, cleanup, validation, docs, and scene/render
|
||||
orchestration; Geometry Script emits inspectable Geometry Nodes groups; `bpy`
|
||||
handles Blender scene machinery and evaluated evidence.
|
||||
|
||||
`vibegeometry/` is the first reusable helper library. It currently holds
|
||||
coordinate-frame helpers, deterministic field/noise helpers, mesh batching,
|
||||
thin Blender object/material/camera helpers, and verifier helpers. The Bloom
|
||||
script imports these primitives directly, so the library is not just a shrine.
|
||||
|
||||
`crates/vg_csg` is the first Rust/Bevy-side interactive geometry organ.
|
||||
RealtimeCSG's public Unity repo exposes a useful brush/tree/operation/generation
|
||||
model, but not the optimized native C++ kernel or a supported runtime editing
|
||||
|
|
@ -70,25 +49,22 @@ additive `CylinderZ`, `DomeCapZ`, and `FloretArm` primitives, Bevy-math mesh
|
|||
buffers, `LevelDsl`, tests, clippy, and an example room. Research note:
|
||||
`docs/research/realtime-csg-bevy-assembler.md`.
|
||||
|
||||
The repo-local Geometry Script clone has Blender 5.1 work for nested `@tree`
|
||||
group reuse, a ported `nodes_to_script` converter, and menu-socket default
|
||||
tolerance. See `docs/research/geometry-script-fork-notes.md`. Run
|
||||
`crates/vg_grammar` is the first Dream Machine grammar layer above CSG. Rules
|
||||
emit semantic solid/void claims with tags, then compile those claims into
|
||||
`vg_csg` brushes. Current rules: `RoomSpec`, `CorridorSpec`, `DoorSpec`.
|
||||
Example: `cargo run -p vg_grammar --example dream_room`. Research note:
|
||||
`docs/research/dream-machine-grammar.md`.
|
||||
|
||||
Repo-local Geometry Script clone notes live in
|
||||
`docs/research/geometry-script-fork-notes.md`. Run
|
||||
`.\tools\setup_geometry_script_clone.ps1` if `external/geometry-script` is
|
||||
missing in a fresh workspace.
|
||||
missing.
|
||||
|
||||
The local toolchain branch is `vibegeometry/blender-5-nodes-to-script`.
|
||||
The upstream PR branch is `vibegeometry/blender-5-nested-tree-groups`, and PR
|
||||
#69 is intentionally limited to the nested-group fix:
|
||||
https://github.com/carson-katri/geometry-script/pull/69.
|
||||
The GameCult fork is intentionally pruned to `main` plus VibeGeometry-owned
|
||||
tooling branches. Do not copy upstream branch soup forward unless a future patch
|
||||
actually needs it.
|
||||
|
||||
The current next action is to move `vg_csg` toward the public RealtimeCSG demo's
|
||||
faster model: add explicit polygon categories, classify brush polygons through
|
||||
boolean tree operations, preserve source/cutter surfaces and material intent,
|
||||
then add spatial rejection/indexing and Bevy `Mesh`/ECS plugin boundaries for
|
||||
the interactive loop.
|
||||
The current next action is to grow `vg_grammar` from room/corridor/door claims
|
||||
into a real procedural level grammar: add frames, seeded variation, rule
|
||||
composition, semantic materials/tags, and generated CSG tree structure, while
|
||||
moving `vg_csg` toward explicit polygon categories and boolean-tree
|
||||
classification.
|
||||
|
||||
## Important Invariants
|
||||
|
||||
|
|
|
|||
|
|
@ -51,3 +51,4 @@
|
|||
{"ts": "2026-05-06T23:06:51+00:00", "type": "implementation", "status": "accepted", "note": "Added vg_csg, a Rust workspace crate for the new interactive Bevy-compatible CSG path: RealtimeCSG-inspired brush ordering and generations, exact AABB box subtraction, additive cylinder/dome/floret primitives, mesh-array output, DSL, tests, clippy, example, and research doctrine. Public RealtimeCSG source informed the shape but not the hidden native kernel."}
|
||||
{"ts": "2026-05-06T23:20:20+00:00", "type": "implementation", "status": "accepted", "note": "Upgraded vg_csg from AABB-only subtraction to a convex-brush stepping-stone kernel: oriented-box brushes, plane splitting, convex fragment emission, angled-cut tests, and updated RealtimeCSG doctrine. Public LogicalError Realtime-CSG-demo and Sander van Rossen blog/article material are now preferred clean research inputs for the faster target model: polygon classification through boolean trees, not decompiled native internals."}
|
||||
{"ts": "2026-05-06T23:31:47+00:00", "type": "research", "status": "accepted", "note": "Distilled public Realtime CSG ecosystem doctrine from Sander van Rossen blog posts, LogicalError/Realtime-CSG-demo, BSO3, GDC talk listing, and downstream engine discussions: target vg_csg should migrate from fragment carving toward polygon classification through boolean trees with explicit categories, half-edge/topology working data, bounds early-outs, dirty affected-brush rebuilds, separate mesh optimization, and CSG as one procedural grammar operator."}
|
||||
{"ts": "2026-05-07T00:12:44+00:00", "type": "implementation", "status": "accepted", "note": "Built the first Dream Machine grammar layer: new vg_grammar crate with semantic solid/void ClaimTree, GrammarContext materials, RoomSpec/CorridorSpec/DoorSpec rules, a dream_room example, and tests proving grammar emits claims that compile into vg_csg brushes and leave doorway voids empty. The authoring split is now grammar writes spatial claims, CSG adjudicates matter, mesh is cache."}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ live_architecture:
|
|||
- Geometry Script emits inspectable reusable Geometry Nodes groups.
|
||||
- bpy handles Blender objects, modifiers, materials, cameras, lights, files, renders, and evaluated-geometry checks.
|
||||
- Rust/Bevy-side CSG tooling provides an interactive brush-and-boolean assembler path for fast level geometry, starting with box CSG and habitat-specific additive primitives.
|
||||
- `vg_grammar` provides the authoring grammar above CSG: procedural rules emit semantic solid/void claims, then `vg_csg` adjudicates the space.
|
||||
- External Python tools inspect source blends, generate converter drafts, compare outputs, and maintain corpus evidence.
|
||||
persistence:
|
||||
- `state/map.yaml` stores canonical mission, boundaries, architecture, artifacts, and next action.
|
||||
|
|
@ -72,6 +73,7 @@ current_artifacts:
|
|||
- docs/architecture/pipeline-overview.md
|
||||
- docs/research/procedural-doctrine.md
|
||||
- docs/research/realtime-csg-doctrine.md
|
||||
- docs/research/dream-machine-grammar.md
|
||||
- docs/research/geometry-script-fork-notes.md
|
||||
- docs/research/translations/ircss-french-houses-system-map.md
|
||||
- docs/research/translations/ircss-french-houses-node-atlas.md
|
||||
|
|
@ -80,6 +82,7 @@ current_artifacts:
|
|||
- docs/research/builds/lucent-tether-habitat.md
|
||||
- docs/research/realtime-csg-bevy-assembler.md
|
||||
- crates/vg_csg/
|
||||
- crates/vg_grammar/
|
||||
- vibegeometry/
|
||||
tools:
|
||||
- tools/vibegeometry_state.py
|
||||
|
|
@ -106,8 +109,8 @@ data_flow:
|
|||
- If state grows faster than understanding, cut it back.
|
||||
|
||||
current_status:
|
||||
summary: VibeGeometry has verified Geometry Script translations for local samples, official Blender demos, and IRCSS French Houses footholds, plus from-scratch Aetheria Bloom and Lucent tether habitat builds. Durable lessons now driving the pipeline: Python orchestrates intent and batching; Geometry Script emits inspectable node groups; source-bound scenes need explicit coordinate contracts before ornament; spin-gravity habitats need ground planes orthogonal to their tether/rotation axis; utility petals, radiators, and solar arrays belong outside pressure glass and may need Citadel-scale presence; large habitat parts need visible load paths across coordinate frames; organic city maps need street fields, irregular parcels, parks, and land-use gradients rather than grids; dense detail must be batched; institutional spaces should model power as surfaces, rails, overlays, thresholds, shader behavior, and camera evidence; and visual acceptance needs domain-facing inspection renders plus verifier checks, not only overview renders. The first reusable `vibegeometry/` helper library now carries coordinate frames, fields, batching, Blender scene primitives, and verifier helpers used by the Bloom and Lucent builds. The Rust crate `vg_csg` now has a convex-brush stepping-stone kernel: RealtimeCSG-inspired ordered brushes, operation types, generation tracking, exact AABB and oriented-box subtraction via convex plane splitting, additive cylinder/dome/floret primitives, mesh-array output, DSL coverage, tests, clippy, and a sample room. Public RealtimeCSG demo/source research points the target away from fragment carving and toward faster polygon classification through boolean trees. Known graph-tooling blockers remain repeat-zone feedback, repeat Top outputs, foreach zones, and gizmo nodes.
|
||||
next_action: Move `vg_csg` toward the public RealtimeCSG demo's faster model: add explicit polygon categories, classify brush polygons through boolean tree operations, preserve source/cutter surfaces and material intent, then add spatial rejection/indexing and Bevy `Mesh`/ECS plugin boundaries for the interactive loop.
|
||||
summary: VibeGeometry has verified Geometry Script translations for local samples, official Blender demos, and IRCSS French Houses footholds, plus from-scratch Aetheria Bloom and Lucent tether habitat builds. Durable lessons now driving the pipeline: Python orchestrates intent and batching; Geometry Script emits inspectable node groups; source-bound scenes need explicit coordinate contracts before ornament; spin-gravity habitats need ground planes orthogonal to their tether/rotation axis; utility petals, radiators, and solar arrays belong outside pressure glass and may need Citadel-scale presence; large habitat parts need visible load paths across coordinate frames; organic city maps need street fields, irregular parcels, parks, and land-use gradients rather than grids; dense detail must be batched; institutional spaces should model power as surfaces, rails, overlays, thresholds, shader behavior, and camera evidence; and visual acceptance needs domain-facing inspection renders plus verifier checks, not only overview renders. The first reusable `vibegeometry/` helper library now carries coordinate frames, fields, batching, Blender scene primitives, and verifier helpers used by the Bloom and Lucent builds. The Rust crate `vg_csg` now has a convex-brush stepping-stone kernel: RealtimeCSG-inspired ordered brushes, operation types, generation tracking, exact AABB and oriented-box subtraction via convex plane splitting, additive cylinder/dome/floret primitives, mesh-array output, DSL coverage, tests, clippy, and a sample room. The new `vg_grammar` crate is the first Dream Machine authoring layer: room/corridor/door rules emit semantic solid/void claims with tags into `vg_csg`, preserving intent before CSG resolves matter. Public RealtimeCSG demo/source research points the target away from fragment carving and toward faster polygon classification through boolean trees. Known graph-tooling blockers remain repeat-zone feedback, repeat Top outputs, foreach zones, and gizmo nodes.
|
||||
next_action: Grow `vg_grammar` from room/corridor/door claims into a real procedural level grammar: add frames, seeded variation, rule composition, semantic materials/tags, and generated CSG tree structure, while moving `vg_csg` toward explicit polygon categories and boolean-tree classification.
|
||||
remotes:
|
||||
vibegeometry: https://github.com/GameCult/VibeGeometry
|
||||
geometry_script_fork: https://github.com/GameCult/geometry-script
|
||||
|
|
|
|||
Loading…
Reference in a new issue