human2ai 0.1.3 → 0.1.4

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.
Files changed (150) hide show
  1. package/README.en.md +36 -4
  2. package/README.md +36 -4
  3. package/dist/cli/main.js +26 -0
  4. package/dist/cli/main.js.map +1 -1
  5. package/dist/database/style-library-repository.d.ts +14 -1
  6. package/dist/database/style-library-repository.js +59 -0
  7. package/dist/database/style-library-repository.js.map +1 -1
  8. package/dist/domain/composition/analysis.d.ts +3 -0
  9. package/dist/domain/composition/analysis.js +4 -0
  10. package/dist/domain/composition/analysis.js.map +1 -1
  11. package/dist/domain/composition/draft.d.ts +1 -0
  12. package/dist/domain/composition/draft.js +73 -2
  13. package/dist/domain/composition/draft.js.map +1 -1
  14. package/dist/domain/composition/frame.d.ts +1 -0
  15. package/dist/domain/composition/frame.js +6 -0
  16. package/dist/domain/composition/frame.js.map +1 -1
  17. package/dist/domain/composition/index.d.ts +4 -1
  18. package/dist/domain/composition/index.js +4 -1
  19. package/dist/domain/composition/index.js.map +1 -1
  20. package/dist/domain/composition/planning-intersections.d.ts +20 -0
  21. package/dist/domain/composition/planning-intersections.js +119 -0
  22. package/dist/domain/composition/planning-intersections.js.map +1 -0
  23. package/dist/domain/composition/planning.d.ts +25 -0
  24. package/dist/domain/composition/planning.js +152 -0
  25. package/dist/domain/composition/planning.js.map +1 -0
  26. package/dist/domain/composition/render.js +8 -0
  27. package/dist/domain/composition/render.js.map +1 -1
  28. package/dist/domain/composition/states.js +4 -1
  29. package/dist/domain/composition/states.js.map +1 -1
  30. package/dist/domain/composition/types.d.ts +46 -0
  31. package/dist/domain/spatial/camera-render-key.d.ts +7 -0
  32. package/dist/domain/spatial/camera-render-key.js +63 -0
  33. package/dist/domain/spatial/camera-render-key.js.map +1 -0
  34. package/dist/domain/spatial/lighting.js +3 -2
  35. package/dist/domain/spatial/lighting.js.map +1 -1
  36. package/dist/domain/spatial/model.d.ts +2 -0
  37. package/dist/domain/spatial/model.js +82 -27
  38. package/dist/domain/spatial/model.js.map +1 -1
  39. package/dist/domain/spatial/preview.d.ts +4 -0
  40. package/dist/domain/spatial/preview.js +23 -0
  41. package/dist/domain/spatial/preview.js.map +1 -0
  42. package/dist/domain/spatial/reference-lines.d.ts +12 -3
  43. package/dist/domain/spatial/reference-lines.js +37 -16
  44. package/dist/domain/spatial/reference-lines.js.map +1 -1
  45. package/dist/domain/spatial/render-inputs.d.ts +1 -1
  46. package/dist/domain/spatial/render-inputs.js +10 -2
  47. package/dist/domain/spatial/render-inputs.js.map +1 -1
  48. package/dist/domain/spatial/scene-cache.d.ts +13 -1
  49. package/dist/domain/spatial/scene-cache.js +88 -10
  50. package/dist/domain/spatial/scene-cache.js.map +1 -1
  51. package/dist/domain/spatial/scene-update.d.ts +6 -0
  52. package/dist/domain/spatial/scene-update.js +52 -0
  53. package/dist/domain/spatial/scene-update.js.map +1 -0
  54. package/dist/domain/spatial/scene.d.ts +3 -1
  55. package/dist/domain/spatial/scene.js +78 -20
  56. package/dist/domain/spatial/scene.js.map +1 -1
  57. package/dist/domain/style/model-input.d.ts +3 -0
  58. package/dist/domain/style/model-input.js +36 -0
  59. package/dist/domain/style/model-input.js.map +1 -0
  60. package/dist/domain/style/types.d.ts +7 -0
  61. package/dist/server/routes/spatial-sessions.js +28 -12
  62. package/dist/server/routes/spatial-sessions.js.map +1 -1
  63. package/dist/server/routes/style-library.js +39 -0
  64. package/dist/server/routes/style-library.js.map +1 -1
  65. package/dist/server/spatial-render-service.d.ts +21 -0
  66. package/dist/server/spatial-render-service.js +67 -0
  67. package/dist/server/spatial-render-service.js.map +1 -0
  68. package/dist/server/spatial-render-worker.d.ts +1 -0
  69. package/dist/server/spatial-render-worker.js +15 -0
  70. package/dist/server/spatial-render-worker.js.map +1 -0
  71. package/dist/server/spatial-render.d.ts +14 -2
  72. package/dist/server/spatial-render.js +38 -7
  73. package/dist/server/spatial-render.js.map +1 -1
  74. package/locales/en/common.json +60 -4
  75. package/migrations/0010_style_preview_models.sql +8 -0
  76. package/package.json +1 -1
  77. package/schemas/composition-draft.schema.json +457 -0
  78. package/skills/human2ai/SKILL.md +12 -4
  79. package/skills/human2ai/references/composition.md +192 -1
  80. package/skills/human2ai/references/spatial-modeling.md +20 -0
  81. package/web/out/404/index.html +1 -1
  82. package/web/out/404.html +1 -1
  83. package/web/out/__next.__PAGE__.txt +6 -6
  84. package/web/out/__next._full.txt +6 -6
  85. package/web/out/__next._tree.txt +3 -3
  86. package/web/out/_next/static/chunks/101.6ef34adad3e9815b.js +1 -0
  87. package/web/out/_next/static/chunks/130-7e9e715a084569bb.js +1 -0
  88. package/web/out/_next/static/chunks/166-96a8c6ae1e9aed59.js +1 -0
  89. package/web/out/_next/static/chunks/218.7b89674409b344b8.js +1 -0
  90. package/web/out/_next/static/chunks/484.92b016222d6749f2.js +1 -0
  91. package/web/out/_next/static/chunks/{773-24ba65074da7fa71.js → 635-611c009924b842be.js} +50 -50
  92. package/web/out/_next/static/chunks/653-6dfb97fec9a2d91b.js +1 -0
  93. package/web/out/_next/static/chunks/678-32d3aa1859450d63.js +1 -0
  94. package/web/out/_next/static/chunks/83607670-fd2f339702a222e4.js +1 -0
  95. package/web/out/_next/static/chunks/app/_not-found/page-b92817fdc4609975.js +1 -0
  96. package/web/out/_next/static/chunks/app/composition/page-6c12ee8472715448.js +1 -0
  97. package/web/out/_next/static/chunks/app/{layout-3b5f82ced220ef42.js → layout-1dd9196cde94389c.js} +1 -1
  98. package/web/out/_next/static/chunks/app/{page-d41d1cdb1d6ed018.js → page-741ecaf9ee8c3c07.js} +1 -1
  99. package/web/out/_next/static/chunks/app/spatial/page-5ba0940650df6c7f.js +1 -0
  100. package/web/out/_next/static/chunks/app/styles/page-1ccfc2c5fbc1e646.js +1 -0
  101. package/web/out/_next/static/chunks/app/ui-sketch/page-ef4f2e531583e684.js +1 -0
  102. package/web/out/_next/static/chunks/{c3f2cda1-9e279dab137b7272.js → c3f2cda1-ef85a0897724e46b.js} +1 -1
  103. package/web/out/_next/static/chunks/{main-app-ec9e35d71481270a.js → main-app-cf37a257d91ce62e.js} +1 -1
  104. package/web/out/_next/static/chunks/next/dist/client/components/builtin/global-error-33b4f58f02e82215.js +1 -0
  105. package/web/out/_next/static/chunks/webpack-d16ce1f994e98178.js +1 -0
  106. package/web/out/_next/static/css/06743b5635914999.css +5 -0
  107. package/web/out/_next/static/css/0b43ff4a0439c97e.css +1 -0
  108. package/web/out/_next/static/css/39e8cace36461a15.css +1 -0
  109. package/web/out/_not-found/__next._full.txt +3 -3
  110. package/web/out/_not-found/__next._not-found.__PAGE__.txt +3 -3
  111. package/web/out/_not-found/__next._tree.txt +1 -1
  112. package/web/out/_not-found/index.html +1 -1
  113. package/web/out/_not-found/index.txt +3 -3
  114. package/web/out/composition/__next._full.txt +6 -6
  115. package/web/out/composition/__next._tree.txt +3 -3
  116. package/web/out/composition/__next.composition.__PAGE__.txt +6 -6
  117. package/web/out/composition/index.html +1 -1
  118. package/web/out/composition/index.txt +6 -6
  119. package/web/out/index.html +1 -1
  120. package/web/out/index.txt +6 -6
  121. package/web/out/spatial/__next._full.txt +6 -6
  122. package/web/out/spatial/__next._tree.txt +3 -3
  123. package/web/out/spatial/__next.spatial.__PAGE__.txt +6 -6
  124. package/web/out/spatial/index.html +1 -1
  125. package/web/out/spatial/index.txt +6 -6
  126. package/web/out/styles/__next._full.txt +6 -6
  127. package/web/out/styles/__next._tree.txt +3 -3
  128. package/web/out/styles/__next.styles.__PAGE__.txt +6 -6
  129. package/web/out/styles/index.html +1 -1
  130. package/web/out/styles/index.txt +6 -6
  131. package/web/out/ui-sketch/__next._full.txt +6 -6
  132. package/web/out/ui-sketch/__next._tree.txt +3 -3
  133. package/web/out/ui-sketch/__next.ui-sketch.__PAGE__.txt +6 -6
  134. package/web/out/ui-sketch/index.html +1 -1
  135. package/web/out/ui-sketch/index.txt +6 -6
  136. package/web/out/_next/static/chunks/130-027b022c82d30077.js +0 -1
  137. package/web/out/_next/static/chunks/678-6f33e7277564a5df.js +0 -1
  138. package/web/out/_next/static/chunks/728-7597352c3a7eeaf9.js +0 -1
  139. package/web/out/_next/static/chunks/83607670-bc1279370476e59f.js +0 -1
  140. package/web/out/_next/static/chunks/app/_not-found/page-58bf95050b473956.js +0 -1
  141. package/web/out/_next/static/chunks/app/composition/page-30184e9c21352991.js +0 -1
  142. package/web/out/_next/static/chunks/app/spatial/page-fc3c66e1f94ed210.js +0 -1
  143. package/web/out/_next/static/chunks/app/styles/page-194a16109270e08d.js +0 -1
  144. package/web/out/_next/static/chunks/app/ui-sketch/page-c28eeab67fea766e.js +0 -1
  145. package/web/out/_next/static/chunks/next/dist/client/components/builtin/global-error-f62e60e5a6e74304.js +0 -1
  146. package/web/out/_next/static/chunks/webpack-fdd377b620f7ea99.js +0 -1
  147. package/web/out/_next/static/css/2ed56cbf8f662d23.css +0 -5
  148. package/web/out/_next/static/css/96839f63fcc5e50d.css +0 -1
  149. /package/web/out/_next/static/{Wakl9xK54qWYuP4Hpi0W9 → n4UcxqMmr_2CBmSxBp52z}/_buildManifest.js +0 -0
  150. /package/web/out/_next/static/{Wakl9xK54qWYuP4Hpi0W9 → n4UcxqMmr_2CBmSxBp52z}/_ssgManifest.js +0 -0
