← Back to Docs
  • index.html
  • Clayground
  • Clayground.Canvas3D
  • LineBatch3D
  • Clayground 2026.2
  • LineBatch3D QML Type

    Renders very large sets of styled polylines in a single instanced draw call. More...

    Import Statement: import Clayground.Canvas3D

    Properties

    Methods

    Detailed Description

    LineBatch3D draws 100k+ polylines, each with its own color and width, as one instanced draw call. Every line segment becomes one GPU instance over a unit-quad base mesh; the vertex shader expands each segment into a camera-facing ribbon with round caps, and the per-line style rides in the instance attributes. This makes it suitable for map lanes, road overlays, flow fields and other cases where thousands of independently styled lines must be updated and drawn cheaply.

    There are two ways to feed data:

    Individual lines can be moved cheaply with updateLinePoints, which patches only that line's region of the instance table.

    Example usage:

    import QtQuick3D
    import Clayground.Canvas3D
    
    View3D {
        id: view
        LineBatch3D {
            viewportSize: Qt.vector2d(view.width, view.height)
            widthUnits: LineBatch3D.Pixel
            lines: [
                { points: [Qt.vector3d(0,0,0), Qt.vector3d(100,50,0)],
                  color: "#00d9ff", width: 3, styleId: 0 },
                { points: [Qt.vector3d(0,0,0), Qt.vector3d(0,80,60)],
                  color: "#ff3366", width: 5, styleId: 0 }
            ]
        }
    }

    Note: In Pixel width mode the shader needs the View3D pixel size, so bind viewportSize to the enclosing View3D's width/height.

    See also MultiLine3D, LineBatchInstancing, and LineBatchGeometry.

    Property Documentation

    count : int [read-only]

    The number of lines currently in the batch.


    depthBias : real

    Pulls the lines toward the camera to win depth fights.

    A positive bias shifts the rendered depth toward the near plane, so overlay lines floating just above other geometry (for example a lane model above roads) draw on top without a separate render pass. Defaults to 0.


    flowAutoPlay : bool

    Convenience clock that advances flowTime automatically.

    When true, an internal FrameAnimation drives flowTime so flowing and pulsing styles animate without any external clock. Defaults to false so a batch is never self-animating (Qt renders on demand); leave it off and drive flowTime yourself when you need to pause, timescale or inspect deterministically.


    flowTime : real

    Animation clock (seconds) driving every flowing/pulsing style.

    A single value shared by the whole batch: each style's flow scales it to march its pattern, and pulse oscillates its opacity from it. The batch never ticks itself (rendering stays on-demand); bind this to your own clock (typically a FrameAnimation's elapsedTime) or set flowAutoPlay to true for the built-in one. Set it explicitly for deterministic, frame-exact inspection.


    lines : list

    Declarative list of styled polylines (convenience path).

    Each element is an object { points: [Qt.vector3d, ...], color: <color>, width: <real>, styleId: <int> }. A polyline with N points produces N-1 segment instances sharing that line's style. For large generated data sets prefer setBulk.


    opaque : bool

    Renders the batch as opaque geometry with early depth rejection.

    When false (the default) the batch draws alpha-blended: a style's opacity multiplier applies and overlapping lines composite by draw order. When true the batch draws without alpha blending and with depth writes, so overlapping lines resolve by depth (the nearer line wins) instead of blending. This lets the GPU reject occluded fragments early and cuts overdraw where many opaque lines stack up (dense lane overlays, road networks).

    Visual semantics in opaque mode:

    Leave false for translucent or additive styling; set true for dense opaque overlays where depth-correct occlusion and lower overdraw matter more than per-line opacity.


    orientation : int

    The active ribbon orientation, one of the Orientation values.

    Defaults to LineBatch3D.Billboard. Only applies in World width mode.


    styles : list

    Per-styleId table of pattern, cap shape, opacity and effects.

    Each element is an object. Only dash / capRound / opacity are required; every other key is optional and defaults to the plain solid or dashed behaviour, so existing style lists keep rendering unchanged.

    The table is baked into a small RGBA32F texture the shader samples per fragment; the pattern phase runs continuously along each polyline. Style index 0 always defaults to solid, round-capped and fully opaque, so lines work unchanged when styles is left empty.

    Example:

    styles: [
        { dash: [0, 0], capRound: true, opacity: 1.0 },              // 0: solid
        { dash: [12, 8], capRound: false, opacity: 1.0 },            // 1: dashed
        { dash: [6, 34], pattern: "dot" },                           // 2: round dots
        { dash: [10, 30], pattern: "chevron", flow: 40, glow: 0.5 }, // 3: flowing chevrons
        { dash: [0, 0], glow: 0.8, head: [3.0, 2.5] }                // 4: glowing arrow
    ]

    See also flowTime and flowAutoPlay.


    viewportSize : vector2d

    The pixel size of the enclosing View3D.

    Required in Pixel width mode to keep on-screen width constant. Bind it to Qt.vector2d(view3D.width, view3D.height).


    widthUnits : int

    The active width interpretation, one of the WidthUnits values.

    Defaults to LineBatch3D.Pixel.


    Method Documentation

    real pathLength(int lineId)

    Returns the total length of line lineId in world units.

    Read-only query over the batch geometry (0 for an unknown index or a line with fewer than two points). Together with positionAt this lets objects and labels ride along a line without duplicating its geometry.


    vector3d positionAt(int lineId, real distance)

    Returns the point distance world units along line lineId.

    The distance is clamped to the line, so 0 gives its first point and any value past pathLength gives its last. Unknown indices return Qt.vector3d(0, 0, 0).


    void setBulk(ByteArray positions, ByteArray startIndices, ByteArray colors, ByteArray widths, ByteArray styleIds)

    Fast path for building the batch from packed binary buffers.


    void updateEndpointsBulk(ByteArray positions)

    Rewrites the endpoints of every single-segment line in one pass.

    positions is a packed float32 buffer with 6 floats per line (p0.xyz, p1.xyz) in line order. This is the fast per-frame path used by ConnectorLayer3D: it patches the affected instance entries in place and triggers a single upload, with no geometry rebuild. Lines that are not single-segment (two points) are skipped.

    See also ConnectorLayer3D.


    void updateLinePoints(int lineIndex, list points)

    Moves a single line by patching only its instance-table region.

    Rewrites line lineIndex from points (a list of Qt.vector3d). When the point count keeps the same number of segments, only that line's entries are rewritten; otherwise the whole table is rebuilt.


    void updatePolylinesBulk(ByteArray positions, int pointsPerLine)

    Rewrites the points of every uniform-topology line in one pass.

    positions is a packed float32 buffer with pointsPerLine * 3 floats per line (p0.xyz, p1.xyz, ...) in line order. This is the fast per-frame path used by ConnectorLayer3D for curved connectors: it rewrites the matching lines' points and re-uploads once, recomputing per-segment path distances so patterns stay continuous along the new curve. Lines whose topology does not match (instanceCount != pointsPerLine - 1) are skipped.

    See also ConnectorLayer3D.