On this page:
18.1 Vectors
vec3
origin3
x-axis3
y-axis3
z-axis3
vec3+
vec3-
vec3*
vec3-scale
vec3-dot
vec3-cross
vec3-length
vec3-distance
vec3-normalize
vec3-lerp
vec3-finite?
18.2 Linear maps and rotations
linear3
identity-linear3
linear3-compose
linear3-invert
linear3-determinant
linear3-transpose
linear3-apply-vector
linear3-normal-transform
rotation3?
rotation3-components
identity-rotation3
axis-angle
rotation3-from-to
rotation3-look-at
rotation3-compose
rotation3-invert
rotation3-apply
rotation3->linear3
rotation3-slerp
18.3 Affine and decomposed transforms
affine3
affine3?
affine3-linear
affine3-translation
identity-affine3
affine3-compose
affine3-invert
affine3-apply-point
affine3-apply-vector
affine3-normal-transform
affine3-lerp
transform3
make-transform3
identity-transform3
transform3->affine3
transform3-compose
transform3-apply-point
transform3-lerp
18.4 Bounds, rays, and planes
aabb3
aabb3?
aabb3-minimum
aabb3-maximum
aabb3-empty
aabb3-empty?
aabb3-union
aabb3-from-points
aabb3-transform
aabb3-center
aabb3-size
aabb3-contains?
ray3
plane3
plane3?
plane3-point
plane3-normal
ray3-plane-hit
ray3-aabb-hit
ray3-triangle-hit
ray3-at
ray3-intersect-plane
ray3-intersect-aabb
ray3-intersect-triangle
18.5 Spatial Visuals and paths
spatial-visual?
spatial-container?
spatial-id
spatial-transform
spatial-with-transform
spatial-opacity
spatial-with-opacity
spatial-local-bounds
spatial-position
spatial-with-position
spatial-rotation
spatial-with-rotation
spatial-scale
spatial-with-scale
spatial-child
group3d
group3d?
group3d-children
group3d-with-children
spatial-path?
spatial-relative-ref
spatial-relative-replace
18.6 Meshes
mesh3d
mesh3d?
mesh3d-vertices
mesh3d-triangles
mesh3d-edges
mesh3d-normals
mesh3d-colors
mesh3d-material
mesh3d-wireframe-color
mesh3d-wireframe-width
mesh3d-local-bounds
18.6.1 Topology diagnostics and explicit orientation repair
mesh3d-duplicate-triangle
mesh3d-analysis
analyze-mesh3d
mesh3d-validate
mesh3d-orientation-report
mesh3d-orient-consistently
mesh3d-orient-outward
mesh3d-self-intersection-candidates
18.7 Materials and lights
material3d
material3d?
material3d-color
material3d-shading
material3d-ambient
material3d-diffuse
material3d-specular
material3d-roughness
material3d-double-sided?
material3d-wireframe?
ambient-light3d
directional-light3d
ambient-light3d?
ambient-light3d-intensity
ambient-light3d-color
directional-light3d?
directional-light3d-direction
directional-light3d-intensity
directional-light3d-color
18.8 Cameras and projection
perspective-projection3d
orthographic-projection3d
perspective-camera3d
orthographic-camera3d
camera3d?
camera3d-position
camera3d-rotation
camera3d-near
camera3d-far
camera3d-projection
camera3d-forward
camera3d-right
camera3d-up
camera3d-look-at
camera3d-world->view
camera3d-view-depth
camera3d-project
camera3d-pixel-ray
camera3d-frustum
18.9 Spatial viewports
view3d
view3d?
view3d-children
view3d-width
view3d-height
view3d-camera
view3d-lights
view3d-background
view3d-render-mode
view3d-transparency-mode
view3d-spatial-ref
view3d-spatial-has?
view3d-spatial-replace
view3d-spatial-update
18.10 Spatial animation and camera authoring
move3d-to
move3d-by
rotate3d-to
rotate3d-by
scale3d-to
scale3d-by
transform3d-to
camera3d-move-to
camera3d-look-at-to
camera3d-orbit-by
camera3d-roll-to
camera3d-field-of-view-to
camera3d-orthographic-height-to
camera3d-dolly-by
camera3d-fit
camera3d-follow
18.11 Semantic spatial relations and projected labels
spatial-dependency?
spatial-visual-dependency
spatial-value-dependency
spatial-camera-dependency
spatial-relation
spatial-relation?
spatial-relation-dependencies
spatial-relation-structure
spatial-relation-cacheability
spatial-relation-context?
spatial-relation-context-spatial-ref
spatial-relation-context-spatial-world-transform
spatial-relation-context-spatial-position
spatial-relation-context-value-ref
spatial-relation-context-camera
segment-between3d
line-between3d
arrow-between3d
plane-through3d
normal-at3d
distance-segment3d
projected-label
projected-label?
follow-projected-point
follow-projected-spatial
18.12 Spatial curves and vector diagrams
stroke3d
stroke3d?
stroke3d-color
stroke3d-width
stroke3d-width-mode
stroke3d-cap
stroke3d-join
stroke3d-miter-limit
stroke3d-dash
stroke3d-dash-offset
stroke3d-dash-space
stroke3d-opacity
stroke3d-depth-mode
stroke3d-depth-bias
stroke3d-with-color
stroke3d-with-opacity
tube-style3d
tube-style3d?
tube-style3d-radius
tube-style3d-sides
tube-style3d-color
point-style3d
point-style3d?
arrow-style3d
arrow-style3d?
point3d
curve3d?
line3d
segment3d
polyline3d
parametric-curve3d
tube3d
arrow3d
double-arrow3d
with-edges3d
edge-style3d?
edge-overlay3d?
axes3d
coordinate-plane3d
grid-plane3d
basis-vectors3d
vector-arrow3d
vector-components3d
move-along-curve3d
orient-along-curve3d
18.13 Parametric surfaces and calculus
parametric-surface3d
function-surface3d
surface3d?
surface3d-resolution
surface3d-position-at
surface3d-normal-at
surface-color
surface-color-by-height
surface-color-by-scalar
surface-checkerboard
surface-point
surface-tangent-u
surface-tangent-v
surface-normal
surface-tangent-plane
surface-coordinate-curve
surface-gradient-arrow
18.14 Adaptive, trimmed, and implicit surfaces
reveal-surface-u
reveal-surface-v
transform-surface3d
18.15 Constructive solids
cube3d
box3d
prism3d
sphere3d
cylinder3d
cone3d
torus3d
extrude3d
revolve3d
sweep3d
mesh3d-smooth-normals
mesh3d-flat-normals
mesh3d-boundary-edges
18.16 Clipping, sections, and transparency
clip-plane3d
clip-plane3d?
clip3d
clip3d?
slice-mesh3d
section-by-plane3d
section3d?
section3d-loops
section3d-chains
section-curve3d
18.17 Cuts, caps, and section measurements
riemann-volume3d
washer-sum3d
shell-sum3d
18.18 Spatial anchors and label layout
18.19 Spatial maps and homotopies
linear-transformation-diagram3d
apply-linear3
apply-affine3
apply-pointwise3
apply-homotopy3
18.20 Prepared spatial ODE trajectories and vector fields
prepare-ode-trajectory3d
ode-trajectory3d?
ode-trajectory3d-position
ode-trajectory3d-time-range
ode-trajectory3d-step-size
ode-trajectory3d-checkpoint-every
ode-trajectory3d-solver
ode-trajectory3d-diagnostics
vector-field3d
streamline3d
streamlines3d
flow-particle3d
flow-cloud3d
18.21 Spatial inspection and exact picking
spatial-inspection
spatial-pick
surface-pick3d
spatial-pick-kind
view3d-spatial-inspections
view3d-spatial-inspection-tree
view3d-spatial-inspection-at
view3d-pick
view3d-surface-pick
view3d-pixel-pick
mesh3d-bvh
mesh3d-bvh?
bvh3d-node?
bvh3d-leaf?
bvh3d-bounds
bvh3d-triangle-indices
bvh3d-ray-candidates
18.22 Retained renderer backends
renderer3d?
renderer3d-id
renderer3d-capabilities
renderer3d-fingerprint
renderer3d-prepare
renderer3d-render
renderer3d-release
renderer3d-capability-set
compiled-geometry3d
compiled-instance3d
compiled-stroke3d
compiled-point-marker3d
compiled-arrow-marker3d
compiled-edge-overlay3d
compiled-view3d
frame3d-spec
compile-view3d
compiled-view3d-primitives
view3d->frame3d-spec
view3d->render3d-request
render3d-request
renderer3d-render-result
renderer3d-render-result->bitmap
software-renderer3d
retained-software-renderer3d
default-software-renderer3d
current-view3d-renderer3d
retained-software-renderer3d-cache-hits
retained-software-renderer3d-cache-misses
retained-software-renderer3d-cache-size
renderer3d-statistics
renderer3d-statistics-reset!
renderer3d-statistics-snapshot
18.23 Optional Racket/  Open  GL backend
opengl-renderer3d-spec
opengl-renderer3d-spec?
opengl-renderer3d
opengl-renderer3d?
opengl-renderer3d-available?
opengl-renderer3d-info
opengl-renderer3d-statistics
opengl-renderer3d-reset-statistics!
opengl-renderer3d-release!
9.3

18 3D Algebra and Opaque Rendering🔗ℹ

 (require animate/3d) package: animate

This module provides the pure spatial algebra kernel. Its values describe right-handed mathematical coordinates; they neither render nor depend on a renderer. All coordinate and matrix fields reject NaN and infinite values.

18.1 Vectors🔗ℹ

struct

