Coming from Three.js / Babylon.js

← prev index next →

Skenra is authored as HTML, so the Three.js / Babylon.js instincts — a scene object, mesh.material, radian attributes, a render loop — are wrong here by default. Each row below converts one instinct: what you would write, what actually happens in Skenra, and what to write instead. This guide owns source-framework correspondence; the general authoring rules (workflow, decision tree, common mistakes) live in the guide:for-agents card the rows link to.

Correspondence table

Three.js / Babylon instinctSkenra realityWrite insteadRelated
scene.add(mesh)
Babylon: scene.addMesh(mesh); grouping via TransformNode is plain element nesting here
there is no scene object to add to — the DOM IS the scene graph, and <sk-scene>'s children are the nodesnest scene elements in .sk markup; use standard DOM (document.createElement + appendChild) only when runtime graph mutation is genuinely requiredconcept:scene-graph, guide:for-agents, guide:for-agents-example-scripting
mesh.material = new MeshStandardMaterial(…)
Babylon: StandardMaterial / PBRMaterial assigned to mesh.material
a mesh has no material property — mesh authoring uses paint children, and a paint references a reusable material resource by id; a paint without material is marked inertdeclare the material with an id under <sk-scene>; bind it from a paint child: <sk-surface-paint material="#mat">concept:material, concept:paint, element:sk-plain-material, element:sk-surface-paint, guide:for-agents-example-primitives-materials
mesh.rotation.y = 1.57.sk angle attributes take CSS angles on the heading/pitch/bank model — a unitless h="90" is invalid and IGNORED; IDL properties take canonical numbersh="90deg" in markup; node.h = Math.PI / 2 in script (canonical radians)type:angle, guide:for-agents
a requestAnimationFrame loop
Babylon: engine.runRenderLoop(fn)
a standalone rAF loop fights the scene-time-driven animation engine and breaks deterministic capturedeclarative <sk-animation> / constraints first; animate() for imperative WAAPI; scene.onFrame (keep its returned cleanup function) for custom per-frame workconcept:animation, element:sk-animation, element:sk-scene, guide:for-agents, guide:for-agents-example-keyframes-easing
new THREE.InstancedMesh(…)
Babylon: thin instances / mesh.createInstance(…)
many-copies rendering is MoGraph-style cloning — a cloner clones a content child onto a points-source, not a monolithic instanced mesh<sk-cloner> + a points-source child (+ point-constraints for per-clone effects)element:sk-cloner, concept:points-source, concept:point-constraint, guide:for-agents-example-cloners
camera.lookAt(target) per frame
Babylon: mesh.lookAt(…) / camera setTarget(…)
constraints replace per-frame update code — a target-at constraint keeps aiming as the target moves, with no loop<sk-target-at-constraint> inside the aiming nodeelement:sk-target-at-constraint, concept:constraint, guide:for-agents-example-constraints
OrbitControls + camera.position.set(…)
Babylon: ArcRotateCamera
camera control is a scene-root element with auto-framing — no manual camera positioning to keep in sync<sk-camera-orbit-control fit-targets="auto"> + a camera; pose the framed view with azimuth / elevationelement:sk-camera-orbit-control, concept:camera, guide:for-agents-example-camera-fit
new THREE.Color(0xff0000)
Babylon: Color3.Red() / Color3.FromHexString(…)
color attributes take CSS color strings — named colors, hex, and var() tokens the browser's CSS engine resolves against the scene's custom properties; there is no color class"red" or "#c05a4e" directly; var(--token) for shared palette tokens — a token's value may itself be color-mix(in oklab, …)type:color, guide:for-agents
Raycaster + intersection tests
Babylon: ActionManager / scene.pick(…)
GPU picking dispatches DOM-style events to the scene elements themselves — no ray setup, no hit-test bookkeepinglowercase HTML handler attributes on the element: onclick, onpointerdown, …attribute:sk-sphere/onclick, guide:for-agents-example-scripting
new TextureLoader().load(…)
Babylon: new Texture(url, scene)
images enter the material pipeline as by-id color sources whose projection/UV behavior is explicit (projection, projection-plane, placement) — not a drop-in texture object<sk-raster-color-source src="…"> referenced by the material's base-color-source="#id", applied through a paintelement:sk-raster-color-source, concept:color-source, concept:material

Verified patterns

Each block is mechanically extracted from the tested migration scene.

mesh.material = new MeshStandardMaterial(…)

<sk-plain-material id="mat" base-color="coral"></sk-plain-material>
<sk-sphere>
    <sk-surface-paint material="#mat"></sk-surface-paint>
</sk-sphere>

new THREE.Color(0xff0000)

<sk-plain-material id="named-mat" base-color="goldenrod"></sk-plain-material>
<sk-plain-material id="token-mat" base-color="var(--accent-color)"></sk-plain-material>
<sk-plain-material id="mixed-mat" base-color="var(--mixed-color)"></sk-plain-material>

new TextureLoader().load(…)

<sk-raster-color-source id="decal"
    src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='64' height='64' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' fill='%23f4a259'/%3E%3Ccircle cx='32' cy='32' r='20' fill='%23216869'/%3E%3Ccircle cx='32' cy='32' r='9' fill='%23f4f1de'/%3E%3C/svg%3E"
    projection-plane="x-y" width="2" anchor="center"
    x="-2.6" y="0" z="0" tile="none"></sk-raster-color-source>
<sk-plain-material id="decal-mat" base-color="white"
    base-color-source="#decal"></sk-plain-material>
<sk-plane x="-2.6" y="0" width="2" height="2" orientation="+z" cull-mode="none">
    <sk-surface-paint material="#decal-mat"></sk-surface-paint>
</sk-plane>

Skenra-native concepts with no one-to-one engine mapping

These Skenra concepts have no one-to-one Three.js/Babylon mapping — fetch the concept record before assuming an engine equivalent exists.