Creates a Sprite3D; add it under view.root to draw it
A bare Texture is short for { texture }, as with pixi's 2D Sprite. Throws when a
material you pass has no baseColor slot.
Construction options, or the texture to draw; see Sprite3DOptions.
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.
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.
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
Whether this mesh is shadowed by lights that cast shadows
Only lit materials take shadows. After changing it at runtime, call invalidate.
Optional ReadonlyskeletonSkeleton that deforms this mesh; undefined for a mesh that doesn't bend
Fixed at construction: to change it, build a new mesh.
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 Sprite3D; an option passed as undefined keeps its default
tint, alpha, alphaMode and alphaCutoff apply only to the FlatMaterial the
sprite makes, never to a material you pass.
Sets the opacity multiplied into the texture's alpha
Opacity from 0 to 1.
Sets the alpha below which 'mask' mode cuts a pixel away
Alpha from 0 to 1.
How the texture's alpha is used; see Sprite3DOptions.alphaMode
A blended sprite casts no shadow. It writes the material, so on a shared material it changes every sprite using it.
Which point of the image sits on the node's origin, as a fraction of its size, with y
measured down from the top edge
(0.5, 0.5) is centred, and y = 1 stands the sprite on the origin. Assign a point or a
single number for both axes, or change it in place. The Sprite3D class notes cover
how it behaves in each billboard mode.
Sets the anchor from a point or a single number for both axes
Fractions of the image's size, y measured from its top edge.
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
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.
Sets how the mesh turns to face the camera
How to orient the mesh toward the camera, or 'none' to draw it as authored.
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.
Sets whether the mesh casts shadows, from the next render
Whether the mesh casts shadows.
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
The geometry this mesh draws; Geometry3D.EMPTY until it's given one
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.
Geometry to draw.
The sprite's height in world units: |scale.y| × texture height × pixelSize
Assigning writes scale.y only; see Sprite3D#width.
Sets scale.y for a height in world units
Height in world units.
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.
Swaps the material
Material to draw the geometry with.
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
Re-sizes the sprite without touching scale
World units per texture pixel.
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
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.
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 image on the quad
Assigning another re-sizes the sprite; switching frames within one sprite sheet is cheap. It
writes the material's baseColor slot, so on a shared material it changes every sprite using
it. A sprite follows in-place changes only to a texture that was dynamic when it got it, as
pixi's 2D Sprite does.
Swaps the image and re-sizes the sprite; rotated sprite sheet frames work too
Image to draw on the quad.
Colour multiplied into the texture
As with Container.tint, it takes any ColorSource and reads back as a hex number. Opacity
is Sprite3D#alpha. It writes the material's baseColor, so on a shared material it
recolours every sprite using it.
Sets the colour multiplied into the texture
Colour to multiply by.
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
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.
Replaces the weights array; does nothing when the geometry has no morph targets or value is
undefined
New weights, one per morph target.
The sprite's width in world units: |scale.x| × texture width × pixelSize
Assigning writes scale.x and leaves Sprite3D#height alone, as on pixi's 2D Sprite;
to keep the aspect ratio, pass width at construction.
Sets scale.x for a width in world units
Width in world units.
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
Destroys the sprite; the shared quad geometry always survives, even destroy(true)
A material the sprite made is always destroyed; one you gave it stays unless you pass
material. texture frees the sprite's texture, as on pixi's 2D Sprite, and
textureSource its source too; textureSource alone frees nothing. Children get your options
unchanged.
Optionaloptions: Destroy3DOptions
Teardown flags; see Destroy3DOptions.
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.
The pass's name, such as '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.
The pass's name, such as 'outline'.
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
Returns the sprite's size in world units, from the texture like Sprite3D#width
A sprite is flat, so depth is always 0.
Object to write into; a new one when omitted
The size, written into out
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.
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)
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
Sizes the sprite in world units, from the texture like Sprite3D#width
A single number sets both axes, and a missing height takes the width, as in pixi's 2D
Sprite. A sprite is flat, so any depth is ignored.
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 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.
view.root.removeChild(mesh);
mesh.unload(); // adding it back re-uploads and re-packs the geometry
Advanced
Rebuilds localTransform with the texture's world size and the anchor offset in it
A texture with no size yet, such as one still loading, shrinks the quad to a point.
StaticfromCreates a self-contained sprite from a texture, or from anything Texture.from accepts: an
asset alias or URL already in the cache, an image, a canvas or a TextureSource
The 3D counterpart of pixi's Sprite.from. An alias the cache doesn't have draws nothing, and
pixi warns; load the asset first.
The texture, or the source to build one from.
Build a fresh texture instead of reusing a cached one for source; an alias
or URL always comes from the cache.
A sprite drawing that texture on its own FlatMaterial.
A textured quad in the 3D scene, sized from its texture and, by default, turned to face the camera
It's
texture pixels × pixelSizeworld units across, with the familiar sprite API:anchor,tint,alpha,widthandheight, plusalphaModefor cutouts. It draws with an unlit FlatMaterial unless you give it another material; a Material3D gives a lit billboard, which a flat stand-in needs to match the lighting of the model it replaces.Batching
Sprites that share a material type, billboard mode, alpha mode and image source, such as the frames of one sprite sheet, draw together as one instanced draw. On WebGPU, sprites with materials of their own, as each sprite makes by default, need more than 16 in a row for that; 16 or fewer draw one each. Switching frames within a sheet costs almost nothing. The opaque pass (
'mask'and'opaque') groups mixed modes and sources well. The transparent pass ('blend') sorts back to front, so every change of mode or source along that order starts a new draw: give each blended effect one mode and one sprite sheet. Tint, alpha, size and position can vary freely.Turning to face the camera costs no CPU time; the GPU does it. Hundreds to a few thousand sprites is what it's built for. For tens of thousands that you set and forget, fill BatchedMesh3D slots instead: give each one PlaneGeometry.spriteQuad, a matrix whose X and Y scale carry the texture's world size, and a
billboardMode.Anchor and origin
'none': the anchor is exact, as on a 2D sprite.'cylindrical':anchor.yis exact, so a tree anchored at its feet turns around its base.anchor.xswings around the spin axis.'spherical': an off-centre anchor drifts as the camera orbits. The centred default is exact.originis in world size units, texture pixels ×pixelSizebeforescale, and applies afteranchor. A 200×400 px texture at the defaultpixelSizeis 2 × 4 units, so with the centred anchororigin = { x: 1, y: 2, z: 0 }turns the sprite around its top-right corner. Under a billboard mode it behaves like an off-centre anchor.Limitations
toLocalwork in quad units, where the image spans -0.5 to 0.5. Treat a sprite as a leaf node.addChildandremoveChildare fine.ContainerTexturedraws upside down on a sprite.Example
See
Sprite3DOptions For the constructor options.