Ollin

SceneViews

The host's Camera menu snaps an auto-orbiting scene to the standard inspection views (Front/Back/Left/Right/Top/Bottom/Isometric and Reset, ⌘0–⌘7), the way a modeling tool's numpad does.

Run
swift run --package-path Examples Example-3D-Camera-SceneViews
Source
Examples/3D/Camera/SceneViews/Sketch.swift
import Ollin

/// Scene inspection views: snap the camera to a known angle while building a scene.
///
/// The camera auto-orbits (and you can grab it with a drag), but the host's
/// **Camera menu** jumps it to a canonical view, the way a modeling tool's numpad
/// does: Reset (⌘0) returns to the opening framing, Front/Back/Left/Right/Top/
/// Bottom (⌘1–⌘6) look straight down each axis, and Isometric (⌘7) is the
/// three-quarter that shows all three axes at once. Each snap glides via the camera
/// rig, then hands back to the orbit.
///
/// The scene is three colored axis rods (X red, Y green, Z blue) around a neutral
/// block, so every view is unambiguous: Front looks down +Z (the blue rod points at
/// you), Right looks down +X (red), Top looks down from +Y (green).
@main
final class SceneViews: Sketch {

    override func draw() {
        background(Color(white: 0.11))
        cameraShowcase(.autoOrbit(period: 32), target: .zero, radius: 9,
                       elevation: 0.35, fieldOfView: .pi / 4)
        cameraAxis()        // the orientation widget: click an axis to snap the view
        groundGrid()        // a faint reference floor at y = 0

        lightingPreset(.threePoint)
        castShadows()

        // The floor that catches the shadows.
        withState {
            translate(0, -2.2, 0)
            fill(Color(white: 0.5)); specular(0.05)
            drawPlane(width: 16, depth: 16)
        }

        // A neutral block at the center, taller than wide so its own orientation
        // reads too.
        withState {
            fill(Color(white: 0.82)); specular(0.2)
            drawBox(width: 1.6, height: 2.2, depth: 1.1)
        }

        // The three positive axes as colored rods with a sphere cap, the universal
        // X-red / Y-green / Z-blue convention.
        axisRod(.x, .red)
        axisRod(.y, .green)
        axisRod(.z, .blue)

        // Top edge so it clears the orientation axis widget parked at bottom-center.
        drawCaption("Camera menu: Reset · Front · Back · Left · Right · Top · " +
                    "Bottom · Isometric    (or drag to orbit)", edge: .top)
    }

    private enum Axis { case x, y, z }

    /// Draw a rod of `length` from the origin along the positive `axis`, capped with
    /// a small sphere, in `color`.
    private func axisRod(_ axis: Axis, _ color: Color) {
        let length = 3.4
        let thick = 0.12
        let mid = length / 2
        withState {
            fill(color); specular(0.4)
            switch axis {
            case .x:
                withState { translate(mid, 0, 0); drawBox(width: length, height: thick, depth: thick) }
                withState { translate(length, 0, 0); drawSphere(radius: 0.26) }
            case .y:
                withState { translate(0, mid, 0); drawBox(width: thick, height: length, depth: thick) }
                withState { translate(0, length, 0); drawSphere(radius: 0.26) }
            case .z:
                withState { translate(0, 0, mid); drawBox(width: thick, height: thick, depth: length) }
                withState { translate(0, 0, length); drawSphere(radius: 0.26) }
            }
        }
    }
}

↑↓ move ↩ open