@sudobility/music_spatial_core 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './geometry';
2
2
  export * from './map-math';
3
3
  export * from './movement';
4
4
  export * from './scene';
5
+ export * from './project';
5
6
  export * from './use-throttled-commit';
6
7
  export { effectiveUnpluggedArrangement, UNPLUGGED_RADIUS, } from '@sudobility/music_types';
7
8
  export type { EffectiveUnpluggedArrangement } from '@sudobility/music_types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AAMvC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAC7E,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,wBAAwB,CAAC;AAMvC,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAC7E,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ export * from './geometry';
2
2
  export * from './map-math';
3
3
  export * from './movement';
4
4
  export * from './scene';
5
+ export * from './project';
5
6
  export * from './use-throttled-commit';
6
7
  // Re-exported for the platform packages, which already depend on
7
8
  // music_types themselves but read these through here alongside everything
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,wBAAwB,CAAC;AAEvC,iEAAiE;AACjE,0EAA0E;AAC1E,2EAA2E;AAC3E,wBAAwB;AACxB,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,wBAAwB,CAAC;AAEvC,iEAAiE;AACjE,0EAA0E;AAC1E,2EAA2E;AAC3E,wBAAwB;AACxB,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AAEjC,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC;AACzB,cAAc,UAAU,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { SpatialScene } from './scene';
2
+ export interface Viewport {
3
+ readonly width: number;
4
+ readonly height: number;
5
+ /** Vertical field of view. Default: the web canvas's 70°. */
6
+ readonly fovDeg?: number;
7
+ }
8
+ /** Flat `[x0, y0, x1, y1, ...]` pixel coordinates, one segment per four
9
+ * numbers. Flat rather than objects so a platform can hand it to a
10
+ * points-mode draw call or build a path string without a second pass. */
11
+ export type Segments = readonly number[];
12
+ export interface ProjectedInstrument {
13
+ readonly trackId: string;
14
+ readonly lit: boolean;
15
+ readonly color: string;
16
+ readonly litColor: string;
17
+ readonly segments: Segments;
18
+ /** 0 = in front of the listener, 1 = fully lost in the fog. */
19
+ readonly fade: number;
20
+ /** View-space distance, for painter's ordering (far first). */
21
+ readonly distance: number;
22
+ }
23
+ /** A batch of segments sharing one fade level, for the floor. */
24
+ export interface FadedSegments {
25
+ readonly segments: Segments;
26
+ readonly fade: number;
27
+ }
28
+ export interface ProjectedScene {
29
+ /** The floor grid's minor lines, batched by fade. */
30
+ readonly floor: readonly FadedSegments[];
31
+ /** The two centre lines of the grid, batched by fade. */
32
+ readonly floorAxes: readonly FadedSegments[];
33
+ /** The default half-circle the instruments start on. */
34
+ readonly ring: readonly FadedSegments[];
35
+ /** Far to near, so drawing in order overpaints correctly. */
36
+ readonly instruments: readonly ProjectedInstrument[];
37
+ }
38
+ /** The web canvas's stage palette, so both platforms draw the same stage. */
39
+ export declare const STAGE_PALETTE: {
40
+ readonly background: "#12161d";
41
+ readonly gridMajor: "#3a4452";
42
+ readonly gridMinor: "#232a34";
43
+ readonly ring: "#4c5a6b";
44
+ };
45
+ /** Linear fog, as the web canvas sets it: fully clear inside `near`, gone at `far`. */
46
+ export declare const FOG_NEAR = 8;
47
+ export declare const FOG_FAR = 30;
48
+ export declare const DEFAULT_FOV_DEG = 70;
49
+ /** How faded a point at `distance` from the eye is: 0 clear, 1 gone. */
50
+ export declare function fogFade(distance: number): number;
51
+ export declare function projectScene(scene: SpatialScene, viewport: Viewport): ProjectedScene;
52
+ //# sourceMappingURL=project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAqB,YAAY,EAAE,MAAM,SAAS,CAAC;AAG/D,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;0EAE0E;AAC1E,MAAM,MAAM,QAAQ,GAAG,SAAS,MAAM,EAAE,CAAC;AAEzC,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,iEAAiE;AACjE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,yDAAyD;IACzD,QAAQ,CAAC,SAAS,EAAE,SAAS,aAAa,EAAE,CAAC;IAC7C,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,SAAS,aAAa,EAAE,CAAC;IACxC,6DAA6D;IAC7D,QAAQ,CAAC,WAAW,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACtD;AAED,6EAA6E;AAC7E,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,uFAAuF;AACvF,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,OAAO,KAAK,CAAC;AAE1B,eAAO,MAAM,eAAe,KAAK,CAAC;AAYlC,wEAAwE;AACxE,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED,wBAAgB,YAAY,CAC1B,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,QAAQ,GACjB,cAAc,CAUhB"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * The 3D stage as 2D line segments: `SpatialScene` projected through its own
3
+ * camera onto a viewport, for a platform that draws lines rather than
4
+ * running a GL rasteriser.
5
+ *
6
+ * ## Why this exists
7
+ *
8
+ * Every instrument model is polylines (`InstrumentSpatialModel.strokes`),
9
+ * the floor is a grid of lines and the stage ring is a polyline, so the web
10
+ * view's three.js scene is, in the end, a few thousand line segments with a
11
+ * camera in front of them. React Native has no GL context of its own —
12
+ * `music_app_rn` is a bare app with macOS and Windows targets, where the
13
+ * one GL provider that exists (`expo-gl`) does not run — but it does have a
14
+ * 2D canvas on every platform. Projecting here, once, in pure math, and
15
+ * handing each platform "these segments, in this colour, this faded" gives
16
+ * every platform the same picture from the same scene, and leaves nothing
17
+ * platform-specific to get the camera wrong in.
18
+ *
19
+ * ## What it mirrors
20
+ *
21
+ * `buildScene` already speaks three.js: right-handed, x mirrored, camera
22
+ * looking down its local -z, `rotation` as an XYZ Euler. This module uses
23
+ * three's own `Matrix4`/`Euler` to compose the transforms so the projection
24
+ * agrees with the GL view to the last sign — re-deriving rotation matrices
25
+ * by hand would be a second, riskier way to compute the same thing (the
26
+ * same reasoning `geometry.ts` gives for not baking poses). The fog is the
27
+ * web canvas's linear fog, applied as a per-segment fade for the floor
28
+ * (whose lines run the whole depth of the stage) and per instrument
29
+ * (small enough that one distance describes it).
30
+ */
31
+ import { Euler, Matrix4, Quaternion, Vector3 } from 'three';
32
+ import { UNPLUGGED_RADIUS } from '@sudobility/music_types';
33
+ /** The web canvas's stage palette, so both platforms draw the same stage. */
34
+ export const STAGE_PALETTE = {
35
+ background: '#12161d',
36
+ gridMajor: '#3a4452',
37
+ gridMinor: '#232a34',
38
+ ring: '#4c5a6b',
39
+ };
40
+ /** Linear fog, as the web canvas sets it: fully clear inside `near`, gone at `far`. */
41
+ export const FOG_NEAR = 8;
42
+ export const FOG_FAR = 30;
43
+ export const DEFAULT_FOV_DEG = 70;
44
+ /** Anything nearer the eye than this is clipped, as the web camera's `near`. */
45
+ const NEAR_PLANE = 0.05;
46
+ /** The floor grid: `GRID_SIZE` metres square, one line per metre — the web's `gridHelper(40, 40)`. */
47
+ const GRID_SIZE = 40;
48
+ const GRID_DIVISIONS = 40;
49
+ /** How many fade levels the floor is batched into. */
50
+ const FADE_STEPS = 8;
51
+ const RING_SEGMENTS = 48;
52
+ const RING_Y = 0.005;
53
+ /** How faded a point at `distance` from the eye is: 0 clear, 1 gone. */
54
+ export function fogFade(distance) {
55
+ const t = (distance - FOG_NEAR) / (FOG_FAR - FOG_NEAR);
56
+ return t <= 0 ? 0 : t >= 1 ? 1 : t;
57
+ }
58
+ export function projectScene(scene, viewport) {
59
+ const projector = new Projector(scene, viewport);
60
+ return {
61
+ floor: projector.floor(false),
62
+ floorAxes: projector.floor(true),
63
+ ring: projector.ring(),
64
+ instruments: scene.instruments
65
+ .map(instrument => projector.instrument(instrument))
66
+ .sort((a, b) => b.distance - a.distance),
67
+ };
68
+ }
69
+ class Projector {
70
+ constructor(scene, viewport) {
71
+ Object.defineProperty(this, "view", {
72
+ enumerable: true,
73
+ configurable: true,
74
+ writable: true,
75
+ value: new Matrix4()
76
+ });
77
+ Object.defineProperty(this, "halfWidth", {
78
+ enumerable: true,
79
+ configurable: true,
80
+ writable: true,
81
+ value: void 0
82
+ });
83
+ Object.defineProperty(this, "halfHeight", {
84
+ enumerable: true,
85
+ configurable: true,
86
+ writable: true,
87
+ value: void 0
88
+ });
89
+ /** Pixels per unit of x/z over -z_view, from the field of view. */
90
+ Object.defineProperty(this, "focalY", {
91
+ enumerable: true,
92
+ configurable: true,
93
+ writable: true,
94
+ value: void 0
95
+ });
96
+ Object.defineProperty(this, "focalX", {
97
+ enumerable: true,
98
+ configurable: true,
99
+ writable: true,
100
+ value: void 0
101
+ });
102
+ Object.defineProperty(this, "eye", {
103
+ enumerable: true,
104
+ configurable: true,
105
+ writable: true,
106
+ value: void 0
107
+ });
108
+ const fov = ((viewport.fovDeg ?? DEFAULT_FOV_DEG) * Math.PI) / 180;
109
+ this.halfWidth = viewport.width / 2;
110
+ this.halfHeight = viewport.height / 2;
111
+ // A vertical field of view: the top of the view is tan(fov/2) units up
112
+ // per unit of depth, whatever the aspect, so the horizontal extent
113
+ // follows from the pixel aspect exactly as three's PerspectiveCamera.
114
+ this.focalY = this.halfHeight / Math.tan(fov / 2);
115
+ this.focalX = this.focalY;
116
+ const [cx, cy, cz] = scene.camera.position;
117
+ const [rx, ry, rz] = scene.camera.rotation;
118
+ this.eye = new Vector3(cx, cy, cz);
119
+ const cameraWorld = new Matrix4().compose(this.eye, new Quaternion().setFromEuler(new Euler(rx, ry, rz, 'XYZ')), new Vector3(1, 1, 1));
120
+ this.view.copy(cameraWorld).invert();
121
+ }
122
+ instrument(instrument) {
123
+ const [px, py, pz] = instrument.position;
124
+ const [rx, ry, rz] = instrument.rotation;
125
+ const model = new Matrix4().compose(new Vector3(px, py, pz), new Quaternion().setFromEuler(new Euler(rx, ry, rz, 'XYZ')), new Vector3(instrument.scale, instrument.scale, instrument.scale));
126
+ const modelView = new Matrix4().multiplyMatrices(this.view, model);
127
+ const segments = [];
128
+ const a = new Vector3();
129
+ const b = new Vector3();
130
+ for (const geometry of instrument.geometry) {
131
+ const positions = geometry.getAttribute('position');
132
+ for (let i = 0; i + 1 < positions.count; i += 2) {
133
+ a.fromBufferAttribute(positions, i).applyMatrix4(modelView);
134
+ b.fromBufferAttribute(positions, i + 1).applyMatrix4(modelView);
135
+ this.pushSegment(segments, a, b);
136
+ }
137
+ }
138
+ const distance = this.eye.distanceTo(new Vector3(px, py, pz));
139
+ return {
140
+ trackId: instrument.trackId,
141
+ lit: instrument.lit,
142
+ color: instrument.color,
143
+ litColor: instrument.litColor,
144
+ segments,
145
+ fade: fogFade(distance),
146
+ distance,
147
+ };
148
+ }
149
+ /** The grid, one metre a segment so the fog can vary along a line. */
150
+ floor(axesOnly) {
151
+ const half = GRID_SIZE / 2;
152
+ const step = GRID_SIZE / GRID_DIVISIONS;
153
+ const buckets = new FadeBuckets();
154
+ const a = new Vector3();
155
+ const b = new Vector3();
156
+ for (let i = 0; i <= GRID_DIVISIONS; i++) {
157
+ const k = -half + i * step;
158
+ const isAxis = k === 0;
159
+ if (isAxis !== axesOnly)
160
+ continue;
161
+ for (let j = 0; j < GRID_DIVISIONS; j++) {
162
+ const s = -half + j * step;
163
+ // A line along z at x = k, then along x at z = k.
164
+ a.set(k, 0, s);
165
+ b.set(k, 0, s + step);
166
+ this.pushWorldSegment(buckets, a, b);
167
+ a.set(s, 0, k);
168
+ b.set(s + step, 0, k);
169
+ this.pushWorldSegment(buckets, a, b);
170
+ }
171
+ }
172
+ return buckets.batches();
173
+ }
174
+ ring() {
175
+ const buckets = new FadeBuckets();
176
+ const a = new Vector3();
177
+ const b = new Vector3();
178
+ for (let i = 0; i < RING_SEGMENTS; i++) {
179
+ const a0 = (Math.PI * i) / RING_SEGMENTS;
180
+ const a1 = (Math.PI * (i + 1)) / RING_SEGMENTS;
181
+ a.set(Math.cos(a0) * UNPLUGGED_RADIUS, RING_Y, Math.sin(a0) * UNPLUGGED_RADIUS);
182
+ b.set(Math.cos(a1) * UNPLUGGED_RADIUS, RING_Y, Math.sin(a1) * UNPLUGGED_RADIUS);
183
+ this.pushWorldSegment(buckets, a, b);
184
+ }
185
+ return buckets.batches();
186
+ }
187
+ pushWorldSegment(buckets, a, b) {
188
+ const fade = fogFade(this.eye.distanceTo(new Vector3((a.x + b.x) / 2, (a.y + b.y) / 2, (a.z + b.z) / 2)));
189
+ if (fade >= 1)
190
+ return;
191
+ a.applyMatrix4(this.view);
192
+ b.applyMatrix4(this.view);
193
+ this.pushSegment(buckets.for(fade), a, b);
194
+ }
195
+ /**
196
+ * One view-space segment to pixels, clipped to the near plane: a segment
197
+ * crossing it is cut at the plane rather than dropped, so a floor line
198
+ * running under the listener's feet still reaches the bottom of the view,
199
+ * and one wholly behind the eye is not drawn at all — projecting a point
200
+ * behind the camera flips it through the origin, which is the scribble a
201
+ * naive projector draws when the listener stands inside the stage.
202
+ */
203
+ pushSegment(out, a, b) {
204
+ // View space looks down -z; "in front" is z < -NEAR_PLANE.
205
+ const aIn = a.z < -NEAR_PLANE;
206
+ const bIn = b.z < -NEAR_PLANE;
207
+ if (!aIn && !bIn)
208
+ return;
209
+ if (!aIn || !bIn) {
210
+ const t = (-NEAR_PLANE - a.z) / (b.z - a.z);
211
+ const cx = a.x + (b.x - a.x) * t;
212
+ const cy = a.y + (b.y - a.y) * t;
213
+ if (aIn)
214
+ b.set(cx, cy, -NEAR_PLANE);
215
+ else
216
+ a.set(cx, cy, -NEAR_PLANE);
217
+ }
218
+ out.push(this.halfWidth + (a.x / -a.z) * this.focalX, this.halfHeight - (a.y / -a.z) * this.focalY, this.halfWidth + (b.x / -b.z) * this.focalX, this.halfHeight - (b.y / -b.z) * this.focalY);
219
+ }
220
+ }
221
+ /** Segments grouped into `FADE_STEPS` fade levels, so a platform draws the
222
+ * floor in a handful of calls rather than one per segment. */
223
+ class FadeBuckets {
224
+ constructor() {
225
+ Object.defineProperty(this, "buckets", {
226
+ enumerable: true,
227
+ configurable: true,
228
+ writable: true,
229
+ value: new Map()
230
+ });
231
+ }
232
+ for(fade) {
233
+ const level = Math.min(FADE_STEPS - 1, Math.floor(fade * FADE_STEPS));
234
+ let bucket = this.buckets.get(level);
235
+ if (!bucket) {
236
+ bucket = [];
237
+ this.buckets.set(level, bucket);
238
+ }
239
+ return bucket;
240
+ }
241
+ batches() {
242
+ return [...this.buckets.entries()]
243
+ .sort((x, y) => y[0] - x[0])
244
+ .map(([level, segments]) => ({
245
+ segments,
246
+ fade: (level + 0.5) / FADE_STEPS,
247
+ }));
248
+ }
249
+ }
250
+ //# sourceMappingURL=project.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/music_spatial_core",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "description": "Platform-agnostic engine behind the Moosiac Spatial view: instrument geometry, scene composition, camera/listener math, movement, and map-overlay math shared by music_spatial and music_spatial_rn.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,13 +31,13 @@
31
31
  },
32
32
  "dependencies": {},
33
33
  "peerDependencies": {
34
- "@sudobility/music_types": "^0.13.39",
34
+ "@sudobility/music_types": "^0.13.40",
35
35
  "react": ">=18",
36
36
  "three": "^0.160.0"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@eslint/js": "^9.38.0",
40
- "@sudobility/music_types": "^0.13.39",
40
+ "@sudobility/music_types": "^0.13.40",
41
41
  "@testing-library/react": "^16.0.0",
42
42
  "@types/react": "^19.2.18",
43
43
  "@types/react-dom": "^19.2.0",