Creates a new AmbientLight; add it under view.root to light the view
Construction options; see AmbientLightOptions.
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.
Whether this light casts shadows; only directional and spot lights can
The first light in a view to cast a shadow makes the view recompile its lit materials, once; later toggles recompile nothing.
shadowQuality, which sets the shadow-map resolution.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.
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.
button.cursor = 'pointer';
handle.cursor = 'grab';
blade.cursor = 'url("crosshair.png") 8 8, crosshair'; // custom, with a hotspot
https://developer.mozilla.org/en-US/docs/Web/CSS/cursor MDN Cursor Documentation
Whether destroy has run, as in pixi's Container
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.
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.
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.
Brightness, multiplied into Light.color
Values above 1 are fine. A point or spot light dims with the square of the distance, so it
needs a higher intensity than a directional light to look as bright. Lit colour brighter than 1
clips under the default toneMapping; a filmic curve such as
'aces' rolls it off instead.
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.
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.
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;
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.
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.
Property-based handler for the click event
Fired when a mouse click on this node completes, with any button but the right one.
mesh.eventMode = 'static';
mesh.onclick = (e) => {
if (e.hit3D) marker.position.copyFrom(e.hit3D.point);
};
IFederatedContainer3D#onpointertap For the equivalent for every pointer type.
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.
Property-based handler for the globalmousemove event
Fired on every mouse move, wherever the pointer is on the page.
IFederatedContainer3D#onglobalpointermove For the equivalent for every pointer type.
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.
Property-based handler for the globaltouchmove event
Fired on every touch move, wherever the touch is on the page.
IFederatedContainer3D#onglobalpointermove For the equivalent for every pointer type.
Property-based handler for the mousedown event
Fired when a mouse button other than the right one goes down over this node.
IFederatedContainer3D#onpointerdown For the equivalent for every pointer type.
Property-based handler for the mouseenter event
Fired when the mouse enters this node. Doesn't bubble.
IFederatedContainer3D#onpointerenter For the equivalent for every pointer type.
Property-based handler for the mouseleave event
Fired when the mouse leaves this node. Doesn't bubble.
IFederatedContainer3D#onpointerleave For the equivalent for every pointer type.
Property-based handler for the mousemove event
Fired while the mouse moves across this node.
IFederatedContainer3D#onpointermove For the equivalent for every pointer type.
Property-based handler for the mouseout event
Fired when the mouse moves off this node. Bubbles, unlike mouseleave.
IFederatedContainer3D#onpointerout For the equivalent for every pointer type.
Property-based handler for the mouseover event
Fired when the mouse moves onto this node. Bubbles, unlike mouseenter.
// 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.
Property-based handler for the mouseup event
Fired when a mouse button other than the right one is released over this node.
IFederatedContainer3D#onpointerup For the equivalent for every pointer type.
Property-based handler for the mouseupoutside event
Fired when a mouse button that went down on this node is released anywhere else.
IFederatedContainer3D#onpointerupoutside For the equivalent for every pointer type.
Property-based handler for the pointercancel event
Never called: pixi delivers no pointer cancellation, in 2D either.
Property-based handler for the pointerdown event
Fired when a pointer goes down on this node: mouse, touch or pen alike.
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.
Property-based handler for the pointerleave event
Fired when a pointer leaves this node. Doesn't bubble.
Property-based handler for the pointermove event
Fired while a pointer moves across this node.
Property-based handler for the pointerout event
Fired when a pointer moves off this node. Bubbles, unlike pointerleave.
Property-based handler for the pointerover event
Fired when a pointer moves onto this node. Bubbles, unlike pointerenter.
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.
Property-based handler for the pointerup event
Fired when a pointer is released over this node.
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.
Property-based handler for the rightclick event
Fired when a right click completes on this node.
Property-based handler for the rightdown event
Fired when the right mouse button goes down over this node.
Property-based handler for the rightup event
Fired when the right mouse button is released over this node.
Property-based handler for the rightupoutside event
Fired when the right mouse button that went down on this node is released anywhere else.
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.
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.
Property-based handler for the touchcancel event
Never called: pixi delivers no touch cancellation, in 2D either.
Property-based handler for the touchend event
Fired when a touch lifts off this node.
IFederatedContainer3D#onpointerup For the equivalent for every pointer type.
Property-based handler for the touchendoutside event
Fired when a touch that started on this node lifts off anywhere else.
IFederatedContainer3D#onpointerupoutside For the equivalent for every pointer type.
Property-based handler for the touchmove event
Fired while a touch moves across this node.
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.
Property-based handler for the touchstart event
Fired when a touch lands on this node.
IFederatedContainer3D#onpointerdown For the equivalent for every pointer type.
Property-based handler for the wheel event
Fired when the wheel turns while the pointer is over this node.
Parent node, or null for a node with none, such as a view's root
This light's shadow settings; see LightShadow
Change a field at any time and the shadow's next redraw uses it.
ReadonlytypeAlways 'ambient'
Readonly AdvanceduidUnique id, assigned at construction
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.
StaticdefaultDefaults for every new AmbientLight; an option passed as undefined keeps its default
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.
Sets the Euler rotation and makes it the rotation in use, even when the values are unchanged
The new Euler angles, in degrees
Advanced
Always false: ambient light has no direction to cast along
Colour of the light, multiplied by Light.intensity
Assign any ColorSource, in display (sRGB) space as everywhere in pixi, or change the
returned Color in place.
Sets the colour, copying the value into the light's own Color
Any colour pixi accepts.
Depth along local z: |scale.z| × local bounds depth
Assigning writes scale.z only; see width.
Scales along z so the depth becomes value
Target depth along z
Height along local y: |scale.y| × local bounds height
Assigning writes scale.y only; see width.
Scales along y so the height becomes value
Target height along y
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.
Sets the origin; a number sets all three axes
The new origin, in local space
Local position
Assigning copies the values in; the object itself never changes.
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.
Sets the quaternion and makes it the rotation in use, even when the values are unchanged
The new rotation, as a unit quaternion
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.
Sets the Euler rotation and makes it the rotation in use, even when the values are unchanged
The new Euler angles, in radians
Local scale
Assigning copies the values in, and a single number scales all three axes; the object itself never changes.
Sets the local scale; a number sets all three axes
The new scale
The View3D this node is in, or null when it isn't in a scene
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.
Shows or hides this container and its descendants
Whether they draw
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.
Scales along x so the width becomes value
Target width along x
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.
Sets position.x
The new x position
Sets position.y
The new y position
Sets position.z
The new z position
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.
The children to add
The first added child
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.
The child to add or move
The destination index
The added child
Removes the light from the scene and frees its shadow's GPU data
Calling it again does nothing.
Optionaloptions: Destroy3DOptions
Forwarded to Container3D.destroy.
Measures the scene again for the fitted shadow box on the next frame, then redraws the shadow
A view with 256 shadow casters or fewer never needs this: the box is measured each time the
shadow redraws.
Past 256 it is measured once and kept, so call this after moving or spawning casters outside
the box. Instances of a BatchedMesh3D count one each. For a cascaded light, a spot light,
or a light with its own bounds, it only redraws the shadow, like
Light.refreshShadows.
Gets the child at index
Index of the child to fetch
The child at index
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.
Exact label, or a pattern to test labels against
Whether to search the whole subtree, not only direct children
The first match, or null when nothing matches
Gets the index of child within this container
The child to look up
The child's index
Collects every child whose label matches, in the order Container3D.getChildByLabel visits them
Exact label, or a pattern to test labels against
Whether to search the whole subtree, not only direct children
Array the matches are appended to; a new one when omitted
out
Returns this container's position in world space: parent.toGlobal(this.position), or a copy
of position with no parent
Point the result is written into. Defaults to a new Vector3.
true to use the parent's cached world transform (see
Container3D.getGlobalTransform); this node's own position is always read as it stands.
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.
Matrix the result is written into. Defaults to a new Matrix4.
true to copy the cached world transform instead of recomputing.
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.
Box to write into; a new one when omitted
out
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.
World-space point to face
World-space up reference; defaults to (0, 1, 0)
Redraws this light's shadow on the next frame, whatever its LightShadow.update rate
With update: 'manual', call it after each change the shadow should show. With a slower rate,
call it after a change that shouldn't wait for the next scheduled redraw.
Removes one or more children from this container; a node that isn't a child is ignored
The children to remove
The first child passed in
Removes the child at index
Index of the child to remove
The removed child
Removes the children from beginIndex up to, but not including, endIndex
First index to remove
OptionalendIndex: number
End of the range, exclusive; defaults to the child count
The removed children, last child first
Moves one or more nodes under this container without moving them in the world; see reparentChildAt
The children to reparent
The first reparented child
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.
The child to reparent
The destination index
The reparented child
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.
Moves an existing child to index within this container
The child to move
The destination index
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.
Swaps the places of two children in this container's list
Converts a point from this container's local space to world space
Pass the result to View3D.worldToScreen to go on to 2D screen coordinates.
The local-space point to convert.
Optionalout: T
Point the result is written into. Defaults to a new Vector3.
true to use the cached world transform (see Container3D.getGlobalTransform).
Container3D.getGlobalPosition For this container's own world position.
Converts a point into this container's local space
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.
true to use cached world transforms (see Container3D.getGlobalTransform).
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.
Called once with each container, this one first
Unloads the geometry of every mesh in this subtree, for a part of the scene you'll show again later
Each mesh keeps its vertex data, so the next render that draws it uploads it again; remove the subtree from the scene first. Geometry3D.unload says what GPU memory that frees. Materials are left alone, since they're usually shared, except under a Model3D, which unloads its own; unload any other material yourself.
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.
Light that reaches every surface equally, whatever its position or direction
It lifts shadowed areas off pure black for almost no cost. Several ambient lights add up. It casts no shadows;
castShadowis ignored. On a Material3D it lights only the non-metal part, so a fully metallic surface gets nothing from it.Example
See
Hemisphere For sky and ground colours that vary with the way a surface faces.