Add SAB-backed rotor transforms and smooth camera controls

Amp-Thread-ID: https://ampcode.com/threads/T-01a01ff8-b91f-724f-8952-f07c6b5042fd
Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-08-21 05:30:09 +00:00
co-authored by heaust
parent 0e6d7e367c
commit 9ca12c237e
17 changed files with 411 additions and 141 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ follow.stop();
follow.start();
```
The input and follow loops never post camera updates to core: they mutate the position, quaternion, camera, and derived matrix rows directly in shared memory.
The input and follow loops never post camera updates to core: they mutate the position, rotor, camera, and derived matrix rows directly in shared memory.
<Playground example="cameras" />
+2 -2
View File
@@ -8,7 +8,7 @@ The shared importer worker fetches and parses glTF/GLB, then the response hydrat
import { importGltf } from "@yawn/handles";
const meshes = await importGltf(scene, "/models/sponza.glb");
meshes[0].position[1] = 0.5;
meshes[0].position.y = 0.5;
```
The importer handles triangle primitives, external/data buffers, standard vertex attributes, indices, node transforms, and metallic-roughness values. Application-specific extensions remain application policy.
@@ -34,7 +34,7 @@ If row allocations relocated since `Picking` was created, refresh its shared des
await picking.refresh();
```
The playground below imports the repository's full LFS-backed `sponza.glb` in the importer worker, preserves its authored transforms, places an arc camera in its coordinate system, and sends a real ray to the BVH worker. Click the preview to pick again.
The playground below imports the repository's full LFS-backed `sponza.glb` in the importer worker, preserves its authored transforms, adds neutral warm lighting, places an arc camera in its coordinate system, and sends a real ray to the BVH worker. Click the preview to pick again.
<Playground example="importing" />
+1 -1
View File
@@ -11,7 +11,7 @@ const point = new PointLight(scene, {
});
const sun = new DirectionalLight(scene, {
quaternion: [0.2, 0, 0, 0.98],
rotor: [0.2, 0, 0, 0.98],
color: [1, 0.95, 0.8],
intensity: 3,
});
+4 -4
View File
@@ -1,6 +1,6 @@
# Scene and shared data
Think of every handle as an array index, not an object mirrored into core. `Node.position`, `Node.quaternion`, and `Node.scale` are views into separate flat SOA arrays.
Think of every handle as an array index, not an object mirrored into core. `Node.position`, `Node.rotor`, and `Node.scale` are component views into separate flat SOA arrays.
## Direct transform movement
@@ -11,12 +11,12 @@ const pivot = new Node(scene, { position: [0, 1, 0] });
await pivot.ready;
canvas.addEventListener("pointermove", (event) => {
pivot.position[0] += event.movementX * 0.002;
pivot.position[1] -= event.movementY * 0.002;
pivot.position.x += event.movementX * 0.002;
pivot.position.y -= event.movementY * 0.002;
});
```
The pointer handler sends no messages. The typed-array view points directly into the arena shared with the render worker. The camera helpers use this same pattern; see [Cameras and controls](/guide/cameras).
The pointer handler sends no messages. Each component property reads or writes its lane in the arena shared with the render worker. Replace complete transforms with `setPosition([x, y, z])`, `setRotor([x, y, z, w])`, and `setScale([x, y, z])`. `translate(...)`, `rotate(...)`, and `rotateX/Y/Z(...)` are convenience methods over those same SAB lanes. The camera helpers use this same pattern; see [Cameras and controls](/guide/cameras).
<Playground example="sab" />