AURA

JSGG

AuraJS
DOCSEXAMPLESGITHUB
09 Meshes, Materials, Scene3D, glTF, and Skinned Mesh
Mesh/material authoring, scene3d, glTF ingestion, and skinned mesh semantics.
docs/external/game-dev-api/09-meshes-materials-scene3d-gltf-and-skinned-mesh.md

Meshes, Materials, Scene3D, glTF, and Skinned Mesh

This page groups the 3D content and scene-management surfaces.

`aura.mesh`

Static/procedural mesh surface:

  • load(path)
  • createBox(width, height, depth)
  • createSphere(radius, segments?)
  • createPlane(width, depth)
  • createCylinder(radius, height, segments?)
  • createCone(radius, height, segments?)
  • createTorus(radius, tubeRadius, segments?)
  • createRing(innerRadius, outerRadius, segments?)
  • createExtrude(shape2d, optionsOrDepth?, segments?)
  • createLathe(points, optionsOrSegments?, phiStart?, phiLength?)
  • createFromVertices(vertices, indices, normals?, uvs?, colorsOrSkinning?, skinning?)
  • setMorphTargets(meshHandle, targets)
  • setMorphWeights(meshHandle, weights)
  • getData(meshHandle)
  • unload(meshHandle)

Generator guidance:

  • Use createRing, createExtrude, and createLathe for compact parametric props, blockouts, and proof slices where the authored shape is clearer in code than as an imported asset.
  • Prefer the options-object form for createExtrude(...) and createLathe(...) when you want the call site to carry explicit authored meaning for depth, segments, phiStart, and phiLength.
  • These generators throw on malformed authored input instead of fuzzily guessing. That is intentional contract behavior.
  • Prefer imported authored assets when the mesh needs complex organic topology, artist-owned asymmetry, or broader reuse outside code.

Skinned instance-group helpers currently also attach under aura.mesh:

  • createInstanceGroup(options)
  • instanceSetTransform(groupHandle, instanceId, transform)
  • instanceSetJointPose(groupHandle, instanceId, jointIndex, pose)
  • instanceSetJointMatrixRaw(groupHandle, instanceId, jointIndex, matrix)
  • destroyInstanceGroup(groupHandle)
  • getInstanceGroupInfo(groupHandle)

`aura.material`

Material surface:

  • create(options)
  • createCustom(options)
  • setColor(materialHandle, color)
  • setTexture(materialHandle, texturePath)
  • setNormalMap(materialHandle, input)
  • setMetallicRoughnessTexture(materialHandle, input)
  • setOcclusionTexture(materialHandle, input)
  • setEmissiveTexture(materialHandle, input)
  • setMetallic(materialHandle, metallic)
  • setRoughness(materialHandle, roughness)
  • setMetallicRoughness(materialHandle, metallic, roughness)
  • setBlendMode(materialHandle, mode)
  • setTextureTransform(materialHandle, options)
  • setEmissive(materialHandle, color, strength?)
  • setClearcoat(materialHandle, clearcoat, roughness?)
  • setRenderTargetTexture(materialHandle, input)
  • setRenderOrder(materialHandle, order)
  • setTransmission(materialHandle, value)
  • setAlphaCutoff(materialHandle, value)
  • setAlphaMode(materialHandle, mode)
  • setDoubleSided(materialHandle, enabled)
  • setSheen(materialHandle, roughness, color)
  • setSpecularFactor(materialHandle, value)
  • setSpecularColor(materialHandle, color)
  • setOcclusionStrength(materialHandle, value)
  • setIOR(materialHandle, value)
  • setThickness(materialHandle, value)
  • setShadingModel(materialHandle, model)
  • setToonSteps(materialHandle, value)
  • setToonEdge(materialHandle, value)
  • setIridescence(materialHandle, factor, ior?, thicknessMin?, thicknessMax?)
  • setAnisotropy(materialHandle, strength, rotation?)
  • setClippingPlanes(materialHandle, planes)
  • clearClippingPlanes(materialHandle)
  • setUniform(materialHandle, name, value)
  • setCustomTexture(materialHandle, texturePath)
  • setCustomTexture(materialHandle, slotNameOrIndex, texturePath)
  • setStencil(materialHandle, options)
  • clearStencil(materialHandle)
  • createDataTexture(width, height, pixelData, options?)
  • updateDataTexture(dataTextureHandle, pixelData)
  • destroyDataTexture(dataTextureHandle)
  • reset(materialHandle)
  • clone(materialHandle)
  • unload(materialHandle)

