Blender-Import-Pipeline: glTF/OBJ, col_*-Proxies, Trigger

Blender wird das Haupt-3D-Tool: zwei Loader (engine/gltf.rs für .glb als
Hauptpfad, engine/obj.rs aus irl3d eingebettet) liefern ein neutrales
engine/model.rs::Model. Loader sind reine Dekoder; das Frontend zieht sie
und schiebt das Ergebnis per Session::load_props in den State, der
Renderer baut sein Mesh (render/props.rs, verschmolzen mit der
Brush-Welt über eine geteilte Texturliste).

glTF trägt Blender-Custom-Properties (node.extras → Object::props) und
Empties (Nodes ohne Mesh) als Entity-Kanal. Namenskonvention: `col_*` =
unsichtbarer Collision-Proxy, aus dem collision::add_model konvexe
Ebenen-Sets baut (konvex-only, daher kein Default-Collider auf
Sichtgeometrie).

Trigger (engine/trigger.rs) hängen an der Custom Property `signal`:
mit Collider = Point-and-Click-Ziel (Session::pick raycastet aus der
Bildmitte, Treffer läuft durch den `use <name>`-Trichter), ohne Collider
= unsichtbare Betretens-Zone, die einmal je Eintritt feuert. Gefeuert
wird nur über Session::exec — der Eingabe-Trichter bleibt der einzige
Weg in den State.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 15:20:00 +02:00
parent 67c4a366c7
commit f7bfdb4a0b
14 changed files with 1465 additions and 43 deletions
+18
View File
@@ -34,6 +34,24 @@ pub(crate) struct Mesh {
pub(crate) batches: Vec<Batch>,
}
impl Mesh {
/// Ein zweites Mesh anhängen (ein Vertex-/Index-Buffer für alles).
/// Voraussetzung: beide wurden gegen *dieselbe* Texturliste gebaut —
/// die Batch-Texturindizes bleiben dann unverändert gültig; nur die
/// Buffer-Offsets verschieben sich.
pub(crate) fn append(&mut self, other: Mesh) {
let vbase = self.verts.len() as u32;
let ibase = self.indices.len() as u32;
self.verts.extend(other.verts);
self.indices.extend(other.indices.iter().map(|i| i + vbase));
self.batches.extend(other.batches.iter().map(|b| Batch {
texture: b.texture,
start: b.start + ibase,
count: b.count,
}));
}
}
/// Spiegelt das `Uniforms`-Struct in scene.wgsl. `_pad` rundet die Größe
/// auf 80 Byte (16er-Vielfaches), wie es die Uniform-Adressraum-Regeln
/// von WGSL verlangen.