Canvas3D Plugin
Overview
The Canvas3D plugin provides components for creating 3D visualizations in Clayground applications. It offers primitives for 3D boxes, areas, lines, and voxel-based structures with support for custom edge rendering, toon shading, and efficient batch rendering.
Getting Started
To use Canvas3D components, import the module in your QML file:
import Clayground.Canvas3D
Minimal Example
Here’s a simple example showing a red box with dark edges:
import QtQuick
import QtQuick3D
import Clayground.Canvas3D
View3D {
anchors.fill: parent
PerspectiveCamera {
position: Qt.vector3d(0, 200, 300)
eulerRotation.x: -30
}
DirectionalLight {
eulerRotation.x: -30
castsShadow: true
shadowFactor: 78
shadowMapQuality: Light.ShadowMapQualityVeryHigh
}
Box3D {
width: 100
height: 100
depth: 100
color: "red"
useToonShading: true
}
}
Core Components
Box3D
The Box3D component creates a 3D box with customizable dimensions, edge
rendering, and cartoon-style shading.
Creating Non-Uniform Shapes
Use scale properties to create pyramids, trapezoids, and other shapes:
// Pyramid
Box3D {
width: 100; height: 100; depth: 100
scaledFace: Box3DGeometry.TopFace
faceScale: Qt.vector2d(0.1, 0.1)
}
Edge Mask Usage
Control which edges are visible:
Box3D {
edgeMask: topEdges | bottomEdges // Only horizontal edges
}
Rounded boxes
bevel chamfers every edge and corner, as a fraction of the box’s shortest
edge; 0 (the default) is a hard box. It rounds the shape without rounding the
cost: 44 triangles instead of 12 and the same single draw call. The outline is
drawn from the face UVs, so it survives the chamfer. Not for use with
edgeMode: Triangles, which outlines every chamfer seam.
Box3D {
bevel: 0.15
}
Poly3D
The area primitive: hand it a ring of 2D points and it fills the polygon.
Anything region-shaped — a lake, a plaza, a footprint, a zone on the ground —
is one Poly3D rather than a fan of faked strips.
Poly3D {
vertices: [Qt.vector2d(-50, -50), Qt.vector2d(50, -50),
Qt.vector2d(50, 50), Qt.vector2d(-50, 50)]
color: "#0f9d9a"
useToonShading: true
}
Concave rings are triangulated properly, and holes takes inner rings, so a
courtyard is part of the same object rather than a second shape punched
through it:
Poly3D {
vertices: [...] // outer ring
holes: [[...], [...]] // inner rings
}
Planes and orientation
The ring is 2D, so plane decides which two world axes its points map to —
Poly3D.XZ (default, flat on the ground), Poly3D.XY (a wall) or
Poly3D.YZ. Any other orientation is the node’s own eulerRotation; a
Poly3D is a Model, so it moves, rotates and scales like anything else.
A polygon lying exactly on another surface will z-fight. surfaceOffset is
the fix: it slides the geometry along the plane normal — +Y for XZ, +Z
for XY, +X for YZ — so the two surfaces stop sharing a depth.
Poly3D {
vertices: lakeRing
color: "#00d9ff"
surfaceOffset: 0.5 // above the ground it would otherwise fight
}
It is a lift, not a depth trick, and named that way on purpose. Model’s
depthBias biases the sort distance and does not offset depth, so it is
not the fix here: on a coplanar lake at a grazing angle, 199 of ~3600
contested pixels survived at depthBias: 0, 925 at 500 and 962 at 100000 —
against 3613 for a plain half-unit lift.
The offset leaves the node’s own position alone, so position stays free
for placing and animating the polygon. extrude still measures from the
ring’s own plane, so lifting a prism displaces it rather than resizing it.
surfaceOffset: 0, the default, is no translation at all — the mesh is
identical to one built without the property.
Extrusion
extrude turns the same ring into a prism: the polygon is the base, walls
rise along the plane normal, and a cap closes the top. Holes get walls too,
so a ring with a courtyard extrudes into a building with a courtyard.
Poly3D {
vertices: [...]
extrude: 120 // 0 = flat area (default)
color: "#00d9ff"
}
Walls are faceted, never smoothed across the ring, so a hexagonal column reads as six flat faces under toon shading rather than as a cylinder.
To animate a prism’s height, scale the node (scale.y for XZ) rather
than animating extrude. Scaling touches no geometry at all; changing
extrude rebuilds the mesh.
Wireframe
showEdges is off by default on Poly3D — a box’s borders are its look, but
a polygon’s triangulation is a deliberate choice. edgeMode picks what the
lines mean:
Poly3D {
vertices: [...]
showEdges: true
edgeMode: Poly3D.Triangles // or Poly3D.FaceBorders
edgeThickness: 1.5 // pixels
edgeColor: "#2f3437"
}
FaceBorders— the outline of every ring, plus the seams of a prism.Triangles— the above plus the triangulation itself, for when the mesh is the subject rather than the shape.
Edges are not free: they need one vertex per index instead of a shared,
indexed mesh, which costs roughly 3x the vertex memory for a flat polygon.
That is why the lean layout is the default. The buffer upgrades the first
time edges are switched on and never downgrades, so binding showEdges to a
hover or selection state costs one rebuild rather than one per toggle.
Scale
One Poly3D is one Model and one draw call — sized for tens of areas, not
thousands. It is the rich end of the family, the way Label3D is next to
LabelBatch3D; there is no batched sibling yet.
Lines
Canvas3D provides several components for drawing lines in 3D space:
- LineBatch3D: Instanced renderer for very large sets of independently
styled polylines in a single draw call. Supports pixel- or world-width
ribbons with round caps, a per-line
styleIdselecting a row of thestylestable (dash pattern in world units, cap shape, opacity), and cheap per-frame updates viaupdateLinePoints/updateEndpointsBulk. - Line3D: Simple wrapper for drawing a single line (batched backend)
- MultiLine3D: Draws multiple line paths with one color/width (batched backend)
- BoxLine3D: Creates a line using connected box segments for thicker, more visible lines
Dynamic Connectors
- ConnectorLayer3D: Owns one
LineBatch3Dand draws all of its connectors as a single instanced draw call, patching only the endpoints that moved each frame. - Connector3D: A declarative link between two scene nodes (
from/to); it follows their scene positions and registers into aConnectorLayer3D(either declared inside one, or via an explicitlayerreference forRepeater3Ddelegates). N connectors cost one draw call.
Styled bulk lines with LineBatch3D
Give each line its own colour, width and dash style, all in one instanced draw
call. The styles table holds dash/cap/opacity rows; a line’s styleId selects
one:
LineBatch3D {
viewportSize: Qt.vector2d(view.width, view.height)
widthUnits: LineBatch3D.Pixel // or LineBatch3D.World
styles: [
{ dash: [0, 0], capRound: true, opacity: 1.0 }, // 0: solid
{ dash: [12, 8], capRound: false, opacity: 1.0 } // 1: dashed
]
lines: [
{ points: [Qt.vector3d(0,0,0), Qt.vector3d(100,0,0)], color: "#00d9ff", width: 2, styleId: 0 },
{ points: [Qt.vector3d(0,0,0), Qt.vector3d(0,0,100)], color: "#ff3366", width: 2, styleId: 1 }
]
}
For very large sets, skip the per-object lines list and push packed binary
buffers via setBulk(positions, startIndices, colors, widths, styleIds) — the
optional fifth styleIds (uint16 per line) is backward-compatible; omit it and
every line renders solid. Move lines cheaply per frame with
updateLinePoints(lineIndex, points) or updateEndpointsBulk(positions) — both
patch the instance table in place instead of rebuilding geometry.
// N moving links as a single instanced batch, endpoints patched each frame.
ConnectorLayer3D {
id: links
viewportSize: Qt.vector2d(view.width, view.height)
widthUnits: LineBatch3D.Pixel
color: "#00d9ff"; width: 1.5
}
Repeater3D {
model: satellites
delegate: Node {
required property int index
Connector3D { layer: links; from: this; to: hubs[index % hubs.length] }
}
}
Labels
Three components put readable text into a 3D scene the way technical illustrations and maps do. All render unlit (never toon-shaded, never shadow-casting) and stay crisp under the camera. Pick by role:
- Label3D - a camera-facing callout pill anchored to a thing. Reach for it to annotate individual entities or points - dozens - with rich, always-readable UI-style tags, optionally with a leader line.
- PathLabel3D - text laid flat along a line, the street-name look. Reach for
it to paint a name onto a road or route from a
LineBatch3D, read from above. - LabelBatch3D - thousands of instanced SDF text labels. Reach for it when you need many cheap, uniform world-anchored labels (map features, data points, particle tags) in a couple of draw calls.
They compose: Label3D is the rich end (one QObject per label), LabelBatch3D
is the mass-scale end (one GPU instance per glyph), and PathLabel3D sits on top
of LineBatch3D for the flat-on-ground case.
Label3D - anchored callouts
A rounded “pill” with optional icon, anchored to a moving anchorNode or a fixed
anchorPosition. It stays parallel to the image plane every frame and, by default, holds a
constant on-screen size (sizeMode: Label3D.Screen); switch to Label3D.World to
scale with the scene. An optional showLeader draws a thin line from the pill to
the anchor - the offset-callout look. A single shared per-view ticker (via
Label3DRegistry) drives all labels in one pass and skips the work entirely while
the camera and anchors are still, so many labels stay cheap and hidden ones are
dormant.
Label3D {
view: view
anchorNode: reactor
text: "REACTOR CORE"
labelOffset: Qt.vector3d(0, 40, 0)
showLeader: true
}
PathLabel3D - names along a line
Street-name style text laid flat on the ground along a line of a LineBatch3D,
the way a map paints a road name. Placement rides the line via pathLength() /
positionAt(): the label centers on at (or the path middle), one flip-to-read
decision per placement keeps text from ever appearing upside-down, and
repeatEvery stamps the name at a fixed spacing along a long road.
It offers two carriers, chosen with glyphPlacement:
- Word mode (default,
glyphPlacement: false): each word rides its own 2x-oversampled texture quad tangent to the path. Cheap; bends happen at word boundaries. Crisp down to roughly the oversample factor. - Glyph mode (
glyphPlacement: true): the text is shaped once and each glyph is placed and rotated individually along the curve (maplibre’s model), so the baseline hugs tight bends smoothly and the whole name - not just each word - reads correctly on a doubling-back leg. Rendering routes through an internalLabelBatch3Dcreated lazily on first use, so word-mode labels pay for no SDF atlas (pay-per-use). Being SDF-baked, glyph mode stays crisp at any zoom. A curvature guard skips a placement whose baseline would wrap too sharp an arc (skippedPlacementsreports how many); a background pill is not supported in glyph mode v1. As a ground decal the glyphs write depth with a small toward-camera bias so they draw above the line they sit on from any camera - the layering contract is lines first, labels above.
LineBatch3D { id: roads /* ... */ }
PathLabel3D {
lines: roads
lineId: 0
text: "CLAY STREET"
worldHeight: 30
repeatEvery: 900
glyphPlacement: true // per-glyph text-on-curve; omit for cheap word mode
}
LabelBatch3D - mass-scale SDF labels
Draws very large sets of short labels - tens of thousands - as instanced
signed-distance-field glyphs over a shared atlas (deck.gl’s TextLayer model): N
labels cost one draw call for the glyphs plus one for the optional pills. Each
label is a world-anchored point with its own text, color and size; glyphs stay
crisp at any zoom. sizeMode picks screen-constant (billboard) or world units,
orientation picks billboard or flat-on-ground, and moving labels can be repositioned
without re-shaping via updatePositionsBulk. It is the mass-scale sibling of
Label3D, not a replacement - rich per-label content, icons and leaders stay
Label3D’s job.
LabelBatch3D {
viewportSize: Qt.vector2d(view.width, view.height)
sizeMode: LabelBatch3D.Screen
halo: true
labels: [
{ position: Qt.vector3d(0, 0, 0), text: "ALPHA", color: "#00d9ff", size: 22 },
{ position: Qt.vector3d(80, 0, 0), text: "BETA", color: "#ff3366", size: 22 }
]
}
Voxel Maps
Voxel maps create 3D structures composed of cubic voxels. Both backends share a compact palette-index store (8-bit per voxel, auto-upgraded to 16-bit past 255 distinct colours) with an incrementally-maintained (O(1)) solid count — no per-change recount.
- StaticVoxelMap: greedy-meshed triangle geometry, chunked and remeshed
off the main thread. A single
set()dirties only its ~32³ chunk, which is remeshed on a worker; the call returns immediately. Best for large maps, and — since the remesh no longer blocks — now perfectly usable under frequent edits. - DynamicVoxelMap: GPU-instanced cubes; each
set()marks the instance table dirty and the rebuild lands at render time. Best for maps that churn (full clear+refill) or need per-voxel instance semantics.
Dynamic Instancing
DynamicInstances3D renders many copies of one base mesh (cars, crowds,
projectiles) through a single GPU instance table whose per-entry transforms are
updated every frame from a packed binary buffer — no per-instance QObject and
no CPU table rebuild on the hot path. It is the C++-backed alternative to a
declarative InstanceList of InstanceListEntry objects, which pays a property
write per entry per changed field and a full table rebuild.
- Set per-entry statics once with
setBulk(scales, colors, customData)— onevector3dscale and onecolorper entry. - Push movement each frame with
updatePoses(first, poses), whereposesis a reusedFloat32Arrayof[x, y, z, yawRad]per entry (pass.buffer). The transform istranslate(x,y,z) * rotateY(yaw) * scale, so the base mesh’s local +Z axis points alongyaw— matching anInstanceListEntrywitheulerRotation (0, yawDeg, 0), so migrations keep their orientation. setEntryColor(i, c)recolors a single entry;setExtents(min, max)declares the roaming volume so the table skips the per-upload bounds rescan.- Read-only
count,bytesLastUpload,packMsLast,uploadsPerSecondfeed a HUD.
Model {
source: "#Cube"
instancing: DynamicInstances3D {
id: fleet
Component.onCompleted: {
var scales = [], colors = []
for (var i = 0; i < 500; ++i) { scales.push(Qt.vector3d(0.02, 0.01, 0.03)); colors.push("#00d9ff") }
setBulk(scales, colors)
setExtents(Qt.vector3d(-200, 0, -200), Qt.vector3d(200, 10, 200))
}
}
materials: PrincipledMaterial { lighting: PrincipledMaterial.NoLighting }
}
// per frame, from a reused Float32Array poseBuf (4 floats per entry):
fleet.updatePoses(0, poseBuf.buffer)
The neoncity demo drives its whole car fleet (body + cabin + window + 4 wheels = four tables) this way.
Toon Shading
Canvas3D implements cartoon-style rendering using a half-lambert lighting model, providing flat, stylized lighting with distinct shadow boundaries.
Optimal Lighting Setup
Toon shading requires specific shadow settings for the characteristic cartoon look:
DirectionalLight {
eulerRotation.x: -35 // Optimal lighting angle
castsShadow: true
shadowFactor: 78 // Strong shadows
shadowMapQuality: Light.ShadowMapQualityVeryHigh // Crisp edges
pcfFactor: 2 // Minimal softening
shadowBias: 18 // Artifact prevention
}
Usage
Enable toon shading on any Canvas3D component:
Box3D {
useToonShading: true
edgeColorFactor: 2.0 // Increase edge contrast for cartoon look
}
StaticVoxelMap {
useToonShading: true // Creates Minecraft-like blocky aesthetics
}
Coordinate System
Canvas3D uses Qt Quick 3D’s coordinate system:
- X-axis: Points right
- Y-axis: Points up
- Z-axis: Points toward the viewer
Voxel Coordinates
The relationship between voxel coordinates and world positions:
worldPosition = voxelCoordinate * (voxelSize + spacing) + voxelOffset
Example dimensions calculation:
StaticVoxelMap {
voxelCountX: 10
voxelCountY: 5
voxelCountZ: 10
voxelSize: 2.0
spacing: 0.5
// width = 10 * (2.0 + 0.5) - 0.5 = 24.5
// height = 5 * (2.0 + 0.5) - 0.5 = 12.0
// depth = 10 * (2.0 + 0.5) - 0.5 = 24.5
}
Edge Rendering
Box3D, VoxelMap and Poly3D all draw their edges by the same rule, so a
scene made of all three reads as one thing.
Thickness is a count of pixels
edgeThickness is measured on screen, not in world units, so a line keeps its
weight as the camera pulls back, as the window resizes and as a surface turns
away. A line straddles the boundary it marks and each surface draws half of
it, which is why a box border, a voxel map’s border and an extruded polygon’s
border all come out the same width at the same setting. A voxel map’s interior
grid lines sit inside one face and are shared with nothing, so they draw both
halves and are correctly twice that width.
Below about 1 px lines start dropping out of the pixel grid, so 1.0 is the
practical floor rather than a soft limit.
Edge colour
edgeColor names the colour outright:
Box3D {
color: "#e6d2f2"
showEdges: true
edgeColor: "#2f3437" // dark edges on a light face
}
Without it, edgeColorFactor scales the fill instead — which can only ever
darken, so a light surface gets washed-out edges and “dark grey on pale
lilac” is inexpressible. edgeColor wins whenever its alpha is above zero;
leave it unset to keep the edgeColorFactor behaviour.
Face borders or triangulation
Box3D and Poly3D both take edgeMode. FaceBorders draws the object’s
own borders — a box’s twelve edges, a polygon’s rings. Triangles draws the
mesh’s triangulation instead, for when how a shape is built is the point.
edgeMask, which selects individual box borders, applies to FaceBorders
only; a triangulation missing some of its lines is not a triangulation.
Edge Artifacts with Greedy Meshing
When using StaticVoxelMap with fill() operations (spheres, cylinders),
disable edges to avoid visual artifacts:
StaticVoxelMap {
voxelCountX: 50
voxelCountY: 50
voxelCountZ: 50
showEdges: false // Prevents grid artifacts with meshed geometry
Component.onCompleted: {
fill({ shape: "sphere", pos: [25,25,25], radius: 10, colors: ["red"] })
}
}
Performance Considerations
Choosing Voxel Map Types
- StaticVoxelMap: large maps and edit-heavy scenes alike — chunked
off-thread greedy meshing means a single voxel edit only remeshes its chunk on
a worker thread (per-edit cost is effectively free on the main thread). It even
outperforms
DynamicVoxelMapfor a single-edit-per-frame storm. - DynamicVoxelMap: full clear+refill churn, or when you need per-voxel instanced cubes rather than meshed geometry.
Edit costs
- A single
set()onStaticVoxelMapdirties ~one chunk; the greedy remesh runs on aQtConcurrentworker, so it does not stall the frame. model.commit()after a batch (e.g.fillBox/fillSphere) dispatches the full build to the worker too — it schedules rather than blocks.- Still prefer the batch path (
fillBox+ onecommit()) over thousands of individualset()calls when generating terrain: it is a single build instead of one per dirtied chunk.
Optimization Tips
- Batch Operations: Call
model.commit()once after multiple voxel changes - Edge Control: Disable
showEdgesfor large voxel maps - Shadow Quality: Balance shadow settings with performance needs
Instrumentation & Benchmarks
Three helper types measure real cost from QML:
- PerfHud: a compact always-on-top overlay for a
View3D(view3D:+ optionalextended: true) showing fps and frame time — drop it into any scene while tuning. It automatically appends anyPerfRegistrysection averages and counter rates beneath the render stats. - PerfRegistry: an app-wide singleton for timing named code sections and
counting events, independent of the renderer. Wrap a block with
PerfRegistry.begin("name")/PerfRegistry.end("name")for a rolling-average section time, or callPerfRegistry.tick("name")for a per-second rate;snapshot()returns the current readings. Cheap when unused. The neoncity car sim instruments"carSim"(control logic) and"carPack"(pose packing + upload) so the HUD shows the split. - BenchLogger: samples a
View3D’srenderStatsat a fixedintervalMsand writes a CSV tooutputPath;extraadds custom columns andannotate(key, value)tags the next sample (e.g. step boundaries).
PerfHud { view3D: view; anchors.right: parent.right }
BenchLogger {
view3D: view
outputPath: "file:///tmp/mybench.csv"
intervalMs: 250
running: true
}
The benchmarks/ directory holds stepped, auto-running scenarios
(Sandbox.qml loads them) covering static/dynamic lines, moving connectors,
animated instances (InstanceList vs DynamicInstances3D), and voxel
edit-storm/churn. Recorded results, the baseline, and the optimized-vs-baseline
comparison live in benchmarks/results/ — see results/COMPARISON-2026-07-18.md
for the line/voxel headline numbers and results/instances-2026-07-19.md for the
instancing comparison.
Examples
Toon-Shaded Voxel Terrain
import QtQuick
import QtQuick3D
import Clayground.Canvas3D
View3D {
environment: SceneEnvironment {
clearColor: "#87CEEB" // Sky blue
backgroundMode: SceneEnvironment.Color
}
PerspectiveCamera {
position: Qt.vector3d(200, 300, 400)
eulerRotation.x: -30
}
DirectionalLight {
eulerRotation.x: -35
eulerRotation.y: -70
castsShadow: true
shadowFactor: 78
shadowMapQuality: Light.ShadowMapQualityVeryHigh
pcfFactor: 2
shadowBias: 18
}
StaticVoxelMap {
id: terrain
voxelCountX: 80
voxelCountY: 30
voxelCountZ: 80
voxelSize: 5
useToonShading: true
showEdges: false // Avoid artifacts with terrain
Component.onCompleted: {
// Create layered terrain
for (let x = 0; x < voxelCountX; x++) {
for (let z = 0; z < voxelCountZ; z++) {
let h = Math.sin(x * 0.1) * Math.cos(z * 0.1) * 8 + 15
for (let y = 0; y < h; y++) {
let color = y < 5 ? "#8B4513" : // Dirt
y < 12 ? "#228B22" : // Grass
"#708090" // Stone
set(x, y, z, color)
}
}
}
model.commit()
}
}
}
Mixed Rendering Styles
Row {
spacing: 200
// Standard PBR rendering
Box3D {
width: 100; height: 100; depth: 100
color: "#e74c3c"
useToonShading: false
}
// Cartoon rendering
Box3D {
width: 100; height: 100; depth: 100
color: "#e74c3c"
useToonShading: true
edgeColorFactor: 2.0 // Enhanced edges for cartoon look
}
}
Best Practices
Toon Shading
- Use strong directional lighting with high shadow factor (70-80)
- Enable crisp shadow maps (VeryHigh quality, low PCF factor)
- Increase
edgeColorFactorfor enhanced cartoon aesthetics - Consider scene ambient lighting balance
Performance
- Choose appropriate voxel map type based on update frequency
- Batch voxel operations when possible
- Use edge rendering selectively on large scenes
- Profile shadow quality vs. performance trade-offs
Visual Design
- Consistent lighting setup across toon-shaded objects
- Use the demos (
Box3DDemo.qml,VoxelDemo.qml) as implementation references - Test both rendering modes during development
Code Organization
- Study shader implementations in
.fragfiles for custom lighting - Refer to geometry classes for edge rendering algorithms
- Use the demo control panels as UI pattern examples
Implementation References
For developers wanting to understand or extend the system:
- Toon Shading:
box3d.frag,voxel_map.frag- complete shader implementations - Edge Rendering:
shouldShowEdge()function, grid line calculations - Greedy Meshing:
VoxelMapGeometry::generateGreedyMesh() - Demo Implementation:
Box3DDemo.qml,VoxelDemo.qml- complete working examples
API Reference
BenchLogger Samples a View3D's renderStats at a fixed interval and writes them to a CSV file
Properties
| Name | Type | Description |
|---|---|---|
extra | var | Map of extra column name to value or zero-argument function. Each entry adds one CSV column; functions are evaluated per sample. The key set is captured when logging starts |
intervalMs | int | Sampling interval in milliseconds |
outputPath | string | Destination CSV file path (plain path or file:// URL) |
running | bool | Set true to open the file and start sampling, false to flush, close and stop |
view3D | var | View3D whose renderStats are sampled. Required |
Methods
| Method | Returns | Description |
|---|---|---|
annotate(string key, var value) | void |
Signals
| Signal | Description |
|---|---|
sampleTaken() |
Box3D A 3D box with customizable dimensions, edge rendering, and toon shading
Properties
| Name | Type | Description |
|---|---|---|
allEdges readonly | int | Convenience constant for showing all edges |
bevel | real | Chamfers every edge and corner, as a fraction of the box's shortest edge. 0 (the default) is a hard box |
color | color | Base color of the box |
depth | real | Depth of the box along the Z axis |
edgeColor | color | Edge color, as an absolute color rather than a factor |
edgeColorFactor | real | Darkening factor for edges (0-1) |
edgeMask | int | Bitmask controlling which edges are visible |
edgeMode | enumeration | Which lines showEdges draws |
edgeThickness | real | Thickness of edge lines, in pixels |
faceScale | vector2d | Scale factor for the selected face |
height | real | Height of the box along the Y axis |
scaledFace | enumeration | Which face of the box should be scaled |
showEdges | bool | Whether to render dark edge lines |
useToonShading | bool | Enables cartoon-style rendering |
width | real | Width of the box along the X axis |
Box3DGeometry Custom geometry for 3D boxes with edge rendering support
Properties
| Name | Type | Description |
|---|---|---|
edgeColor | color | Edge color, as an absolute color rather than a factor |
edgeColorFactor | real | Darkening factor for edge colors |
edgeMask | int | Bitmask controlling which edges are visible |
edgeMode | enumeration | Which lines showEdges draws |
edgeThickness | real | Thickness of edge lines in pixels |
faceScale | vector2d | Scale factor applied to the selected face |
scaledFace | enumeration | Which face of the box should be scaled |
showEdges | bool | Whether to render edge lines on the box |
size | vector3d | Dimensions of the box as a 3D vector (width, height, depth) |
BoxLine3D Renders a 3D line as connected box segments using GPU instancing
Properties
| Name | Type | Description |
|---|---|---|
color | color | Of the line |
material | Material | Used for rendering |
positions | vector3d | List of 3D positions defining the line path |
width | real | Of the box-shaped line segments |
Connector3D A dynamic connection line between two scene nodes, drawn in a batch
Properties
| Name | Type | Description |
|---|---|---|
color | color | Connector color. Defaults to the layer's color |
from | QtObject | Node the connector starts at (its scene position is tracked) |
layer | ConnectorLayer3D | This connector draws into |
styleId | int | Style-table row selecting dash/cap/opacity. Defaults to the layer's styleId. See LineBatch3D::styles |
to | QtObject | Node the connector ends at (its scene position is tracked) |
width | real | Connector width. Defaults to the layer's width |
ConnectorLayer3D Draws many dynamic Connector3D lines as a single instanced batch
Properties
| Name | Type | Description |
|---|---|---|
arcHeight | real | Arc lift as a fraction of link length (only when segmentsPerLink > 1) |
color | color | Default line color for connectors that do not set their own |
count readonly | int | Number of connectors currently drawn in the batch |
depthBias | real | Depth bias forwarded to the batch, see LineBatch3D::depthBias |
flowTime | real | Animation clock forwarded to the batch, see LineBatch3D::flowTime |
segmentsPerLink | int | Number of straight segments each connector is drawn with |
styleId | int | Default styleId for connectors that do not set their own |
styles | list | Style table forwarded to the batch, see LineBatch3D::styles |
viewportSize | vector2d | Enclosing View3D pixel size, forwarded to the batch. Required in Pixel width mode |
width | real | Default line width for connectors that do not set their own |
widthUnits | enumeration | How connector width is interpreted, see LineBatch3D::widthUnits |
DynamicInstances3D Fast, general-purpose dynamic instance table for animated fleets
Properties
| Name | Type | Description |
|---|---|---|
bytesLastUpload readonly | int | Size in bytes of the instance data handed to the renderer on the last upload (count * 80) |
capacity | int | Preallocated number of entries the table can hold |
count readonly | int | Number of active entries currently rendered |
packMsLast readonly | real | Wall-clock milliseconds spent packing the last updatePoses call |
uploadsPerSecond readonly | real | Rolling rate of updatePoses calls over the last second |
Methods
| Method | Returns | Description |
|---|---|---|
setBulk(list scales, list colors, list customData) | void | |
setEntryColor(int i, color c) | void | |
setExtents(vector3d min, vector3d max) | void | |
updatePoses(int first, ByteArray poses) | void |
DynamicVoxelMap Voxel map optimized for frequent updates using GPU instancing
Properties
| Name | Type | Description |
|---|---|---|
voxelCountX | int | Number of voxels along the X axis |
voxelCountY | int | Number of voxels along the Y axis (height) |
voxelCountZ | int | Number of voxels along the Z axis |
Label3D A camera-facing callout label anchored to a 3D node or position
Properties
| Name | Type | Description |
|---|---|---|
anchorNode | QtObject | Node the label tracks; its scene position drives placement |
anchorPosition | vector3d | Fixed scene position to anchor to when anchorNode is null |
camera | QtObject | The label faces. Defaults to view.camera |
distanceFade | bool | When true, fade the label out with camera distance (Screen mode) |
fadeFar | real | Camera distance at and beyond which the label is fully transparent |
fadeNear | real | Camera distance at and below which the label is fully opaque |
iconSource | url | Optional icon shown left of the text. Empty hides it |
labelOffset | vector3d | World-space offset of the pill from the anchor |
labelStyle | QtObject | Grouped pill styling: colors, radius, padding, halo and font |
leaderStyle | QtObject | Grouped leader-line styling: color and width (pixels) |
maxScreenSize | real | Upper clamp for the on-screen pill height in pixels (0 disables) |
minScreenSize | real | Lower clamp for the on-screen pill height in pixels (0 disables) |
priority | int | Ordering hint for the future declutter manager; higher wins |
scaleQuantum | real | Relative scale change required before the pill is re-scaled (0 disables) |
screenHeight | real | Target on-screen pill height in pixels (Screen size mode) |
showLeader | bool | When true, draw a thin line from the pill edge to the anchor |
sizeMode | int | Active size mode, see SizeMode |
text | string | Label text |
view | QtObject | Enclosing View3D, used to resolve the camera, size the leader and register with the per-view label registry |
worldHeight | real | Pill height in world units (World size mode) |
LabelBatch3D Renders thousands of SDF text labels in a few instanced draw calls
Properties
| Name | Type | Description |
|---|---|---|
ascentPx readonly | real | Font ascent in atlas base pixels (for mapping a world text height onto setCurvedLabels sizes) |
atlasHeight readonly | int | Current glyph-atlas height in texels |
atlasWidth readonly | int | Current glyph-atlas width in texels |
batchOpacity | real | Batch-wide opacity multiplier (0..1). Default 1 |
capHeightPx readonly | real | Font cap height in atlas base pixels |
count readonly | int | Number of labels currently in the batch |
depthBias | real | Shifts the glyph depth toward the camera (0..~0.001). Default 0 |
descentPx readonly | real | Font descent in atlas base pixels |
font | QtObject | Grouped font config for the shared glyph atlas |
glyphCount readonly | int | Number of glyph instances currently drawn |
halo | bool | Whether glyphs get a halo outline for busy backgrounds. Default true |
haloColor | color | Halo color (a dark halo is the robust default on bright and dark) |
haloWidth | real | Halo band width in SDF units past the glyph edge (0..0.5). Default 0.18 |
labels | list | Declarative list of labels |
orientation | int | Active orientation, one of the Orientation values. Default Billboard. Only applies in World size mode |
pill | bool | Whether a rounded background pill is drawn behind each label. Default false |
pillColor | color | Pill fill color (dark semi-transparent default) |
pillPadding | real | Padding in base pixels between the text box and the pill edge |
pillRadius | real | Pill corner radius in base pixels |
shapeMsLast readonly | real | Wall-clock milliseconds spent shaping on the last setLabels |
sizeMode | int | Active size mode, one of the SizeMode values. Default Screen |
viewportSize | vector2d | Pixel size of the enclosing View3D |
writesDepth | bool | Whether inked glyph fragments write depth. Default false |
Methods
| Method | Returns | Description |
|---|---|---|
glyphAdvances(string text, real size) | list | |
priorities() | list | |
setCurvedLabels(list labels) | void | |
setLabels(list labels) | void | |
updatePositionsBulk(ByteArray positions, int first) | void |
LabelBatchInstancing Per-glyph instance table for the batched LabelBatch3D renderer
Properties
| Name | Type | Description |
|---|---|---|
labels | list | Declarative list of labels to render |
Methods
| Method | Returns | Description |
|---|---|---|
glyphAdvances(string text, real size) | list | |
setCurvedLabels(list labels) | void | |
updatePositionsBulk(ByteArray positions, int first) | void |
LabelGlyphAtlas Incremental single-channel SDF glyph atlas for LabelBatch3D
Properties
| Name | Type | Description |
|---|---|---|
baseSize | int | Rasterization size in pixels. Higher = crisper when magnified, larger atlas. Changing it clears the atlas |
fontFamily | string | Font family baked into the atlas. Changing it clears the atlas |
fontWeight | int | Font weight (e.g. 400 normal, 700 bold). Changing it clears the atlas |
LabelPillInstancing Per-label pill-background instance table for LabelBatch3D
Line3D A simple 3D line connecting multiple points
Properties
| Name | Type | Description |
|---|---|---|
color | color | Of the line |
coords | vector3d | List of 3D points defining the line path |
width | real | Of the line in world units |
LineBatch3D Renders very large sets of styled polylines in a single instanced draw call
Properties
| Name | Type | Description |
|---|---|---|
count readonly | int | Number of lines currently in the batch |
depthBias | real | Pulls the lines toward the camera to win depth fights |
flowAutoPlay | bool | Convenience clock that advances flowTime automatically |
flowTime | real | Animation clock (seconds) driving every flowing/pulsing style |
lines | list | Declarative list of styled polylines (convenience path) |
opaque | bool | Renders the batch as opaque geometry with early depth rejection |
orientation | int | Active ribbon orientation, one of the Orientation values |
shapedShadows | bool | Carved (default) versus cheap rectangular shadows |
styles | list | Per-styleId table of pattern, cap shape, opacity and effects |
viewportSize | vector2d | Pixel size of the enclosing View3D |
widthUnits | int | Active width interpretation, one of the WidthUnits values |
Methods
| Method | Returns | Description |
|---|---|---|
pathLength(int lineId) | real | |
positionAt(int lineId, real distance) | vector3d | |
setBulk(ByteArray positions, ByteArray startIndices, ByteArray colors, ByteArray widths, ByteArray styleIds) | void | |
updateEndpointsBulk(ByteArray positions) | void | |
updateLinePoints(int lineIndex, list points) | void | |
updatePolylinesBulk(ByteArray positions, int pointsPerLine) | void |
LineBatchGeometry Base quad geometry for the instanced LineBatch3D renderer
Properties
| Name | Type | Description |
|---|---|---|
boundsMax | vector3d | Maximum corner of the axis-aligned bounding box covering all lines |
boundsMin | vector3d | Minimum corner of the axis-aligned bounding box covering all lines |
LineBatchInstancing Per-line instance table for the batched LineBatch3D renderer
Properties
| Name | Type | Description |
|---|---|---|
count readonly | int | Number of lines (polylines) currently in the batch |
lines | list | Declarative list of styled polylines |
Methods
| Method | Returns | Description |
|---|---|---|
pathLength(int lineIndex) | real | |
positionAt(int lineIndex, real distance) | vector3d | |
setBulk(ByteArray positions, ByteArray startIndices, ByteArray colors, ByteArray widths, ByteArray styleIds) | void | |
updateEndpointsBulk(ByteArray positions) | void | |
updateLinePoints(int lineIndex, list points) | void | |
updatePolylinesBulk(ByteArray positions, int pointsPerLine) | void |
LineInstancing GPU instancing for rendering lines as connected box segments
Properties
| Name | Type | Description |
|---|---|---|
color | color | Applied to all line segment instances |
positions | list<vector3d> | List of 3D positions defining the line path |
width | real | Of the line segments in world units |
LineStyleTextureData Bakes a list of line styles into a small RGBA32F lookup texture
Properties
| Name | Type | Description |
|---|---|---|
styleCount readonly | int | Number of style columns in the texture (always at least 1) |
styles | list | Declarative list of line styles baked into the texture |
MultiLine3D Renders multiple 3D line paths in a single draw call
Properties
| Name | Type | Description |
|---|---|---|
castsShadows | bool | Whether the lines drop a shadow. Off by default |
color | color | Of all lines. Defaults to red |
coords | list<vector3d> | Array of line paths, each path being an array of 3D points |
orientation | int | LineBatch3D.Billboard (default) or LineBatch3D.Flat |
shapedShadows | bool | Forwarded to LineBatch3D::shapedShadows: carved (default) versus cheap rectangular shadows while castsShadows is active |
width | real | Of all lines in world units. Defaults to 1 |
OrbitCamera3D An orbit camera on a leash: circles a pivot, never dives through the floor
Properties
| Name | Type | Description |
|---|---|---|
aspect readonly | real | Width over height of the frame; 0 while view is not set |
camera readonly | PerspectiveCamera | |
distance | real | Distance to the pivot |
fieldOfView | real | Vertical FOV of the camera |
follow | var | What to keep in frame while it moves: a function returning a vector3d or an array of them, called every frame. Null is off |
followMs | int | How long one follow correction glides; the lag of the pan |
followSlack | real | How much of the half-frame the subject may cross before the rig pans: 0 pans at the first pixel, 0.25 (default) lets it reach three quarters of the way to the edge |
goalDistance readonly | real | Distance the rig is travelling to |
goalPitch readonly | real | Pitch the rig is travelling to |
goalPivot readonly | vector3d | Pivot the rig is travelling to |
goalPosition readonly | vector3d | Where the camera ends up, in world coordinates |
goalYaw readonly | real | Yaw the rig is travelling to |
gripMs | int | Glide while gripped. Zero, and rarely anything else |
gripped | bool | A hand is driving the pose right now, so it does not glide |
hasReturnPose readonly | bool | A frameWithReturn dive is open, so the next one comes home |
homePivot | vector3d | Point panLeash measures from. Defaults to the origin |
jumpDepth | int | How many places back the jumplist remembers |
jumpsAhead readonly | int | Places jumpForward can still take you |
jumpsBack readonly | int | Places jumpBack can still take you |
leashSoftness | real | How much overshoot the leash allows, as a fraction of itself |
maxDistance | real | Furthest allowed retreat |
maxPitch | real | Steepest allowed angle (< 90) |
minDistance | real | Closest allowed approach |
minHeight | real | Lowest the camera may sit above the pivot plane |
minPitch | real | Flattest allowed angle |
minPivotY readonly | real | How deep the pivot may sink: exactly as far as it can climb out of |
panLeash | real | Furthest the pivot may wander from homePivot; 0 is no limit |
pitch | real | Angle above the pivot plane, degrees |
pivot | vector3d | Point the camera looks at |
smoothMs | int | Glide time for every move, in milliseconds; 0 snaps |
travelMs | int | Glide time for a goTo / focusOn journey, in milliseconds |
travelling readonly | bool | A glide is in progress |
view | var | View3D this rig renders through. Optional |
viewpoints | var | Named poses, as { name: {yaw, pitch, distance, px, py, pz} } |
yaw | real | Angle around the pivot, degrees |
Methods
| Method | Returns | Description |
|---|---|---|
applyState(var s) | void | |
clamp() | void | |
clearJumps() | void | |
clearReturn() | void | |
covers(var points, real margin, bool goal) | bool | |
fit(var points, var opts) | bool | |
focusOn(var what, real pad, int ms) | void | |
frame(var points, real pad, var angles) | void | |
frameWithReturn(var points, real pad) | bool | |
goTo(string name, int ms) | bool | |
jumpBack(int ms) | bool | |
jumpForward(int ms) | bool | |
orbitAround(var anchor, real dYaw, real dPitch) | void | |
orbitBy(real dYaw, real dPitch) | void | |
panBy(real dRight, real dAway) | void | |
project(var p, bool goal) | var | |
pushJump() | void | |
reanchor(var p) | bool | |
setDistance(real d) | void | |
setPivot(var p) | void | |
state() | var | |
viewpointNames() | var | |
worldPerPixel(real viewportHeight) | real | |
zoomBy(real factor) | void | |
zoomToward(var p, real factor) | void |
OrbitInput3D Turns drags, wheels and double-clicks into OrbitCamera3D moves, under one rule: the left button is never the camera's
Properties
| Name | Type | Description |
|---|---|---|
active readonly | bool | A drag is in progress |
anchor readonly | var | World point this orbit is turning about, or null |
anchorOrbit | bool | An orbit turns about the point under the cursor at press |
clickSlop | real | Pixels a press may travel and still count as a click |
cursorShape readonly | int | Closed hand while a drag runs, plain arrow otherwise |
flick | bool | Let a fast drag coast for a moment after the button comes up |
flickDecay | real | Velocity kept per frame while coasting |
flickThreshold | real | Pixels per frame a drag needs to coast at all |
gesture readonly | string | Drag in progress: "orbit", "pan" or "" |
groundY | real | Height of the plane groundAt() hits |
hovering | var | What was under the cursor at the last hoverAt, or null |
invertPitch | bool | Flip the vertical orbit direction |
orbitButtons | int | Buttons that turn the rig |
panButtons | int | Buttons that drag the world |
panModifiers | int | Modifiers that make any button pan |
panSpeed | real | Multiplier on the grab-the-ground pan |
pickObjects | bool | Ask the view what object a pick landed on, as well as where |
pitchPerPixel | real | Degrees of pitch per pixel dragged |
rig | var | OrbitCamera3D to drive |
springNav | bool | Pan on the left button too, while this is true |
universalPanButtons | int | Buttons that always drag the world |
view | var | View3D the gestures happen in |
yawPerPixel | real | Degrees of yaw per pixel dragged |
zoomStep | real | Distance factor for one wheel notch inwards |
zoomToCursor | bool | Wheel zooms towards the point under the cursor |
Methods
| Method | Returns | Description |
|---|---|---|
begin(real x, real y, int button, int modifiers) | string | |
beginAs(string g, real x, real y) | string | |
cancel() | void | |
clearHover() | void | |
end() | void | |
groundAt(real x, real y) | var | |
hoverAt(real x, real y) | var | |
move(real x, real y) | bool | |
pickAt(real x, real y) | var | |
recenterAt(real x, real y) | bool | |
wants(int button, int modifiers) | string | |
wheel(real angleDelta, real x, real y) | void |
Signals
| Signal | Description |
|---|---|
cancelled() | |
zoomedAt(var point) |
PathLabel3D Street-name style text laid flat on the ground, following a line
Properties
| Name | Type | Description |
|---|---|---|
at | real | Path distance (world units) the label centers on |
glyphBatchActive readonly | bool | Whether the lazy internal glyph batch currently exists (read-only) |
glyphPlacement | bool | Selects per-glyph text-on-curve placement instead of per-word quads |
groundOffset | real | Height in world units the quads sit above y=0 to avoid z-fighting |
labelStyle | QtObject | Grouped ground-paint styling: color, halo, optional background, font |
lineId | int | Index of the line inside lines to run the text along |
lines | QtObject | LineBatch3D whose geometry the label follows |
oversample | real | Texture oversample factor for crispness (2 renders at 2x texels) |
readingDirection | vector2d | Reference reading direction in the ground (X, Z) plane |
repeatEvery | real | Spacing in world units between repeated placements (0 = single) |
skippedPlacements readonly | int | Number of placements skipped by the curvature guard (read-only) |
text | string | Label text; split on whitespace into per-word quads |
uniqueTextureCount readonly | int | Number of distinct word textures currently in use (read-only) |
wordSpacing | real | Gap in world units between consecutive words. Negative auto-derives it from worldHeight |
worldHeight | real | Text height in world units; the quad width follows the text aspect |
Methods
| Method | Returns | Description |
|---|---|---|
rebuild() | void |
PerfHud Compact always-on-top performance overlay for a View3D
Properties
| Name | Type | Description |
|---|---|---|
extended | bool | When true, additionally shows Qt's DebugView with resource details next to the compact panel |
view3D | var | View3D whose renderStats are displayed. Required |
PerfRegistry App-wide singleton for measuring named code sections and event rates
Methods
| Method | Returns | Description |
|---|---|---|
begin(string name) | void | |
end(string name) | void | |
reset() | void | |
snapshot() | list | |
tick(string name) | void |
Poly3D A filled planar polygon, with holes, in any of the three world planes
Properties
| Name | Type | Description |
|---|---|---|
color | color | Fill color of the polygon |
cullMode | enumeration | Which side of the polygon is drawn |
edgeColor | color | Edge color, as an absolute color rather than a factor |
edgeColorFactor | real | Darkening factor for edges (0-1) |
edgeMode | enumeration | Which lines showEdges draws |
edgeThickness | real | Thickness of the edge lines, in pixels |
extrude | real | How far the polygon rises along its plane normal |
holes | list<vector2d> | Inner rings cut out of the polygon |
plane | enumeration | Which world plane the 2D points map to |
showEdges | bool | Whether the polygon draws its own edges |
surfaceOffset | real | How far the polygon is lifted off its own plane |
useToonShading | bool | Enables cartoon-style rendering |
vertices | vector2d | Outer ring of the polygon, in plane coordinates |
Poly3DGeometry Custom geometry for filled planar polygons
Properties
| Name | Type | Description |
|---|---|---|
edgeColor | color | Absolute edge color; a visible alpha is what counts as set |
edgeColorFactor | real | Darkening factor applied to the fill when edgeColor is unset |
edgeMode | enumeration | Which lines the wireframe draws |
edgeThickness | real | Edge line thickness in pixels |
extrude | real | How far the polygon rises along the plane normal |
hasEdgeAttributes readonly | bool | Whether the uploaded buffer carries the barycentric channel |
holes | list<list<vector2d>> | Inner rings cut out of the polygon |
plane | enumeration | Which world plane the 2D points map to |
showEdges | bool | Whether the polygon draws its own edges |
surfaceOffset | real | How far the finished mesh is slid along the plane normal |
vertices | list<vector2d> | Outer ring of the polygon |
StaticVoxelMap Optimized voxel map for large, static structures
Properties
| Name | Type | Description |
|---|---|---|
chunkSize | int | Edge length (in voxels) of a meshing chunk |
voxelCountX | int | Number of voxels along the X axis |
voxelCountY | int | Number of voxels along the Y axis (height) |
voxelCountZ | int | Number of voxels along the Z axis |
VoxelMap Base type for voxel-based 3D structures
Properties
| Name | Type | Description |
|---|---|---|
autoCommit | bool | Whether to automatically commit changes |
depth readonly | real | Total depth of the voxel map in world units |
edgeColor | color | Edge color, as an absolute color rather than a factor |
edgeColorFactor | real | Darkening factor for edges |
edgeThickness | real | Thickness of grid edge lines, in pixels |
height readonly | real | Total height of the voxel map in world units |
model | var | Underlying voxel data model |
showEdges | bool | Whether to render voxel grid lines |
spacing | real | Gap between adjacent voxels in world units |
useToonShading | bool | Enables cartoon-style rendering |
voxelCountX | int | Number of voxels along the X axis |
voxelCountY | int | Number of voxels along the Y axis (height) |
voxelCountZ | int | Number of voxels along the Z axis |
voxelOffset | vector3d | Offset applied to voxel edge calculations |
voxelSize | real | Size of each voxel cube in world units |
width readonly | real | Total width of the voxel map in world units |
Methods
| Method | Returns | Description |
|---|---|---|
fill(var shapes) | void | |
get(int x, int y, int z) | color | |
load(string path) | void | |
save(string path) | void | |
set(int x, int y, int z, color color) | void |
VoxelMapGeometry Optimized geometry for static voxel maps using chunked greedy meshing
Properties
| Name | Type | Description |
|---|---|---|
chunkSize | int | Edge length (in voxels) of a meshing chunk |
spacing | real | Gap between adjacent voxels in world units |
vertexCount readonly | int | Current number of vertices in the generated geometry |
voxelCountX | int | Number of voxels along the X axis |
voxelCountY | int | Number of voxels along the Y axis (height) |
voxelCountZ | int | Number of voxels along the Z axis |
voxelSize | real | Size of each voxel cube in world units |
Methods
| Method | Returns | Description |
|---|---|---|
commit() | void | |
fillBox(int cx, int cy, int cz, int width, int height, int depth, list colorDistribution, real noiseFactor) | void | |
fillCylinder(int cx, int cy, int cz, int r, int height, list colorDistribution, real noiseFactor) | void | |
fillSphere(int cx, int cy, int cz, int r, list colorDistribution, real noiseFactor) | void | |
loadFromFile(string path) | bool | |
saveToFile(string path) | bool | |
setVoxel(int x, int y, int z, color color) | void | |
voxel(int x, int y, int z) | color |
VoxelMapInstancing GPU instancing for dynamic voxel maps with per-voxel colors
Properties
| Name | Type | Description |
|---|---|---|
spacing | real | Gap between adjacent voxels in world units |
voxelCountX | int | Number of voxels along the X axis |
voxelCountY | int | Number of voxels along the Y axis (height) |
voxelCountZ | int | Number of voxels along the Z axis |
voxelSize | real | Size of each voxel cube in world units |
Methods
| Method | Returns | Description |
|---|---|---|
commit() | void | |
fillBox(int cx, int cy, int cz, int width, int height, int depth, list colorDistribution, real noiseFactor) | void | |
fillCylinder(int cx, int cy, int cz, int r, int height, list colorDistribution, real noiseFactor) | void | |
fillSphere(int cx, int cy, int cz, int r, list colorDistribution, real noiseFactor) | void | |
loadFromFile(string path) | bool | |
saveToFile(string path) | bool | |
setVoxel(int x, int y, int z, color color) | void | |
voxel(int x, int y, int z) | color |