(struct vec3 (x y z)
    #:transparent)
  x : finite-real?
  y : finite-real?
  z : finite-real?
An immutable spatial point or displacement. Positive z points out of the screen toward a conventional viewer.

value

origin3 : vec3? = (vec3 0 0 0)

The spatial origin.

value

x-axis3 : vec3? = (vec3 1 0 0)

The positive x unit vector.

value

y-axis3 : vec3? = (vec3 0 1 0)

The positive y unit vector.

value

z-axis3 : vec3? = (vec3 0 0 1)

The positive z unit vector.

procedure

(vec3+ first second)  vec3?

  first : vec3?
  second : vec3?
Adds components.

procedure

(vec3- first second)  vec3?

  first : vec3?
  second : vec3?
Subtracts components.

procedure

(vec3* first second)  vec3?

  first : vec3?
  second : vec3?
Multiplies components.

procedure

(vec3-scale scalar value)  vec3?

  scalar : finite-real?
  value : vec3?
Scales every component.

procedure

(vec3-dot first second)  finite-real?

  first : vec3?
  second : vec3?
Returns the Euclidean dot product.

procedure

(vec3-cross first second)  vec3?

  first : vec3?
  second : vec3?
Returns first × second in the right-handed coordinate system.

procedure

(vec3-length value)  nonnegative-real?

  value : vec3?
Returns Euclidean length.

procedure

(vec3-distance first second)  nonnegative-real?

  first : vec3?
  second : vec3?
Returns Euclidean distance.

procedure

(vec3-normalize value)  vec3?

  value : vec3?
Returns an inexact unit vector. The zero vector raises an exception.

procedure

(vec3-lerp first second progress)  vec3?

  first : vec3?
  second : vec3?
  progress : finite-real?
Linearly interpolates components; progress outside 0 through 1 performs extrapolation.

procedure

(vec3-finite? value)  boolean?

  value : any/c
Reports whether value is a finite vec3.

18.2 Linear maps and rotations🔗ℹ

struct

(struct linear3 (m00 m01 m02 m10 m11 m12 m20 m21 m22)
    #:transparent)
  m00 : finite-real?
  m01 : finite-real?
  m02 : finite-real?
  m10 : finite-real?
  m11 : finite-real?
  m12 : finite-real?
  m20 : finite-real?
  m21 : finite-real?
  m22 : finite-real?
A 3×3 matrix in row-major order, acting on column vectors. Thus (linear3 a b c d e f g h i) represents rows
[a b c]
[d e f]
[g h i]
and (linear3-compose outer inner) means outer ∘ inner: inner acts first.

The identity matrix.

procedure

(linear3-compose outer inner)  linear3?

  outer : linear3?
  inner : linear3?
Composes two maps as outer ∘ inner.

procedure

(linear3-invert map)  linear3?

  map : linear3?
Returns the inverse or raises an exception for a singular matrix.

procedure

(linear3-determinant map)  finite-real?

  map : linear3?
Returns the determinant.

procedure

(linear3-transpose map)  linear3?

  map : linear3?
Returns the transpose.

procedure

(linear3-apply-vector map value)  vec3?

  map : linear3?
  value : vec3?
Applies map to a column vector.

procedure

(linear3-normal-transform map)  linear3?

  map : linear3?
Returns the inverse-transpose normal map. The linear map must be invertible.

procedure

(rotation3? value)  boolean?

  value : any/c
Recognizes a normalized proper rotation.

procedure

(rotation3-components rotation)  vector?

  rotation : rotation3?
Returns a debugging vector containing scalar-first quaternion components. The constructor is intentionally not public; all public construction normalizes and canonicalizes quaternion sign.
The identity rotation.

procedure

(axis-angle axis angle)  rotation3?

  axis : vec3?
  angle : finite-real?
Constructs the right-handed rotation by angle radians about nonzero axis.

procedure

(rotation3-from-to from-direction    
  to-direction)  rotation3?
  from-direction : vec3?
  to-direction : vec3?
Returns the shortest rotation sending one nonzero direction to the other. Opposite directions use a deterministic perpendicular axis.

procedure

(rotation3-look-at forward [#:up up])  rotation3?

  forward : vec3?
  up : vec3? = y-axis3
Maps local positive z to forward while keeping local positive y as close as possible to up. Parallel inputs are rejected.

procedure

(rotation3-compose outer inner)  rotation3?

  outer : rotation3?
  inner : rotation3?
Composes rotations as outer ∘ inner.

procedure

(rotation3-invert rotation)  rotation3?

  rotation : rotation3?
Returns the inverse rotation.

procedure

(rotation3-apply rotation value)  vec3?

  rotation : rotation3?
  value : vec3?
Rotates a displacement vector.

procedure

(rotation3->linear3 rotation)  linear3?

  rotation : rotation3?
Converts a rotation to its proper orthogonal matrix.

procedure

(rotation3-slerp from to progress)  rotation3?

  from : rotation3?
  to : rotation3?
  progress : (and/c finite-real? (>=/c 0) (<=/c 1))
Interpolates along the shortest quaternion arc. Near coincident rotations use normalized linear interpolation. Progress zero and one return the exact input endpoint values.

18.3 Affine and decomposed transforms🔗ℹ

procedure

(affine3 linear translation)  affine3?

  linear : linear3?
  translation : vec3?
Constructs a full affine map. It can represent shear, reflection, and singular linear maps exactly.

procedure

(affine3? value)  boolean?

  value : any/c
Recognizes a full affine map.

procedure

(affine3-linear map)  linear3?

  map : affine3?
Returns the linear component.

procedure

(affine3-translation map)  vec3?

  map : affine3?
Returns the translation component.
The identity affine map.

procedure

(affine3-compose outer inner)  affine3?

  outer : affine3?
  inner : affine3?
Composes maps as outer ∘ inner.

procedure

(affine3-invert map)  affine3?

  map : affine3?
Returns the inverse; singular maps raise an exception.

procedure

(affine3-apply-point map point)  vec3?

  map : affine3?
  point : vec3?
Applies both linear component and translation.

procedure

(affine3-apply-vector map value)  vec3?

  map : affine3?
  value : vec3?
Applies only the linear component.

procedure

(affine3-normal-transform map)  linear3?

  map : affine3?
Returns the inverse-transpose normal map.

procedure

(affine3-lerp from to progress)  affine3?

  from : affine3?
  to : affine3?
  progress : (and/c finite-real? (>=/c 0) (<=/c 1))
Interpolates corresponding matrix entries and translation, with exact endpoints.

struct

(struct transform3 (translation rotation scale)
    #:transparent)
  translation : vec3?
  rotation : rotation3?
  scale : vec3?
An author-oriented transform with nonzero scale components. It applies local scale, then rotation, then translation. Negative scale is allowed, but an interpolation that would cross a zero scale is rejected.

procedure

(make-transform3 [#:translation translation    
  #:rotation rotation    
  #:scale scale])  transform3?
  translation : vec3? = origin3
  rotation : rotation3? = identity-rotation3
  scale : vec3? = (vec3 1 1 1)
Constructs a validated decomposed transform.
The decomposed identity transform.

procedure

(transform3->affine3 transform)  affine3?

  transform : transform3?
Converts a decomposed transform to an exact affine map.

procedure

(transform3-compose outer inner)  affine3?

  outer : transform3?
  inner : transform3?
Composes transforms as an affine3, retaining shear that arbitrary nonuniform-scale composition can induce.

procedure

(transform3-apply-point transform point)  vec3?

  transform : transform3?
  point : vec3?
Applies scale, rotation, then translation.

procedure

(transform3-lerp from to progress)  transform3?

  from : transform3?
  to : transform3?
  progress : (and/c finite-real? (>=/c 0) (<=/c 1))
Interpolates translation, scale, and shortest-arc rotation with exact endpoints.

18.4 Bounds, rays, and planes🔗ℹ

procedure

(aabb3 minimum maximum)  aabb3?

  minimum : (or/c #f vec3?)
  maximum : (or/c #f vec3?)
Constructs an inclusive axis-aligned box. Both corners must be vec3 values ordered coordinatewise, or both must be #f for the empty box.

procedure

(aabb3? value)  boolean?

  value : any/c
Recognizes a spatial AABB.

procedure

(aabb3-minimum bounds)  (or/c #f vec3?)

  bounds : aabb3?
Returns the lower corner or #f when empty.

procedure

(aabb3-maximum bounds)  (or/c #f vec3?)

  bounds : aabb3?
Returns the upper corner or #f when empty.
The empty AABB.

procedure

(aabb3-empty? bounds)  boolean?

  bounds : aabb3?
Reports whether bounds are empty.

procedure

(aabb3-union first second)  aabb3?

  first : aabb3?
  second : aabb3?
Returns their least enclosing AABB.

procedure

(aabb3-from-points points)  aabb3?

  points : (listof vec3?)
Returns enclosing bounds, or aabb3-empty for no points.

procedure

(aabb3-transform bounds map)  aabb3?

  bounds : aabb3?
  map : affine3?
Transforms all eight corners and encloses them.

procedure

(aabb3-center bounds)  vec3?

  bounds : aabb3?
Returns nonempty bounds’ centre; empty bounds raise an exception.

procedure

(aabb3-size bounds)  vec3?

  bounds : aabb3?
Returns nonempty bounds’ nonnegative size; empty bounds raise an exception.

procedure

(aabb3-contains? bounds point)  boolean?

  bounds : aabb3?
  point : vec3?
Tests inclusive containment.

struct

(struct ray3 (origin direction)
    #:transparent)
  origin : vec3?
  direction : vec3?
A ray (+ origin (* t direction)) for t at least zero. Its direction must be nonzero but is not normalized automatically.

procedure

(plane3 point normal)  plane3?

  point : vec3?
  normal : vec3?
Constructs a point-normal plane and normalizes its nonzero normal.

procedure

(plane3? value)  boolean?

  value : any/c
Recognizes a spatial plane.

procedure

(plane3-point plane)  vec3?

  plane : plane3?
Returns one point in the plane.

procedure

(plane3-normal plane)  vec3?

  plane : plane3?
Returns its normalized normal.

struct

(struct ray3-plane-hit (point distance)
    #:transparent)
  point : vec3?
  distance : nonnegative-real?
A forward ray-plane intersection.

struct

(struct ray3-aabb-hit (entry exit)
    #:transparent)
  entry : nonnegative-real?
  exit : nonnegative-real?
The inclusive ray-parameter interval inside an AABB.

struct

(struct ray3-triangle-hit (point distance barycentric normal)
    #:transparent)
  point : vec3?
  distance : nonnegative-real?
  barycentric : vec3?
  normal : vec3?
An exact, double-sided ray/triangle hit. barycentric holds the weights for the triangle’s first, second, and third vertices, and normal follows the triangle’s declared winding.

procedure

(ray3-at ray distance)  vec3?

  ray : ray3?
  distance : finite-real?
Returns the algebraic point at distance.

procedure

(ray3-intersect-plane ray plane)  (or/c #f ray3-plane-hit?)

  ray : ray3?
  plane : plane3?
Returns the nearest forward hit, or #f when parallel or behind the origin.

procedure

(ray3-intersect-aabb ray bounds)  (or/c #f ray3-aabb-hit?)

  ray : ray3?
  bounds : aabb3?
Returns forward entry/exit parameters, or #f for no hit.

procedure

(ray3-intersect-triangle ray    
  first    
  second    
  third)  (or/c #f ray3-triangle-hit?)
  ray : ray3?
  first : vec3?
  second : vec3?
  third : vec3?
Returns the nearest exact forward intersection with the finite triangle, or #f. Both windings are pickable; renderer back-face culling is a separate display decision.

18.5 Spatial Visuals and paths🔗ℹ

SCENE-3D-B keeps spatial content in a protocol distinct from ordinary two-dimensional visual? values. This prevents an ordinary scene path or two-dimensional animation request from silently treating a mesh as a Pict. Only its enclosing view3d is an ordinary two-dimensional Visual.

procedure

(spatial-visual? value)  boolean?

  value : any/c
Recognizes an immutable spatial Visual.

procedure

(spatial-container? value)  boolean?

  value : any/c
Recognizes an immutable spatial container. It is deliberately separate from the ordinary 2D container protocol.

procedure

(spatial-id object)  symbol?

  object : spatial-visual?
Returns its stable identity within one spatial container.

procedure

(spatial-transform object)  transform3?

  object : spatial-visual?
Returns its local transform.

procedure

(spatial-with-transform object transform)  spatial-visual?

  object : spatial-visual?
  transform : transform3?
Returns a transformed immutable copy.

procedure

(spatial-opacity object)  (and/c real? (between/c 0 1))

  object : spatial-visual?
Returns the opacity inherited by descendants.

procedure

(spatial-with-opacity object opacity)  spatial-visual?

  object : spatial-visual?
  opacity : (and/c real? (between/c 0 1))
Returns an immutable opacity update.

procedure

(spatial-local-bounds object)  aabb3?

  object : spatial-visual?
Returns local untransformed spatial bounds.

procedure

(spatial-position object)  vec3?

  object : spatial-visual?
Returns the translation component of the local transform.

procedure

(spatial-with-position object position)  spatial-visual?

  object : spatial-visual?
  position : vec3?
Replaces that local translation.

procedure

(spatial-rotation object)  rotation3?

  object : spatial-visual?
Returns the local rotation.

procedure

(spatial-with-rotation object rotation)  spatial-visual?

  object : spatial-visual?
  rotation : rotation3?
Replaces that local rotation.

procedure

(spatial-scale object)  vec3?

  object : spatial-visual?
Returns the local scale.

procedure

(spatial-with-scale object scale)  spatial-visual?

  object : spatial-visual?
  scale : vec3?
Replaces the nonzero local scale components.

struct

(struct spatial-child (id visual)
    #:transparent)
  id : symbol?
  visual : spatial-visual?
An immutable direct-child entry. Its id must be the child Visual’s spatial-id. Direct-child order is significant and stable.

procedure

(group3d children    
  #:id id    
  [#:transform transform    
  #:opacity opacity])  group3d?
  children : (listof spatial-visual?)
  id : symbol?
  transform : transform3? = identity-transform3
  opacity : (and/c real? (between/c 0 1)) = 1
Creates an immutable spatial container. Direct child identities must be unique and cannot equal the group’s identity.

procedure

(group3d? value)  boolean?

  value : any/c
Recognizes a spatial group.

procedure

(group3d-children group)  (listof spatial-visual?)

  group : group3d?
Returns direct children in their declared order.

procedure

(group3d-with-children group children)  group3d?

  group : group3d?
  children : (listof spatial-visual?)
Returns an immutable direct-child replacement.

procedure

(spatial-path? value)  boolean?

  value : any/c
Recognizes a nonempty list of symbols.

procedure

(spatial-relative-ref container path)  spatial-visual?

  container : spatial-container?
  path : spatial-path?
Resolves a nonempty path relative to a spatial container.

procedure

(spatial-relative-replace container    
  path    
  replacement)  spatial-container?
  container : spatial-container?
  path : spatial-path?
  replacement : spatial-visual?
Rebuilds an immutable spatial ancestry, requiring the replacement to retain the final path identity.

18.6 Meshes🔗ℹ

procedure

(mesh3d #:id id    
  #:vertices vertices    
  [#:triangles triangles    
  #:edges edges    
  #:normals normals    
  #:colors colors]    
  #:material material    
  [#:transform transform    
  #:opacity opacity    
  #:wireframe-color color    
  #:wireframe-width width])  mesh3d?
  id : symbol?
  vertices : vector?
  triangles : vector? = #()
  edges : (or/c #f vector?) = #f
  normals : (or/c #f vector?) = #f
  colors : (or/c #f vector?) = #f
  material : material3d?
  transform : transform3? = identity-transform3
  opacity : (and/c real? (between/c 0 1)) = 1
  color : any/c = "steelblue"
  width : positive-real? = 2
Creates an immutable indexed mesh. Vertices are vec3 values. Triangles are vectors of three valid vertex indices and edges are vectors of two valid indices. Inputs are copied to immutable vectors. When edges is #f, a stable de-duplicated edge list is derived from triangles.

In 'wireframe mode the stable edge order remains visible. In 'opaque mode triangles are flattened in declared order, clipped, depth-tested, and shaded with material. Flat and smooth materials use the declared face or interpolated vertex normals respectively; per-vertex colours are interpolated perspective-correctly.

procedure

(mesh3d? value)  boolean?

  value : any/c
Recognizes an immutable indexed mesh.

procedure

(mesh3d-vertices mesh)  vector?

  mesh : mesh3d?
Returns immutable vertices.

procedure

(mesh3d-triangles mesh)  vector?

  mesh : mesh3d?
Returns immutable triangle indices.

procedure

(mesh3d-edges mesh)  vector?

  mesh : mesh3d?
Returns immutable wireframe edge indices.

procedure

(mesh3d-normals mesh)  (or/c #f vector?)

  mesh : mesh3d?
Returns optional immutable normals.

procedure

(mesh3d-colors mesh)  (or/c #f vector?)

  mesh : mesh3d?
Returns optional immutable colours.

procedure

(mesh3d-material mesh)  material3d?

  mesh : mesh3d?
Returns the surface material.

procedure

(mesh3d-wireframe-color mesh)  any/c

  mesh : mesh3d?
Returns the current edge colour.

procedure

(mesh3d-wireframe-width mesh)  positive-real?

  mesh : mesh3d?
Returns the cosmetic edge width.

procedure

(mesh3d-local-bounds mesh)  aabb3?

  mesh : mesh3d?
Returns bounds enclosing local vertices.

18.6.1 Topology diagnostics and explicit orientation repair🔗ℹ

struct

(struct mesh3d-duplicate-triangle (first-triangle-index
    duplicate-triangle-index
    winding)
    #:transparent)
  first-triangle-index : exact-nonnegative-integer?
  duplicate-triangle-index : exact-nonnegative-integer?
  winding : (or/c 'same 'reversed)
Records a later triangle that has the same three indexed vertices as an earlier one, independent of cyclic rotation.

struct

(struct mesh3d-analysis (vertex-count
    triangle-count
    edge-count
    degenerate-triangles
    duplicate-triangles
    boundary-edges
    boundary-loops
    nonmanifold-edges
    inconsistent-winding-edges
    connected-components
    isolated-vertices
    signed-component-volumes
    watertight?
    orientable?
    consistently-wound?)
    #:transparent)
  vertex-count : exact-nonnegative-integer?
  triangle-count : exact-nonnegative-integer?
  edge-count : exact-nonnegative-integer?
  degenerate-triangles : vector?
  duplicate-triangles : vector?
  boundary-edges : vector?
  boundary-loops : vector?
  nonmanifold-edges : vector?
  inconsistent-winding-edges : vector?
  connected-components : vector?
  isolated-vertices : vector?
  signed-component-volumes : vector?
  watertight? : boolean?
  orientable? : boolean?
  consistently-wound? : boolean?
An immutable, deterministic report over indexed geometry. Edge records retain first-triangle encounter order; components and loops retain source-index order. Degeneracy uses a tolerance proportional to the mesh’s squared extent rather than one universal world-coordinate epsilon.

procedure

(analyze-mesh3d mesh)  mesh3d-analysis?

  mesh : mesh3d?
Computes topology and geometric diagnostics without changing mesh.

procedure

(mesh3d-validate mesh)  mesh3d-analysis?

  mesh : mesh3d?
An explicit alias for analyze-mesh3d. Mesh construction remains cheap and does not implicitly run this potentially expensive analysis.

struct

(struct mesh3d-orientation-report (initial-analysis
    final-analysis
    flipped-triangle-indices
    outward?)
    #:transparent)
  initial-analysis : mesh3d-analysis?
  final-analysis : mesh3d-analysis?
  flipped-triangle-indices : vector?
  outward? : boolean?
An immutable explanation of an explicit orientation repair. Per-vertex normals are authored attributes and are not silently regenerated by repair.
Returns a replacement mesh with each manifold adjacent pair oppositely wound, or raises for degenerate, non-manifold, or parity-conflicting input.
Additionally makes every closed, orientable, nonzero-volume component outward-facing. Open, non-manifold, non-orientable, and zero-volume components fail explicitly because they have no unambiguous outside.

procedure

(mesh3d-self-intersection-candidates mesh)  vector?

  mesh : mesh3d?
Returns deterministic pairs of non-adjacent faces whose local AABBs overlap. This is a broad-phase candidate query, not a narrow-phase proof of intersection.

18.7 Materials and lights🔗ℹ

procedure

(material3d [#:color color    
  #:shading shading    
  #:ambient ambient    
  #:diffuse diffuse    
  #:specular specular    
  #:roughness roughness    
  #:double-sided? double-sided?    
  #:wireframe? wireframe?])  material3d?
  color : any/c = "cornflowerblue"
  shading : (or/c 'unlit 'flat 'smooth) = 'flat
  ambient : nonnegative-real? = 1
  diffuse : nonnegative-real? = 1
  specular : nonnegative-real? = 0
  roughness : positive-real? = 1
  double-sided? : boolean? = #f
  wireframe? : boolean? = #f
Constructs an immutable surface material. 'unlit uses its base colour; 'flat evaluates one face normal using ambient and directional lights; and 'smooth interpolates supplied vertex normals. The colour may include alpha; the renderer’s explicit transparent pass controls its compositing policy. Specular, roughness, and wireframe flags are immutable authoring data reserved for later renderer stages.

procedure

(material3d? value)  boolean?

  value : any/c
Recognizes a material.

procedure

(material3d-color material)  rgba-color?

  material : material3d?
Returns base colour and alpha.

procedure

(material3d-shading material)  (or/c 'unlit 'flat 'smooth)

  material : material3d?
Returns its active shading mode.

procedure

(material3d-ambient material)  nonnegative-real?

  material : material3d?
Returns ambient coefficient.

procedure

(material3d-diffuse material)  nonnegative-real?

  material : material3d?
Returns diffuse coefficient.

procedure

(material3d-specular material)  nonnegative-real?

  material : material3d?
Returns retained specular coefficient.

procedure

(material3d-roughness material)  positive-real?

  material : material3d?
Returns retained roughness.

procedure

(material3d-double-sided? material)  boolean?

  material : material3d?
Reports whether back-face culling is disabled for this mesh.

procedure

(material3d-wireframe? material)  boolean?

  material : material3d?
Returns retained wireframe intent.

procedure

(ambient-light3d [#:intensity intensity    
  #:color color])  ambient-light3d?
  intensity : nonnegative-real? = 1
  color : any/c = "white"
Creates uniform opaque ambient illumination.

procedure

(directional-light3d direction 
  [#:intensity intensity 
  #:color color]) 
  directional-light3d?
  direction : vec3?
  intensity : nonnegative-real? = 1
  color : any/c = "white"
Creates an opaque directional light. Its direction is the direction in which illumination travels, so a normal facing its negation receives diffuse light.

procedure

(ambient-light3d? value)  boolean?

  value : any/c
Recognizes ambient light.

procedure

(ambient-light3d-intensity light)  nonnegative-real?

  light : ambient-light3d?
Returns ambient intensity.

procedure

(ambient-light3d-color light)  rgba-color?

  light : ambient-light3d?
Returns opaque ambient colour.

procedure

(directional-light3d? value)  boolean?

  value : any/c
Recognizes directional light.

procedure

(directional-light3d-direction light)  vec3?

  light : directional-light3d?
Returns normalized travel direction.

procedure

(directional-light3d-intensity light)  nonnegative-real?

  light : directional-light3d?
Returns directional intensity.

procedure

(directional-light3d-color light)  rgba-color?

  light : directional-light3d?
Returns opaque directional colour.

18.8 Cameras and projection🔗ℹ

A camera’s local x axis is screen-right, local y is screen-up, and local negative z is forward. A default camera is at (vec3 0 0 8) and looks at origin3. The camera is reusable: viewport aspect is supplied when projecting or rendering, rather than stored in the camera.

struct

(struct perspective-projection3d (vertical-field-of-view)
    #:transparent)
  vertical-field-of-view : finite-real?
A perspective projection measured in radians.

struct

(struct orthographic-projection3d (vertical-size)
    #:transparent)
  vertical-size : positive-real?
An orthographic projection with the stated visible vertical size.

procedure

(perspective-camera3d [#:position position 
  #:look-at target 
  #:up up 
  #:rotation rotation 
  #:near near 
  #:far far 
  #:vertical-field-of-view field-of-view]) 
  camera3d?
  position : vec3? = (vec3 0 0 8)
  target : vec3? = origin3
  up : vec3? = y-axis3
  rotation : (or/c #f rotation3?) = #f
  near : positive-real? = 1/10
  far : positive-real? = 100
  field-of-view : finite-real? = (/ pi 4)
Creates a perspective camera. An explicit rotation wins over the look-at fields.

procedure

(orthographic-camera3d [#:position position    
  #:look-at target    
  #:up up    
  #:rotation rotation    
  #:near near    
  #:far far    
  #:vertical-size size])  camera3d?
  position : vec3? = (vec3 0 0 8)
  target : vec3? = origin3
  up : vec3? = y-axis3
  rotation : (or/c #f rotation3?) = #f
  near : positive-real? = 1/10
  far : positive-real? = 100
  size : positive-real? = 6
Creates a parallel orthographic camera.

procedure

(camera3d? value)  boolean?

  value : any/c
Recognizes an immutable camera.

procedure

(camera3d-position camera)  vec3?

  camera : camera3d?
Returns its world position.

procedure

(camera3d-rotation camera)  rotation3?

  camera : camera3d?
Returns camera-local axes in world coordinates.

procedure

(camera3d-near camera)  positive-real?

  camera : camera3d?
Returns nearest visible forward depth.

procedure

(camera3d-far camera)  positive-real?

  camera : camera3d?
Returns farthest visible forward depth.
Returns its lens.

procedure

(camera3d-forward camera)  vec3?

  camera : camera3d?
Returns world-space local negative z.

procedure

(camera3d-right camera)  vec3?

  camera : camera3d?
Returns world-space local positive x.

procedure

(camera3d-up camera)  vec3?

  camera : camera3d?
Returns world-space local positive y.

procedure

(camera3d-look-at camera target [#:up up])  camera3d?

  camera : camera3d?
  target : vec3?
  up : vec3? = y-axis3
Returns an immutable reorientation toward target.

procedure

(camera3d-world->view camera point)  vec3?

  camera : camera3d?
  point : vec3?
Converts a world point to camera coordinates; visible forward points have negative z.

procedure

(camera3d-view-depth camera point)  finite-real?

  camera : camera3d?
  point : vec3?
Returns positive depth along the camera’s forward axis.

procedure

(camera3d-project camera    
  point    
  [#:aspect aspect])  (or/c #f vec2?)
  camera : camera3d?
  point : vec3?
  aspect : positive-real? = 1
Projects to normalized viewport coordinates. It returns #f behind the camera or outside the inclusive near/far interval.

procedure

(camera3d-pixel-ray camera    
  pixel-x    
  pixel-y    
  #:width width    
  #:height height)  ray3?
  camera : camera3d?
  pixel-x : finite-real?
  pixel-y : finite-real?
  width : exact-positive-integer?
  height : exact-positive-integer?
Returns a world ray through a top-left-origin pixel coordinate.

procedure

(camera3d-frustum camera [#:aspect aspect])  vector?

  camera : camera3d?
  aspect : positive-real? = 1
Returns immutable inward-facing near, far, left, right, bottom, and top planes.

18.9 Spatial viewports🔗ℹ

procedure

(view3d children    
  #:id id    
  [#:center center    
  #:width width    
  #:height height    
  #:rotation rotation    
  #:scale scale    
  #:opacity opacity    
  #:camera camera    
  #:lights lights    
  #:background background    
  #:render-mode render-mode    
  #:transparency-mode transparency-mode])  view3d?
  children : (listof spatial-visual?)
  id : symbol?
  center : vec2? = origin
  width : positive-real? = 12
  height : positive-real? = 27/4
  rotation : finite-real? = 0
  scale : (or/c positive-real? vec2?) = 1
  opacity : (and/c real? (between/c 0 1)) = 1
  camera : camera3d? = (perspective-camera3d)
  lights : (listof (or/c ambient-light3d? directional-light3d?))
   = null
  background : any/c = "white"
  render-mode : (or/c 'wireframe 'opaque) = 'wireframe
  transparency-mode : (or/c 'object-sorted 'triangle-sorted)
   = 'triangle-sorted
Creates the boundary between a normal two-dimensional Scene and a spatial tree. Its position, rotation, scale, opacity, and placement act as they do for other ordinary Visuals. 'wireframe retains the initial clipped-edge adapter. 'opaque uses a deterministic software triangle renderer: six-plane frustum clipping, CCW front-face culling (unless a material is double-sided), pixel-centre rasterization, and a z-buffer. An empty lights list uses a deterministic ambient-plus-directional default. When material or effective spatial opacity is below one, transparent triangles are composited after the opaque depth-writing pass using the selected explicit sorting mode.

procedure

(view3d? value)  boolean?

  value : any/c
Recognizes a 2D viewport Visual containing a spatial tree.

procedure

(view3d-children view)  (listof spatial-visual?)

  view : view3d?
Returns direct spatial children.

procedure

(view3d-width view)  positive-real?

  view : view3d?
Returns local 2D viewport width.

procedure

(view3d-height view)  positive-real?

  view : view3d?
Returns local 2D viewport height.

procedure

(view3d-camera view)  camera3d?

  view : view3d?
Returns the spatial camera.

procedure

(view3d-lights view)  list?

  view : view3d?
Returns immutable light declarations.

procedure

(view3d-background view)  any/c

  view : view3d?
Returns the opaque viewport background.

procedure

(view3d-render-mode view)  (or/c 'wireframe 'opaque)

  view : view3d?
Returns the renderer mode.

procedure

(view3d-transparency-mode view)

  (or/c 'object-sorted 'triangle-sorted)
  view : view3d?
Returns its transparent-pass ordering policy.

procedure

(view3d-spatial-ref view path)  spatial-visual?

  view : view3d?
  path : spatial-path?
Resolves a path rooted with the outer view identity, such as '(world cube).

procedure

(view3d-spatial-has? view path)  boolean?

  view : view3d?
  path : any/c
Reports whether a rooted spatial path exists.

procedure

(view3d-spatial-replace view    
  path    
  replacement)  view3d?
  view : view3d?
  path : spatial-path?
  replacement : spatial-visual?
Returns a view with one same-identity descendant replaced.

procedure

(view3d-spatial-update view path update)  view3d?

  view : view3d?
  path : spatial-path?
  update : procedure?
Applies an immutable same-identity update to a descendant.

18.10 Spatial animation and camera authoring🔗ℹ

SCENE-3D-D keeps three-dimensional motion in the ordinary immutable scene timeline. A spatial target is a path beginning with its owning view3d identifier, for example '(world cube). A camera target is the owning view identifier alone, for example 'world. Every request captures its endpoint from the clip-start state. Sampling at a time does not depend on having sampled an earlier frame.

(scene-play
 (scene-add (make-scene) world matrix)
 (rotate3d-by '(world cube) (axis-angle y-axis3 pi))
 (camera3d-orbit-by 'world #:azimuth (/ pi 2))
 #:duration 2)

procedure

(move3d-to path position)  any/c

  path : spatial-path?
  position : vec3?
Moves one spatial Visual to an absolute local translation.

procedure

(move3d-by path delta)  any/c

  path : spatial-path?
  delta : vec3?
Moves one spatial Visual by a local translation from its clip-start value.

procedure

(rotate3d-to path rotation)  any/c

  path : spatial-path?
  rotation : rotation3?
Sets an absolute local orientation.

procedure

(rotate3d-by path rotation)  any/c

  path : spatial-path?
  rotation : rotation3?
Applies a local rotation after the clip-start orientation.

procedure

(scale3d-to path scale)  any/c

  path : spatial-path?
  scale : vec3?
Sets a nonzero componentwise local scale.

procedure

(scale3d-by path factor)  any/c

  path : spatial-path?
  factor : vec3?
Multiplies the clip-start componentwise local scale.

procedure

(transform3d-to path transform)  any/c

  path : spatial-path?
  transform : transform3?
Sets translation, rotation, and scale together. A scale interpolation that would pass through zero is rejected when the clip is compiled.

procedure

(camera3d-move-to view-id position)  any/c

  view-id : symbol?
  position : vec3?
Moves a camera to an absolute position, retaining its lens and orientation.

procedure

(camera3d-look-at-to view-id target [#:up up])  any/c

  view-id : symbol?
  target : vec3?
  up : vec3? = y-axis3
Reorients a camera to look at a world point.

procedure

(camera3d-orbit-by view-id    
  [#:center center    
  #:azimuth azimuth    
  #:elevation elevation])  any/c
  view-id : symbol?
  center : vec3? = origin3
  azimuth : finite-real? = 0
  elevation : finite-real? = 0
Creates a finite orbit about center. Position follows the exact orbit; at every sampled position, orientation is a normalized quaternion that looks directly at center. This prevents a camera from looking away from its subject midway through a large orbit.

procedure

(camera3d-roll-to view-id angle)  any/c

  view-id : symbol?
  angle : finite-real?
Sets the absolute roll around the current forward direction.

procedure

(camera3d-field-of-view-to view-id    
  field-of-view)  any/c
  view-id : symbol?
  field-of-view : finite-real?
Interpolates a perspective camera’s vertical field of view. It rejects an orthographic camera.

procedure

(camera3d-orthographic-height-to view-id    
  height)  any/c
  view-id : symbol?
  height : positive-real?
Interpolates an orthographic camera’s visible height. It rejects a perspective camera.

procedure

(camera3d-dolly-by view-id distance)  any/c

  view-id : symbol?
  distance : finite-real?
Moves along the clip-start forward axis; positive distance moves forward.

procedure

(camera3d-fit view-id [#:padding padding])  any/c

  view-id : symbol?
  padding : positive-real? = 11/10
Frames the current spatial bounds conservatively.

procedure

(camera3d-follow view-id path)  any/c

  view-id : symbol?
  path : spatial-path?
Retains the clip-start camera offset from a spatial target path rooted at the same view. It is resolved after local spatial transforms at each sampled time.

All these forms work as leaves of timed, succession, animation-group, and lagged-start. A 3D camera remains separate from the ordinary two-dimensional render camera, so a formula or caption stays fixed while the view’s spatial camera moves.

In interactive preview, an inspection camera is an overlay on the authored camera: drag in a spatial viewport to orbit, shift-drag to pan its target, use the mouse wheel to dolly (or orthographic zoom), and press R to return to the authored view. The override is part of the immutable preview render request—including a subprocess worker request—and is never written into source or the Scene. The Animate menu can reset it or copy an expression/animation scratch form for authoring.

For runnable examples, see "examples/3d/wireframe-cube.rkt", "examples/3d/opaque-cube.rkt", and "examples/3d/depth-test.rkt"; "examples/3d/camera-orbit.rkt" is the canonical motion probe.

Current limitation: opaque mode is a software rasterizer for filled triangles. It has flat, unlit, and smooth shading, depth-aware transparency, spatial relations, and projected labels, but no texture mapping, no specular response, no shadows, order-independent transparency, or 3D picking. An ordinary two-dimensional traversal of a spatial child is rejected: use rooted 3D animation paths or view3d-spatial-*.

18.11 Semantic spatial relations and projected labels🔗ℹ

SCENE-3D-E adds derived spatial geometry without a mutable per-frame updater. A spatial-relation is a spatial Visual declaration with a concrete template, an explicit list of inputs, and a resolver. During a regular scene sample, Animate first samples ordinary spatial and camera animation, then resolves spatial relations inside each view3d, then renders the spatial viewport, and finally resolves projected labels as ordinary two-dimensional Visuals. This order means a label may use the resolved position of a relation result, while ordinary 2D layout can still use the label.

The three dependency declarations make a resolver’s inputs inspectable:

procedure

(spatial-dependency? value)  boolean?

  value : any/c
Recognizes a declared spatial relation dependency.

procedure

(spatial-visual-dependency target)  spatial-dependency?

  target : spatial-path?
Declares a relative or view-rooted path to a spatial Visual.

procedure

(spatial-value-dependency target)  spatial-dependency?

  target : symbol?
Declares one immutable named Scene value.

procedure

(spatial-camera-dependency view-id)  spatial-dependency?

  view-id : symbol?
Declares the camera of one owning view3d.

procedure

(spatial-relation template 
  [#:depends-on dependencies 
  #:structure structure 
  #:cache-key cache-key] 
  resolver) 
  spatial-relation?
  template : spatial-visual?
  dependencies : (listof spatial-dependency?) = null
  structure : (or/c 'root-only 'fixed) = 'root-only
  cache-key : any/c = #f
  resolver : procedure?
Creates a semantic spatial Visual. resolver accepts a spatial-relation-context? and the transform-free local template, and must return concrete spatial geometry with the template’s ID. Its outer transform and opacity remain independently animatable.

A 'root-only relation may change all of its internal structure and can only be addressed at its own root path. A 'fixed relation must return the template’s exact child-ID tree, so a descendant is addressable. Generic resolver procedures are intentionally not cross-process-cacheable; supply a stable #:cache-key to declare an explicit cache identity.

procedure

(spatial-relation? value)  boolean?

  value : any/c
Recognizes a semantic spatial relation.

procedure

(spatial-relation-dependencies relation)

  (listof spatial-dependency?)
  relation : spatial-relation?
Returns the declared inputs.

procedure

(spatial-relation-structure relation)

  (or/c 'root-only 'fixed)
  relation : spatial-relation?
Returns the declared structural policy.

procedure

(spatial-relation-cacheability relation)

  (or/c 'explicit-key 'disabled)
  relation : spatial-relation?
Reports whether the relation has an explicit stable cache key.

The resolver context is read-only and accepts only declared inputs.

procedure

(spatial-relation-context? value)  boolean?

  value : any/c
Recognizes a spatial relation resolver context.

procedure

(spatial-relation-context-spatial-ref context 
  target) 
  spatial-visual?
  context : spatial-relation-context?
  target : spatial-path?
Resolves a declared relative or rooted target.

procedure

(spatial-relation-context-spatial-world-transform context 
  target) 
  affine3?
  context : spatial-relation-context?
  target : spatial-path?
Returns a declared target’s sampled world transform.

procedure

(spatial-relation-context-spatial-position context    
  target)  vec3?
  context : spatial-relation-context?
  target : spatial-path?
Returns a declared target’s sampled world origin.

procedure

(spatial-relation-context-value-ref context    
  target)  any/c
  context : spatial-relation-context?
  target : symbol?
Reads a declared immutable named Scene value.
Reads the declared camera of the owning view.

An undeclared access is an authoring error. Relations resolve lazily with one cache for the sampled viewport; a cycle reports complete paths rooted at the owning view, such as '(world links ab).

The initial relation vocabulary is intentionally small:

procedure

(segment-between3d from    
  to    
  #:id id    
  [#:color color    
  #:width width    
  #:opacity opacity])  spatial-relation?
  from : spatial-path?
  to : spatial-path?
  id : symbol?
  color : any/c = "slategray"
  width : positive-real? = 2
  opacity : real? = 1
Produces a finite semantic segment between the current world origins of two declared targets.

procedure

(line-between3d from    
  to    
  #:id id    
  [#:padding padding    
  #:color color    
  #:width width    
  #:opacity opacity])  spatial-relation?
  from : spatial-path?
  to : spatial-path?
  id : symbol?
  padding : nonnegative-real? = 10
  color : any/c = "slategray"
  width : positive-real? = 2
  opacity : real? = 1
Produces the displayed portion of the infinite line through two current origins.

procedure

(arrow-between3d from    
  to    
  #:id id    
  [#:color color    
  #:width width    
  #:tip-size tip-size    
  #:opacity opacity])  spatial-relation?
  from : spatial-path?
  to : spatial-path?
  id : symbol?
  color : any/c = "slategray"
  width : positive-real? = 2
  tip-size : positive-real? = 1/4
  opacity : real? = 1
Produces a segment with a small semantic arrow head at to.

procedure

(plane-through3d first    
  second    
  third    
  #:id id    
  [#:color color    
  #:opacity opacity])  spatial-relation?
  first : spatial-path?
  second : spatial-path?
  third : spatial-path?
  id : symbol?
  color : any/c = "lightskyblue"
  opacity : real? = 1
Produces a double-sided triangular plane through three current origins.

procedure

(normal-at3d target    
  normal    
  #:id id    
  [#:length length    
  #:color color    
  #:width width    
  #:tip-size tip-size    
  #:opacity opacity])  spatial-relation?
  target : spatial-path?
  normal : vec3?
  id : symbol?
  length : positive-real? = 1
  color : any/c = "darkmagenta"
  width : positive-real? = 2
  tip-size : positive-real? = 1/4
  opacity : real? = 1
Produces a directed normal marker from a target’s current origin.

procedure

(distance-segment3d from    
  to    
  #:id id    
  [#:color color    
  #:width width    
  #:opacity opacity])  spatial-relation?
  from : spatial-path?
  to : spatial-path?
  id : symbol?
  color : any/c = "darkgoldenrod"
  width : positive-real? = 2
  opacity : real? = 1
Produces a semantically named finite distance segment.

procedure

(projected-label template    
  #:view view-id    
  #:target target    
  [#:offset offset    
  #:occlusion occlusion])  projected-label?
  template : visual?
  view-id : symbol?
  target : (or/c vec3? spatial-path?)
  offset : vec2? = origin
  occlusion : (or/c 'always-visible 'hide 'fade)
   = 'always-visible
Creates an ordinary 2D text, formula, or other concrete Visual whose centre follows a point projected through a sampled view3d. offset is in screen pixels (with Animate’s y-up convention), so it is not enlarged or rotated by the spatial camera.

procedure

(projected-label? value)  boolean?

  value : any/c
Recognizes a projected label definition.

procedure

(follow-projected-point template 
  #:view view-id 
  #:point point 
  [#:offset offset 
  #:occlusion occlusion]) 
  projected-label?
  template : visual?
  view-id : symbol?
  point : vec3?
  offset : vec2? = origin
  occlusion : (or/c 'always-visible 'hide 'fade)
   = 'always-visible
The literal-point spelling of projected-label.

procedure

(follow-projected-spatial template 
  #:view view-id 
  #:target target 
  [#:offset offset 
  #:occlusion occlusion]) 
  projected-label?
  template : visual?
  view-id : symbol?
  target : spatial-path?
  offset : vec2? = origin
  occlusion : (or/c 'always-visible 'hide 'fade)
   = 'always-visible
The spatial-path spelling of projected-label.

The canonical example uses all of this without a second timeline:

(define label-a
  (follow-projected-spatial
   (math-tex #:id 'label-a "A")
   #:view 'world
   #:target '(tetrahedron A)
   #:offset (vec2 -20 -18)))
 
(scene-play
 (scene-add (make-scene) world label-a)
 (rotate3d-by '(world tetrahedron) (axis-angle y-axis3 pi))
 (camera3d-orbit-by 'world #:azimuth pi)
 #:duration 2)

For the complete moving tetrahedron with labels A–D, see "examples/3d/projected-labels.rkt".

18.12 Spatial curves and vector diagrams🔗ℹ

SCENE-3D-F added finite spatial diagram geometry; SCENE-3D-O separates a sampled curve’s centreline from its rendering style. A mathematical stroke3d is resolved after projection and can retain a constant pixel width. A tube-style3d creates explicit physical tube geometry whose apparent width changes with the camera. Partial curves, reveals, and curve-following are sampled directly from the complete immutable centreline at the requested scene time; they never use a mutable updater or the preceding frame.

procedure

(stroke3d [#:color color    
  #:width width    
  #:width-mode width-mode    
  #:cap cap    
  #:join join    
  #:miter-limit miter-limit    
  #:dash dash    
  #:dash-offset dash-offset    
  #:dash-space dash-space    
  #:opacity opacity    
  #:depth-mode depth-mode    
  #:depth-bias depth-bias])  stroke3d?
  color : color-spec? = "steelblue"
  width : positive? = 2
  width-mode : (or/c 'screen 'world) = 'screen
  cap : (or/c 'butt 'square 'round) = 'round
  join : (or/c 'miter 'bevel 'round) = 'round
  miter-limit : positive? = 4
  dash : (or/c #f list? vector?) = #f
  dash-offset : finite-real? = 0
  dash-space : (or/c 'screen 'world) = width-mode
  opacity : (real-in 0 1) = 1
  depth-mode : (or/c 'test 'always 'hidden) = 'test
  depth-bias : nonnegative-real? = 1e-5
Creates an immutable mathematical-stroke style. In 'screen mode, width and default dashes are pixels after projection; in 'world mode width is a full physical diameter. A dash pattern is an even-length list or vector of positive finite lengths. 'test draws visible portions, 'hidden draws occluded portions, and 'always ignores depth.

procedure

(stroke3d? value)  boolean?

  value : any/c
Recognizes a stroke style.

procedure

(stroke3d-color style)  color-spec?

  style : stroke3d?
Returns stroke colour.

procedure

(stroke3d-width style)  positive?

  style : stroke3d?
Returns width.

procedure

(stroke3d-width-mode style)  (or/c 'screen 'world)

  style : stroke3d?
Returns width units.

procedure

(stroke3d-cap style)  (or/c 'butt 'square 'round)

  style : stroke3d?
Returns endpoint-cap style.

procedure

(stroke3d-join style)  (or/c 'miter 'bevel 'round)

  style : stroke3d?
Returns polyline-join style.

procedure

(stroke3d-miter-limit style)  positive?

  style : stroke3d?
Returns miter limit.

procedure

(stroke3d-dash style)  (or/c #f vector?)

  style : stroke3d?
Returns the validated dash pattern.

procedure

(stroke3d-dash-offset style)  finite-real?

  style : stroke3d?
Returns dash phase.

procedure

(stroke3d-dash-space style)  (or/c 'screen 'world)

  style : stroke3d?
Returns dash units.

procedure

(stroke3d-opacity style)  (real-in 0 1)

  style : stroke3d?
Returns local opacity.

procedure

(stroke3d-depth-mode style)  (or/c 'test 'always 'hidden)

  style : stroke3d?
Returns depth policy.

procedure

(stroke3d-depth-bias style)  nonnegative-real?

  style : stroke3d?
Returns normalized depth bias.

procedure

(stroke3d-with-color style color)  stroke3d?

  style : stroke3d?
  color : color-spec?
Recolours a stroke.

procedure

(stroke3d-with-opacity style opacity)  stroke3d?

  style : stroke3d?
  opacity : (real-in 0 1)
Changes local opacity.

procedure

(tube-style3d [#:radius radius    
  #:sides sides    
  #:color color])  tube-style3d?
  radius : positive? = 1/20
  sides : exact-positive-integer? = 8
  color : color-spec? = "steelblue"
Creates the explicit physical style used when a curve should lower to a tube mesh.

procedure

(tube-style3d? value)  boolean?

  value : any/c
Recognizes a tube style.

procedure

(tube-style3d-radius style)  positive?

  style : tube-style3d?
Returns physical radius.

procedure

(tube-style3d-sides style)  exact-positive-integer?

  style : tube-style3d?
Returns radial tessellation count.

procedure

(tube-style3d-color style)  color-spec?

  style : tube-style3d?
Returns tube colour.

procedure

(point-style3d [#:size size    
  #:size-mode size-mode    
  #:color color    
  #:opacity opacity    
  #:depth-mode depth-mode    
  #:depth-bias depth-bias])  point-style3d?
  size : positive? = 8
  size-mode : (or/c 'screen 'world) = 'screen
  color : color-spec? = "cornflowerblue"
  opacity : (real-in 0 1) = 1
  depth-mode : (or/c 'test 'always 'hidden) = 'test
  depth-bias : nonnegative-real? = 1e-5
Creates a circular point-marker style. Screen size is its diameter in pixels; world size is a physical diameter projected at the point anchor.

procedure

(point-style3d? value)  boolean?

  value : any/c
Recognizes a point-marker style.

procedure

(arrow-style3d [#:length length    
  #:length-mode length-mode    
  #:width width    
  #:color color    
  #:opacity opacity    
  #:depth-mode depth-mode    
  #:depth-bias depth-bias])  arrow-style3d?
  length : positive? = 12
  length-mode : (or/c 'screen 'world) = 'screen
  width : (or/c #f positive?) = #f
  color : color-spec? = "tomato"
  opacity : (real-in 0 1) = 1
  depth-mode : (or/c 'test 'always 'hidden) = 'test
  depth-bias : nonnegative-real? = 1e-5
Creates a screen or world arrowhead style. Its direction is taken from the final projected nondegenerate shaft segment.

procedure

(arrow-style3d? value)  boolean?

  value : any/c
Recognizes an arrowhead style.

procedure

(point3d position #:id id [#:style style])  spatial-visual?

  position : vec3?
  id : symbol?
  style : point-style3d? = (point-style3d)
Creates one finite screen/world point marker.

procedure

(curve3d? value)  boolean?

  value : any/c
Recognizes a sampled spatial curve.

procedure

(line3d from to #:id id [#:style style])  curve3d?

  from : vec3?
  to : vec3?
  id : symbol?
  style : (or/c stroke3d? tube-style3d?) = (stroke3d)
Creates a finite straight spatial line. The alias segment3d has the same arguments.

procedure

(segment3d from to #:id id [#:style style])  curve3d?

  from : vec3?
  to : vec3?
  id : symbol?
  style : (or/c stroke3d? tube-style3d?) = (stroke3d)
Creates the same finite geometry as line3d.

procedure

(polyline3d points    
  #:id id    
  [#:style style    
  #:closed? closed?    
  #:transform transform    
  #:opacity opacity])  curve3d?
  points : (or/c list? vector?)
  id : symbol?
  style : (or/c stroke3d? tube-style3d?) = (stroke3d)
  closed? : boolean? = #f
  transform : transform3? = identity-transform3
  opacity : (real-in 0 1) = 1
Creates a sampled polyline. Adjacent repeated points are removed before stroke preparation or tube frames are formed.

procedure

(parametric-curve3d procedure    
  [#:range range    
  #:samples samples]    
  #:id id    
  [#:style style    
  #:closed? closed?])  curve3d?
  procedure : procedure?
  range : (list/c finite-real? finite-real?) = (list 0 1)
  samples : exact-positive-integer? = 64
  id : symbol?
  style : (or/c stroke3d? tube-style3d?) = (stroke3d)
  closed? : boolean? = #f
Samples procedure at equally spaced, inclusive range endpoints. The declared samples locations are deterministic.

procedure

(tube3d points    
  #:id id    
  [#:radius radius    
  #:sides sides    
  #:closed? closed?]    
  #:width-mode width-mode)  mesh3d?
  points : (or/c list? vector?)
  id : symbol?
  radius : positive? = 1/20
  sides : exact-positive-integer? = 8
  closed? : boolean? = #f
  width-mode : 'world
Creates a tube mesh using transported local frames.

procedure

(arrow3d from    
  to    
  #:id id    
  [#:shaft-style shaft-style    
  #:tip-style tip-style])  group3d?
  from : vec3?
  to : vec3?
  id : symbol?
  shaft-style : stroke3d? = (stroke3d #:color "tomato")
  tip-style : arrow-style3d? = (arrow-style3d #:color "tomato")
Creates a shaft and screen/world marker tip at stable descendants 'shaft and 'tip.

procedure

(double-arrow3d from    
  to    
  #:id id    
  [#:shaft-style shaft-style    
  #:tip-style tip-style])  group3d?
  from : vec3?
  to : vec3?
  id : symbol?
  shaft-style : stroke3d? = (stroke3d #:color "tomato")
  tip-style : arrow-style3d? = (arrow-style3d #:color "tomato")
Creates a shaft with one marker tip at each endpoint.

procedure

(with-edges3d mesh    
  [#:edges edges    
  #:visible visible    
  #:hidden hidden    
  #:crease-angle crease-angle    
  #:surface surface])  edge-overlay3d?
  mesh : mesh3d?
  edges : (or/c 'explicit 'all 'boundary 'crease 'silhouette 'feature)
   = 'feature
  visible : (or/c #f stroke3d?)
   = (stroke3d #:color "black" #:width 2)
  hidden : (or/c #f stroke3d?) = #f
  crease-angle : finite-real? = (/ pi 6)
  surface : (or/c 'visible 'depth-only 'none) = 'visible
Wraps a mesh with camera-prepared outlines without adding a path component. 'feature means boundary, crease, and silhouette edges. A 'depth-only surface occludes lines without painting a surface colour.

procedure

(edge-style3d? value)  boolean?

  value : any/c
Recognizes a mesh-outline style.

procedure

(edge-overlay3d? value)  boolean?

  value : any/c
Recognizes an outlined mesh wrapper.

procedure

(axes3d #:id id    
  [#:x-range x-range    
  #:y-range y-range    
  #:z-range z-range])  group3d?
  id : symbol?
  x-range : list? = (list -3 3)
  y-range : list? = (list -3 3)
  z-range : list? = (list -3 3)
Creates finite axes. Paths such as '(world axes x-axis), '(world axes x-ticks), and '(world axes labels x) remain stable. The final path is an invisible 3D anchor intended for follow-projected-spatial.

procedure

(coordinate-plane3d plane #:id id)  mesh3d?

  plane : (or/c 'xy 'xz 'yz)
  id : symbol?
Creates one finite double-sided coordinate plane.

procedure

(grid-plane3d plane #:id id)  group3d?

  plane : (or/c 'xy 'xz 'yz)
  id : symbol?
Creates a finite grid of physical-width spatial lines.

procedure

(basis-vectors3d #:id id)  group3d?

  id : symbol?
Creates coloured i, j, and k arrows.

procedure

(vector-arrow3d vector #:id id)  group3d?

  vector : vec3?
  id : symbol?
Creates one arrow from the origin to vector.

procedure

(vector-components3d vector #:id id)  group3d?

  vector : vec3?
  id : symbol?
Creates orthogonal component arrows plus a resultant at stable descendants.

procedure

(move-along-curve3d target    
  curve    
  [#:start start    
  #:end end])  any/c
  target : spatial-path?
  curve : spatial-path?
  start : finite-real? = 0
  end : finite-real? = 1
Moves a spatial target by arc-length fraction along a curve path in the same view3d.

procedure

(orient-along-curve3d target    
  curve    
  [#:start start    
  #:end end])  any/c
  target : spatial-path?
  curve : spatial-path?
  start : finite-real? = 0
  end : finite-real? = 1
Rotates the target’s local positive x direction to the sampled tangent.

For an already-present curve path, (create '(world curve)), (uncreate '(world curve)), and (show-passing-flash '(world curve)) use the same direct curve sampling. A passing flash adds a temporary coloured tube sliver over its unchanged source curve; it disappears at each clip endpoint. The canonical vector-camera-orbit example is "examples/3d/vector-components.rkt".

18.13 Parametric surfaces and calculus🔗ℹ

SCENE-3D-G adds fixed-topology rectangular parametric surfaces. A surface is sampled once at inclusive parameter-grid sites and therefore has stable vertex and triangle identities. Its normals use declared analytic derivatives when both are supplied; otherwise they use deterministic centred/one-sided finite differences, adjacent-face fallback, and explicit unresolved-index reporting.

procedure

(parametric-surface3d procedure    
  [#:u-range u-range    
  #:v-range v-range    
  #:resolution resolution]    
  #:id id)  surface3d?
  procedure : procedure?
  u-range : list? = (list -1 1)
  v-range : list? = (list -1 1)
  resolution : list? = (list 33 33)
  id : symbol?
Creates a fixed rectangular sampled parameterization.

procedure

(function-surface3d function    
  [#:x-range x-range    
  #:y-range y-range    
  #:resolution resolution]    
  #:id id)  surface3d?
  function : procedure?
  x-range : list? = (list -1 1)
  y-range : list? = (list -1 1)
  resolution : list? = (list 33 33)
  id : symbol?
Creates the graph (vec3 x y (function x y)) and retains scalar-field data for calculus helpers.

procedure

(surface3d? value)  boolean?

  value : any/c
Recognizes an immutable sampled surface.

procedure

(surface3d-resolution surface)  list?

  surface : surface3d?
Returns its fixed (list u-count v-count) topology.

procedure

(surface3d-position-at surface u v)  vec3?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
Evaluates a point in the authored parameter domain.

procedure

(surface3d-normal-at surface u v)  vec3?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
Returns a safe unit normal, using the recorded deterministic fallback when necessary.

procedure

(surface-color surface color)  surface3d?

  surface : surface3d?
  color : color-spec?
Changes the uniform material colour without changing samples or topology.

procedure

(surface-color-by-height surface)  surface3d?

  surface : surface3d?
Adds an opaque per-vertex z-height colour field.

procedure

(surface-color-by-scalar surface scalar)  surface3d?

  surface : surface3d?
  scalar : procedure?
Adds a deterministic opaque per-vertex colour ramp from the scalar evaluated at each existing sample.

procedure

(surface-checkerboard surface)  surface3d?

  surface : surface3d?
Adds a deterministic parameter-space checkerboard colour field.

procedure

(surface-point surface u v #:id id)  mesh3d?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
  id : symbol?
Creates a point at a surface parameter.

procedure

(surface-tangent-u surface u v #:id id)  group3d?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
  id : symbol?
Draws an arrow in the u tangent direction.

procedure

(surface-tangent-v surface u v #:id id)  group3d?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
  id : symbol?
Draws an arrow in the v tangent direction.

procedure

(surface-normal surface u v #:id id)  group3d?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
  id : symbol?
Draws an arrow in the direct tangent-plane normal direction.

procedure

(surface-tangent-plane surface u v #:id id)  mesh3d?

  surface : surface3d?
  u : finite-real?
  v : finite-real?
  id : symbol?
Creates a finite tangent parallelogram at the parameter point.

procedure

(surface-coordinate-curve surface #:id id)  curve3d?

  surface : surface3d?
  id : symbol?
Samples one fixed-u or fixed-v coordinate curve.

procedure

(surface-gradient-arrow surface x y #:id id)  group3d?

  surface : surface3d?
  x : finite-real?
  y : finite-real?
  id : symbol?
Creates the xy gradient arrow for a declared function-surface3d.

18.14 Adaptive, trimmed, and implicit surfaces🔗ℹ

SCENE-3D-Q adds three producers which all lower to the same immutable indexed surface record returned by surface3d-mesh. The record preserves vertex and triangle provenance as well as a topology key, while renderer caches remain outside authored values.

adaptive-parametric-surface3d accepts the same parameterization shape as parametric-surface3d, but samples it on a deterministic dyadic quadtree. Its position, normal-angle, and maximum-edge-length tolerances are camera independent. Neighbouring cells are conformed before lowering, so their shared edge vertices are identical rather than merely close.

trimmed-parametric-surface3d accepts signed surface-trim fields in parameter space. It clips the retained adaptive triangles and shares edge/trim intersections by canonical keys. Consequently surface3d-domain-contains? and surface3d-position-at? can distinguish a point in the original parameter box from one outside its trim.

implicit-surface3d samples a finite scalar field within a declared axis-aligned box and extracts one level set with deterministic marching tetrahedra. It shares lattice-edge intersections, estimates normals from central field differences, and records whether the surface touches the box boundary. The initial extractor is a fixed-resolution algorithm; it does not yet adapt its 3D cells. view3d-surface-pick uses the ordinary CPU BVH hit and attaches the retained triangle provenance: barycentrically interpolated (vector u v) parameters for parametric surfaces and the source cube/ tetrahedron record for implicit ones. It does not claim a separate analytic implicit intersection solver.

The focused executable probe is "examples/3d/adaptive-trimmed-implicit-surfaces.rkt".

procedure

(reveal-surface-u target)  any/c

  target : spatial-path?
Reveals an existing surface directly from its minimum-u boundary without changing its grid size.

procedure

(reveal-surface-v target)  any/c

  target : spatial-path?
The analogous minimum-v reveal.

procedure

(transform-surface3d target destination)  any/c

  target : spatial-path?
  destination : surface3d?
Interpolates matching topology and material structure directly from immutable source/destination grids.

The canonical acceptance scene is "examples/3d/tangent-plane.rkt".

18.15 Constructive solids🔗ℹ

SCENE-3D-H adds deterministic indexed solid meshes. The standard constructors and regular-polyhedron constructors return ordinary mesh3d values. Their tessellation parameters are part of the authored immutable value, not a renderer decision.

procedure

(cube3d side #:id id)  mesh3d?

  side : finite-real?
  id : symbol?
Creates a cube.

procedure

(box3d width height depth #:id id)  mesh3d?

  width : finite-real?
  height : finite-real?
  depth : finite-real?
  id : symbol?
Creates an axis-aligned box.

procedure

(prism3d sides #:id id)  mesh3d?

  sides : exact-positive-integer?
  id : symbol?
Creates a regular prism.

procedure

(sphere3d radius #:id id)  mesh3d?

  radius : finite-real?
  id : symbol?
Creates a latitude-longitude sphere.

procedure

(cylinder3d radius height #:id id)  mesh3d?

  radius : finite-real?
  height : finite-real?
  id : symbol?
Creates a cylinder.

procedure

(cone3d radius height #:id id)  mesh3d?

  radius : finite-real?
  height : finite-real?
  id : symbol?
Creates a cone.

procedure

(torus3d major-radius minor-radius #:id id)  mesh3d?

  major-radius : finite-real?
  minor-radius : finite-real?
  id : symbol?
Creates a torus.

procedure

(extrude3d contour    
  #:id id    
  #:vector direction)  mesh3d?
  contour : (listof vec2?)
  id : symbol?
  direction : vec3?
Extrudes one simple closed xy-plane contour through a noncoplanar vector. Caps use deterministic ear clipping.

procedure

(revolve3d profile #:id id [#:axis axis])  mesh3d?

  profile : (listof vec2?)
  id : symbol?
  axis : (or/c 'x 'y 'z) = 'z
Revolves a nonnegative-radius profile around an axis.

procedure

(sweep3d profile curve #:id id)  mesh3d?

  profile : (listof vec2?)
  curve : curve3d?
  id : symbol?
Sweeps a simple profile along a sampled curve using a direct parallel-transport frame.

procedure

(mesh3d-smooth-normals mesh)  mesh3d?

  mesh : mesh3d?
Computes stable area-weighted shared-vertex normals.

procedure

(mesh3d-flat-normals mesh)  mesh3d?

  mesh : mesh3d?
Duplicates face vertices so every triangle receives one normal.

procedure

(mesh3d-boundary-edges mesh)  vector?

  mesh : mesh3d?
Reports its deterministically ordered manifold boundary edges.

The canonical acceptance scene is "examples/3d/solid-of-revolution.rkt".

18.16 Clipping, sections, and transparency🔗ℹ

SCENE-3D-I distinguishes a render instruction from a geometric operation. clip3d keeps its source subtree intact and clips only the triangles submitted to a view3d renderer. slice-mesh3d instead returns new half-space mesh geometry; it deliberately does not invent a cap. Use section-by-plane3d for the actual plane intersection and section-curve3d to draw every loop or open chain as ordinary spatial curves.

procedure

(clip-plane3d plane [#:keep keep])  clip-plane3d?

  plane : plane3?
  keep : (or/c 'positive 'negative) = 'positive
Describes the retained half-space of a clipping plane.

procedure

(clip-plane3d? value)  boolean?

  value : any/c
Recognizes a clipping-plane description.

procedure

(clip3d content clip #:id id)  clip3d?

  content : spatial-visual?
  clip : (or/c plane3? clip-plane3d?)
  id : symbol?
Wraps one spatial subtree with local render-only clipping.

procedure

(clip3d? value)  boolean?

  value : any/c
Recognizes a render-clip wrapper.

procedure

(slice-mesh3d mesh clip)  mesh3d?

  mesh : mesh3d?
  clip : (or/c plane3? clip-plane3d?)
Returns actual, deterministically triangulated clipped mesh geometry in the source mesh’s local coordinates.

procedure

(section-by-plane3d mesh clip)  section3d?

  mesh : mesh3d?
  clip : (or/c plane3? clip-plane3d?)
Returns deterministic section3d topology. Its section3d-loops and section3d-chains accessors distinguish closed components from open ones.

procedure

(section3d? value)  boolean?

  value : any/c
Recognizes plane-section topology.

procedure

(section3d-loops section)  (listof (listof vec3?))

  section : section3d?
Returns its closed components in deterministic plane orientation.

procedure

(section3d-chains section)  (listof (listof vec3?))

  section : section3d?
Returns its open components in deterministic endpoint order.

procedure

(section-curve3d mesh clip #:id id)  group3d?

  mesh : mesh3d?
  clip : (or/c plane3? clip-plane3d?)
  id : symbol?
Builds a group of physical-radius tube curves for every section component.

material3d accepts an alpha-bearing semantic colour. In an opaque view3d, fully opaque geometry writes the depth buffer first; transparent geometry is then rendered far-to-near with 'object-sorted or 'triangle-sorted #:transparency-mode. Transparent triangles depth-test against opaque geometry but do not write depth. A projected-label accepts #:occlusion 'always-visible, 'hide, or 'fade; its occlusion test uses that opaque depth target, preserving the label as a crisp 2D Visual.

18.17 Cuts, caps, and section measurements🔗ℹ

SCENE-3D-R extends a plane section with an explicit local numerical policy, plane basis, and component records. cut-mesh3d returns both clipped halves plus their shared section3d and optional separate cap meshes; it does not mutate the source mesh. section3d-area, section3d-centroid, and section3d-perimeter operate on the same preserved section topology. clip-planes3d and clip-box3d build ordered render-only half-space sequences.

section-fill3d exposes a separate cap-style mesh for a section; section-hatch3d creates deterministic even/odd stroke intervals in the plane-local basis, including empty intervals for nested holes. slice-stack3d retains stable section-group paths as planes advance along a normal. prepare-cross-section-function3d makes an immutable table of sections, areas, centroids, and diagnostics, which volume-by-slices3d evaluates with a declared midpoint, trapezoid, or Simpson rule. The sampling convention is part of the table and is checked by the chosen numerical rule. riemann-volume3d provides a separate midpoint-column construction for graph-volume explanations; each row and cell is an ordinary stable spatial child. washer-sum3d creates stable midpoint annular slabs about the x axis, and shell-sum3d creates stable midpoint cylindrical shells about the z axis. These are explanatory geometry groups; numerical volume estimation remains explicit.

The cap triangulator handles simple concave, hole-free section loops with deterministic ear clipping. Nested loops (cap holes) remain explicitly rejected rather than silently filling the wrong region. Multi-plane render clipping is semantic and ordered, but the optional OpenGL backend has not yet received its corresponding multi-plane uniform path. See "examples/3d/capped-cube-cutaway.rkt".

procedure

(riemann-volume3d function    
  [#:x-range x-range    
  #:y-range y-range    
  #:resolution resolution    
  #:base base]    
  #:id id)  group3d?
  function : procedure?
  x-range : list? = (list -1 1)
  y-range : list? = (list -1 1)
  resolution : list? = (list 8 8)
  base : finite-real? = 0
  id : symbol?
Builds midpoint columns between base and (function x y). Children have stable 'row-n then 'cell-n identifiers. A zero-height sample is a stable empty cell group, not an invented nonzero solid.

procedure

(washer-sum3d outer    
  inner    
  [#:x-range x-range    
  #:count count]    
  #:id id)  group3d?
  outer : procedure?
  inner : procedure?
  x-range : list? = (list -1 1)
  count : exact-positive-integer? = 8
  id : symbol?
Builds midpoint annular washer slabs about the x axis. outer and inner must return nonnegative radii with inner no larger than outer. Children are stably named 'washer-n.

procedure

(shell-sum3d height    
  [#:radius-range radius-range    
  #:count count    
  #:base base]    
  #:id id)  group3d?
  height : procedure?
  radius-range : list? = (list 0 1)
  count : exact-positive-integer? = 8
  base : finite-real? = 0
  id : symbol?
Builds midpoint annular cylindrical shells about the z axis between base and (height radius). Children are stably named 'shell-n.

18.18 Spatial anchors and label layout🔗ℹ

SCENE-3D-S begins the annotation layer with immutable anchor3d? descriptors. vertex-anchor3d, edge-anchor3d, face-anchor3d, curve-anchor3d, surface-anchor3d, and bounds/origin anchors resolve after every spatial transformation into a resolved-anchor3d world point, normal/tangent when available, source path, and stable provenance identity. A regular parametric surface anchor also exposes its evaluated normal and u-tangent after its complete world transform. Generated adaptive/trimmed frames remain a separately documented provenance-boundary limitation.

label3d uses such an anchor while retaining its content as a crisp ordinary 2D Visual. label-placement3d and layout-labels3d provide a deterministic, pure direct-mode candidate layout in output pixels. prepare-label-layout3d optionally computes an immutable dynamic-programming candidate table for a declared finite frame grid, applying explicit movement and switching penalties without relying on the previously displayed frame. Equal-priority labels retain declaration order, and equal-cost candidates retain the declared preferred-direction order. 2D leader rendering, mathematical dimensions, and textured/camera-facing billboards remain later work; they are intentionally not simulated by mutable callbacks. The executable anchor probe is "examples/3d/anchor-aware-labels.rkt".

The canonical acceptance scene is "examples/3d/sphere-plane-section.rkt".

18.19 Spatial maps and homotopies🔗ℹ

SCENE-3D-J adds map requests to the ordinary immutable scene timeline. Every target is a rooted spatial path, and every map procedure is authored in world coordinates. This makes a map applied to a nested child mean the same thing as applying it to an equivalent top-level child. A surrounding parent map must therefore be invertible when the result is rebased into that parent’s local coordinate system.

apply-linear3 and apply-affine3 retain the original spatial subtree and attach a full affine map to it. They consequently preserve the indexed topology exactly, even for a shear, reflection, or singular map. A named child of a transformed group3d remains addressable. The canonical linear-transformation-diagram3d groups coordinate planes, a unit cube, basis arrows, and an arbitrary vector so one map applies to all of them coherently.

(scene-play
 (scene-add (make-scene) world)
 (apply-linear3 '(world diagram)
                (linear3 1 0 1
                         0 1 0
                         0 0 1))
 (apply-homotopy3
  '(world sheet)
  (lambda (point phase)
    (vec3 (vec3-x point)
          (* (cos phase) (vec3-y point))
          (* (sin phase) (vec3-y point)))))
 #:duration 2)

procedure

(linear-transformation-diagram3d #:id id 
  [#:vector vector 
  #:cube-side cube-side 
  #:plane-size plane-size]) 
  group3d?
  id : symbol?
  vector : vec3? = (vec3 3/2 1 1/2)
  cube-side : positive-real? = 1
  plane-size : positive-real? = 3
Creates the named coordinate-plane, unit-cube, basis-arrow, and vector diagram intended for a coherent linear transformation.

procedure

(apply-linear3 path map)  any/c

  path : spatial-path?
  map : linear3?
Animates a world-coordinate linear map from identity to map.

procedure

(apply-affine3 path map)  any/c

  path : spatial-path?
  map : affine3?
Animates a world-coordinate affine map from identity to map.

procedure

(apply-pointwise3 path 
  map-point 
  [#:on-failure on-failure 
  #:recompute-normals? recompute-normals?]) 
  any/c
  path : spatial-path?
  map-point : procedure?
  on-failure : (or/c 'error 'drop-triangle) = 'error
  recompute-normals? : boolean? = #t
Maps the source mesh’s authored world-space vertices. During the clip, each vertex moves linearly from its source position to (map-point source-point). The default reports a bad map result; the explicit 'drop-triangle policy removes every incident triangle.

procedure

(apply-homotopy3 path 
  homotopy 
  [#:on-failure on-failure 
  #:recompute-normals? recompute-normals?]) 
  any/c
  path : spatial-path?
  homotopy : procedure?
  on-failure : (or/c 'error 'drop-triangle) = 'error
  recompute-normals? : boolean? = #t
Evaluates (homotopy source-point phase) directly at each nonzero requested phase. Unlike endpoint interpolation, the supplied homotopy controls the complete intermediate geometry.

The canonical acceptance scene is "examples/3d/spatial-maps-and-homotopies.rkt".

18.20 Prepared spatial ODE trajectories and vector fields🔗ℹ

SCENE-3D-K adds direct-time flow geometry without a mutable per-frame updater. prepare-ode-trajectory3d records an immutable numerical path once; subsequent position lookup accepts any supported time in any order. A field accepts either (field x y z) or (field time x y z) and must return exactly one finite vec3. The fixed default is checkpointed RK4. With adaptive-rk45, accepted Dormand–Prince nodes and endpoint derivatives are stored, so lookup uses cubic Hermite dense output and never calls the author field.

flow-particle3d is a semantic spatial relation. Before an image or preview worker resolves it, Animate samples its requested phase values into an immutable table. Thus worker rendering reads positions and tangents only; it does not evaluate the field procedure. Direct lookup of a fixed RK4 trajectory may still take the bounded suffix after its nearest checkpoint.

(define lorenz-path
  (prepare-ode-trajectory3d
   (lambda (x y z) (vec3 (* 10 (- y x)) (- (* x (- 28 z)) y)
                         (- (* x y) (* 8/3 z))))
   (vec3 0 1 21/20)
   #:time-range (cons 0 20)
   #:solver (adaptive-rk45 #:relative-tolerance 1e-6)))
 
(define phase (parameter 'time 0))
(flow-particle3d lorenz-path phase #:id 'particle #:tangent-length 1)

procedure

(prepare-ode-trajectory3d field 
  seed 
  #:time-range time-range 
  [#:step-size step-size 
  #:checkpoint-every checkpoint-every 
  #:solver solver]) 
  ode-trajectory3d?
  field : 
(or/c (procedure-arity-includes/c 3)
      (procedure-arity-includes/c 4))
  seed : vec3?
  time-range : (cons/c finite-real? finite-real?)
  step-size : (and/c finite-real? positive?) = 1/20
  checkpoint-every : exact-positive-integer? = 16
  solver : (or/c false/c adaptive-rk45?) = #f
Prepares one immutable spatial trajectory over the closed range (cons start-time end-time). The seed is at time zero; the range may extend on either side of it.

procedure

(ode-trajectory3d? value)  boolean?

  value : any/c
Recognizes a prepared fixed-RK4 or adaptive-RK45 spatial trajectory.

procedure

(ode-trajectory3d-position trajectory time)  vec3?

  trajectory : ode-trajectory3d?
  time : finite-real?
Returns the position at a supported time. Adaptive lookup reads only stored data.

procedure

(ode-trajectory3d-time-range trajectory)

  (cons/c finite-real? finite-real?)
  trajectory : ode-trajectory3d?
Returns its supported range.

procedure

(ode-trajectory3d-step-size trajectory)

  (or/c positive? false/c)
  trajectory : ode-trajectory3d?
Returns a fixed path’s RK4 step, or #f for an adaptive path.
Returns a fixed path’s checkpoint spacing, or #f for an adaptive path.

procedure

(ode-trajectory3d-solver trajectory)  any/c

  trajectory : ode-trajectory3d?
Returns 'fixed-rk4 or the immutable adaptive-rk45? configuration.

procedure

(ode-trajectory3d-diagnostics trajectory)  any/c

  trajectory : ode-trajectory3d?
For an adaptive path, returns immutable solver name, accepted/rejected step count, final time, and maximum norm-relative embedded-error ratio; it returns #f for fixed RK4.

procedure

(vector-field3d field 
  #:id id 
  [#:x-range x-range 
  #:y-range y-range 
  #:z-range z-range 
  #:x-count x-count 
  #:y-count y-count 
  #:z-count z-count 
  #:normalize? normalize? 
  #:length-range length-range 
  #:color-by-magnitude? color-by-magnitude? 
  #:seed-order seed-order]) 
  group3d?
  field : 
(or/c (procedure-arity-includes/c 3)
      (procedure-arity-includes/c 4))
  id : symbol?
  x-range : list? = (list -2 2)
  y-range : list? = (list -2 2)
  z-range : list? = (list -2 2)
  x-count : exact-positive-integer? = 5
  y-count : exact-positive-integer? = 5
  z-count : exact-positive-integer? = 5
  normalize? : boolean? = #f
  length-range : (or/c false/c list? pair?) = #f
  color-by-magnitude? : boolean? = #f
  seed-order : symbol? = 'xyz
Samples an explicit finite rectangular grid once. Zero derivatives are omitted. #:seed-order is one of 'xyz, 'xzy, 'yxz, 'yzx, 'zxy, or 'zyx, giving stable child order. When requested, magnitude controls the displayed arrow length and colour.

procedure

(streamline3d field seed #:id id)  curve3d?

  field : procedure?
  seed : vec3?
  id : symbol?
Creates one finite static RK4 streamline.

procedure

(streamlines3d field seeds #:id id)  group3d?

  field : procedure?
  seeds : (listof vec3?)
  id : symbol?
Creates deterministic static streamline children.

procedure

(flow-particle3d trajectory 
  phase 
  #:id id 
  [#:tangent-length tangent-length]) 
  spatial-relation?
  trajectory : ode-trajectory3d?
  phase : scene-parameter?
  id : symbol?
  tangent-length : (or/c false/c positive?) = #f
Creates a prepared position marker, optionally with a visible nonzero tangent. At an equilibrium, the tangent child remains structurally present but invisible rather than claiming an arbitrary direction.

procedure

(flow-cloud3d trajectories phase #:id id)  group3d?

  trajectories : (listof ode-trajectory3d?)
  phase : scene-parameter?
  id : symbol?
Creates one prepared particle per trajectory using the shared time parameter.

The canonical acceptance scene is "examples/3d/prepared-lorenz-flow.rkt".

18.21 Spatial inspection and exact picking🔗ℹ

SCENE-3D-L exposes the spatial hierarchy that an already sampled view3d submits to its renderer. Inspection is immutable query data; it never adds a wireframe, selection flag, acceleration structure, or other hidden state to an authored Scene. The preview uses the same query data after a viewport click and paints its AABB, exact triangle, normal, local frame, and ray-pixel marker only after the cached bitmap has been drawn.

struct

(struct spatial-inspection (path
    kind
    local-transform
    world-transform
    local-bounds
    world-bounds
    material
    triangle-count
    vertex-count
    camera-position
    view-position
    projected-position
    view-depth
    metadata)
    #:transparent)
  path : (listof symbol?)
  kind : symbol?
  local-transform : transform3?
  world-transform : affine3?
  local-bounds : aabb3?
  world-bounds : aabb3?
  material : any/c
  triangle-count : exact-nonnegative-integer?
  vertex-count : exact-nonnegative-integer?
  camera-position : vec3?
  view-position : (or/c #f vec3?)
  projected-position : (or/c #f vec2?)
  view-depth : (or/c #f nonnegative-real?)
  metadata : immutable-hash?
One deterministic pre-order description of a spatial group, mesh, curve, or surface. path begins with the enclosing view3d identity; local-transform is the authored decomposition while world-transform includes all spatial ancestors. Empty geometry has false projection/depth fields rather than an invented point.

struct

(struct spatial-pick (inspection
    path
    triangle-index
    point
    distance
    barycentric
    normal
    ray
    metadata)
    #:transparent)
  inspection : spatial-inspection?
  path : (listof symbol?)
  triangle-index : (or/c #f exact-nonnegative-integer?)
  point : vec3?
  distance : nonnegative-real?
  barycentric : vec3?
  normal : vec3?
  ray : ray3?
  metadata : immutable-hash?
The nearest spatial pick. spatial-pick-kind returns 'mesh-triangle, 'stroke-segment, 'point-marker, or 'arrow-marker. Mesh hits are exact ray/triangle intersections; screen marks use the same prepared projected footprint and depth predicate as the renderer. Stroke metadata includes source segment index/progress, world point, view depth, pixel distance, and style. Ties are resolved by depth, drawing index, then authored triangle or source segment index.

struct

(struct surface-pick3d (spatial-pick
    surface-kind
    parameter
    trim-boundary
    source-cell
    interpolated-normal)
    #:transparent)
  spatial-pick : spatial-pick?
  surface-kind : symbol?
  parameter : (or/c #f vector?)
  trim-boundary : any/c
  source-cell : any/c
  interpolated-normal : (or/c #f vec3?)
A refinement of an exact mesh spatial-pick for a surface3d. The source cell is immutable triangle provenance, not an implementation cache.

procedure

(spatial-pick-kind pick)

  (or/c 'mesh-triangle 'stroke-segment 'point-marker 'arrow-marker)
  pick : spatial-pick?
Returns the selected primitive kind.

procedure

(view3d-spatial-inspections view)

  (listof spatial-inspection?)
  view : view3d?
Returns deterministic pre-order records, including containers.
An explicit spelling for the same pre-order hierarchy, convenient for a tree UI.

procedure

(view3d-spatial-inspection-at view path)

  (or/c #f spatial-inspection?)
  view : view3d?
  path : (listof symbol?)
Returns the matching record, or #f when path does not occur in this view.

procedure

(view3d-pick view ray)  (or/c #f spatial-pick?)

  view : view3d?
  ray : ray3?
Picks a spatial object with world ray ray. It first culls world AABBs, transforms the candidate ray to mesh-local coordinates, traverses a local BVH, and finishes with exact triangle and barycentric testing.

procedure

(view3d-surface-pick view ray)  (or/c #f surface-pick3d?)

  view : view3d?
  ray : ray3?
Uses the same CPU path as view3d-pick, returning #f unless the nearest hit is a surface. Parametric parameters are interpolated from retained vertex provenance; an implicit result retains its source grid/tetrahedron record instead.

procedure

(view3d-pixel-pick view    
  pixel-x    
  pixel-y    
  #:width width    
  #:height height)  (or/c #f spatial-pick?)
  view : view3d?
  pixel-x : finite-real?
  pixel-y : finite-real?
  width : exact-positive-integer?
  height : exact-positive-integer?
Builds the camera ray through a top-left-origin viewport pixel. It performs exact mesh picking and supplements it with prepared screen-stroke and marker footprints; it does not sample a rendered bitmap or require a GUI.

procedure

(mesh3d-bvh mesh)  mesh3d-bvh?

  mesh : mesh3d?
Returns the immutable local acceleration tree used for picking. It splits on the longest centroid axis, uses a stable median, and breaks ties by triangle index. The cache is an implementation resource, not semantic scene state.

procedure

(mesh3d-bvh? value)  boolean?

  value : any/c
Recognizes an inspection BVH.

procedure

(bvh3d-node? value)  boolean?

  value : any/c
Recognizes an internal BVH node.

procedure

(bvh3d-leaf? value)  boolean?

  value : any/c
Recognizes a BVH leaf.

procedure

(bvh3d-bounds tree)  aabb3?

  tree : mesh3d-bvh?
Returns local bounds for a node or leaf.
Returns the complete stable set of contained triangle indices.

procedure

(bvh3d-ray-candidates tree ray)

  (listof exact-nonnegative-integer?)
  tree : mesh3d-bvh?
  ray : ray3?
Returns deterministic local triangle candidates. Exact triangle testing remains separate.

The canonical preview probe is "examples/3d/spatial-inspector-picking.rkt". Open it with animate/preview, click a visible facet, then use the Animate → 3D selection menu to copy the spatial path, hit point, or normal; its scratch action also supplies a clipping plane. Focusing the inspection camera changes only the preview override, never the authored camera or timeline.

18.22 Retained renderer backends🔗ℹ

SCENE-3D-N keeps animate/3d pure and places effectful implementation choice in animate/3d/render. SCENE-3D-O extends that compiled view with ordered, renderer-neutral centreline strokes and screen markers. A backend receives an immutable render3d-request containing a camera-independent compiled view plus a frame specification, may retain geometry and preparation resources that it owns, and returns copied ARGB bytes. Thus changing a backend, releasing its cache, or recovering from a failed optional native renderer cannot mutate a view3d or any of its spatial children.

 (require animate/3d/render) package: animate

procedure

(renderer3d? value)  boolean?

  value : any/c
Recognizes a renderer-backend instance.

procedure

(renderer3d-id renderer)  symbol?

  renderer : renderer3d?
Returns a stable backend identity, such as 'software-reference.

procedure

(renderer3d-capabilities renderer)  renderer3d-capability-set?

  renderer : renderer3d?
Returns the backend’s declared facility set.

procedure

(renderer3d-fingerprint renderer request)  any/c

  renderer : renderer3d?
  request : render3d-request?
Returns an implementation-owned cache key for this immutable request. It is diagnostic and cache data, never a scene identity.

procedure

(renderer3d-prepare renderer request)  any/c

  renderer : renderer3d?
  request : render3d-request?
Builds or retrieves backend-owned preparation data.

procedure

(renderer3d-render renderer    
  preparation    
  request)  renderer3d-render-result?
  renderer : renderer3d?
  preparation : any/c
  request : render3d-request?
Rasterizes a fresh frame from a preparation and request.

procedure

(renderer3d-release renderer)  void?

  renderer : renderer3d?
Releases every resource retained by renderer. It does not change an existing Scene or an already returned render result.

struct

(struct renderer3d-capability-set (wireframe
    opaque-triangles
    perspective
    orthographic
    depth-buffer
    flat-shading
    smooth-shading
    transparency
    clipping-planes)
    #:transparent)
  wireframe : boolean?
  opaque-triangles : boolean?
  perspective : boolean?
  orthographic : boolean?
  depth-buffer : boolean?
  flat-shading : boolean?
  smooth-shading : boolean?
  transparency : boolean?
  clipping-planes : boolean?
The explicit feature record returned by renderer3d-capabilities. Project capability declarations use this same record rather than a separate 3D capability type.

struct

(struct compiled-geometry3d (key
    mesh
    local-bounds
    face-normals
    edge-adjacency
    analysis)
    #:transparent)
  key : any/c
  mesh : mesh3d?
  local-bounds : aabb3?
  face-normals : vector?
  edge-adjacency : vector?
  analysis : mesh3d-analysis?
A camera-independent geometry resource. Its canonical key includes local vertices, triangle and explicit-edge topology, normals, and per-vertex colours; it excludes material, opacity, transforms, camera, lights, and viewport settings.

struct

(struct compiled-instance3d (path
    geometry-key
    world-transform
    normal-transform
    material
    opacity
    clip-planes
    drawing-index
    surface-mode)
    #:transparent)
  path : (listof symbol?)
  geometry-key : any/c
  world-transform : affine3?
  normal-transform : linear3?
  material : material3d?
  opacity : real?
  clip-planes : list?
  drawing-index : exact-nonnegative-integer?
  surface-mode : (or/c 'visible 'depth-only 'none)
The ordered placement and style of one compiled geometry use.

struct

(struct compiled-stroke3d (path
    points
    closed?
    world-transform
    style
    opacity
    clip-planes
    drawing-index
    source-kind
    source-metadata)
    #:transparent)
  path : (listof symbol?)
  points : vector?
  closed? : boolean?
  world-transform : affine3?
  style : stroke3d?
  opacity : real?
  clip-planes : list?
  drawing-index : exact-nonnegative-integer?
  source-kind : symbol?
  source-metadata : immutable-hash?
A camera-independent sampled centreline. Screen width, dashes, clipping, depth classification, and cap/join coverage are prepared only for a concrete frame.

struct

(struct compiled-point-marker3d (path
    position
    world-transform
    style
    opacity
    clip-planes
    drawing-index)
    #:transparent)
  path : (listof symbol?)
  position : vec3?
  world-transform : affine3?
  style : point-style3d?
  opacity : real?
  clip-planes : list?
  drawing-index : exact-nonnegative-integer?
A camera-independent point marker.

struct

(struct compiled-arrow-marker3d (path
    from
    to
    world-transform
    style
    opacity
    clip-planes
    drawing-index)
    #:transparent)
  path : (listof symbol?)
  from : vec3?
  to : vec3?
  world-transform : affine3?
  style : arrow-style3d?
  opacity : real?
  clip-planes : list?
  drawing-index : exact-nonnegative-integer?
A camera-independent arrowhead marker.

struct

(struct compiled-edge-overlay3d (path
    geometry-key
    world-transform
    normal-transform
    style
    opacity
    clip-planes
    drawing-index)
    #:transparent)
  path : (listof symbol?)
  geometry-key : any/c
  world-transform : affine3?
  normal-transform : linear3?
  style : edge-style3d?
  opacity : real?
  clip-planes : list?
  drawing-index : exact-nonnegative-integer?
An outlined mesh reference whose feature selection is deliberately deferred until camera-frame preparation.

struct

(struct compiled-view3d (geometries
    instances
    strokes
    point-markers
    arrow-markers
    edge-overlays
    background
    render-mode
    transparency-mode)
    #:transparent)
  geometries : vector?
  instances : vector?
  strokes : vector?
  point-markers : vector?
  arrow-markers : vector?
  edge-overlays : vector?
  background : any/c
  render-mode : symbol?
  transparency-mode : symbol?
The immutable camera-independent renderer input. Use compiled-view3d-primitives for stable drawing-index order across these primitive vectors.

struct

(struct frame3d-spec (camera lights width height)
    #:transparent)
  camera : camera3d?
  lights : list?
  width : exact-positive-integer?
  height : exact-positive-integer?
The state which may change from one rendered frame to the next.

procedure

(compile-view3d view)  compiled-view3d?

  view : view3d?
Lowers a spatial tree deterministically, sharing equal geometry resources in first encounter order. It does not inspect the view’s camera.

procedure

(compiled-view3d-primitives view)  vector?

  view : compiled-view3d?
Returns the mesh instances, strokes, point markers, arrow markers, and edge overlays in stable drawing-index order.

procedure

(view3d->frame3d-spec view width height)  frame3d-spec?

  view : view3d?
  width : exact-positive-integer?
  height : exact-positive-integer?
Extracts frame-varying camera, light, and viewport state.

procedure

(view3d->render3d-request 
  view 
  width 
  height 
  [#:cancellation-token cancellation-token]) 
  render3d-request?
  view : view3d?
  width : exact-positive-integer?
  height : exact-positive-integer?
  cancellation-token : any/c = #f
Conveniently compiles view and packages the resulting compiled view and frame specification.

struct

(struct render3d-request (compiled-view
    frame-spec
    cancellation-token)
    #:transparent)
  compiled-view : compiled-view3d?
  frame-spec : frame3d-spec?
  cancellation-token : any/c
One backend-local request. The cancellation field is either #f or the preview’s cooperative cancellation token; it is not serialised into scene state.

struct

(struct renderer3d-render-result (width
    height
    argb-bytes
    diagnostics)
    #:transparent)
  width : exact-positive-integer?
  height : exact-positive-integer?
  argb-bytes : bytes?
  diagnostics : any/c
A completed backend-independent frame. Its ARGB byte vector is immutable and may outlive the backend that produced it.

procedure

(renderer3d-render-result->bitmap result)  bitmap?

  result : renderer3d-render-result?
Converts the copied ARGB frame to a Racket bitmap for the ordinary view3d Pict boundary.

Creates a stateless deterministic reference backend.

procedure

(retained-software-renderer3d [#:capacity capacity])

  renderer3d?
  capacity : exact-positive-integer? = 32
Creates a bounded, thread-safe backend that retains prepared camera-space triangles, while allocating a new colour/depth target for every render.
The bounded retained backend used by view3d’s opaque Pict adapter.

parameter

(current-view3d-renderer3d)  renderer3d?

(current-view3d-renderer3d renderer)  void?
  renderer : renderer3d?
Dynamically selects the backend used by opaque view3d rendering. The parameter affects the effectful rendering boundary only; it is not captured in semantic scene values.
Reports retained preparation hits.
Reports retained preparation misses.
Reports the current bounded cache size.

struct

(struct renderer3d-statistics (spatial-compilations
    geometry-fingerprints
    geometry-cache-hits
    geometry-cache-misses
    geometry-cache-bytes
    instance-count
    source-triangle-count
    clipped-triangle-count
    raster-triangle-count
    pixel-count
    bitmap-conversion-count
    preparation-milliseconds
    raster-milliseconds
    readback-milliseconds)
    #:transparent)
  spatial-compilations : exact-nonnegative-integer?
  geometry-fingerprints : exact-nonnegative-integer?
  geometry-cache-hits : exact-nonnegative-integer?
  geometry-cache-misses : exact-nonnegative-integer?
  geometry-cache-bytes : integer?
  instance-count : exact-nonnegative-integer?
  source-triangle-count : exact-nonnegative-integer?
  clipped-triangle-count : exact-nonnegative-integer?
  raster-triangle-count : exact-nonnegative-integer?
  pixel-count : exact-nonnegative-integer?
  bitmap-conversion-count : exact-nonnegative-integer?
  preparation-milliseconds : real?
  raster-milliseconds : real?
  readback-milliseconds : real?
An immutable snapshot of renderer-owned counters and elapsed-time observations. They are benchmark evidence, not timing assertions for CI.

procedure

(renderer3d-statistics-reset! renderer)  void?

  renderer : renderer3d?
Resets the built-in software renderer’s counters without changing semantic values.

procedure

(renderer3d-statistics-snapshot renderer)

  renderer3d-statistics?
  renderer : renderer3d?
Returns a coherent immutable metric snapshot.

18.23 Optional Racket/OpenGL backend🔗ℹ

 (require animate/3d/opengl) package: animate

SCENE-3D-P adds an explicit GPU implementation of the same renderer3d protocol. Requiring this module is the opt-in boundary for opengl and racket/gui/base; neither animate, animate/3d, nor animate/3d/render loads it. The renderer owns a hidden canvas only to obtain a context, renders each view3d to an owned RGBA8/depth framebuffer, reads it back, flips the rows, and returns the ordinary top-down straight-alpha ARGB result used by the Pict compositor.

procedure

(opengl-renderer3d-spec [#:samples samples 
  #:cache-megabytes cache-megabytes 
  #:fallback fallback]) 
  opengl-renderer3d-spec?
  samples : exact-positive-integer? = 4
  cache-megabytes : exact-positive-integer? = 512
  fallback : (or/c 'error 'software) = 'error
Declares an explicit backend configuration. 'error rejects an unavailable context. 'software is the only deliberate fallback policy and is reported in backend statistics; no request silently changes backend.

procedure

(opengl-renderer3d-spec? value)  boolean?

  value : any/c
Recognizes an OpenGL backend declaration.
Creates a retained backend with one serialized owned OpenGL context. It checks for OpenGL 3.2 and GLSL 1.50 plus VBO/EBO/VAO/FBO/depth/readback support before returning.

procedure

(opengl-renderer3d? value)  boolean?

  value : any/c
Recognizes an OpenGL renderer instance, including one whose explicit fallback is active.
Creates and closes a short lived hidden context to test availability. It is a real capability probe, not a package-presence test.

procedure

(opengl-renderer3d-info renderer)  immutable-hash?

  renderer : opengl-renderer3d?
Returns serializable GL version, GLSL version, vendor, renderer, profile, limits, required-capability, and optional-feature diagnostics.

procedure

(opengl-renderer3d-statistics renderer)  immutable-hash?

  renderer : opengl-renderer3d?
Returns backend counters plus geometry-cache and framebuffer-cache information.

procedure

(opengl-renderer3d-reset-statistics! renderer)  void?

  renderer : opengl-renderer3d?
Resets measured counters without changing cached immutable geometry.

procedure

(opengl-renderer3d-release! renderer)  void?

  renderer : opengl-renderer3d?
Deletes shader, VAO/VBO/EBO, framebuffer, and context-owner resources. It is idempotent and never changes an authored spatial value.

For final project output, use an explicit declaration:

(render-spec
 #:renderer3d
 (opengl-renderer3d-spec #:samples 4 #:cache-megabytes 512 #:fallback 'error)
 #:workers 1)

An OpenGL project must run in Racket 9.3 gracket; a plain racket process produces an actionable project diagnostic instead of selecting software implicitly. Project preview inherits this declaration and owns the retained renderer for the lifetime of its window. Camera motion changes uniforms and a viewport-size change only reallocates the FBO; neither reuploads immutable geometry.

OpenGL limitations: The first backend has one serialized context and therefore requires #:workers 1; it does not create threaded GPU workers. It uses FBO readback rather than direct OpenGL preview-canvas composition. There is no GPU picking, textures, shadows, specular/roughness lighting, persistent mapped buffers, PBO pipelining, compute/geometry shaders, or order-independent transparency. The software backend remains the portable default and conformance reference. Compare GPU/software pixels by tolerance: opaque interiors, antialiased edges, and transparent regions need different thresholds and must not be expected to be bit-identical.

The reference/retained conformance tests compare projected output at exact endpoints and in nonmonotonic camera-frame order. The canonical probe is "examples/3d/retained-renderer.rkt"; evaluating (retained-renderer-summary) there demonstrates a cache hit without changing the visible scene.

The repository tool "tools/run-3d-probes.rkt" renders the canonical visual probes for any visible stage from 3D-B through 3D-P. For example, gracket tools/run-3d-probes.rkt stage 3D-P renderer opengl output rendered-examples/3d-p-opengl writes frame PNGs plus manifest.rktd and a diagnostics.rktd file per probe. The manifest records Animate and Racket versions, renderer ID, output dimensions, sample times, sampled 3D cameras, renderer-fingerprint digests, compiled geometry keys/counts, frame hashes, and for O, compiled stroke/marker/outline counts and requested screen/world width modes. compare-renderers software,opengl writes side-by-side software and OpenGL trees, per-frame absolute-difference PNGs, and channel-difference metrics in comparison.rktd. Probe images are human review evidence; semantic and small-raster tests remain the correctness oracle. "tools/benchmark-3d.rkt" measures the same ten named workloads through either backend. Its OpenGL run reports first context/shader/allocation work separately from warm frames, plus retained geometry, framebuffer, readback, and renderer counters. It has no CI timing threshold; the acceptance checks are zero geometry uploads for warm camera/object-transform work and zero framebuffer reallocations at an unchanged viewport.

Current limitation: Screen strokes use deterministic software coverage, not analytic antialiasing. Curve centreline detail is limited by authored samples. Hidden-line classification uses opaque and 'depth-only surfaces only: transparent surfaces are not reliable hidden-line occluders. Screen points and arrowheads are camera-facing marks, not lit mesh spheres or cones. Surface topology is a fixed rectangular grid. Solid construction currently supports only simple single contours (no holes or self-intersections), and revolution accepts only nonnegative-radius profiles around a cardinal axis. There is no adaptive tessellation, trimmed domain, texture mapping, arbitrary implicit surface, or cap generation for arbitrary sliced meshes. Transparent intersections are not order-independent: triangle sorting is a useful deterministic approximation, not OIT. Section joining does not repair pathological nonmanifold meshes. Projected labels are crisp 2D overlays and may overlap; only opaque depth is considered for their hide/fade policy. Linear and affine map requests do not resample geometry; singular maps use a deterministic authored-normal shading fallback. Pointwise and homotopy maps currently accept only an unwrapped mesh3d, not curves, surfaces, or arbitrary containers. They use the source’s fixed authored vertices without adaptive remeshing, so non-injective maps can create degenerate or self-intersecting triangles. 'drop-triangle leaves open holes and does not cap or repair them; it is deliberately not the default. Turning off normal recomputation preserves source normals and can make nonlinear shading misleading. Spatial ODE fields require finite vec3 results. Vector fields and streamlines have finite explicit author samples; they do not offer adaptive field-line topology, event detection, or adaptive stopping. There is no 3D ODE source inspector. Spatial picking accelerates indexed mesh triangles (including generated tube/surface meshes) with object bounds and a local BVH, and uses the same prepared screen footprints for strokes and markers. It does not yet expose texture UVs, interpolate supplied vertex normals for a pick, support analytic implicit geometry, or perform a GPU-backed selection pass. Preview overlays and selection scratch values are diagnostic-only and are intentionally absent from normal frame/video renders. The retained software backend caches immutable geometry separately from the reference renderer’s camera-space preparations; a camera or viewport change may therefore miss that software preparation cache. The optional OpenGL backend retains immutable geometry separately and uses tolerant, not bit-exact, image comparison.