InstancedMeshNode class final
One mesh drawn many times in one call, each copy with a transform and a colour of its own.
A thousand nodes is a thousand draws; this is one. Grass, rubble, a crowd, the pillars of a hall — the same geometry at many places is the commonest shape a scene has, and drawing it one node at a time spends a pipeline bind, six uniform writes and a draw on every copy. The particle system has drawn its embers this way since it existed; this is the same path for ordinary meshes.
What an instance is
A transform in the node's space and a colour that multiplies the
vertex colour. Relative to the node rather than to the world, so the
batch moves with its node the way a child would, and moving a batch of a
thousand costs one uniform write. Sixteen floats each: three rows of a 3x4
affine matrix — the bottom row of one is always (0, 0, 0, 1), and a
quarter of the buffer would be spent saying so — and an RGBA colour.
A copy can also wear its own morph weights — see setMorphWeights — which is how a crowd gets faces rather than one face repeated. Those do not live in the instance record: they are a texture read by instance id, so that the record's size, which is part of the vertex layout, is not paid by every batch in every game for a feature most of them never use.
What it is not, yet
- Culled as one. The batch's bounds are the union of its instances' and the frustum test is one sphere around them, so a field that straddles the horizon is drawn whole. Per-instance culling is a CPU pass that costs more than it saves on a small batch, which is why other engines make it opt-in; it is not here until a scene asks.
- Uniform scale per instance. A rotation and a uniform scale keep a normal a normal; a non-uniform instance scale skews the lighting, and the vertex stage says so rather than paying an inverse transpose per vertex.
- No skinning. A skinned mesh has its own vertex stage and layout, and a skinned batch would be a third.
- Sorted as one. A translucent batch sorts by the node, not by each instance, so overlapping translucent instances may draw in the wrong order within the batch.
- Picked as a box. A ray hits the batch's bounds, not the instances.
Constructors
- InstancedMeshNode(MeshGeometry mesh, Material material, {required int capacity, String? name})
Properties
- capacity → int
-
How many instances the buffer can hold.
no setter
- castsShadow ↔ bool
-
Whether this node is drawn into the shadow maps.
getter/setter pairinherited
- castsShadowFromEveryFace → bool
-
Whether the shadow passes record every face of this node rather than the
side
ShadowSettings.casterFacesnames for a lamp, orShadowSettings.directionalCasterFacesfor the sun.no setterinherited -
children
→ List<
SceneNode> -
no setterinherited
-
childrenView
→ List<
SceneNode> -
Direct access for internal traversal, avoiding the unmodifiable copy.
no setterinherited
- count ↔ int
-
How many instances are drawn, never more than capacity.
getter/setter pair
- dataVersion → int
-
Bumped on every write, so a reader can tell whether anything changed.
no setter
- drawsTransparent → bool
-
Whether this draws in the transparent pass: its material blends, or
tint fades it.
no setterinherited
- frustumCulled ↔ bool
-
Skips frustum culling for this node.
getter/setter pairinherited
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasInstanceMorphWeights → bool
-
Whether any instance has been given weights of its own.
no setter
- instanceBytes → ByteData
-
The drawn instances as bytes, for binding as the per-instance slot.
no setter
- instanceData → Float32List
-
The whole buffer, capacity instances of floatsPerInstance floats.
no setter
- inverseWorldMatrix → Matrix4
-
The world-to-node transform, cached on worldVersion.
no setterinherited
- isTinted → bool
-
Whether tint changes anything.
no setterinherited
- layerMask ↔ int
-
Bitmask filtered against a render view's mask, in the manner of three.js
layers. Bit 0 is the default layer.
getter/setter pairinherited
- lightChannels ↔ int
-
Which light channels this node accepts —
gfx-12n.getter/setter pairinherited - lightmapped ↔ bool
-
Whether this mesh's vertex colour is its place in a lightmap.
getter/setter pairinherited
- localBounds → Aabb3
-
The union of every drawn instance's transformed mesh bounds, in the
node's space.
no setteroverride
- localMatrix → Matrix4
-
no setterinherited
- material ↔ Material
-
getter/setter pairinherited
- mesh ↔ MeshGeometry
-
getter/setter pairinherited
- morph ↔ MorphState?
-
The shapes this mesh blends towards, and how much of each.
getter/setter pairinherited
-
morphWeights
→ List<
double> -
What each target is worth right now, from nought to one.
no setterinherited
- name ↔ String?
-
getter/setter pairinherited
- occluder ↔ bool
-
Whether this mesh hides what is behind it from the software occlusion
test —
C2,RenderSettings.occlusionset toOcclusionMode.software.getter/setter pairinherited - occluderMesh ↔ MeshData?
-
The triangles to occlude with in place of mesh's, in the same local
space. A box standing in for a detailed building, or the walls of a
room without its furniture. Null occludes with the mesh's own triangles,
which have to be on the CPU (
MeshGeometry.source) to be used at all.getter/setter pairinherited - ownBounds → Aabb3?
-
What a subtree bound has to contain on this node's account —
gfx-66n.no setterinherited - ownBoundsAreCullable → bool
-
Whether ownBounds may be culled.
no setterinherited
- parent → SceneNode?
-
no setterinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- scene → Scene?
-
The scene this node currently belongs to, if any.
no setterinherited
- shadowCasting ↔ ShadowCastingMode
-
How this node takes part in the shadow passes.
getter/setter pairinherited
- shadowIsStatic ↔ bool
-
Whether this caster never moves.
getter/setter pairinherited
- skeleton ↔ Skeleton?
-
The skeleton deforming this mesh, when it is skinned.
getter/setter pairinherited
- skinReach ↔ double
-
How far the surface reaches from its joints, in the mesh's own units.
getter/setter pairinherited
- subtreeAlwaysDrawn → bool
-
Whether anything in this subtree has opted out of frustum culling.
no setterinherited
- subtreeBounds → Aabb3?
-
What this node and everything under it occupies, or null when the subtree
draws nothing.
no setterinherited
- tint → Vector4
-
Multiplies this node's colour and opacity, over whatever its material
says: white is the material as it is,
(1, 0.3, 0.3, 1)a red flash,(1, 1, 1, 0.5)half faded out.finalinherited - visible ↔ bool
-
Whether this node and its subtree are drawn.
getter/setter pairinherited
- visibleInHierarchy → bool
-
True when this node and every ancestor is visible.
no setterinherited
- worldBounds → Aabb3
-
World-space axis-aligned bounds, recomputed only when the transform changes.
no setterinherited
- worldBoundsCentre → Vector3
-
Centre of the world bounding sphere used for the cheap culling test.
no setterinherited
- worldBoundsRadius → double
-
no setterinherited
- worldIsMirrored → bool
-
True when the world transform mirrors, i.e. its determinant is negative.
no setterinherited
- worldMatrix → Matrix4
-
The node-to-world transform, always current.
no setterinherited
- worldNormalMatrix → Matrix4
-
Inverse-transpose of the world matrix, for transforming normals.
no setterinherited
- worldVersion → int
-
Changes whenever worldMatrix changes. Use it as an invalidation key.
no setterinherited
Methods
-
acquire(
{Matrix4? transform, Vector4? color}) → InstanceHandle - Takes a slot for something that comes and goes, and returns the handle that keeps finding it: a shot, a spark, an invader.
-
add(
SceneNode child) → void -
Adds
child, keeping its local transform (so it moves with this node).inherited -
addInstance(
Matrix4 transform, {Vector4? color}) → int - Appends an instance and returns its index.
-
attach(
SceneNode child) → void -
Adds
childwhile preserving its current world transform.inherited -
bindToScene(
Scene? scene) → void -
Binds this node's subtree to
scene. Called by Scene for its own root; user code attaches nodes with add instead.inherited -
clear(
) → void - Empties the batch without giving up the buffer it has.
-
ensureCapacity(
int wanted) → void -
Grows the buffer to hold at least
wantedinstances, keeping what is in it. -
findByName(
String target) → SceneNode? -
First descendant with a matching name, or null.
inherited
-
instanceMorphWeights(
GraphicsDevice device) → TextureHandle? - The weights as a texture the instanced vertex stage can read, or null when no instance has any.
-
lookAt(
Vector3 target, {Vector3? up}) → void -
Points the node's local -Z at
target, given in world space.inherited -
markBoundsDirty(
) → void -
Says the cached bounds no longer describe the node.
inherited
-
markInstancesChanged(
) → void - Says the buffer was written through instanceData.
-
morphWeightsOf(
int index) → List< double> -
Instance
index's weights, as they were set. -
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onAttachedToScene(
Scene scene) → void -
Hook for subclasses to register themselves in the scene's flat registries.
inherited
-
onDetachedFromScene(
Scene scene) → void -
inherited
-
readPosition(
[Vector3? out]) → Vector3 -
Reads the local position into
outto avoid allocating.inherited -
readRotation(
[Quaternion? out]) → Quaternion -
inherited
-
readScale(
[Vector3? out]) → Vector3 -
inherited
-
readTransform(
int index, Matrix4 out) → void -
Reads instance
index's transform back intoout. -
readWorldPosition(
[Vector3? out]) → Vector3 -
inherited
-
release(
InstanceHandle handle) → void -
Gives
handle's slot back: the last drawn slot moves into it, colour and morph weights with it, and count drops by one. Releasing a handle twice, or one from another batch, is a mistake and throws. -
remove(
SceneNode child) → void -
inherited
-
removeFromParent(
) → void -
Detaches this node from its parent.
inherited
-
setColor(
int index, Vector4 color) → void -
Tints instance
index: multiplied into the vertex colour. -
setLocalForward(
Vector3 direction, {Vector3? up}) → void -
Aims the node's local -Z along
direction, expressed in the parent's space.inherited -
setLocalMatrix(
Matrix4 value) → void -
Replaces the local transform by decomposing a matrix.
inherited
-
setMorphWeights(
int index, List< double> weights) → void -
Gives instance
indexits own morph weights. -
setPosition(
double x, double y, double z) → void -
inherited
-
setPositionFrom(
Vector3 value) → void -
inherited
-
setRotation(
Quaternion value) → void -
inherited
-
setRotationYawPitchRoll(
double yaw, double pitch, double roll) → void -
Yaw about Y, then pitch about X, then roll about Z — the order that reads
naturally for cameras and turntables.
inherited
-
setScale(
double x, double y, double z) → void -
inherited
-
setTransform(
int index, Matrix4 transform) → void -
Places instance
indexwithtransform, in the node's space. -
setUniformScale(
double value) → void -
inherited
-
toString(
) → String -
A string representation of this object.
inherited
-
translate(
double dx, double dy, double dz) → void -
inherited
-
traverse(
void visit(SceneNode child)) → void -
Walks this node and its descendants.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Constants
- floatsPerInstance → const int
- Floats one instance occupies: three rows of the transform, then RGBA.
- maxMorphTargets → const int
-
The most targets an instance can be given weights for.
kMorphMaxinlib/morph.glsl, and the two have to move together. - strideInBytes → const int
- Bytes one instance occupies.