Skip to main content

Scene Graph & Yugma Scene Language

SceneObject (Core Type)

Every object in the 3D scene is a SceneObject:

interface SceneObject {
id: string // nanoid(10), stable forever
name: string // Semantic: "wall_north", "hero_sphere"
type: GeometryType // box|sphere|cylinder|plane|torus|cone|
// capsule|tetrahedron|dodecahedron|custom_gltf
transform: {
position: [number, number, number] // meters, Y-up, world space
rotation: [number, number, number] // degrees, Euler XYZ
scale: [number, number, number] // multiplier (1 = default)
}
material: {
color: string // hex "#rrggbb"
roughness: number // 0.0 (mirror) → 1.0 (chalk)
metalness: number // 0.0 (plastic) → 1.0 (metal)
opacity: number // 0.0 → 1.0
wireframe: boolean
emissive: string // hex, "#000000" = off
emissiveIntensity: number // 0 = off, 1-10 = glow
}
geometry: GeometryParams // Type-specific (width, radius, etc.)
tags: string[] // Semantic: ["wall", "structural"]
parentId: string | null // Group hierarchy
visible: boolean
locked: boolean
castShadow: boolean
receiveShadow: boolean

// YSL v1.5 additive fields
userData?: Record<string, unknown> // Extension point
semanticRole?: string // "wall", "floor", "hero", "prop"
relationships?: { // Soft scene-graph links
parentOf?: string[]
nextTo?: string[]
supports?: string[]
references?: string[]
}

createdAt: number
updatedAt: number
}

Coordinate System

AxisDirectionConvention
+XRightThree.js / WebGL
+YUp
-ZForward
UnitsMetersHuman ≈ 1.8m, door ≈ 2.1m
RotationDegreesEuler XYZ order
ColorsHex"#rrggbb"

Geometry Types

TypeParams
boxwidth, height, depth
sphereradius, widthSegments, heightSegments
cylinderradiusTop, radiusBottom, cylinderHeight, radialSegments
coneradius, cylinderHeight, radialSegments
torustorusRadius, tube, torusSegments
planewidth, height
capsuleradius, cylinderHeight
tetrahedronradius, detail
dodecahedronradius, detail
custom_gltfgltfUrl

Scene Environment

interface SceneEnvironment {
hdriPreset: string // city, sunset, dawn, night, forest, studio, warehouse, apartment
backgroundColor: string // hex
ambientIntensity: number // 0-2
fogEnabled: boolean
fogColor: string
fogNear: number
fogFar: number
}

YSL — Yugma Scene Language

YSL is a compact text format designed for LLM context windows. Key properties:

MetricYSLUSDGLTF JSON
Tokens/object~45~400~300
50-obj scene~2,400 tokens~20,000 tokens~15,000 tokens
LLM-parseableYesPartiallyNo

YSL Output Example

[★ hero_sphere] sphere id=abc pos=[2,0.5,0] rot=[0,0,0] s=[1,1,1]
mat=#ff0000 r=0.3 m=0.8 e=#000000 ei=0 op=1 tags=[hero,accent]
role=hero nextTo=[def456]

marks the currently selected object. The serializer (aiSerializer.ts) outputs all objects in hierarchy order.

Schema Evolution

VersionAddedBreaking?
v1.0Core SceneObject, tags, material, geometryN/A
v1.5userData, semanticRole, relationshipsNo — all optional, additive-only
v2.0 (planned)Constraints, physics bodies, LOD, animationsNo — additive

All evolution is additive-only. Existing documents load unchanged. New fields default to undefined.

State Management

The scene graph lives in useSceneStore (Zustand). Key actions:

ActionEffect
addObject(type, overrides?)Create new object, auto-select, return ID
updateObject(id, patch)Deep merge with special handling for tags, material, transform, relationships
removeObject(id)Delete + deselect if selected
duplicateObject(id)Clone with +1m X offset
reparentObject(id, parentId)Set parent for grouping
selectObject(id)Set selection
setCameraTarget(target)Trigger smooth camera tween
setEnvironment(patch)Update HDRI, fog, ambient
clearScene()Remove all objects
loadScene(objects, order, env)Bulk load