Current material-authoring truth:

  • advanced PBR knobs such as alphaCutoff, doubleSided, clearcoat, sheenColor, sheenRoughness, specularFactor, and specularColor are already available at material creation time
  • runtime setter parity now also covers setAlphaCutoff, setAlphaMode, setDoubleSided, setSheen, setSpecularFactor, setSpecularColor, setOcclusionStrength, and the secondary texture setters setNormalMap, setMetallicRoughnessTexture, setOcclusionTexture, and setEmissiveTexture
  • secondary texture setters accept either a string asset path, a DataTextureHandle, or null; the current non-albedo data-texture path is a snapshot-at-bind seam rather than a live-linked material slot
  • some advanced knobs still remain create-time only, including the texture-backed sheen/specular lanes and broader subsurface-style material breadth
  • treat data textures, texture transforms, and stencil as shipped material-side surfaces today rather than future-work rumors

Custom-shader guidance:

  • createCustom(options) is a narrow advanced seam, not the default material path. Use it when standard PBR material controls cannot express the effect you need.
  • uniforms declares only scalar/vector/matrix data. Texture access is declared separately with texture: true for one legacy slot or textures: ['base', 'accent'] for named multi-slot contracts, then mutated later with setCustomTexture(...).
  • setUniform(...) and setCustomTexture(...) return stable structured failure reasons on contract errors such as unknown uniforms, invalid uniform values, or missing texture declaration.
  • Bad WGSL can still fail later on the native compile path even after a handle is returned. Treat the public proof slices and conformance cases as the truth surface for what is actually frozen.

Reusable shader-kit guidance:

  • AuraJS now also ships a plain-JS shader-kit layer at @auraindustry/aurajs/shader-kits for reusable authored presets over this same custom-material seam.
  • Current shipped presets are:
    • hologram / fresnel
    • dissolve
    • foliage / wind
    • rim / emissive accent
  • These kits are convenience wrappers over createCustom(...), setUniform(...), and setCustomTexture(...). They are not a shader graph, material editor, or a broader renderer abstraction.

`aura.scene3d`

Hierarchy and transform helpers

  • createNode(initialTransform?)
  • removeNode(nodeId)
  • setParent(nodeId, parentId)
  • getParent(nodeId)
  • setLocalTransform(nodeId, transform)
  • getLocalTransform(nodeId)
  • getWorldTransform(nodeId)
  • traverse(rootNodeId, callback)

Interaction query helpers

  • screenToRay(pixelX, pixelY)
  • pick(pixelX, pixelY, options?)
  • queryRaycast(originOrOptions, maybeDirection?, maybeOptions?)
  • raycast(origin, direction, options?)

Current query truth:

  • queryRaycast(...) and pick(...) operate on retained scene3d nodes and return authored node identity such as nodeId, plus current render-binding identity like layer, meshHandle, materialHandle, visible, and hasRenderBinding
  • queryRaycast(...) supports retained-scene filters such as firstOnly, visibleOnly, requireRenderBinding, layerMask, includeNodeIds, and excludeNodeIds
  • raycast(...) is the submitted draw-mesh lane; it returns mesh hits and optional triangle hits, but not retained scene3d node identity
  • use physics3d.queryRaycast(...) instead when the query must follow physics bodies and physics-world filters rather than retained scene/render identity

Render binding and culling helpers

  • bindRenderNode(nodeId, meshHandle, materialHandle, options?)
  • unbindRenderNode(nodeId)
  • setNodeVisibility(nodeId, visible)
  • setNodeLayer(nodeId, layer)
  • setNodeCulling(nodeId, enabled, options?)
  • setNodeLod(nodeId, lodSpec)
  • clearNodeLod(nodeId)
  • getNodeLod(nodeId)
  • getLodState()
  • setCameraLayerMask(mask)
  • setCullBounds(bounds)
  • clearCullBounds()
  • submitRenderBindings(options?)
  • getRenderSubmissionState()

