@pixi/3d
    Preparing search index...

    Class Mesh3D

    A drawable node: a Geometry3D drawn with a BaseMaterial3D

    Add it anywhere under view.root and the view draws it in the passes its material and settings call for: opaque, transparent, shadow and so on. A mesh with a Skeleton bends with its bones, and one whose geometry has morph targets blends them by its weights. For thousands of copies, BatchedMesh3D draws them without a node each.

    The geometry and material can come later: until it has both, a mesh draws nothing. Assigning them, before or after the mesh joins a view, gives the same mesh as passing them to the constructor, and a Mesh3D#castShadow, Mesh3D#enablePass or Mesh3D#disablePass change made while it waits applies once it has both.

    import { Mesh3D, Material3D } from '@pixi/3d';

    const mesh = new Mesh3D({ geometry, material: new Material3D({ baseColor: 0xff8844 }) });
    mesh.position.set(0, 1, 0);
    view.root.addChild(mesh);

    // Skinned mesh:
    const skinned = new Mesh3D({ geometry: skinnedGeometry, material, skeleton });

    // Geometry and material assigned later:
    const later = new Mesh3D({ parent: view.root });
    later.geometry = geometry;
    later.material = material;

    // Toggle shadow casting at runtime:
    mesh.castShadow = false;

    Mesh3DOptions For the constructor options.

    Hierarchy (View Summary)

    Index
    boundsVolume: Box | null = null

    A fixed local-space box measured in place of this container and its subtree, or null to measure the geometry

    Set one on a large subtree whose extent you already know, such as a level chunk, to skip walking it. getLocalBounds and the size members read it. It's pixi's boundsArea; it doesn't change culling.

    swarm.boundsVolume = new Box(new Vector3(-10, 0, -10), new Vector3(10, 5, 10));
    
    children: Container3D[] = []

    Child nodes

    Their order doesn't decide what draws first. Read the array, but change it through addChild and removeChild. To visit the whole subtree, use traverse.

    for (const child of group.children) child.visible = false;
    
    cursor: string & {} | Cursor | null

    CSS cursor shown while this node is the pointer's target

    Only the target's own cursor counts, as in 2D: a hit on a 'passive' child shows its interactive ancestor's cursor, so set it on the node with the listeners. null shows the View3D's own cursor. Any CSS cursor value works, url(...) included.

    null
    
    button.cursor = 'pointer';
    handle.cursor = 'grab';
    blade.cursor = 'url("crosshair.png") 8 8, crosshair'; // custom, with a hotspot
    destroyed: boolean = false

    Whether destroy has run, as in pixi's Container

    eventMode: EventMode

    How this node takes part in pointer events, as on a pixi.js Container

    • 'none': never picked, and neither is anything below it. The subtree costs nothing per pointer event.
    • 'passive' (default): fires no listeners and is never the target. Under an interactive ancestor it is still picked, and the hit goes to that ancestor with this node's surface data. So one 'static' group makes its whole subtree clickable, with the group as target.
    • 'auto': as 'passive', but ray-tested even with no interactive ancestor, which costs time and finds no target. Prefer 'passive'.
    • 'static': picked against its hitVolume, and fires listeners.
    • 'dynamic': as 'static', and the View3D also picks again while a mouse or pen is still, so a node that moves under it gets its enter and leave events.

    The renderer's eventMode option only sets the default for 2D containers, and the View warns once when it isn't 'passive'. Picking costs time for each node that takes part, so set the mode on the nodes and groups that need it.

    'passive'
    
    button.eventMode = 'static';   // a clickable mesh
    spinner.eventMode = 'dynamic'; // it moves under a still pointer
    panel.eventMode = 'none'; // decoration; skip it and its children

    // A whole model that answers as one target; its meshes need no setup
    robot.eventMode = 'static';
    hitVolume: HitVolume3DInput

    Shape the pointer ray is tested against when picking this node, like hitArea in 2D

    Setting it doesn't make the node interactive; eventMode does that. Left null, a Mesh3D uses its geometry's bounding box and a plain Container3D has no shape, so it only hears events from its children.

    A shape you set also clips the node's descendants, as hitArea does in 2D: a descendant only hits where the hit point is inside every such shape above it, whatever those nodes' eventMode. A clipped hit doesn't block what is behind it. A Geometry3D clips by its bounding box, an IHitVolume3D only through its optional containsPoint, and the default bounding box never clips. A ray that misses a Box or Sphere shape, or a Geometry3D's bounding box, skips the exact test of every descendant under it.

    null
    
    mesh.interactive = true;                  // picked by its bounding box
    mesh.hitVolume = 'geometry'; // picked per triangle
    mesh.hitVolume = new Sphere(center, 0.4); // a cheaper or tighter shape
    mesh.hitVolume = null; // back to the bounding box

    // Children of the porthole only pick inside its sphere
    porthole.hitVolume = new Sphere(new Vector3(), 1);

    HitVolume3DInput For what each accepted value resolves to.

    interactive: boolean

    Shorthand for eventMode, as on a pixi.js Container

    true sets 'static' and false sets 'passive'. It reads true for 'static' and 'dynamic'. false doesn't stop picking: under an interactive ancestor, a 'passive' node is still picked on that ancestor's behalf. Set eventMode = 'none' to take a node and its subtree out of picking.

    mesh.interactive = true;  // eventMode = 'static'
    mesh.interactive = false; // eventMode = 'passive'
    interactiveChildren: boolean

    Whether this node's descendants can be picked, as on a pixi.js Container

    false takes the whole subtree out of picking: descendants neither hit nor block what is behind them, and cost nothing per pointer event. The node itself still picks by its own eventMode and volume, so it can answer for the subtree.

    true
    
    menu.interactiveChildren = false; // nothing in the menu can be picked
    menu.interactiveChildren = true; // every button picks again, eventMode intact

    // One sphere answers for the whole robot: one ray test instead of one per mesh
    robot.eventMode = 'static';
    robot.hitVolume = new Sphere(new Vector3(), 2);
    robot.interactiveChildren = false;
    label: string | null = null

    Name to find the node by, with getChildByLabel

    Animation tracks find their target by it too. A plain Container3D starts with null; built-in subclasses such as Mesh3D start with their class name.

    turret.label = 'turret';
    tank.getChildByLabel('turret', true)?.lookAt(target);
    localTransform: Matrix4 = ...

    Local transform matrix, built from the position, rotation, scale and origin

    It catches up with changes in the view's transform pass, or when you call updateLocalTransform. Read it, but change the components instead: the next rebuild overwrites it.

    onclick: Pointer3DEventHandler | null

    Property-based handler for the click event

    Fired when a mouse click on this node completes, with any button but the right one.

    null
    
    mesh.eventMode = 'static';
    mesh.onclick = (e) => {
    if (e.hit3D) marker.position.copyFrom(e.hit3D.point);
    };

    IFederatedContainer3D#onpointertap For the equivalent for every pointer type.

    oncontextmenu: Pointer3DEventHandler | null

    Property-based handler for the contextmenu event

    Fired when the browser is about to open its context menu over this node; call preventDefault() to keep it closed.

    null
    
    mesh.oncontextmenu = (e) => {
    e.preventDefault();
    openMenuFor(mesh, e.global);
    };
    onglobalmousemove: Pointer3DEventHandler | null

    Property-based handler for the globalmousemove event

    Fired on every mouse move, wherever the pointer is on the page.

    null
    
    mesh.onglobalmousemove = (e) => {
    if (dragging) dragTo(e.global);
    };

    IFederatedContainer3D#onglobalpointermove For the equivalent for every pointer type.

    onglobalpointermove: Pointer3DEventHandler | null

    Property-based handler for the globalpointermove event

    Fired on every pointer move on the page, whether or not the pointer is over this node. The node still needs eventMode 'static' or 'dynamic' to hear it.

    null
    
    // Keep a drag going once the pointer runs off the dragged mesh
    mesh.onglobalpointermove = (e) => {
    const hit = dragging && view3d.screenToWorld(e.global, ground);
    if (hit) mesh.position.copyFrom(hit);
    };
    onglobaltouchmove: Pointer3DEventHandler | null

    Property-based handler for the globaltouchmove event

    Fired on every touch move, wherever the touch is on the page.

    null
    
    mesh.onglobaltouchmove = (e) => {
    if (dragging) dragTo(e.global);
    };

    IFederatedContainer3D#onglobalpointermove For the equivalent for every pointer type.

    onmousedown: Pointer3DEventHandler | null

    Property-based handler for the mousedown event

    Fired when a mouse button other than the right one goes down over this node.

    null
    
    mesh.onmousedown = (e) => {
    if (e.button === 1) startPan(e.global); // middle button
    };

    IFederatedContainer3D#onpointerdown For the equivalent for every pointer type.

    onmouseenter: Pointer3DEventHandler | null

    Property-based handler for the mouseenter event

    Fired when the mouse enters this node. Doesn't bubble.

    null
    
    mesh.onmouseenter = () => (tooltip.visible = true);
    

    IFederatedContainer3D#onpointerenter For the equivalent for every pointer type.

    onmouseleave: Pointer3DEventHandler | null

    Property-based handler for the mouseleave event

    Fired when the mouse leaves this node. Doesn't bubble.

    null
    
    mesh.onmouseleave = () => (tooltip.visible = false);
    

    IFederatedContainer3D#onpointerleave For the equivalent for every pointer type.

    onmousemove: Pointer3DEventHandler | null

    Property-based handler for the mousemove event

    Fired while the mouse moves across this node.

    null
    
    mesh.onmousemove = (e) => tooltip.position.copyFrom(e.global);
    

    IFederatedContainer3D#onpointermove For the equivalent for every pointer type.

    onmouseout: Pointer3DEventHandler | null

    Property-based handler for the mouseout event

    Fired when the mouse moves off this node. Bubbles, unlike mouseleave.

    null
    
    shelf.onmouseout = (e) => unhighlight(e.target3D);
    

    IFederatedContainer3D#onpointerout For the equivalent for every pointer type.

    onmouseover: Pointer3DEventHandler | null

    Property-based handler for the mouseover event

    Fired when the mouse moves onto this node. Bubbles, unlike mouseenter.

    null
    
    // One handler on the shelf hears every item on it
    shelf.onmouseover = (e) => highlight(e.target3D);

    IFederatedContainer3D#onpointerover For the equivalent for every pointer type.

    onmouseup: Pointer3DEventHandler | null

    Property-based handler for the mouseup event

    Fired when a mouse button other than the right one is released over this node.

    null
    
    mesh.onmouseup = (e) => {
    if (e.button === 1) endPan();
    };

    IFederatedContainer3D#onpointerup For the equivalent for every pointer type.

    onmouseupoutside: Pointer3DEventHandler | null

    Property-based handler for the mouseupoutside event

    Fired when a mouse button that went down on this node is released anywhere else.

    null
    
    mesh.onmouseupoutside = () => endPan();
    

    IFederatedContainer3D#onpointerupoutside For the equivalent for every pointer type.

    onpointercancel: Pointer3DEventHandler | null

    Property-based handler for the pointercancel event

    Never called: pixi delivers no pointer cancellation, in 2D either.

    null
    
    // End a drag on these two instead
    handle.onpointerup = endDrag;
    handle.onpointerupoutside = endDrag;
    onpointerdown: Pointer3DEventHandler | null

    Property-based handler for the pointerdown event

    Fired when a pointer goes down on this node: mouse, touch or pen alike.

    null
    
    handle.eventMode = 'static';
    handle.onpointerdown = (e) => {
    if (!e.hit3D) return;
    dragOffset.copyFrom(e.hit3D.localPoint); // where on the handle it was grabbed
    dragging = true;
    };
    onpointerenter: Pointer3DEventHandler | null

    Property-based handler for the pointerenter event

    Fired when a pointer enters this node. Doesn't bubble, so an ancestor hears it only when the pointer enters the ancestor itself.

    null
    
    button.eventMode = 'static';
    button.onpointerenter = () => button.scale.set(1.1);
    onpointerleave: Pointer3DEventHandler | null

    Property-based handler for the pointerleave event

    Fired when a pointer leaves this node. Doesn't bubble.

    null
    
    button.onpointerleave = () => button.scale.set(1);
    
    onpointermove: Pointer3DEventHandler | null

    Property-based handler for the pointermove event

    Fired while a pointer moves across this node.

    null
    
    // Trail the cursor across the surface it is over
    table.eventMode = 'static';
    table.onpointermove = (e) => {
    if (e.hit3D) cursorMarker.position.copyFrom(e.hit3D.point);
    };
    onpointerout: Pointer3DEventHandler | null

    Property-based handler for the pointerout event

    Fired when a pointer moves off this node. Bubbles, unlike pointerleave.

    null
    
    shelf.onpointerout = (e) => unhighlight(e.target3D);
    
    onpointerover: Pointer3DEventHandler | null

    Property-based handler for the pointerover event

    Fired when a pointer moves onto this node. Bubbles, unlike pointerenter.

    null
    
    // One handler on the shelf hears every item on it
    shelf.onpointerover = (e) => highlight(e.target3D);
    onpointertap: Pointer3DEventHandler | null

    Property-based handler for the pointertap event

    Fired when a pointer completes a tap on this node, for any pointer type and any button, right clicks included.

    null
    
    // Works for mouse, touch and pen alike
    mesh.eventMode = 'static';
    mesh.onpointertap = (e) => select(e.target3D);
    onpointerup: Pointer3DEventHandler | null

    Property-based handler for the pointerup event

    Fired when a pointer is released over this node.

    null
    
    handle.onpointerup = () => {
    dragging = false;
    };
    onpointerupoutside: Pointer3DEventHandler | null

    Property-based handler for the pointerupoutside event

    Fired when a pointer that went down on this node is released anywhere else. The event's target3D is the node that was pressed, and hit3D is what the pointer was released over.

    null
    
    // The release that ends a drag usually happens off the mesh
    handle.onpointerupoutside = () => {
    dragging = false;
    };
    onrightclick: Pointer3DEventHandler | null

    Property-based handler for the rightclick event

    Fired when a right click completes on this node.

    null
    
    mesh.onrightclick = () => openMenuFor(mesh);
    
    onrightdown: Pointer3DEventHandler | null

    Property-based handler for the rightdown event

    Fired when the right mouse button goes down over this node.

    null
    
    mesh.onrightdown = (e) => startRotate(e.global);
    
    onrightup: Pointer3DEventHandler | null

    Property-based handler for the rightup event

    Fired when the right mouse button is released over this node.

    null
    
    mesh.onrightup = endRotate;
    
    onrightupoutside: Pointer3DEventHandler | null

    Property-based handler for the rightupoutside event

    Fired when the right mouse button that went down on this node is released anywhere else.

    null
    
    mesh.onrightupoutside = endRotate;
    
    ontap: Pointer3DEventHandler | null

    Property-based handler for the tap event

    Fired when a touch completes a tap on this node. Chrome gives each touch a new pointerId, and detail only counts repeat taps by the same one, so it stays 1 there; time a double tap yourself.

    null
    
    let lastTap = 0;
    mesh.ontap = (e) => {
    if (e.timeStamp - lastTap < 300) focusOn(mesh); // double tap
    lastTap = e.timeStamp;
    };

    IFederatedContainer3D#onpointertap For the equivalent for every pointer type.

    ontouchcancel: Pointer3DEventHandler | null

    Property-based handler for the touchcancel event

    Never called: pixi delivers no touch cancellation, in 2D either.

    null
    
    // End a drag on these two instead
    handle.ontouchend = endDrag;
    handle.ontouchendoutside = endDrag;
    ontouchend: Pointer3DEventHandler | null

    Property-based handler for the touchend event

    Fired when a touch lifts off this node.

    null
    
    handle.ontouchend = endDrag;
    

    IFederatedContainer3D#onpointerup For the equivalent for every pointer type.

    ontouchendoutside: Pointer3DEventHandler | null

    Property-based handler for the touchendoutside event

    Fired when a touch that started on this node lifts off anywhere else.

    null
    
    handle.ontouchendoutside = endDrag;
    

    IFederatedContainer3D#onpointerupoutside For the equivalent for every pointer type.

    ontouchmove: Pointer3DEventHandler | null

    Property-based handler for the touchmove event

    Fired while a touch moves across this node.

    null
    
    canvasMesh.hitVolume = 'geometry'; // per triangle, so hits carry a uv
    canvasMesh.ontouchmove = (e) => {
    if (e.hit3D) paintAt(e.hit3D.uv);
    };

    IFederatedContainer3D#onpointermove For the equivalent for every pointer type.

    ontouchstart: Pointer3DEventHandler | null

    Property-based handler for the touchstart event

    Fired when a touch lands on this node.

    null
    
    handle.ontouchstart = (e) => startDrag(e.pointerId);
    

    IFederatedContainer3D#onpointerdown For the equivalent for every pointer type.

    onwheel: Wheel3DEventHandler | null

    Property-based handler for the wheel event

    Fired when the wheel turns while the pointer is over this node.

    null
    
    // Scroll to push the panel away from the camera
    panel.eventMode = 'static';
    panel.onwheel = (e) => {
    panel.position.z += e.deltaY * 0.01;
    };
    parent: Container3D | null = null

    Parent node, or null for a node with none, such as a view's root

    receiveShadow: boolean

    Whether this mesh is shadowed by lights that cast shadows

    Only lit materials take shadows. After changing it at runtime, call invalidate.

    water.receiveShadow = false;
    water.invalidate();
    skeleton?: Skeleton

    Skeleton that deforms this mesh; undefined for a mesh that doesn't bend

    Fixed at construction: to change it, build a new mesh.

    const head = mesh.skeleton?.indexOf('Head');
    
    uid: number = ...

    Unique id, assigned at construction

    worldTransform: Matrix4 = ...

    World transform: the parent's world transform times this node's localTransform

    The view updates it once per frame, before drawing, for visible nodes only, and not at all while the view holds no mesh. So it can be out of date after a change this frame or while the node or an ancestor is hidden, and a node outside any view keeps the identity matrix. getGlobalTransform always works out a current one.

    defaultOptions: Partial<Mesh3DOptions> = ...

    Defaults for every new Mesh3D; an option passed as undefined keeps its default

    Mesh3D.defaultOptions.castShadow = false;
    const mesh = new Mesh3D({ geometry, material }); // picks up the override above
    • get angle(): PointLike3D

      rotation in degrees, as in pixi.js

      It reads and writes rotation, so the two always agree. Reading converts back from radians, so a value can come back a hair off, such as 30 as 29.999999999999996; compare with a tolerance.

      Returns PointLike3D

      node.angle.y = 90; // same as node.rotation.y = Math.PI / 2
      node.angle = { x: 0, y: 45, z: 0 };
    • set angle(value: PointData3D): void

      Sets the Euler rotation and makes it the rotation in use, even when the values are unchanged

      Parameters

      Returns void

    • get billboardMode(): BillboardMode

      How this mesh turns to face the camera; see BillboardMode for the modes

      Local +Z turns to face the viewer, so author a card facing +Z; any material works, lit or unlit. A solid mesh keeps its depth and the scale along each axis as it turns, but loses the shear of a non-uniformly scaled parent under a rotation. Its shadow and its culling use the unturned mesh, so geometry off-centre from its origin can be culled while on screen, and meshes with different modes don't share a draw.

      Returns BillboardMode

      card.billboardMode = 'cylindrical';
      
    • set billboardMode(value: BillboardMode): void

      Sets how the mesh turns to face the camera

      Parameters

      • value: BillboardMode

        How to orient the mesh toward the camera, or 'none' to draw it as authored.

      Returns void

    • get boundingSphere(): Sphere

      This mesh's bounding Sphere in world space, large enough for morph weights from 0 to 1

      Cached until the world transform or geometry changes, so reading it often is cheap. It follows worldTransform, so it can be out of date after a change this frame. Dynamic geometry gives an empty sphere (radius < 0). The sphere is shared: don't change it, and clone() it to keep a copy.

      Returns Sphere

      if (camera.frustum.intersectsSphere(enemy.boundingSphere)) enemy.lookAt(player.position);
      
    • get castShadow(): boolean

      Whether this mesh casts shadows

      A mesh whose material has alphaMode: 'blend', or uses transmission, casts none even while this is true. Setting it is enablePass('shadow') or disablePass('shadow').

      Returns boolean

      grass.castShadow = false;
      
    • set castShadow(value: boolean): void

      Sets whether the mesh casts shadows, from the next render

      Parameters

      • value: boolean

        Whether the mesh casts shadows.

      Returns void

    • get depth(): number

      Depth along local z: |scale.z| × local bounds depth

      Assigning writes scale.z only; see width.

      Returns number

      bench.depth = 0.5;
      
    • set depth(value: number): void

      Scales along z so the depth becomes value

      Parameters

      • value: number

        Target depth along z

      Returns void

    • get geometry(): Geometry3D

      The geometry this mesh draws; Geometry3D.EMPTY until it's given one

      Returns Geometry3D

      rock.geometry = isFar ? lowDetailRock : highDetailRock;
      
    • set geometry(value: Geometry3D): void

      Swaps the geometry, refitting a hitVolume given as 'box' or 'geometry'

      A geometry with as many morph targets as there are Mesh3D#weights keeps them; one with a different count gets new weights, all 0; one with none leaves weights undefined.

      Parameters

      Returns void

    • get height(): number

      Height along local y: |scale.y| × local bounds height

      Assigning writes scale.y only; see width.

      Returns number

      tree.height = 6;
      
    • set height(value: number): void

      Scales along y so the height becomes value

      Parameters

      • value: number

        Target height along y

      Returns void

    • get material(): BaseMaterial3D

      The material this mesh draws with; BaseMaterial3D.EMPTY until it's given one

      Many meshes can draw one material, and a value written to it shows on all of them. A Model3D's meshes draw its source's materials, shared with every model built from that source; Model3D#materials gives one model copies of its own. For one mesh alone, assign mesh.material.clone({ baseColor: 0xff0000 }), and destroy the copy when you're done with it.

      Returns BaseMaterial3D

      crate.material = selected ? highlightMaterial : crateMaterial;
      
    • set material(value: BaseMaterial3D): void

      Swaps the material

      Parameters

      Returns void

    • get origin(): ObservableVector3

      Point in local space that rotation and scale happen around, as in pixi.js

      Unlike a pivot, it leaves an unrotated, unscaled node where it is: the origin sits at position + origin in the parent. Assigning copies the values in, and a single number sets all three axes.

      Returns ObservableVector3

      // Tip a crate over its bottom-right edge without moving it first.
      crate.origin = { x: 0.5, y: -0.5, z: 0 };
      crate.angle.z = -90;
    • set origin(value: number | PointData3D): void

      Sets the origin; a number sets all three axes

      Parameters

      • value: number | PointData3D

        The new origin, in local space

      Returns void

    • get position(): ObservableVector3

      Local position

      Assigning copies the values in; the object itself never changes.

      Returns ObservableVector3

      node.position.set(0, 1, 0);
      node.position = { x: 0, y: 1, z: 0 };
    • set position(value: PointData3D): void

      Sets the local position

      Parameters

      Returns void

    • get quaternion(): ObservableQuaternion

      Local rotation as a unit quaternion; see rotation for which of the two is in use

      Assigning copies the values in, so node.quaternion = other.quaternion doesn't link the two.

      Returns ObservableQuaternion

      node.quaternion = other.quaternion;
      node.quaternion = { x: 0, y: Math.SQRT1_2, z: 0, w: Math.SQRT1_2 };
    • set quaternion(value: QuaternionData): void

      Sets the quaternion and makes it the rotation in use, even when the values are unchanged

      Parameters

      Returns void

    • get renderPassMask(): number
      Advanced

      The RenderPassBit flags of the passes that draw this mesh: its material's passes, plus SHADOW while it casts shadows, or none while it holds Geometry3D.EMPTY or BaseMaterial3D.EMPTY

      The mesh's own Mesh3D#enablePass and Mesh3D#disablePass win over its material's, and a blended or transmissive material casts no shadow.

      Returns number

      const castsShadow = (mesh.renderPassMask & RenderPassBit.SHADOW) !== 0;
      
    • get rotation(): ObservableVector3

      Local rotation as Euler angles in radians: turns around Z, then Y, then X, each about the parent's axes

      The node keeps both this and quaternion, and whichever you set last is the rotation in use. Assigning copies the values in. Writing unchanged values to either through a component, set or copyFrom doesn't switch which one is in use; assign it whole.

      Returns ObservableVector3

      node.rotation.y = Math.PI / 2;
      node.rotation = { x: 0, y: Math.PI / 2, z: 0 };
    • set rotation(value: PointData3D): void

      Sets the Euler rotation and makes it the rotation in use, even when the values are unchanged

      Parameters

      Returns void

    • get scale(): ObservableVector3

      Local scale

      Assigning copies the values in, and a single number scales all three axes; the object itself never changes.

      Returns ObservableVector3

      node.scale.set(2, 1, 1);
      node.scale = 2; // uniform
    • set scale(value: number | PointData3D): void

      Sets the local scale; a number sets all three axes

      Parameters

      Returns void

    • get visible(): boolean

      Whether this container and its descendants draw

      Hiding is cheap, and a hidden node stays in the scene; to take it out, remove it with removeChild. Emits visibleChanged when the value changes.

      Returns boolean

      door.visible = false;
      
    • set visible(value: boolean): void

      Shows or hides this container and its descendants

      Parameters

      • value: boolean

        Whether they draw

      Returns void

    • get weights(): Float32Array<ArrayBufferLike> | undefined

      Morph target weights, one per target; undefined when the geometry has no morph targets

      Change its values at any time rather than assigning a new array: a playing animation keeps writing the old one, and the parts a model node's mesh splits into share one array, so a new array cuts this mesh loose from both.

      Returns Float32Array<ArrayBufferLike> | undefined

      if (face.weights) face.weights[smileIndex] = 0.8;
      
    • set weights(value: Float32Array<ArrayBufferLike> | undefined): void

      Replaces the weights array; does nothing when the geometry has no morph targets or value is undefined

      Parameters

      • value: Float32Array<ArrayBufferLike> | undefined

        New weights, one per morph target.

      Returns void

    • get width(): number

      Width along local x: |scale.x| × local bounds width

      Assigning writes scale.x only. To set several axes, setSize measures the bounds once instead of once per axis.

      Returns number

      crate.width = 2;
      
    • set width(value: number): void

      Scales along x so the width becomes value

      Parameters

      • value: number

        Target width along x

      Returns void

    • get worldVisible(): number

      1 when this node and every ancestor are visible, otherwise 0

      The view works it out once per frame, so it lags a visible change until the next render.

      Returns number

    • get x(): number

      Local position on the x axis; the same as position.x

      Returns number

      player.x += speed * dt;
      
    • set x(value: number): void

      Sets position.x

      Parameters

      • value: number

        The new x position

      Returns void

    • get y(): number

      Local position on the y axis; the same as position.y

      Returns number

      ball.y = Math.abs(Math.sin(time)) * 2;
      
    • set y(value: number): void

      Sets position.y

      Parameters

      • value: number

        The new y position

      Returns void

    • get z(): number

      Local position on the z axis; the same as position.z

      Returns number

      if (car.z > finishLine) finish();
      
    • set z(value: number): void

      Sets position.z

      Parameters

      • value: number

        The new z position

      Returns void

    • Adds one or more children to the end of this container's child list

      A child with another parent leaves it first. A child that is already here moves to the end, without events.

      Type Parameters

      Parameters

      • ...children: U

        The children to add

      Returns U[0]

      The first added child

      view.root.addChild(crate, lamp);
      
    • Adds child at index, or moves it there when it is already a child of this container

      A move within this container emits no events.

      Type Parameters

      Parameters

      • child: U

        The child to add or move

      • index: number

        The destination index

      Returns U

      The added child

      rack.addChildAt(sword, 0);
      

      When index is out of bounds.

    • Takes this mesh out of a render pass, whatever its material says

      The mesh leaves the pass on the next render, and other meshes sharing the material stay in it. disablePass('opaque') draws nothing of the mesh while it still casts its shadow. Only the named pass is left, so a material that later turns 'blend' brings the mesh into the transparent pass. Mesh3D#enablePass undoes it. Does nothing for a pass name nothing has used yet.

      Parameters

      • name: string

        The pass's name, such as 'opaque'.

      Returns void

      shadowProxy.disablePass('opaque');
      
    • Adds this mesh to a render pass, whatever its material says

      BaseMaterial3D#enablePass for one mesh: the pass draws this mesh from the next render, and other meshes sharing the material don't follow. It undoes this mesh's own disablePass for the pass. 'shadow' is the same as setting castShadow.

      Parameters

      • name: string

        The pass's name, such as 'outline'.

      Returns void

      hovered.enablePass('outline');
      
    • Gets the child at index

      Type Parameters

      Parameters

      • index: number

        Index of the child to fetch

      Returns U

      The child at index

      const first = group.getChildAt(0);
      

      When index is out of bounds.

    • Returns the first child whose label matches, or null

      Each container checks its direct children before searching inside them. An unlabelled node never matches, even a pattern.

      Parameters

      • label: string | RegExp

        Exact label, or a pattern to test labels against

      • deep: boolean = false

        Whether to search the whole subtree, not only direct children

      Returns Container3D | null

      The first match, or null when nothing matches

      const wheel = car.getChildByLabel('wheel_front_left', true);
      const anyWheel = car.getChildByLabel(/^wheel_/, true);
    • Gets the index of child within this container

      Parameters

      Returns number

      The child's index

      const slot = rack.getChildIndex(sword);
      

      When child is not a child of this container.

    • Collects every child whose label matches, in the order Container3D.getChildByLabel visits them

      Parameters

      • label: string | RegExp

        Exact label, or a pattern to test labels against

      • deep: boolean = false

        Whether to search the whole subtree, not only direct children

      • out: Container3D[] = []

        Array the matches are appended to; a new one when omitted

      Returns Container3D[]

      out

      const wheels = car.getChildrenByLabel(/^wheel_/, true);
      
    • Returns this container's position in world space: parent.toGlobal(this.position), or a copy of position with no parent

      Parameters

      • out: Vector3 = ...

        Point the result is written into. Defaults to a new Vector3.

      • skipUpdate: boolean = false

        true to use the parent's cached world transform (see Container3D.getGlobalTransform); this node's own position is always read as it stands.

      Returns Vector3

      const screenPos = view3d.worldToScreen(mesh.getGlobalPosition());
      
    • Works out this container's current world transform into out

      It walks up the parent chain, so the result is right even before the view's transform pass has run this frame. With skipUpdate it copies the cached worldTransform instead, which is cheaper but can be stale.

      Parameters

      • out: Matrix4 = ...

        Matrix the result is written into. Defaults to a new Matrix4.

      • skipUpdate: boolean = false

        true to copy the cached world transform instead of recomputing.

      Returns Matrix4

      const world = mesh.getGlobalTransform();
      const localRay = ray.applyMatrix4(world.getInverse(world), new Ray());
    • Measures the bounding box of this container and its descendants, in this container's local space

      A subtree with a boundsVolume counts as that box. Hidden descendants are left out; this container counts whether or not it is visible. An empty subtree measures as a zero box at the origin. Each call walks the subtree, so cache the result if you need it every frame.

      Parameters

      • out: Box = ...

        Box to write into; a new one when omitted

      Returns Box

      out

      const bounds = model.getLocalBounds();
      const center = bounds.getCenter();
    • Returns the scaled size of this container, measuring the local bounds once

      Parameters

      • out: Size3D = ...

        Object to write into; a new one when omitted

      Returns Size3D

      The size, written into out

      const { width, height, depth } = model.getSize();
      
    • Makes the mesh rebuild its shader and draw state on the next frame

      Assigning geometry, material or billboardMode does this for you, and so do most material changes; BaseMaterial3D lists the ones that need this call. Call it too after changing receiveShadow. It doesn't re-read vertex data edited in place; call Geometry3D.unload for that.

      Returns void

      mesh.receiveShadow = false;
      mesh.invalidate();
    • Whether this node fires listeners and can be an event target

      True for eventMode 'static' and 'dynamic', as in 2D.

      Returns boolean

      mesh.eventMode = 'dynamic';
      mesh.isInteractive(); // true

      mesh.eventMode = 'auto';
      mesh.isInteractive(); // false: hit-tested, but never the target
    • Advanced

      Prints this container's subtree to the console as an indented tree of ConstructorName "label" lines, for debugging

      Parameters

      • depth: number = 0

        Indentation level to start at; used by the recursion

      Returns void

      model.logHierarchy();
      
    • Turns this node so its forward axis, local +Z, points at a world-space target

      Cameras and lights aim local -Z instead. The node aims from position + origin, and uses the parent's current world transform, so a move earlier in the frame counts.

      Parameters

      • target: PointData3D

        World-space point to face

      • up: PointData3D = _lookAtDefaultUp

        World-space up reference; defaults to (0, 1, 0)

      Returns void

      turret.lookAt(enemy.getGlobalPosition());
      
    • Removes one or more children from this container; a node that isn't a child is ignored

      Type Parameters

      Parameters

      • ...children: U

        The children to remove

      Returns U[0]

      The first child passed in

      view.root.removeChild(crate);
      
    • Removes the child at index

      Type Parameters

      Parameters

      • index: number

        Index of the child to remove

      Returns U

      The removed child

      const newest = queue.removeChildAt(queue.children.length - 1);
      

      When index is out of bounds.

    • Removes the children from beginIndex up to, but not including, endIndex

      Parameters

      • beginIndex: number = 0

        First index to remove

      • OptionalendIndex: number

        End of the range, exclusive; defaults to the child count

      Returns Container3D[]

      The removed children, last child first

      const debris = level.removeChildren();
      

      When beginIndex is negative or past endIndex, or equal to it while this container has children.

    • Removes this container from its parent, if it has one

      Returns void

      pickup.removeFromParent();
      
    • Moves one or more nodes under this container without moving them in the world; see reparentChildAt

      Type Parameters

      Parameters

      • ...child: U

        The children to reparent

      Returns U[0]

      The first reparented child

      hand.reparentChild(sword);
      
    • Moves child under this container at index without moving it in the world

      Its local position, rotation and scale change so that it renders where it did, and it keeps its origin. Unlike pixi, it uses current world transforms, so a move earlier in the frame counts. A child that is already here only changes index.

      Type Parameters

      Parameters

      • child: U

        The child to reparent

      • index: number

        The destination index

      Returns U

      The reparented child

      rack.reparentChildAt(sword, 0);
      
    • Replaces oldChild with newChild at the same index, copying oldChild's local position, rotation and scale onto newChild

      newChild keeps its own origin, and its position is solved so it sits exactly where oldChild did.

      Type Parameters

      Parameters

      • oldChild: U

        The child to replace

      • newChild: T

        The child that takes its place

      Returns void

      car.replaceChild(flatTyre, spareWheel);
      

      When oldChild is not a child of this container.

    • Moves an existing child to index within this container

      Parameters

      • child: Container3D

        The child to move

      • index: number

        The destination index

      Returns void

      rack.setChildIndex(sword, 0);
      

      When index is out of bounds or child is not a child of this container.

    • Rescales this container so its size matches the given width, height and depth

      A missing height or depth takes the width. An axis whose local extent is zero, such as a flat plane's depth, keeps a unit scale. The sign of each scale axis is kept, so a mirrored node stays mirrored.

      Parameters

      • value: number | Pick<Size3D, "width"> & Partial<Size3D>

        Target width, or an object with width and optional height / depth

      • Optionalheight: number

        Target height; defaults to the width

      • Optionaldepth: number

        Target depth; defaults to the width

      Returns void

      model.setSize(2); // stretch each axis to 2
      model.setSize(4, 2, 1);
      model.setSize({ width: 4, height: 2 }); // depth follows width: 4
    • Swaps the places of two children in this container's list

      Type Parameters

      Parameters

      • child: U

        The first child

      • child2: U

        The second child

      Returns void

      rack.swapChildren(sword, shield);
      

      When either argument is not a child of this container.

    • Converts a point into this container's local space

      Type Parameters

      Parameters

      • position: PointData3D

        The point to convert.

      • Optionalfrom: Container3D

        Container whose local space position is in. Defaults to world space.

      • Optionalout: T

        Point the result is written into. Defaults to a new Vector3.

      • skipUpdate: boolean = false

        true to use cached world transforms (see Container3D.getGlobalTransform).

      Returns T

      const targetFromTurret = turret.toLocal({ x: 0, y: 0, z: 0 }, target);
      
    • Calls callback with this container, then with every container under it, depth first

      Each container comes before its children, and hidden ones are visited too. A Skeleton's bones and a BatchedMesh3D's items aren't containers, so the walk doesn't reach them. It can't stop early or skip a subtree.

      The callback may remove, destroy or replace the container it's given. A container it adds with addChild is visited only if its new parent hasn't been visited yet. Other changes to the tree during the walk can skip a container or visit one twice.

      Parameters

      • callback: (container: Container3D) => void

        Called once with each container, this one first

      Returns void

      const robot = new Model3D(source);

      robot.traverse((container) => {
      if (container instanceof Mesh3D) container.enablePass('outline');
      });
    • Unloads this mesh's geometry now

      The vertex data stays on the CPU, so the next frame that draws the mesh uploads it again. Remove the mesh from the scene first, or that happens straight away. The material is left alone, since it's usually shared: call BaseMaterial3D.unload for that, or Model3D.unload to free a model's geometry and textures together.

      Returns void

      view.root.removeChild(mesh);
      mesh.unload(); // adding it back re-uploads and re-packs the geometry
    • Advanced

      Rebuilds localTransform from the position, rotation, scale and origin

      The view calls it for each node that changed, so you only need it to read a current localTransform before the next frame. When rotation is the rotation in use, it updates the quaternion to match.

      Returns void

      crate.rotation.y = Math.PI / 4;
      crate.updateLocalTransform();
      const local = crate.localTransform.clone();