---
contentHash: sha256:a05da37028f095ea93ddedaeb03ce7c5a3048ba81bb88c79b52939371242c4a0
documentId: element:sk-cloner
kind: element
schemaVersion: 1
skenraVersion: 0.1.0-alpha.1
---
# sk-cloner

<a id="overview"></a>

## Overview

Stamps copies of its content across a set of points — the way to place many
instances (a grid of spheres, particles over a mesh's surface) without
authoring each one by hand.

The cloner is a SceneNode that instances geometry on the GPU: it takes
*what* to clone from its content children (any clonable node — a mesh, a spline)
and *where* to place them from a points-source. One points-source and one small
template become thousands of positioned copies, and when the points-source
changes the clones follow automatically.

**Key attributes.** `mode` chooses how clones are drawn: `object` renders each as
a full instance (its own transform, pickable), `vertex` merges them into one
particle-like batch that is cheaper at high counts. `clone-scale` uniformly
resizes every clone. `align-to-normal` orients clones to the source surface's
normal (with `alignment-axis` selecting which local axis points along it) — useful
for studding a surface. `illumination-min-scale` / `illumination-max-scale` size
clones by how much light they receive.

**Related.** The points-source child decides the layout: sk-grid-points-source
for a lattice, sk-mesh-vertex-points-source to sit on a mesh's vertices,
and the other `*-points-source` shapes. To drive each clone individually on the
GPU (push them from a point, weight them by a field) add a
sk-simple-point-constraint — the per-clone counterpart to the single-node
constraints.

<a id="example"></a>

## Example

```sk
<!-- A side-by-side demo of `align-to-normal` + `alignment-axis`. Both halves
     are built identically: a lattice cloner (#lattice-y / #lattice-z) clones a
     vertical reference line at every point of a 3×3 grid — so you can SEE the
     clone positions — and a SECOND cloner reuses those exact positions via
     <sk-cloner-points-source cloner="#…"> (sharing the lattice's GPU transform
     buffer rather than recomputing a grid). That second cloner ROUND-ROBINS
     three templates across the positions: a gold CONE, a blue cube spinning
     about its y-axis, and a group holding BOTH (one template, stamped
     together). Templates can be a mesh, a SPLINE, or a group.

     The two second-cloners differ ONLY in `alignment-axis`. `align-to-normal`
     orients each clone to its source surface's normal; the grid is flat so
     that normal points straight up (+y). `alignment-axis` picks WHICH local
     axis follows it: LEFT uses `+y`, so each cone's own tip (its +y) points up
     and the cones stand UPRIGHT; RIGHT uses `+z`, so each cone's side (its +z)
     points up and the cones lie TIPPED on their sides. Same clones, one
     attribute changed, a visibly different result. -->
<sk-scene>
    <sk-directional-light p="40deg" h="25deg" intensity="1.0"></sk-directional-light>
    <sk-ambient-light intensity="0.4"></sk-ambient-light>
    <sk-plain-material id="cone-mat" base-color="#d8a24a"></sk-plain-material>
    <sk-plain-material id="cube-mat" base-color="#5b7b9a"></sk-plain-material>
    <sk-plain-material id="line-mat" base-color="#8bab8a"></sk-plain-material>

    <!-- Ground plane under the cloners: standard dark-gray floor + darker grid. -->
    <sk-plain-material id="ground-mat" base-color="#3a3a3a"></sk-plain-material>
    <sk-plain-material id="grid-mat" base-color="#1c1c1c"></sk-plain-material>
    <sk-plane y="-0.5" width="18" height="9" width-segments="12" height-segments="6">
        <sk-surface-paint material="#ground-mat"></sk-surface-paint>
        <sk-edge-paint material="#grid-mat"></sk-edge-paint>
    </sk-plane>

    <!-- ===== LEFT: alignment-axis="+y" (cones stand upright) ===== -->
    <!-- Lattice: the position source — a 3×3 grid marked by vertical lines. -->
    <sk-cloner id="lattice-y" mode="object" x="-4">
        <sk-grid-points-source count-x="3" count-y="1" count-z="3"
            spacing-x="1.8" spacing-y="1.8" spacing-z="1.8"></sk-grid-points-source>
        <sk-spline>
            <sk-points-spline-source basis="linear"
                points="[[0,0,0],[0,1.6,0]]"></sk-points-spline-source>
            <sk-stroke-paint material="#line-mat" width="2.5"></sk-stroke-paint>
        </sk-spline>
    </sk-cloner>
    <!-- Round-robin cone / spinning cube / group — aligned +y (tips follow the
         up-normal, so the cones stand upright). -->
    <sk-cloner mode="object" x="-4" align-to-normal alignment-axis="+y">
        <sk-cloner-points-source cloner="#lattice-y"></sk-cloner-points-source>
        <sk-cone bottom-radius="0.35" height="1.0" orientation="+y">
            <sk-surface-paint material="#cone-mat"></sk-surface-paint>
        </sk-cone>
        <sk-cube size="0.6">
            <sk-surface-paint material="#cube-mat"></sk-surface-paint>
            <sk-animation duration="2500ms" iterations="Infinity">
                <sk-keyframe offset="0" h="0deg"></sk-keyframe>
                <sk-keyframe offset="1" h="360deg"></sk-keyframe>
            </sk-animation>
        </sk-cube>
        <sk-scene-node>
            <sk-cone bottom-radius="0.35" height="1.0" orientation="+y">
                <sk-surface-paint material="#cone-mat"></sk-surface-paint>
            </sk-cone>
            <sk-cube size="0.6">
                <sk-surface-paint material="#cube-mat"></sk-surface-paint>
                <sk-animation duration="2500ms" iterations="Infinity">
                    <sk-keyframe offset="0" h="0deg"></sk-keyframe>
                    <sk-keyframe offset="1" h="360deg"></sk-keyframe>
                </sk-animation>
            </sk-cube>
        </sk-scene-node>
    </sk-cloner>
    <sk-overlay-annotation x="-4" y="3.2" anchor="center">
        <div style="color:#fff; background:rgba(0,0,0,0.55); padding:2px 6px;
                    border-radius:3px; font:12px sans-serif;">alignment-axis="+y"</div>
    </sk-overlay-annotation>

    <!-- ===== RIGHT: alignment-axis="+z" (cones tip onto their sides) ===== -->
    <sk-cloner id="lattice-z" mode="object" x="4">
        <sk-grid-points-source count-x="3" count-y="1" count-z="3"
            spacing-x="1.8" spacing-y="1.8" spacing-z="1.8"></sk-grid-points-source>
        <sk-spline>
            <sk-points-spline-source basis="linear"
                points="[[0,0,0],[0,1.6,0]]"></sk-points-spline-source>
            <sk-stroke-paint material="#line-mat" width="2.5"></sk-stroke-paint>
        </sk-spline>
    </sk-cloner>
    <!-- The SAME round-robin templates — aligned +z (sides follow the
         up-normal, so the cones tip over). -->
    <sk-cloner mode="object" x="4" align-to-normal alignment-axis="+z">
        <sk-cloner-points-source cloner="#lattice-z"></sk-cloner-points-source>
        <sk-cone bottom-radius="0.35" height="1.0" orientation="+y">
            <sk-surface-paint material="#cone-mat"></sk-surface-paint>
        </sk-cone>
        <sk-cube size="0.6">
            <sk-surface-paint material="#cube-mat"></sk-surface-paint>
            <sk-animation duration="2500ms" iterations="Infinity">
                <sk-keyframe offset="0" h="0deg"></sk-keyframe>
                <sk-keyframe offset="1" h="360deg"></sk-keyframe>
            </sk-animation>
        </sk-cube>
        <sk-scene-node>
            <sk-cone bottom-radius="0.35" height="1.0" orientation="+y">
                <sk-surface-paint material="#cone-mat"></sk-surface-paint>
            </sk-cone>
            <sk-cube size="0.6">
                <sk-surface-paint material="#cube-mat"></sk-surface-paint>
                <sk-animation duration="2500ms" iterations="Infinity">
                    <sk-keyframe offset="0" h="0deg"></sk-keyframe>
                    <sk-keyframe offset="1" h="360deg"></sk-keyframe>
                </sk-animation>
            </sk-cube>
        </sk-scene-node>
    </sk-cloner>
    <sk-overlay-annotation x="4" y="3.2" anchor="center">
        <div style="color:#fff; background:rgba(0,0,0,0.55); padding:2px 6px;
                    border-radius:3px; font:12px sans-serif;">alignment-axis="+z"</div>
    </sk-overlay-annotation>
</sk-scene>
```

<a id="children"></a>

## Children

One or more clonable children defining the content to instance — meshes (sphere/cube/cylinder/etc.), splines, SceneNode groups (all descendants cloned together as one template unit), or nested cloners; multiple direct children alternate across points. Plus zero or more point-source / point-constraint / field-constraint children to place the clones. Point constraints also attach to mesh vertices and spline polyline vertices, not only cloners (Issues #2495, #2513).

<a id="attr-id"></a>

## id

Type: `<id>` · Required: no · Animatable: no

Unique identifier for the node, reflected to the host `id` attribute.

Related: [`type:id`](types/id.md)

<a id="attr-draggable"></a>

## draggable

Type: `<boolean>` · Required: no · Animatable: no · Default: `false` · Inherited from `sk-scene-node`

Gets whether this node can be dragged.

Related: [`type:boolean`](types/boolean.md)

<a id="attr-x"></a>

## x

Type: `<number>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

X position.

Related: [`type:number`](types/number.md)

<a id="attr-y"></a>

## y

Type: `<number>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

Y position.

Related: [`type:number`](types/number.md)

<a id="attr-z"></a>

## z

Type: `<number>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

Z position.

Related: [`type:number`](types/number.md)

<a id="attr-h"></a>

## h

Type: `<angle>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

Heading (Y-axis rotation) in radians.

Related: [`type:angle`](types/angle.md)

<a id="attr-p"></a>

## p

Type: `<angle>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

Pitch (X-axis rotation) in radians.

Related: [`type:angle`](types/angle.md)

<a id="attr-b"></a>

## b

Type: `<angle>` · Required: no · Animatable: yes · Default: `0` · Inherited from `sk-scene-node`

Bank (Z-axis rotation) in radians.

Related: [`type:angle`](types/angle.md)

<a id="attr-quaternion"></a>

## quaternion

Type: `<quaternion>` · Required: no · Animatable: yes · Inherited from `sk-scene-node`

Rotation as quaternion (overrides h, p, b if provided)

Related: [`type:quaternion`](types/quaternion.md)

<a id="attr-sx"></a>

## sx

Type: `<number>` · Required: no · Animatable: yes · Default: `1` · Inherited from `sk-scene-node`

X-axis scale factor.

Related: [`type:number`](types/number.md)

<a id="attr-sy"></a>

## sy

Type: `<number>` · Required: no · Animatable: yes · Default: `1` · Inherited from `sk-scene-node`

Y-axis scale factor.

Related: [`type:number`](types/number.md)

<a id="attr-sz"></a>

## sz

Type: `<number>` · Required: no · Animatable: yes · Default: `1` · Inherited from `sk-scene-node`

Z-axis scale factor.

Related: [`type:number`](types/number.md)

<a id="attr-s"></a>

## s

Type: `<number>` · Required: no · Animatable: no · Inherited from `sk-scene-node`

Uniform scale factor for all axes (overrides sx, sy, sz if provided)

Related: [`type:number`](types/number.md)

<a id="attr-overlay"></a>

## overlay

Type: `<boolean>` · Required: no · Animatable: no · Default: `false`

Whether this cloner's entire rendered output (all clones) renders as

Related: [`type:boolean`](types/boolean.md)

<a id="attr-overlay-occluded-opacity"></a>

## overlay-occluded-opacity

Type: `<number>` · Required: no · Animatable: no · Default: `0.3`

Alpha multiplier for overlay fragments occluded by scene geometry.

Related: [`type:number`](types/number.md)

<a id="attr-cast-shadow"></a>

## cast-shadow

Type: `<boolean>` · Required: no · Animatable: no · Default: `true`

Gets whether this cloner's instances cast shadows.

Related: [`type:boolean`](types/boolean.md)

<a id="attr-mode"></a>

## mode

Type: `<cloner-mode>` · Required: no · Animatable: no

Cloning operation mode.

Related: [`type:cloner-mode`](types/cloner-mode.md)

<a id="attr-align-to-normal"></a>

## align-to-normal

Type: `<boolean>` · Required: no · Animatable: no

Whether to orient clones to align with point normals.

Related: [`type:boolean`](types/boolean.md)

<a id="attr-alignment-axis"></a>

## alignment-axis

Type: `<orientation-axis>` · Required: no · Animatable: no

Which local axis of the cloned content aligns with the normal direction.

Related: [`type:orientation-axis`](types/orientation-axis.md)

<a id="attr-apply-scale"></a>

## apply-scale

Type: `<boolean>` · Required: no · Animatable: no

Whether to apply each point's per-clone scale (the source localMatrix's

Related: [`type:boolean`](types/boolean.md)

<a id="attr-clone-scale"></a>

## clone-scale

Type: `<number>` · Required: no · Animatable: yes

Uniform scale factor applied to each clone.

Related: [`type:number`](types/number.md)

<a id="attr-illumination-enabled"></a>

## illumination-enabled

Type: `<boolean>` · Required: no · Animatable: no · Default: `false`

Whether illumination-based scaling is enabled.

Related: [`type:boolean`](types/boolean.md)

<a id="attr-illumination-min-scale"></a>

## illumination-min-scale

Type: `<number>` · Required: no · Animatable: yes

Minimum scale factor for illumination-based scaling.

Related: [`type:number`](types/number.md)

<a id="attr-illumination-max-scale"></a>

## illumination-max-scale

Type: `<number>` · Required: no · Animatable: yes

Maximum scale factor for illumination-based scaling.

Related: [`type:number`](types/number.md)

<a id="attr-illumination-use-shadows"></a>

## illumination-use-shadows

Type: `<boolean>` · Required: no · Animatable: no · Default: `false`

Whether to use shadow map for illumination visibility calculations.

Related: [`type:boolean`](types/boolean.md)

<a id="event-handlers"></a>

## Event handlers

<a id="attr-onclick"></a><a id="attr-ondblclick"></a><a id="attr-onauxclick"></a><a id="attr-oncontextmenu"></a><a id="attr-onpointerdown"></a><a id="attr-onpointerup"></a><a id="attr-onpointermove"></a><a id="attr-onpointercancel"></a><a id="attr-onpointerover"></a><a id="attr-onpointerout"></a><a id="attr-onpointerenter"></a><a id="attr-onpointerleave"></a><a id="attr-ongotpointercapture"></a><a id="attr-onlostpointercapture"></a><a id="attr-onwheel"></a><a id="attr-ondragstart"></a><a id="attr-ondrag"></a><a id="attr-ondragenter"></a><a id="attr-ondragover"></a><a id="attr-ondragleave"></a><a id="attr-ondrop"></a><a id="attr-ondragend"></a>

`onclick` — Handler for the click event.

`ondblclick` — Handler for the dblclick event.

`onauxclick` — Handler for the auxclick event.

`oncontextmenu` — Handler for the contextmenu event.

`onpointerdown` — Handler for the pointerdown event.

`onpointerup` — Handler for the pointerup event.

`onpointermove` — Handler for the pointermove event.

`onpointercancel` — Handler for the pointercancel event.

`onpointerover` — Handler for the pointerover event.

`onpointerout` — Handler for the pointerout event.

`onpointerenter` — Handler for the pointerenter event.

`onpointerleave` — Handler for the pointerleave event.

`ongotpointercapture` — Handler for the gotpointercapture event.

`onlostpointercapture` — Handler for the lostpointercapture event.

`onwheel` — Handler for the wheel event.

`ondragstart` — Handler for the dragstart event.

`ondrag` — Handler for the drag event.

`ondragenter` — Handler for the dragenter event.

`ondragover` — Handler for the dragover event.

`ondragleave` — Handler for the dragleave event.

`ondrop` — Handler for the drop event.

`ondragend` — Handler for the dragend event.

---

Related records: [`type:angle`](types/angle.md), [`type:boolean`](types/boolean.md), [`type:cloner-mode`](types/cloner-mode.md), [`type:id`](types/id.md), [`type:number`](types/number.md), [`type:orientation-axis`](types/orientation-axis.md), [`type:quaternion`](types/quaternion.md)