glTF import helpers

Current import-related surface spans both metadata helpers and normalized import-record helpers:

  • loadGltfScene(path, options?)
  • unloadGltfScene(importId)
  • getImportedScene(importId)
  • getImportedSceneMetadata(importId)
  • getImportedCameras(importId)
  • getImportedLights(importId)
  • getImportedAnimations(importId)
  • playImportedAnimation(importId, animationName, options?)

Current native importer notes:

  • .gltf external buffer files resolve relative to the source asset path.
  • Sparse animation accessors are supported in the native import path.
  • Invalid external URI schemes or malformed sparse payloads fail with stable import reason codes.

Clip and crossfade helpers

  • createClip(options)
  • playClip(clipId)
  • pauseClip(clipId)
  • resumeClip(clipId)
  • seekClip(clipId, time)
  • setClipWeight(clipId, weight)
  • setClipLoop(clipId, loop)
  • setClipSkinning(clipId, options)
  • crossfadeClips(fromClipId, toClipId, options)
  • updateClips(dt)
  • onClipEvent(clipId, callback, order?)
  • getClipState(clipId)

Avatar runtime helpers

  • createAvatar(options)
  • updateAvatars(dt, avatars?)

The current avatar runtime sits on top of scene3d imported-scene bindings, clip playback, and character3d. The returned avatar object exposes:

  • spawn(spawnOptions?)
  • destroy()
  • setInput(input)
  • jump(velocity?)
  • setVisual(options) / bindModel(options)
  • setAnimations(animations, options?)
  • setAnimationState(options)
  • defineSocket(name, options?)
  • attach(socketName, sceneNodeId, options?)
  • detach(socketName)
  • getSockets()
  • onAnimationEvent(callback)
  • playAnimation(clipKeyOrEntry, options?)
  • getAvailableAnimations()
  • clearAnimation()
  • setPosition(position)
  • getRenderTransform()
  • getState()
  • tick(dtSeconds)

Practical imported-avatar path:

const imported = aura.scene3d.loadGltfScene('examples/starter-templates/3d/assets/models/starter-avatar.gltf', {
  bindRenderNodes: true,
  visible: true,
  cull: false,
});

const avatar = aura.scene3d.createAvatar({
  spawn: false,
  sceneNodeId: imported.nodeHandles[0].nodeId,
  importId: imported.importId,
  animations: {
    idle: 'Idle',
    walk: 'Walk',
    run: 'Run',
    jump: 'Jump',
    fall: 'Fall',
  },
  camera: {
    offset: { x: 0, y: 2.7, z: -6.8 },
    lookOffset: { x: 0, y: 0.72, z: 0 },
    rotateWithFacing: true,
  },
});

avatar.spawn();
avatar.setInput({ moveX: 1, run: true });
avatar.tick(dt);
aura.scene3d.submitRenderBindings();

Honest boundary:

  • the current proof asset is the shipped starter-avatar.gltf fixture
  • it is a compact committed transform-rigged avatar, not a production skinned hero asset
  • use aura.skinnedMesh when you need direct skeleton/joint ownership rather than the higher-level imported-avatar runtime path

`aura.skinnedMesh`

Dedicated skinned-mesh namespace:

  • create(options)
  • setJointTransforms(handle, transforms)
  • playAnimation(handle, clipName, options?)
  • stopAnimation(handle)
  • blendAnimations(handle, fromClip, toClip, options?)
  • getJointPosition(handle, jointNameOrIndex)
  • addClip(handle, clipSpec)

Practical split of responsibilities

Use these namespaces this way:

  • aura.mesh: create/load mesh assets and procedural geometry
  • aura.material: create and mutate materials
  • aura.scene3d: node hierarchy, imported-scene metadata, render binding, raycasts, clips, avatar runtime
  • aura.skinnedMesh: dedicated skinned character helpers
  • aura.draw3d: actual draw submission
DOCUMENT REFERENCE
docs/external/game-dev-api/09-meshes-materials-scene3d-gltf-and-skinned-mesh.md
AURAJS
Cmd/Ctrl+K
aurajsgg