‹ projects

reverb-m1

Native wired VR on Apple silicon: Reverb G1 display bring-up and stereo demo
git clone https://umhau.org/code/reverb-m1.git
Log | Files | Refs

Scene.swift (3505B)


      1 // Demo scene: a spinning cube at 1.5 m, a ground grid, and reference pillars at several depths.
      2 import simd
      3 
      4 /// A run of vertices in the shared scene buffer, drawn with one model matrix.
      5 struct SceneItem { var first: Int; var count: Int; var model: simd_float4x4; var spins = false; var floorGrid = false }
      6 
      7 /// Eye height above the floor in metres (the head sits at the origin, -Y is down).
      8 let floorY: Float = -1.4
      9 
     10 enum Scene {
     11     /// Axis-aligned box centred at `c` with full size `s`, as 12 triangles. Nil colour = per-face colours.
     12     static func box(center c: SIMD3<Float>, size s: SIMD3<Float>, color: SIMD3<Float>? = nil) -> [Vertex] {
     13         let faces: [(n: SIMD3<Float>, u: SIMD3<Float>, v: SIMD3<Float>, c: SIMD3<Float>)] = [
     14             ([1, 0, 0], [0, 0, -1], [0, 1, 0], [0.95, 0.30, 0.25]),
     15             ([-1, 0, 0], [0, 0, 1], [0, 1, 0], [0.25, 0.80, 0.95]),
     16             ([0, 1, 0], [1, 0, 0], [0, 0, -1], [0.40, 0.90, 0.35]),
     17             ([0, -1, 0], [1, 0, 0], [0, 0, 1], [0.95, 0.85, 0.30]),
     18             ([0, 0, 1], [1, 0, 0], [0, 1, 0], [0.75, 0.40, 0.95]),
     19             ([0, 0, -1], [-1, 0, 0], [0, 1, 0], [0.95, 0.60, 0.20]),
     20         ]
     21         var out: [Vertex] = []
     22         for f in faces {
     23             let ctr = c + f.n * s * 0.5
     24             let du = f.u * s * 0.5, dv = f.v * s * 0.5
     25             let p: [SIMD3<Float>] = [ctr - du - dv, ctr + du - dv, ctr + du + dv, ctr - du + dv]
     26             for i in [0, 1, 2, 0, 2, 3] { out.append(Vertex(pos: p[i], normal: f.n, color: color ?? f.c)) }
     27         }
     28         return out
     29     }
     30 
     31     /// Builds the whole scene: one vertex array plus the items that index into it.
     32     static func make() -> (vertices: [Vertex], items: [SceneItem]) {
     33         var verts: [Vertex] = [], items: [SceneItem] = []
     34         func add(_ v: [Vertex], _ model: simd_float4x4 = matrix_identity_float4x4, spins: Bool = false, floorGrid: Bool = false) {
     35             items.append(SceneItem(first: verts.count, count: v.count, model: model, spins: spins, floorGrid: floorGrid))
     36             verts += v
     37         }
     38         // Hero cube: unit cube scaled to 0.4 m, 1.5 m ahead at eye level, spun by the renderer.
     39         add(box(center: .zero, size: [1, 1, 1]), translation([0, 0, -1.5]) * scale(0.4), spins: true)
     40 
     41         // One floor surface; the fragment shader draws a pixel-filtered metric grid.
     42         // Thin geometry otherwise compresses the transverse lines below one panel pixel at distance.
     43         add(box(center: [0, floorY - 0.01, -20], size: [60, 0.02, 60], color: [0.10, 0.11, 0.15]), floorGrid: true)
     44 
     45         // Reference pillars at increasing depth, alternating sides, in distinct colours.
     46         let pillars: [(x: Float, z: Float, c: SIMD3<Float>)] = [
     47             (-0.5, -0.7, [0.95, 0.35, 0.35]), (0.9, -2.5, [0.35, 0.85, 0.45]),
     48             (-1.6, -4.0, [0.40, 0.55, 0.95]), (2.2, -6.0, [0.95, 0.80, 0.30]),
     49             (-3.0, -9.0, [0.85, 0.40, 0.90]), (4.0, -14.0, [0.30, 0.85, 0.85]),
     50         ]
     51         for p in pillars {
     52             let h: Float = 1.0   // 1 m tall pillars standing on the floor
     53             add(box(center: [p.x, floorY + h / 2, p.z], size: [0.25, h, 0.25], color: p.c))
     54         }
     55         // Small cubes floating at head height, near and far, to compare parallax at the same height.
     56         add(box(center: [0.35, 0.1, -0.5], size: [0.08, 0.08, 0.08]))
     57         add(box(center: [-1.2, 0.1, -3.0], size: [0.3, 0.3, 0.3]))
     58         add(box(center: [1.8, 0.1, -8.0], size: [0.8, 0.8, 0.8]))
     59         return (verts, items)
     60     }
     61 }