@@ -1,6 +1,14 @@
1
1
  import { canonicalJson } from "../fingerprint.js";
2
+ const keys = new WeakMap();
2
3
  /** Authored names and instructions do not alter spatial geometry or camera output. */
3
- export function spatialEntityRenderKey({ name: _name, note: _note, ...data }) {
4
- return canonicalJson(data);
4
+ export function spatialEntityRenderKey(entity) {
5
+ const { name: _name, note: _note, ...data } = entity;
6
+ // A cheap snapshot also detects in-place edits; reference identity alone is unsafe.
7
+ const raw = JSON.stringify(data), previous = keys.get(entity);
8
+ if (previous?.raw === raw)
9
+ return previous.key;
10
+ const key = canonicalJson(data);
11
+ keys.set(entity, { raw, key });
12
+ return key;
5
13
  }
6
14
  //# sourceMappingURL=render-inputs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-inputs.js","sourceRoot":"","sources":["../../../src/domain/spatial/render-inputs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,sFAAsF;AACtF,MAAM,UAAU,sBAAsB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAoC;IAC5G,OAAO,aAAa,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
1
+ {"version":3,"file":"render-inputs.js","sourceRoot":"","sources":["../../../src/domain/spatial/render-inputs.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,MAAM,IAAI,GAAG,IAAI,OAAO,EAAkE,CAAC;AAE3F,sFAAsF;AACtF,MAAM,UAAU,sBAAsB,CAAC,MAAwC;IAC7E,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC;IACrD,oFAAoF;IACpF,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9D,IAAI,QAAQ,EAAE,GAAG,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC;IAC/C,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/B,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -1,15 +1,27 @@
1
- import { Group } from "three";
1
+ import { Color, Group, Mesh } from "three";
2
2
  import type { SpatialDraft } from "./types.ts";
3
+ interface SceneCacheOptions {
4
+ shade?(draft: SpatialDraft): Promise<Float32Array[]>;
5
+ onShaded?(): void;
6
+ }
3
7
  /** Editor-owned meshes; deterministic exports continue to use createSpatialScene. */
4
8
  export declare class SpatialSceneCache {
9
+ private options;
5
10
  readonly scene: Group<import("three").Object3DEventMap>;
6
11
  private entries;
12
+ readonly baseColors: WeakMap<Mesh<import("three").BufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>, import("three").Material<import("three").MaterialEventMap> | import("three").Material<import("three").MaterialEventMap>[], import("three").Object3DEventMap>, Color>;
7
13
  private shadedKey?;
8
14
  private shadedTopology?;
9
15
  private colors?;
16
+ private desired?;
17
+ private shading;
18
+ private disposed;
19
+ constructor(options?: SceneCacheOptions);
10
20
  update(draft: SpatialDraft, options?: {
11
21
  showRig?: boolean;
12
22
  dragging?: boolean;
13
23
  }): boolean;
24
+ private scheduleShading;
14
25
  dispose(): void;
15
26
  }
27
+ export {};
@@ -1,14 +1,24 @@
1
1
  import { Group } from "three";
2
- import { createSpatialScene, disposeSpatialScene } from "./scene.js";
2
+ import { createSpatialScene, disposeSpatialScene, updateSpatialRig } from "./scene.js";
3
3
  import { applySpatialContactShading, spatialSurfaces } from "./lighting.js";
4
4
  import { spatialEntityRenderKey } from "./render-inputs.js";
5
+ import { entityMatrix, rememberSpatialColors, updateSpatialGeometry } from "./scene-update.js";
6
+ import { updateCharacterModel } from "./model.js";
5
7
  /** Editor-owned meshes; deterministic exports continue to use createSpatialScene. */
6
8
  export class SpatialSceneCache {
9
+ options;
7
10
  scene = new Group();
8
11
  entries = new Map();
12
+ baseColors = new WeakMap();
9
13
  shadedKey;
10
14
  shadedTopology;
11
15
  colors;
16
+ desired;
17
+ shading = false;
18
+ disposed = false;
19
+ constructor(options = {}) {
20
+ this.options = options;
21
+ }
12
22
  update(draft, options = {}) {
13
23
  const next = new Map();
14
24
  let changed = false;
@@ -16,14 +26,49 @@ export class SpatialSceneCache {
16
26
  const key = JSON.stringify([spatialEntityRenderKey(entity), Boolean(options.showRig)]);
17
27
  let entry = this.entries.get(entity.id);
18
28
  if (entry?.key !== key) {
19
- if (entry) {
20
- this.scene.remove(entry.group);
21
- disposeSpatialScene(entry.group);
29
+ const shapeKey = JSON.stringify([spatialEntityRenderKey({ ...entity, position: [0, 0, 0], rotation: [0, 0, 0] }), Boolean(options.showRig)]);
30
+ if (entry?.shapeKey === shapeKey) {
31
+ entry.group.matrixAutoUpdate = false;
32
+ entry.group.matrix.copy(entityMatrix(entity).multiply(entry.origin));
33
+ entry.group.matrixWorldNeedsUpdate = true;
34
+ entry.key = key;
35
+ }
36
+ else {
37
+ const part = "bones" in entity
38
+ ? { ...draft, characters: [entity], objects: [] }
39
+ : { ...draft, characters: [], objects: [entity] };
40
+ const rig = entry?.group.children.filter(object => object.userData.rig) ?? [];
41
+ if (rig.length)
42
+ entry.group.remove(...rig);
43
+ const model = entry?.group.children[0];
44
+ if (entry && "bones" in entity && model instanceof Group && updateCharacterModel(model, entity)) {
45
+ entry.group.matrixAutoUpdate = true;
46
+ entry.group.matrix.identity();
47
+ entry = { key, shapeKey, group: entry.group, origin: entityMatrix(entity).invert() };
48
+ }
49
+ else {
50
+ const fresh = createSpatialScene(part);
51
+ if (entry && updateSpatialGeometry(entry.group, fresh)) {
52
+ disposeSpatialScene(fresh);
53
+ entry = { key, shapeKey, group: entry.group, origin: entityMatrix(entity).invert() };
54
+ }
55
+ else {
56
+ if (entry) {
57
+ this.scene.remove(entry.group);
58
+ disposeSpatialScene(entry.group);
59
+ }
60
+ entry = { key, shapeKey, group: fresh, origin: entityMatrix(entity).invert() };
61
+ }
62
+ }
63
+ if ("bones" in entity && options.showRig && entity.appearance !== "geometric") {
64
+ if (rig.length)
65
+ entry.group.add(...rig);
66
+ updateSpatialRig(entry.group, entity, true);
67
+ }
68
+ else if (rig.length)
69
+ disposeSpatialScene(new Group().add(...rig));
70
+ rememberSpatialColors(entry.group, this.baseColors);
22
71
  }
23
- const part = "bones" in entity
24
- ? { ...draft, characters: [entity], objects: [] }
25
- : { ...draft, characters: [], objects: [entity] };
26
- entry = { key, group: createSpatialScene(part, options) };
27
72
  changed = true;
28
73
  }
29
74
  next.set(entity.id, entry);
@@ -45,10 +90,22 @@ export class SpatialSceneCache {
45
90
  if (changed)
46
91
  this.scene.updateMatrixWorld(true);
47
92
  // Cameras, selection, helpers and light switches do not affect contact rays.
48
- const surfaceKey = JSON.stringify([draft.characters.map(spatialEntityRenderKey), draft.objects.map(spatialEntityRenderKey)]);
93
+ const surfaceKey = JSON.stringify([...next.values()].map(entry => entry.key));
49
94
  const meshes = spatialSurfaces(this.scene);
50
95
  const topology = meshes.map(mesh => JSON.stringify([mesh.userData, mesh.geometry.getAttribute("position").count])).join("/");
51
- if (!this.colors || topology !== this.shadedTopology || (!options.dragging && surfaceKey !== this.shadedKey)) {
96
+ const needsShading = !this.colors || topology !== this.shadedTopology || surfaceKey !== this.shadedKey;
97
+ this.desired = !options.dragging && needsShading ? { draft, key: surfaceKey, topology } : undefined;
98
+ if (this.options.shade) {
99
+ if (!this.colors || topology !== this.shadedTopology) {
100
+ this.colors = meshes.map(mesh => new Float32Array(mesh.geometry.getAttribute("position").count * 3).fill(1));
101
+ this.shadedTopology = topology;
102
+ this.shadedKey = undefined;
103
+ }
104
+ if (changed)
105
+ applySpatialContactShading(this.scene, draft, this.colors);
106
+ this.scheduleShading();
107
+ }
108
+ else if (!this.colors || topology !== this.shadedTopology || (!options.dragging && needsShading)) {
52
109
  this.colors = applySpatialContactShading(this.scene, draft);
53
110
  this.shadedKey = surfaceKey;
54
111
  this.shadedTopology = topology;
@@ -58,7 +115,28 @@ export class SpatialSceneCache {
58
115
  }
59
116
  return changed;
60
117
  }
118
+ scheduleShading() {
119
+ if (this.shading || !this.desired || this.disposed)
120
+ return;
121
+ const request = this.desired;
122
+ this.shading = true;
123
+ void this.options.shade(request.draft).then(colors => {
124
+ if (this.disposed || this.desired?.key !== request.key || this.desired.topology !== request.topology)
125
+ return;
126
+ this.colors = applySpatialContactShading(this.scene, request.draft, colors);
127
+ this.shadedKey = request.key;
128
+ this.shadedTopology = request.topology;
129
+ this.desired = undefined;
130
+ this.options.onShaded?.();
131
+ }).catch(() => {
132
+ // Keep the last valid colors; a subsequent scene change can retry the worker.
133
+ if (this.desired?.key === request.key)
134
+ this.desired = undefined;
135
+ }).finally(() => { this.shading = false; this.scheduleShading(); });
136
+ }
61
137
  dispose() {
138
+ this.disposed = true;
139
+ this.desired = undefined;
62
140
  disposeSpatialScene(this.scene);
63
141
  this.scene.clear();
64
142
  this.entries.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"scene-cache.js","sourceRoot":"","sources":["../../../src/domain/spatial/scene-cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene-cache.js","sourceRoot":"","sources":["../../../src/domain/spatial/scene-cache.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Color, Group, Matrix4, Mesh } from "three";
2
+ import type { SpatialCharacter, SpatialObject } from "./types.ts";
3
+ export declare const entityMatrix: (entity: SpatialCharacter | SpatialObject) => Matrix4;
4
+ /** Preserve GPU buffers and picking identity when authored topology stays the same. */
5
+ export declare function updateSpatialGeometry(target: Group, source: Group): boolean;
6
+ export declare function rememberSpatialColors(group: Group, colors: WeakMap<Mesh, Color>): void;
@@ -0,0 +1,52 @@
1
+ import { LineSegments, Matrix4, Mesh, MeshLambertMaterial, Vector3 } from "three";
2
+ import { quaternion, vector } from "./kinematics.js";
3
+ export const entityMatrix = (entity) => new Matrix4().compose(vector(entity.position), quaternion(entity.rotation), new Vector3(1, 1, 1));
4
+ const drawable = (object) => object instanceof Mesh || object instanceof LineSegments;
5
+ /** Preserve GPU buffers and picking identity when authored topology stays the same. */
6
+ export function updateSpatialGeometry(target, source) {
7
+ const before = [], after = [];
8
+ target.traverse(object => before.push(object));
9
+ source.traverse(object => after.push(object));
10
+ if (before.length !== after.length || before.some((object, i) => {
11
+ const next = after[i];
12
+ if (object.type !== next.type || JSON.stringify(object.userData) !== JSON.stringify(next.userData))
13
+ return true;
14
+ if (!drawable(object) || !drawable(next))
15
+ return false;
16
+ return object.geometry.getAttribute("position").count !== next.geometry.getAttribute("position").count
17
+ || object.geometry.index?.count !== next.geometry.index?.count
18
+ || Object.entries(next.geometry.attributes).some(([name, attribute]) => object.geometry.getAttribute(name)?.array.length !== attribute.array.length);
19
+ }))
20
+ return false;
21
+ before.forEach((object, i) => {
22
+ const next = after[i];
23
+ object.position.copy(next.position);
24
+ object.quaternion.copy(next.quaternion);
25
+ object.scale.copy(next.scale);
26
+ object.matrixAutoUpdate = next.matrixAutoUpdate;
27
+ object.matrix.copy(next.matrix);
28
+ if (!drawable(object) || !drawable(next))
29
+ return;
30
+ for (const [name, attribute] of Object.entries(next.geometry.attributes)) {
31
+ const previous = object.geometry.getAttribute(name);
32
+ previous.array.set(attribute.array);
33
+ previous.needsUpdate = true;
34
+ }
35
+ if (object.geometry.index && next.geometry.index) {
36
+ object.geometry.index.array.set(next.geometry.index.array);
37
+ object.geometry.index.needsUpdate = true;
38
+ }
39
+ object.geometry.boundingBox = null;
40
+ object.geometry.boundingSphere = null;
41
+ if (!Array.isArray(object.material) && !Array.isArray(next.material))
42
+ object.material.copy(next.material);
43
+ });
44
+ return true;
45
+ }
46
+ export function rememberSpatialColors(group, colors) {
47
+ group.traverse(object => {
48
+ if (object instanceof Mesh && object.material instanceof MeshLambertMaterial)
49
+ colors.set(object, object.material.color.clone());
50
+ });
51
+ }
52
+ //# sourceMappingURL=scene-update.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-update.js","sourceRoot":"","sources":["../../../src/domain/spatial/scene-update.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,10 @@
1
1
  import { Group, OrthographicCamera, PerspectiveCamera } from "three";
2
- import type { SpatialCamera, SpatialDraft } from "./types.ts";
2
+ import type { SpatialCamera, SpatialCharacter, SpatialDraft } from "./types.ts";
3
3
  export declare function createOutputCamera(source: SpatialCamera): OrthographicCamera | PerspectiveCamera;
4
4
  export declare function createSpatialScene(draft: SpatialDraft, options?: {
5
5
  showRig?: boolean;
6
6
  handCreases?: boolean;
7
7
  }): Group;
8
+ /** Unit helper geometry survives pose/proportion changes; only transforms change. */
9
+ export declare function updateSpatialRig(scene: Group, actor: SpatialCharacter, batch?: boolean): void;
8
10
  export declare function disposeSpatialScene(scene: Group): void;
@@ -1,4 +1,4 @@
1
- import { BoxGeometry, Color, CylinderGeometry, DoubleSide, Group, Mesh, MeshLambertMaterial, LineSegments, OrthographicCamera, PerspectiveCamera, Quaternion, SphereGeometry, Vector3, } from "three";
1
+ import { BoxGeometry, Color, CylinderGeometry, DoubleSide, Group, InstancedMesh, Matrix4, Mesh, MeshLambertMaterial, LineSegments, OrthographicCamera, PerspectiveCamera, Quaternion, SphereGeometry, Vector3, } from "three";
2
2
  import { createCharacterModel } from "./model.js";
3
3
  import { jointWorldTransforms, quaternion, vector } from "./kinematics.js";
4
4
  import { fingerPart } from "./hands.js";
@@ -27,25 +27,7 @@ export function createSpatialScene(draft, options = {}) {
27
27
  scene.add(createCharacterModel(actor, options));
28
28
  if (!options.showRig || actor.appearance === "geometric")
29
29
  continue;
30
- const world = jointWorldTransforms(actor);
31
- const overlay = (mesh) => {
32
- mesh.material.depthTest = false;
33
- mesh.renderOrder = 2;
34
- };
35
- for (const joint of actor.joints.filter(j => !j.terminal || Boolean(fingerPart(actor.bones.find(b => b.endJointId === j.id)?.modelPart ?? "")))) {
36
- overlay(add(new SphereGeometry(joint.radius, 12, 8), "#e6a65c", world[joint.id].position, world[joint.id].rotation, { characterId: actor.id, jointId: joint.id, rig: "joint" }));
37
- }
38
- for (const bone of actor.bones) {
39
- const finger = fingerPart(bone.modelPart);
40
- if (finger?.segment === 0)
41
- continue;
42
- const start = world[bone.startJointId].position, end = world[bone.endJointId].position;
43
- const direction = end.clone().sub(start), length = direction.length();
44
- const data = { characterId: actor.id, boneId: bone.id, rig: "bone" };
45
- const radius = actor.height * (finger ? .0018 : .009);
46
- const mesh = add(new CylinderGeometry(radius, radius, length, 10), "#728aa1", start.clone().add(end).multiplyScalar(.5), new Quaternion().setFromUnitVectors(new Vector3(0, 1, 0), direction.normalize()), data);
47
- overlay(mesh);
48
- }
30
+ updateSpatialRig(scene, actor);
49
31
  }
50
32
  for (const object of draft.objects) {
51
33
  const size = vector(object.size);
@@ -57,9 +39,85 @@ export function createSpatialScene(draft, options = {}) {
57
39
  scene.updateMatrixWorld(true);
58
40
  return scene;
59
41
  }
42
+ /** Unit helper geometry survives pose/proportion changes; only transforms change. */
43
+ export function updateSpatialRig(scene, actor, batch = false) {
44
+ const parts = spatialRigParts(actor);
45
+ if (batch) {
46
+ const matrix = new Matrix4();
47
+ for (const rig of ["joint", "bone"]) {
48
+ const instances = parts.filter(part => part.data.rig === rig);
49
+ let mesh = scene.children.find(object => object instanceof InstancedMesh && object.userData.characterId === actor.id && object.userData.rig === rig);
50
+ if (mesh && mesh.count !== instances.length) {
51
+ scene.remove(mesh);
52
+ disposeSpatialScene(new Group().add(mesh));
53
+ mesh = undefined;
54
+ }
55
+ if (!mesh) {
56
+ mesh = new InstancedMesh(rigGeometry(rig), new MeshLambertMaterial({ side: DoubleSide, depthTest: false }), instances.length);
57
+ mesh.renderOrder = 2;
58
+ scene.add(mesh);
59
+ }
60
+ mesh.userData = { characterId: actor.id, rig, instances: instances.map(part => part.data) };
61
+ const color = new Color(rig === "joint" ? "#e6a65c" : "#728aa1");
62
+ instances.forEach((part, i) => {
63
+ mesh.setMatrixAt(i, matrix.compose(part.position, part.rotation, part.scale));
64
+ mesh.setColorAt(i, color);
65
+ });
66
+ mesh.instanceMatrix.needsUpdate = true;
67
+ if (mesh.instanceColor)
68
+ mesh.instanceColor.needsUpdate = true;
69
+ mesh.computeBoundingSphere();
70
+ }
71
+ return;
72
+ }
73
+ const existing = new Map(scene.children.filter(object => object.userData.rig && object.userData.characterId === actor.id)
74
+ .map(object => [`${object.userData.rig}/${object.userData.jointId ?? object.userData.boneId}`, object]));
75
+ const add = (rig, id) => {
76
+ const key = `${rig}/${id}`;
77
+ let mesh = existing.get(key);
78
+ existing.delete(key);
79
+ if (!mesh) {
80
+ mesh = new Mesh(rigGeometry(rig), new MeshLambertMaterial({ side: DoubleSide, depthTest: false }));
81
+ mesh.userData = { characterId: actor.id, rig, [rig === "joint" ? "jointId" : "boneId"]: id };
82
+ mesh.renderOrder = 2;
83
+ scene.add(mesh);
84
+ }
85
+ mesh.material.color.set(rig === "joint" ? "#e6a65c" : "#728aa1");
86
+ return mesh;
87
+ };
88
+ for (const part of parts) {
89
+ const mesh = add(part.data.rig, part.data.jointId ?? part.data.boneId);
90
+ mesh.position.copy(part.position);
91
+ mesh.quaternion.copy(part.rotation);
92
+ mesh.scale.copy(part.scale);
93
+ }
94
+ for (const mesh of existing.values()) {
95
+ scene.remove(mesh);
96
+ mesh.geometry.dispose();
97
+ mesh.material.dispose();
98
+ }
99
+ }
100
+ const rigGeometry = (rig) => rig === "joint" ? new SphereGeometry(1, 12, 8) : new CylinderGeometry(1, 1, 1, 10);
101
+ function spatialRigParts(actor) {
102
+ const world = jointWorldTransforms(actor), parts = [];
103
+ for (const joint of actor.joints.filter(j => !j.terminal || Boolean(fingerPart(actor.bones.find(b => b.endJointId === j.id)?.modelPart ?? "")))) {
104
+ parts.push({ data: { characterId: actor.id, rig: "joint", jointId: joint.id }, position: world[joint.id].position, rotation: world[joint.id].rotation, scale: new Vector3().setScalar(joint.radius) });
105
+ }
106
+ for (const bone of actor.bones) {
107
+ const finger = fingerPart(bone.modelPart);
108
+ if (finger?.segment === 0)
109
+ continue;
110
+ const start = world[bone.startJointId].position, end = world[bone.endJointId].position;
111
+ const direction = end.clone().sub(start), length = direction.length(), radius = actor.height * (finger ? .0018 : .009);
112
+ parts.push({ data: { characterId: actor.id, rig: "bone", boneId: bone.id }, position: start.clone().add(end).multiplyScalar(.5), rotation: new Quaternion().setFromUnitVectors(new Vector3(0, 1, 0), direction.normalize()), scale: new Vector3(radius, length, radius) });
113
+ }
114
+ return parts;
115
+ }
60
116
  export function disposeSpatialScene(scene) {
61
117
  scene.traverse(object => {
62
118
  if (object instanceof Mesh || object instanceof LineSegments) {
119
+ if (object instanceof InstancedMesh)
120
+ object.dispose();
63
121
  object.geometry.dispose();
64
122
  for (const material of Array.isArray(object.material) ? object.material : [object.material])
65
123
  material.dispose();
@@ -1 +1 @@
1
- {"version":3,"file":"scene.js","sourceRoot":"","sources":["../../../src/domain/spatial/scene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene.js","sourceRoot":"","sources":["../../../src/domain/spatial/scene.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAC1G,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,OAAO,GACzF,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAE3E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,UAAU,kBAAkB,CAAC,MAAqB;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,KAAK,cAAc;QACjD,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,IAAI,GAAG,MAAM,GAAG,CAAC,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC;QAC7H,CAAC,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,MAAM,CAAC,iBAAiB,EAAE,CAAC;IAC3B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAmB,EAAE,UAAwD,EAAE;IAChH,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,CAAC,QAAyD,EAAE,KAAa,EAAE,QAAiB,EAAE,QAAoB,EAAE,QAAgC,EAAE,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE;QAChM,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,mBAAmB,CAAC,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC;QACxG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAAC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC/G,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,UAAU,KAAK,WAAW;YAAE,SAAS;QACnE,gBAAgB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACvG,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO;YAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5C,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACnH,CAAC;IACD,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,gBAAgB,CAAC,KAAY,EAAE,KAAuB,EAAE,KAAK,GAAG,KAAK;IACnF,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,CAAU,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAC9D,IAAI,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,YAAY,aAAa,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,KAAK,KAAK,CAAC,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,KAAK,GAAG,CAA8B,CAAC;YAClL,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;gBAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBAAC,mBAAmB,CAAC,IAAI,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAC,IAAI,GAAG,SAAS,CAAC;YAAC,CAAC;YAClI,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,IAAI,aAAa,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,mBAAmB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;gBAC9H,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;gBAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxC,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5F,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACjE,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;gBAC5B,IAAK,CAAC,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBAAC,IAAK,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAC7G,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC;YACvC,IAAI,IAAI,CAAC,aAAa;gBAAE,IAAI,CAAC,aAAa,CAAC,WAAW,GAAG,IAAI,CAAC;YAC9D,IAAI,CAAC,qBAAqB,EAAE,CAAC;QAC/B,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,KAAK,KAAK,CAAC,EAAE,CAAC;SACtH,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAc,CAAC,CAAC,CAAC,CAAC;IACnH,MAAM,GAAG,GAAG,CAAC,GAAqB,EAAE,EAAU,EAAE,EAAE;QAChD,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,EAAE,EAAE,CAAC;QAC3B,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,IAAI,mBAAmB,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YACnG,IAAI,CAAC,QAAQ,GAAG,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;YAC7F,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;YAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;QACA,IAAI,CAAC,QAAgC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC1F,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,MAAO,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtG,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QACrC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAAE,IAAI,CAAC,QAAgC,CAAC,OAAO,EAAE,CAAC;IAChG,CAAC;AACH,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,GAAqB,EAAE,EAAE,CAAC,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC,CAAC,EAAC,EAAE,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,EAAC,EAAE,CAAC,CAAC;AAE7H,SAAS,eAAe,CAAC,KAAuB;IAC9C,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,EAAE,KAAK,GAAc,EAAE,CAAC;IACjE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChJ,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,OAAO,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzM,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,MAAM,EAAE,OAAO,KAAK,CAAC;YAAE,SAAS;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC;QACvF,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACvH,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,UAAU,EAAE,CAAC,kBAAkB,CAAC,IAAI,OAAO,CAAC,CAAC,EAAC,CAAC,EAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,OAAO,CAAC,MAAM,EAAC,MAAM,EAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzQ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAY;IAC9C,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;QACtB,IAAI,MAAM,YAAY,IAAI,IAAI,MAAM,YAAY,YAAY,EAAE,CAAC;YAC7D,IAAI,MAAM,YAAY,aAAa;gBAAE,MAAM,CAAC,OAAO,EAAE,CAAC;YACtD,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAC1B,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;QAClH,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const MAX_STYLE_MODEL_BYTES: number;
2
+ /** Accept a self-contained, static GLB example, never executable generator code. */
3
+ export declare function validStyleModel(data: Buffer): boolean;
@@ -0,0 +1,36 @@
1
+ export const MAX_STYLE_MODEL_BYTES = 10 * 1024 * 1024;
2
+ /** Accept a self-contained, static GLB example, never executable generator code. */
3
+ export function validStyleModel(data) {
4
+ if (!Buffer.isBuffer(data) || data.length < 28 || data.length > MAX_STYLE_MODEL_BYTES)
5
+ return false;
6
+ if (data.readUInt32LE(0) !== 0x46546c67 || data.readUInt32LE(4) !== 2 || data.readUInt32LE(8) !== data.length)
7
+ return false;
8
+ const jsonLength = data.readUInt32LE(12);
9
+ if (jsonLength % 4 || 20 + jsonLength > data.length || data.readUInt32LE(16) !== 0x4e4f534a)
10
+ return false;
11
+ try {
12
+ const document = JSON.parse(data.subarray(20, 20 + jsonLength).toString("utf8"));
13
+ if (document.asset?.version !== "2.0" || !document.scenes?.length || !document.nodes?.length || !document.meshes?.length)
14
+ return false;
15
+ // Textures and geometry must live in this file, with no decoder dependencies.
16
+ if (document.extensionsRequired?.some((name) => ["KHR_draco_mesh_compression", "EXT_meshopt_compression", "KHR_texture_basisu"].includes(name)))
17
+ return false;
18
+ if (JSON.stringify(document).includes('"uri":'))
19
+ return false;
20
+ const binaryOffset = 20 + jsonLength;
21
+ if (binaryOffset + 8 > data.length || data.readUInt32LE(binaryOffset + 4) !== 0x004e4942)
22
+ return false;
23
+ const binaryLength = data.readUInt32LE(binaryOffset);
24
+ if (binaryLength % 4 || binaryOffset + 8 + binaryLength !== data.length)
25
+ return false;
26
+ if (document.buffers?.length !== 1 || !Number.isInteger(document.buffers[0].byteLength) || document.buffers[0].byteLength <= 0 || document.buffers[0].byteLength > binaryLength)
27
+ return false;
28
+ return Array.isArray(document.bufferViews) && document.bufferViews.every((view) => (view.buffer === 0 && Number.isInteger(view.byteOffset ?? 0) && (view.byteOffset ?? 0) >= 0
29
+ && Number.isInteger(view.byteLength) && view.byteLength > 0
30
+ && (view.byteOffset ?? 0) + view.byteLength <= document.buffers[0].byteLength));
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ //# sourceMappingURL=model-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-input.js","sourceRoot":"","sources":["../../../src/domain/style/model-input.ts"],"names":[],"mappings":"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"}
@@ -22,10 +22,17 @@ export interface StyleEntry {
22
22
  description: string;
23
23
  promptSummary: string;
24
24
  referenceImages: StyleReferenceImage[];
25
+ previewModel?: StylePreviewModel;
25
26
  revision: number;
26
27
  createdAt: string;
27
28
  updatedAt: string;
28
29
  }
30
+ export interface StylePreviewModel {
31
+ id: string;
32
+ originalFilename: string;
33
+ byteSize: number;
34
+ createdAt: string;
35
+ }
29
36
  export interface SessionStyleState {
30
37
  session: Session;
31
38
  style: StyleEntry | null;
@@ -1,6 +1,8 @@
1
1
  import schema from "../../../schemas/spatial-draft.schema.json" with { type: "json" };
2
2
  import { createSpatialDraft, SpatialConstraintError } from "../../domain/spatial/index.js";
3
- import { renderSpatialPng, renderSpatialCameraBoxPng } from "../spatial-render.js";
3
+ import { SpatialRenderService } from "../spatial-render-service.js";
4
+ import { SpatialCameraRenderKeys } from "../../domain/spatial/camera-render-key.js";
5
+ import { cameraBoxView } from "../../domain/spatial/camera-box.js";
4
6
  import { SPATIAL_BOX_FACES, SPATIAL_RENDER_PASSES } from "../../domain/spatial/types.js";
5
7
  import { parseSpatialBoxViews } from "../../domain/spatial/camera-box-sheet.js";
6
8
  import en from "../../../locales/en/common.json" with { type: "json" };
@@ -10,15 +12,25 @@ export function registerSpatialSessionRoutes(server, repository) {
10
12
  server.addSchema(fastifySchema);
11
13
  registerDraftVersionRoutes(server, { routePrefix: "/api/v1/sessions/:sessionId/spatial", draftSchema: { $ref: schema.$id }, repository });
12
14
  const cache = new Map();
15
+ const inFlight = new Map();
16
+ const renderer = new SpatialRenderService(), renderKeys = new SpatialCameraRenderKeys();
17
+ server.addHook("onClose", () => renderer.close());
13
18
  const cached = (key, render) => {
14
- let pending = cache.get(key);
19
+ const image = cache.get(key);
20
+ if (image) {
21
+ cache.delete(key);
22
+ cache.set(key, image);
23
+ return Promise.resolve(image);
24
+ }
25
+ let pending = inFlight.get(key);
15
26
  if (!pending) {
16
- pending = render();
17
- cache.set(key, pending);
18
- if (cache.size > 24)
19
- cache.delete(cache.keys().next().value);
20
- void pending.catch(() => { if (cache.get(key) === pending)
21
- cache.delete(key); });
27
+ pending = render().then(image => {
28
+ cache.set(key, image);
29
+ if (cache.size > 24)
30
+ cache.delete(cache.keys().next().value);
31
+ return image;
32
+ }).finally(() => { inFlight.delete(key); });
33
+ inFlight.set(key, pending);
22
34
  }
23
35
  return pending;
24
36
  };
@@ -46,8 +58,8 @@ export function registerSpatialSessionRoutes(server, repository) {
46
58
  if (!camera)
47
59
  return reply.code(404).send({ code: "SPATIAL_CAMERA_NOT_FOUND", message: "Camera not found" });
48
60
  const pass = request.query.pass ?? "color";
49
- const key = JSON.stringify([sessionId, version?.revision ?? 0, cameraId, pass]);
50
- const pending = cached(key, () => renderSpatialPng(draft, camera, pass));
61
+ const key = JSON.stringify([sessionId, cameraId, renderKeys.key(draft, camera, pass)]);
62
+ const pending = cached(key, () => renderer.render({ draft, camera, pass }));
51
63
  return reply.header("cache-control", request.query.revision ? "private, max-age=31536000, immutable" : "no-cache")
52
64
  .header("x-spatial-revision", version?.revision ?? 0).header("x-spatial-render-pass", pass).type("image/png").send(await pending);
53
65
  }
@@ -71,8 +83,12 @@ export function registerSpatialSessionRoutes(server, repository) {
71
83
  if (!box || !version)
72
84
  return reply.code(404).send({ code: "SPATIAL_CAMERA_NOT_FOUND", message: "Camera box not found" });
73
85
  const pass = request.query.pass ?? "color", view = views ?? request.query.view ?? "sheet";
74
- const key = JSON.stringify([sessionId, version.revision, "camera-box", boxId, view, pass]);
75
- const png = cached(key, () => renderSpatialCameraBoxPng(version.draft, box, view, pass));
86
+ const faces = typeof view === "string" ? view === "sheet" ? SPATIAL_BOX_FACES : [view] : view;
87
+ const key = JSON.stringify([sessionId, "camera-box", boxId, view, faces.map(face => {
88
+ const { source, camera } = cameraBoxView(box, face);
89
+ return renderKeys.key(version.draft, source, pass, camera);
90
+ })]);
91
+ const png = cached(key, () => renderer.render({ draft: version.draft, box, view, pass }));
76
92
  return reply.header("cache-control", request.query.revision ? "private, max-age=31536000, immutable" : "no-cache")
77
93
  .header("x-spatial-revision", version.revision).header("x-spatial-render-pass", pass).header("x-spatial-box-view", typeof view === "string" ? view : "sheet")
78
94
  .header("x-spatial-box-views", views?.join(",") ?? (view === "sheet" ? SPATIAL_BOX_FACES.join(",") : view)).type("image/png").send(await png);