@nodetool-ai/video-nodes 0.8.1

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 (152) hide show
  1. package/README.md +58 -0
  2. package/dist/.nodetool-build-stamp +1 -0
  3. package/dist/index.d.ts +9 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +11 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/nodes/ffmpeg-helpers.d.ts +77 -0
  8. package/dist/nodes/ffmpeg-helpers.d.ts.map +1 -0
  9. package/dist/nodes/ffmpeg-helpers.js +220 -0
  10. package/dist/nodes/ffmpeg-helpers.js.map +1 -0
  11. package/dist/nodes/lib-video-download.d.ts +29 -0
  12. package/dist/nodes/lib-video-download.d.ts.map +1 -0
  13. package/dist/nodes/lib-video-download.js +353 -0
  14. package/dist/nodes/lib-video-download.js.map +1 -0
  15. package/dist/nodes/model3d/analysis.d.ts +16 -0
  16. package/dist/nodes/model3d/analysis.d.ts.map +1 -0
  17. package/dist/nodes/model3d/analysis.js +38 -0
  18. package/dist/nodes/model3d/analysis.js.map +1 -0
  19. package/dist/nodes/model3d/base.d.ts +28 -0
  20. package/dist/nodes/model3d/base.d.ts.map +1 -0
  21. package/dist/nodes/model3d/base.js +20 -0
  22. package/dist/nodes/model3d/base.js.map +1 -0
  23. package/dist/nodes/model3d/boolean-ops.d.ts +2 -0
  24. package/dist/nodes/model3d/boolean-ops.d.ts.map +1 -0
  25. package/dist/nodes/model3d/boolean-ops.js +172 -0
  26. package/dist/nodes/model3d/boolean-ops.js.map +1 -0
  27. package/dist/nodes/model3d/cleanup.d.ts +56 -0
  28. package/dist/nodes/model3d/cleanup.d.ts.map +1 -0
  29. package/dist/nodes/model3d/cleanup.js +144 -0
  30. package/dist/nodes/model3d/cleanup.js.map +1 -0
  31. package/dist/nodes/model3d/convert.d.ts +27 -0
  32. package/dist/nodes/model3d/convert.d.ts.map +1 -0
  33. package/dist/nodes/model3d/convert.js +66 -0
  34. package/dist/nodes/model3d/convert.js.map +1 -0
  35. package/dist/nodes/model3d/defaults.d.ts +34 -0
  36. package/dist/nodes/model3d/defaults.d.ts.map +1 -0
  37. package/dist/nodes/model3d/defaults.js +28 -0
  38. package/dist/nodes/model3d/defaults.js.map +1 -0
  39. package/dist/nodes/model3d/document-ops.d.ts +4 -0
  40. package/dist/nodes/model3d/document-ops.d.ts.map +1 -0
  41. package/dist/nodes/model3d/document-ops.js +40 -0
  42. package/dist/nodes/model3d/document-ops.js.map +1 -0
  43. package/dist/nodes/model3d/generation.d.ts +56 -0
  44. package/dist/nodes/model3d/generation.d.ts.map +1 -0
  45. package/dist/nodes/model3d/generation.js +203 -0
  46. package/dist/nodes/model3d/generation.js.map +1 -0
  47. package/dist/nodes/model3d/glb.d.ts +29 -0
  48. package/dist/nodes/model3d/glb.d.ts.map +1 -0
  49. package/dist/nodes/model3d/glb.js +255 -0
  50. package/dist/nodes/model3d/glb.js.map +1 -0
  51. package/dist/nodes/model3d/index.d.ts +22 -0
  52. package/dist/nodes/model3d/index.d.ts.map +1 -0
  53. package/dist/nodes/model3d/index.js +41 -0
  54. package/dist/nodes/model3d/index.js.map +1 -0
  55. package/dist/nodes/model3d/io.d.ts +81 -0
  56. package/dist/nodes/model3d/io.d.ts.map +1 -0
  57. package/dist/nodes/model3d/io.js +162 -0
  58. package/dist/nodes/model3d/io.js.map +1 -0
  59. package/dist/nodes/model3d/mesh-ops.d.ts +40 -0
  60. package/dist/nodes/model3d/mesh-ops.d.ts.map +1 -0
  61. package/dist/nodes/model3d/mesh-ops.js +775 -0
  62. package/dist/nodes/model3d/mesh-ops.js.map +1 -0
  63. package/dist/nodes/model3d/nodes.d.ts +2 -0
  64. package/dist/nodes/model3d/nodes.d.ts.map +1 -0
  65. package/dist/nodes/model3d/nodes.js +2 -0
  66. package/dist/nodes/model3d/nodes.js.map +1 -0
  67. package/dist/nodes/model3d/ops.d.ts +44 -0
  68. package/dist/nodes/model3d/ops.d.ts.map +1 -0
  69. package/dist/nodes/model3d/ops.js +142 -0
  70. package/dist/nodes/model3d/ops.js.map +1 -0
  71. package/dist/nodes/model3d/render.d.ts +51 -0
  72. package/dist/nodes/model3d/render.d.ts.map +1 -0
  73. package/dist/nodes/model3d/render.js +124 -0
  74. package/dist/nodes/model3d/render.js.map +1 -0
  75. package/dist/nodes/model3d/render3d-core.d.ts +177 -0
  76. package/dist/nodes/model3d/render3d-core.d.ts.map +1 -0
  77. package/dist/nodes/model3d/render3d-core.js +366 -0
  78. package/dist/nodes/model3d/render3d-core.js.map +1 -0
  79. package/dist/nodes/model3d/render3d-headless.d.ts +75 -0
  80. package/dist/nodes/model3d/render3d-headless.d.ts.map +1 -0
  81. package/dist/nodes/model3d/render3d-headless.js +190 -0
  82. package/dist/nodes/model3d/render3d-headless.js.map +1 -0
  83. package/dist/nodes/model3d/render3d-page.d.ts +16 -0
  84. package/dist/nodes/model3d/render3d-page.d.ts.map +1 -0
  85. package/dist/nodes/model3d/render3d-page.js +51 -0
  86. package/dist/nodes/model3d/render3d-page.js.map +1 -0
  87. package/dist/nodes/model3d/transforms.d.ts +56 -0
  88. package/dist/nodes/model3d/transforms.d.ts.map +1 -0
  89. package/dist/nodes/model3d/transforms.js +148 -0
  90. package/dist/nodes/model3d/transforms.js.map +1 -0
  91. package/dist/nodes/model3d/types.d.ts +82 -0
  92. package/dist/nodes/model3d/types.d.ts.map +1 -0
  93. package/dist/nodes/model3d/types.js +2 -0
  94. package/dist/nodes/model3d/types.js.map +1 -0
  95. package/dist/nodes/model3d/utils.d.ts +46 -0
  96. package/dist/nodes/model3d/utils.d.ts.map +1 -0
  97. package/dist/nodes/model3d/utils.js +190 -0
  98. package/dist/nodes/model3d/utils.js.map +1 -0
  99. package/dist/nodes/model3d.d.ts +2 -0
  100. package/dist/nodes/model3d.d.ts.map +1 -0
  101. package/dist/nodes/model3d.js +2 -0
  102. package/dist/nodes/model3d.js.map +1 -0
  103. package/dist/nodes/placeholder-values.d.ts +10 -0
  104. package/dist/nodes/placeholder-values.d.ts.map +1 -0
  105. package/dist/nodes/placeholder-values.js +19 -0
  106. package/dist/nodes/placeholder-values.js.map +1 -0
  107. package/dist/nodes/script.d.ts +161 -0
  108. package/dist/nodes/script.d.ts.map +1 -0
  109. package/dist/nodes/script.js +673 -0
  110. package/dist/nodes/script.js.map +1 -0
  111. package/dist/nodes/storyboard.d.ts +269 -0
  112. package/dist/nodes/storyboard.d.ts.map +1 -0
  113. package/dist/nodes/storyboard.js +1017 -0
  114. package/dist/nodes/storyboard.js.map +1 -0
  115. package/dist/nodes/timeline/assetFiles.d.ts +19 -0
  116. package/dist/nodes/timeline/assetFiles.d.ts.map +1 -0
  117. package/dist/nodes/timeline/assetFiles.js +52 -0
  118. package/dist/nodes/timeline/assetFiles.js.map +1 -0
  119. package/dist/nodes/timeline/compositeRender.d.ts +60 -0
  120. package/dist/nodes/timeline/compositeRender.d.ts.map +1 -0
  121. package/dist/nodes/timeline/compositeRender.js +508 -0
  122. package/dist/nodes/timeline/compositeRender.js.map +1 -0
  123. package/dist/nodes/timeline/contactSheet.d.ts +43 -0
  124. package/dist/nodes/timeline/contactSheet.d.ts.map +1 -0
  125. package/dist/nodes/timeline/contactSheet.js +78 -0
  126. package/dist/nodes/timeline/contactSheet.js.map +1 -0
  127. package/dist/nodes/timeline/outputFormats.d.ts +69 -0
  128. package/dist/nodes/timeline/outputFormats.d.ts.map +1 -0
  129. package/dist/nodes/timeline/outputFormats.js +173 -0
  130. package/dist/nodes/timeline/outputFormats.js.map +1 -0
  131. package/dist/nodes/timeline/pngSequence.d.ts +44 -0
  132. package/dist/nodes/timeline/pngSequence.d.ts.map +1 -0
  133. package/dist/nodes/timeline/pngSequence.js +172 -0
  134. package/dist/nodes/timeline/pngSequence.js.map +1 -0
  135. package/dist/nodes/timeline/rasterizers.d.ts +47 -0
  136. package/dist/nodes/timeline/rasterizers.d.ts.map +1 -0
  137. package/dist/nodes/timeline/rasterizers.js +103 -0
  138. package/dist/nodes/timeline/rasterizers.js.map +1 -0
  139. package/dist/nodes/timeline/rawFrames.d.ts +149 -0
  140. package/dist/nodes/timeline/rawFrames.d.ts.map +1 -0
  141. package/dist/nodes/timeline/rawFrames.js +598 -0
  142. package/dist/nodes/timeline/rawFrames.js.map +1 -0
  143. package/dist/nodes/timeline.d.ts +206 -0
  144. package/dist/nodes/timeline.d.ts.map +1 -0
  145. package/dist/nodes/timeline.js +1395 -0
  146. package/dist/nodes/timeline.js.map +1 -0
  147. package/dist/nodes/video.d.ts +705 -0
  148. package/dist/nodes/video.d.ts.map +1 -0
  149. package/dist/nodes/video.js +2672 -0
  150. package/dist/nodes/video.js.map +1 -0
  151. package/dist/render3d-page.js +4118 -0
  152. package/package.json +95 -0
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Shared three.js render core for `nodetool.model3d.RenderToImage` and for
3
+ * the timeline's `model3d` clips.
4
+ *
5
+ * A **session** loads a GLB once and draws many frames from it
6
+ * (`createModel3DRenderSession`); `renderGlbToPng` is the one-frame case.
7
+ * Turning bytes into pixels needs a WebGL context on an `OffscreenCanvas`,
8
+ * so the same module runs in two hosts:
9
+ *
10
+ * - the in-browser workflow runner and the timeline preview (main thread or
11
+ * worker), importing this file directly;
12
+ * - a headless Chromium page on the Node backend, via the esbuild bundle
13
+ * `dist/render3d-page.js` (entry: `render3d-page.ts`).
14
+ *
15
+ * Editor-only clutter (grid, axes, gizmos) never exists here — the scene is
16
+ * built fresh from the model plus the requested lights and nothing else.
17
+ */
18
+ export type LightingPreset = "studio" | "soft" | "flat";
19
+ /**
20
+ * The 3D half of a timeline clip's style.
21
+ *
22
+ * These three interfaces are declared here, not imported, because
23
+ * `@nodetool-ai/timeline` is pure document logic and this file is the GPU
24
+ * side: the bundle that ships to a headless Chromium page must not pull the
25
+ * document package in. They are structurally identical to the
26
+ * `ClipModel3DCamera` / `ClipModel3DAnimation` / `ClipModel3DStyle` of
27
+ * `packages/timeline/src/types.ts`, so a caller assigns one to the other
28
+ * without a conversion.
29
+ */
30
+ export type Model3DCameraMode = "orbit" | "scene";
31
+ export interface ClipModel3DCamera {
32
+ /** `orbit` frames the model's bounding sphere; `scene` uses a glTF camera. */
33
+ mode: Model3DCameraMode;
34
+ /** Horizontal orbit angle around the model, degrees. 0 looks down -Z. */
35
+ azimuthDeg: number;
36
+ /** Vertical angle above the horizon, degrees. */
37
+ elevationDeg: number;
38
+ /** Vertical field of view, degrees. */
39
+ fovDeg: number;
40
+ /** Distance multiplier on the auto-framed fit: >1 closer. */
41
+ zoom: number;
42
+ /** Look-at offset from the bounding-sphere center, world units. */
43
+ targetOffset?: [number, number, number];
44
+ /** `scene` mode: the glTF camera's name; the first camera when absent. */
45
+ sceneCameraName?: string;
46
+ }
47
+ export interface ClipModel3DAnimation {
48
+ /** glTF animation name; every animation plays when absent. */
49
+ clipName?: string;
50
+ loop: boolean;
51
+ /** Playback multiplier on top of the clip's own speed / time remap. */
52
+ speed: number;
53
+ }
54
+ export interface ClipModel3DStyle {
55
+ camera: ClipModel3DCamera;
56
+ animation: ClipModel3DAnimation;
57
+ lighting: LightingPreset;
58
+ lightIntensity: number;
59
+ background: {
60
+ transparent: true;
61
+ } | {
62
+ transparent: false;
63
+ color: string;
64
+ };
65
+ /** A Blender render of this clip at a given style. */
66
+ bake?: {
67
+ assetId: string;
68
+ dependencyHash: string;
69
+ };
70
+ }
71
+ export interface Render3DOptions {
72
+ /** Output image width in pixels. */
73
+ width: number;
74
+ /** Output image height in pixels. */
75
+ height: number;
76
+ /** Horizontal orbit angle around the model, degrees. 0 looks down -Z. */
77
+ azimuthDeg: number;
78
+ /** Vertical angle above the horizon, degrees. 90 is straight down. */
79
+ elevationDeg: number;
80
+ /** Vertical field of view, degrees. */
81
+ fovDeg: number;
82
+ /** Camera distance multiplier on the auto-framed fit: >1 closer, <1 farther. */
83
+ zoom: number;
84
+ lighting: LightingPreset;
85
+ /** Multiplier applied to every light in the preset. */
86
+ lightIntensity: number;
87
+ /** CSS color for the background; ignored when `transparent` is true. */
88
+ backgroundColor: string;
89
+ transparent: boolean;
90
+ }
91
+ export interface Model3DRenderFrame {
92
+ timeSec: number;
93
+ /** Already folded with the animated camera channels. */
94
+ camera: ClipModel3DCamera;
95
+ width: number;
96
+ height: number;
97
+ }
98
+ export interface Model3DRenderSession {
99
+ /** Names of the glTF's animations and cameras, for the inspector and the validator. */
100
+ readonly animations: readonly string[];
101
+ readonly cameras: readonly string[];
102
+ /** Draws one frame into the session's canvas and returns it. */
103
+ render(frame: Model3DRenderFrame): OffscreenCanvas;
104
+ dispose(): void;
105
+ }
106
+ /**
107
+ * Everything a session fixes at creation. Two layers share a session only
108
+ * when these are equal, so the key of every pool and every headless group is
109
+ * `assetId` plus this object, never `assetId` alone.
110
+ */
111
+ export interface Model3DSessionOptions {
112
+ lighting: ClipModel3DStyle["lighting"];
113
+ lightIntensity: number;
114
+ background: ClipModel3DStyle["background"];
115
+ animation: ClipModel3DAnimation;
116
+ }
117
+ interface CameraFraming {
118
+ /** Distance from the bounding-sphere center to the camera. */
119
+ distance: number;
120
+ near: number;
121
+ far: number;
122
+ }
123
+ /**
124
+ * Distance that fits a bounding sphere of `radius` fully into a camera with
125
+ * the given vertical fov and aspect, then applies `zoom` (>1 moves closer).
126
+ * Pure math, exported for tests.
127
+ */
128
+ export declare function computeFraming(radius: number, fovDeg: number, aspect: number, zoom: number): CameraFraming;
129
+ /** Spherical → cartesian offset for the orbit camera. Exported for tests. */
130
+ export declare function orbitOffset(azimuthDeg: number, elevationDeg: number, distance: number): {
131
+ x: number;
132
+ y: number;
133
+ z: number;
134
+ };
135
+ /**
136
+ * Map a clip-local animation time onto the mixer's time.
137
+ *
138
+ * With `loop` on the time wraps at `duration`; off, it clamps to the last
139
+ * frame. A model with no animation (`duration` 0, or a non-finite duration)
140
+ * has one pose, so every time maps to 0. Pure, exported for tests.
141
+ */
142
+ export declare function mixerTimeFor(t: number, duration: number, loop: boolean): number;
143
+ /**
144
+ * The animation clips `animation.clipName` selects: the named one, or every
145
+ * clip when the name is absent. Pure, exported for tests.
146
+ */
147
+ export declare function selectAnimationClips<T extends {
148
+ name: string;
149
+ }>(clips: readonly T[], clipName?: string): T[];
150
+ /**
151
+ * The glTF camera `camera.sceneCameraName` selects, or the first one when the
152
+ * name is absent. Pure, exported for tests.
153
+ */
154
+ export declare function selectSceneCamera<T extends {
155
+ name: string;
156
+ }>(cameras: readonly T[], sceneCameraName?: string): T;
157
+ /** The session options a one-shot `Render3DOptions` describes. */
158
+ export declare function sessionOptionsFromRender3DOptions(options: Render3DOptions): Model3DSessionOptions;
159
+ /** The single frame a one-shot `Render3DOptions` describes. */
160
+ export declare function renderFrameFromRender3DOptions(options: Render3DOptions): Model3DRenderFrame;
161
+ /**
162
+ * Load a model once and draw frames from it. Must run in a browser context
163
+ * (window or worker) with WebGL and `OffscreenCanvas`.
164
+ *
165
+ * Every option here is fixed for the session's life: a style edit that
166
+ * touches one of them disposes the session and creates a new one, because a
167
+ * mixer whose actions were rebuilt mid-session is the same picture as a fresh
168
+ * one and harder to prove.
169
+ */
170
+ export declare function createModel3DRenderSession(glb: Uint8Array, options: Model3DSessionOptions): Promise<Model3DRenderSession>;
171
+ /**
172
+ * Render GLB (or embedded-buffer glTF JSON) bytes to PNG bytes. Must run in a
173
+ * browser context (window or worker) with WebGL and `OffscreenCanvas`.
174
+ */
175
+ export declare function renderGlbToPng(glb: Uint8Array, options: Render3DOptions): Promise<Uint8Array>;
176
+ export {};
177
+ //# sourceMappingURL=render3d-core.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render3d-core.d.ts","sourceRoot":"","sources":["../../../src/nodes/model3d/render3d-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,366 @@
1
+ /// <reference lib="dom" />
2
+ /**
3
+ * Shared three.js render core for `nodetool.model3d.RenderToImage` and for
4
+ * the timeline's `model3d` clips.
5
+ *
6
+ * A **session** loads a GLB once and draws many frames from it
7
+ * (`createModel3DRenderSession`); `renderGlbToPng` is the one-frame case.
8
+ * Turning bytes into pixels needs a WebGL context on an `OffscreenCanvas`,
9
+ * so the same module runs in two hosts:
10
+ *
11
+ * - the in-browser workflow runner and the timeline preview (main thread or
12
+ * worker), importing this file directly;
13
+ * - a headless Chromium page on the Node backend, via the esbuild bundle
14
+ * `dist/render3d-page.js` (entry: `render3d-page.ts`).
15
+ *
16
+ * Editor-only clutter (grid, axes, gizmos) never exists here — the scene is
17
+ * built fresh from the model plus the requested lights and nothing else.
18
+ */
19
+ import * as THREE from "three";
20
+ import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
21
+ import { MeshoptDecoder } from "meshoptimizer";
22
+ /**
23
+ * Distance that fits a bounding sphere of `radius` fully into a camera with
24
+ * the given vertical fov and aspect, then applies `zoom` (>1 moves closer).
25
+ * Pure math, exported for tests.
26
+ */
27
+ export function computeFraming(radius, fovDeg, aspect, zoom) {
28
+ const safeRadius = Math.max(radius, 1e-6);
29
+ const vFov = (Math.max(fovDeg, 1) * Math.PI) / 180;
30
+ const hFov = 2 * Math.atan(Math.tan(vFov / 2) * Math.max(aspect, 1e-6));
31
+ const fitV = safeRadius / Math.sin(vFov / 2);
32
+ const fitH = safeRadius / Math.sin(hFov / 2);
33
+ const distance = Math.max(fitV, fitH) / Math.max(zoom, 1e-3);
34
+ return {
35
+ distance,
36
+ near: Math.max(distance - safeRadius * 4, distance / 100, 1e-4),
37
+ far: distance + safeRadius * 10
38
+ };
39
+ }
40
+ /** Spherical → cartesian offset for the orbit camera. Exported for tests. */
41
+ export function orbitOffset(azimuthDeg, elevationDeg, distance) {
42
+ const az = (azimuthDeg * Math.PI) / 180;
43
+ const el = (Math.min(Math.max(elevationDeg, -89.9), 89.9) * Math.PI) / 180;
44
+ return {
45
+ x: distance * Math.cos(el) * Math.sin(az),
46
+ y: distance * Math.sin(el),
47
+ z: distance * Math.cos(el) * Math.cos(az)
48
+ };
49
+ }
50
+ /**
51
+ * Map a clip-local animation time onto the mixer's time.
52
+ *
53
+ * With `loop` on the time wraps at `duration`; off, it clamps to the last
54
+ * frame. A model with no animation (`duration` 0, or a non-finite duration)
55
+ * has one pose, so every time maps to 0. Pure, exported for tests.
56
+ */
57
+ export function mixerTimeFor(t, duration, loop) {
58
+ if (!Number.isFinite(t))
59
+ return 0;
60
+ if (!Number.isFinite(duration) || duration <= 0)
61
+ return 0;
62
+ if (!loop)
63
+ return Math.min(Math.max(t, 0), duration);
64
+ return ((t % duration) + duration) % duration;
65
+ }
66
+ /**
67
+ * The animation clips `animation.clipName` selects: the named one, or every
68
+ * clip when the name is absent. Pure, exported for tests.
69
+ */
70
+ export function selectAnimationClips(clips, clipName) {
71
+ if (clipName === undefined || clipName === "")
72
+ return [...clips];
73
+ const found = clips.filter((clip) => clip.name === clipName);
74
+ if (found.length > 0)
75
+ return found;
76
+ throw new Error(clips.length === 0
77
+ ? `Model3D render: animation "${clipName}" is not in this model — it has no animations`
78
+ : `Model3D render: animation "${clipName}" is not in this model — available animations: ${clips
79
+ .map((clip) => clip.name)
80
+ .join(", ")}`);
81
+ }
82
+ /**
83
+ * The glTF camera `camera.sceneCameraName` selects, or the first one when the
84
+ * name is absent. Pure, exported for tests.
85
+ */
86
+ export function selectSceneCamera(cameras, sceneCameraName) {
87
+ if (cameras.length === 0) {
88
+ throw new Error("Model3D render: camera mode is \"scene\" but this model has no cameras — use orbit mode");
89
+ }
90
+ if (sceneCameraName === undefined || sceneCameraName === "") {
91
+ return cameras[0];
92
+ }
93
+ const found = cameras.find((camera) => camera.name === sceneCameraName);
94
+ if (found)
95
+ return found;
96
+ throw new Error(`Model3D render: camera "${sceneCameraName}" is not in this model — available cameras: ${cameras
97
+ .map((camera) => camera.name)
98
+ .join(", ")}`);
99
+ }
100
+ /**
101
+ * Build the preset's lights into `scene`. Key/fill/rim ride along with the
102
+ * camera azimuth so the visible side of the model is always lit, whatever
103
+ * angle the user picked — `aim` is what puts them there.
104
+ */
105
+ function createLightRig(scene, preset, intensity) {
106
+ const scaled = (base) => base * intensity;
107
+ const directionals = [];
108
+ let hemisphere = null;
109
+ const placeDirectional = (color, lightIntensity, direction) => {
110
+ const light = new THREE.DirectionalLight(color, lightIntensity);
111
+ scene.add(light);
112
+ scene.add(light.target);
113
+ directionals.push({ light, direction });
114
+ };
115
+ switch (preset) {
116
+ case "studio": {
117
+ scene.add(new THREE.AmbientLight(0xffffff, scaled(0.5)));
118
+ placeDirectional(0xffffff, scaled(2.2), (toCamera, side, up) => toCamera
119
+ .clone()
120
+ .add(side.clone().multiplyScalar(0.8))
121
+ .add(up.clone().multiplyScalar(0.9)));
122
+ placeDirectional(0xffffff, scaled(0.8), (toCamera, side, up) => toCamera
123
+ .clone()
124
+ .sub(side.clone().multiplyScalar(1.1))
125
+ .add(up.clone().multiplyScalar(0.2)));
126
+ placeDirectional(0xffffff, scaled(1.4), (toCamera, _side, up) => toCamera.clone().negate().add(up.clone().multiplyScalar(1.2)));
127
+ break;
128
+ }
129
+ case "soft": {
130
+ hemisphere = new THREE.HemisphereLight(0xffffff, 0x555566, scaled(1.6));
131
+ scene.add(hemisphere);
132
+ placeDirectional(0xffffff, scaled(0.9), (toCamera, _side, up) => toCamera.clone().add(up));
133
+ break;
134
+ }
135
+ case "flat":
136
+ scene.add(new THREE.AmbientLight(0xffffff, scaled(3)));
137
+ break;
138
+ }
139
+ return {
140
+ aim(cameraPosition, target) {
141
+ const toCamera = cameraPosition.clone().sub(target).normalize();
142
+ const up = new THREE.Vector3(0, 1, 0);
143
+ const side = new THREE.Vector3().crossVectors(up, toCamera).normalize();
144
+ if (side.lengthSq() < 1e-6)
145
+ side.set(1, 0, 0);
146
+ for (const entry of directionals) {
147
+ entry.light.position
148
+ .copy(target)
149
+ .add(entry.direction(toCamera, side, up));
150
+ entry.light.target.position.copy(target);
151
+ }
152
+ if (hemisphere)
153
+ hemisphere.position.copy(target).add(up);
154
+ }
155
+ };
156
+ }
157
+ function disposeMaterial(material) {
158
+ for (const value of Object.values(material)) {
159
+ if (value instanceof THREE.Texture)
160
+ value.dispose();
161
+ }
162
+ material.dispose();
163
+ }
164
+ function disposeScene(scene) {
165
+ scene.traverse((object) => {
166
+ const mesh = object;
167
+ if (mesh.geometry)
168
+ mesh.geometry.dispose();
169
+ const material = mesh.material;
170
+ if (Array.isArray(material)) {
171
+ material.forEach(disposeMaterial);
172
+ }
173
+ else if (material) {
174
+ disposeMaterial(material);
175
+ }
176
+ });
177
+ }
178
+ function toArrayBuffer(bytes) {
179
+ // GLTFLoader wants an ArrayBuffer that starts at offset 0.
180
+ return bytes.buffer instanceof ArrayBuffer &&
181
+ bytes.byteOffset === 0 &&
182
+ bytes.byteLength === bytes.buffer.byteLength
183
+ ? bytes.buffer
184
+ : bytes.slice().buffer;
185
+ }
186
+ /** The session options a one-shot `Render3DOptions` describes. */
187
+ export function sessionOptionsFromRender3DOptions(options) {
188
+ return {
189
+ lighting: options.lighting,
190
+ lightIntensity: options.lightIntensity,
191
+ background: options.transparent
192
+ ? { transparent: true }
193
+ : { transparent: false, color: options.backgroundColor },
194
+ animation: { loop: false, speed: 1 }
195
+ };
196
+ }
197
+ /** The single frame a one-shot `Render3DOptions` describes. */
198
+ export function renderFrameFromRender3DOptions(options) {
199
+ return {
200
+ timeSec: 0,
201
+ width: options.width,
202
+ height: options.height,
203
+ camera: {
204
+ mode: "orbit",
205
+ azimuthDeg: options.azimuthDeg,
206
+ elevationDeg: options.elevationDeg,
207
+ fovDeg: options.fovDeg,
208
+ zoom: options.zoom
209
+ }
210
+ };
211
+ }
212
+ /**
213
+ * Load a model once and draw frames from it. Must run in a browser context
214
+ * (window or worker) with WebGL and `OffscreenCanvas`.
215
+ *
216
+ * Every option here is fixed for the session's life: a style edit that
217
+ * touches one of them disposes the session and creates a new one, because a
218
+ * mixer whose actions were rebuilt mid-session is the same picture as a fresh
219
+ * one and harder to prove.
220
+ */
221
+ export async function createModel3DRenderSession(glb, options) {
222
+ if (typeof OffscreenCanvas === "undefined") {
223
+ throw new Error("RenderToImage needs a browser context with OffscreenCanvas support");
224
+ }
225
+ const loader = new GLTFLoader();
226
+ await MeshoptDecoder.ready;
227
+ loader.setMeshoptDecoder(MeshoptDecoder);
228
+ const gltf = await loader.parseAsync(toArrayBuffer(glb), "");
229
+ const scene = new THREE.Scene();
230
+ scene.add(gltf.scene);
231
+ // Resolve the world matrix before measuring, or the box is stale.
232
+ scene.updateMatrixWorld(true);
233
+ const box = new THREE.Box3().setFromObject(gltf.scene);
234
+ if (box.isEmpty()) {
235
+ disposeScene(scene);
236
+ throw new Error("RenderToImage: the model contains no visible geometry");
237
+ }
238
+ // The framing sphere is the model's rest pose, so a camera does not drift
239
+ // as the animation moves the geometry.
240
+ const sphere = box.getBoundingSphere(new THREE.Sphere());
241
+ const sceneCameras = gltf.cameras;
242
+ const selected = selectAnimationClips(gltf.animations, options.animation.clipName);
243
+ const duration = selected.reduce((longest, clip) => Math.max(longest, clip.duration), 0);
244
+ const loop = options.animation.loop;
245
+ const mixer = selected.length > 0 ? new THREE.AnimationMixer(gltf.scene) : null;
246
+ const actions = [];
247
+ if (mixer) {
248
+ for (const clip of selected) {
249
+ const action = mixer.clipAction(clip);
250
+ if (loop) {
251
+ action.setLoop(THREE.LoopRepeat, Infinity);
252
+ }
253
+ else {
254
+ // LoopOnce holds the last frame at exactly `duration`; LoopRepeat
255
+ // would wrap it back to 0 there.
256
+ action.setLoop(THREE.LoopOnce, 1);
257
+ action.clampWhenFinished = true;
258
+ }
259
+ action.play();
260
+ actions.push(action);
261
+ }
262
+ }
263
+ const rig = createLightRig(scene, options.lighting, options.lightIntensity);
264
+ if (!options.background.transparent) {
265
+ scene.background = new THREE.Color(options.background.color);
266
+ }
267
+ const canvas = new OffscreenCanvas(1, 1);
268
+ const renderer = new THREE.WebGLRenderer({
269
+ canvas,
270
+ antialias: true,
271
+ alpha: true,
272
+ preserveDrawingBuffer: true
273
+ });
274
+ renderer.toneMapping = THREE.NeutralToneMapping;
275
+ renderer.outputColorSpace = THREE.SRGBColorSpace;
276
+ if (options.background.transparent) {
277
+ renderer.setClearColor(0x000000, 0);
278
+ }
279
+ const orbitCamera = new THREE.PerspectiveCamera();
280
+ const target = new THREE.Vector3();
281
+ const eye = new THREE.Vector3();
282
+ let disposed = false;
283
+ return {
284
+ animations: gltf.animations.map((clip) => clip.name),
285
+ cameras: sceneCameras.map((camera) => camera.name),
286
+ render(frame) {
287
+ if (disposed) {
288
+ throw new Error("Model3D render: this session is already disposed");
289
+ }
290
+ const width = Math.max(1, Math.round(frame.width));
291
+ const height = Math.max(1, Math.round(frame.height));
292
+ const aspect = width / height;
293
+ if (mixer) {
294
+ // Reset before every frame so a render depends only on its own time:
295
+ // a scrub backwards, or one past a non-looping clip's end, draws the
296
+ // same picture whatever was drawn before it.
297
+ for (const action of actions)
298
+ action.reset();
299
+ mixer.setTime(mixerTimeFor(frame.timeSec, duration, loop));
300
+ }
301
+ scene.updateMatrixWorld(true);
302
+ target.copy(sphere.center);
303
+ if (frame.camera.targetOffset) {
304
+ target.x += frame.camera.targetOffset[0];
305
+ target.y += frame.camera.targetOffset[1];
306
+ target.z += frame.camera.targetOffset[2];
307
+ }
308
+ let camera;
309
+ if (frame.camera.mode === "scene") {
310
+ const sceneCamera = selectSceneCamera(sceneCameras, frame.camera.sceneCameraName);
311
+ if (sceneCamera instanceof THREE.PerspectiveCamera) {
312
+ sceneCamera.aspect = aspect;
313
+ sceneCamera.updateProjectionMatrix();
314
+ }
315
+ sceneCamera.getWorldPosition(eye);
316
+ camera = sceneCamera;
317
+ }
318
+ else {
319
+ const framing = computeFraming(sphere.radius, frame.camera.fovDeg, aspect, frame.camera.zoom);
320
+ const offset = orbitOffset(frame.camera.azimuthDeg, frame.camera.elevationDeg, framing.distance);
321
+ orbitCamera.fov = frame.camera.fovDeg;
322
+ orbitCamera.aspect = aspect;
323
+ orbitCamera.near = framing.near;
324
+ orbitCamera.far = framing.far;
325
+ orbitCamera.updateProjectionMatrix();
326
+ orbitCamera.position.set(target.x + offset.x, target.y + offset.y, target.z + offset.z);
327
+ orbitCamera.lookAt(target);
328
+ orbitCamera.updateMatrixWorld(true);
329
+ eye.copy(orbitCamera.position);
330
+ camera = orbitCamera;
331
+ }
332
+ rig.aim(eye, target);
333
+ renderer.setSize(width, height, false);
334
+ renderer.render(scene, camera);
335
+ return canvas;
336
+ },
337
+ dispose() {
338
+ if (disposed)
339
+ return;
340
+ disposed = true;
341
+ if (mixer) {
342
+ mixer.stopAllAction();
343
+ mixer.uncacheRoot(gltf.scene);
344
+ }
345
+ disposeScene(scene);
346
+ renderer.dispose();
347
+ renderer.forceContextLoss();
348
+ }
349
+ };
350
+ }
351
+ /**
352
+ * Render GLB (or embedded-buffer glTF JSON) bytes to PNG bytes. Must run in a
353
+ * browser context (window or worker) with WebGL and `OffscreenCanvas`.
354
+ */
355
+ export async function renderGlbToPng(glb, options) {
356
+ const session = await createModel3DRenderSession(glb, sessionOptionsFromRender3DOptions(options));
357
+ try {
358
+ const canvas = session.render(renderFrameFromRender3DOptions(options));
359
+ const blob = await canvas.convertToBlob({ type: "image/png" });
360
+ return new Uint8Array(await blob.arrayBuffer());
361
+ }
362
+ finally {
363
+ session.dispose();
364
+ }
365
+ }
366
+ //# sourceMappingURL=render3d-core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render3d-core.js","sourceRoot":"","sources":["../../../src/nodes/model3d/render3d-core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Node-side driver for `nodetool.model3d.RenderToImage`.
3
+ *
4
+ * The backend has no WebGL, so it launches a headless Chromium, injects the
5
+ * self-contained render bundle (`dist/render3d-page.js`, built by
6
+ * `scripts/bundle-render3d-page.mjs`), and calls `__nodetoolRenderGlbFrames`
7
+ * over CDP. SwiftShader flags keep WebGL working on GPU-less servers.
8
+ *
9
+ * Chrome discovery follows the automation nodes: `CHROME_PATH` when set,
10
+ * otherwise chrome-launcher's platform search. Everything here is
11
+ * lazy-imported so merely registering the node never requires Chrome.
12
+ */
13
+ import { type Model3DRenderFrame, type Model3DSessionOptions, type Render3DOptions } from "./render3d-core.js";
14
+ interface RuntimeEvaluateResult {
15
+ result?: {
16
+ type?: string;
17
+ value?: unknown;
18
+ };
19
+ exceptionDetails?: {
20
+ text?: string;
21
+ exception?: {
22
+ description?: string;
23
+ value?: unknown;
24
+ };
25
+ };
26
+ }
27
+ interface CdpClient {
28
+ Runtime: {
29
+ /** CDP commands with no return parameters resolve to an empty object. */
30
+ enable(): Promise<object>;
31
+ evaluate(params: {
32
+ expression: string;
33
+ awaitPromise?: boolean;
34
+ returnByValue?: boolean;
35
+ }): Promise<RuntimeEvaluateResult>;
36
+ };
37
+ close(): Promise<void>;
38
+ }
39
+ /**
40
+ * Attach to a freshly launched Chrome's debug port, retrying while it refuses.
41
+ *
42
+ * `chrome-launcher` resolves as soon as the port accepts a TCP connection, but
43
+ * `chrome-remote-interface` then issues an HTTP request to `/json/list` that a
44
+ * still-initializing Chrome refuses outright. A single attempt loses that race
45
+ * on a loaded machine — it turned up as an `ECONNREFUSED` on CI while several
46
+ * other Chrome-driving suites were running — so poll until the endpoint is
47
+ * actually serving.
48
+ *
49
+ * Exported for tests.
50
+ */
51
+ export declare function connectCdp(port: number, { timeoutMs, retryMs }?: {
52
+ retryMs?: number | undefined;
53
+ timeoutMs?: number | undefined;
54
+ }): Promise<CdpClient>;
55
+ /**
56
+ * Launch Chrome, retrying once after a beat. `chrome-launcher` rejects with
57
+ * its port poll's raw error (an `ECONNREFUSED`) when Chromium is too slow to
58
+ * open its debug port on a loaded machine — the same transient race the CDP
59
+ * attach retry above covers, one step earlier. A machine that cannot run
60
+ * Chrome at all fails the same way twice and the second error propagates.
61
+ *
62
+ * Exported for tests.
63
+ */
64
+ export declare function launchChromeWithRetry<T>(launch: () => Promise<T>, retryDelayMs?: number): Promise<T>;
65
+ /**
66
+ * Render one session's worth of frames in a fresh headless Chromium: one
67
+ * launch, one model load, one PNG per frame. One Chrome per call keeps the
68
+ * node stateless; launch cost (~1s) is negligible next to a typical
69
+ * workflow's model-generation steps.
70
+ */
71
+ export declare function renderGlbFramesHeadless(glb: Uint8Array, options: Model3DSessionOptions, frames: readonly Model3DRenderFrame[]): Promise<Uint8Array[]>;
72
+ /** Render GLB bytes to PNG bytes: the one-frame case of the above. */
73
+ export declare function renderGlbHeadless(glb: Uint8Array, options: Render3DOptions): Promise<Uint8Array>;
74
+ export {};
75
+ //# sourceMappingURL=render3d-headless.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render3d-headless.d.ts","sourceRoot":"","sources":["../../../src/nodes/model3d/render3d-headless.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AA0B5B,UAAU,qBAAqB;IAC7B,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5C,gBAAgB,CAAC,EAAE;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,SAAS,CAAC,EAAE;YAAE,WAAW,CAAC,EAAE,MAAM,CAAC;YAAC,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC;KACvD,CAAC;CACH;AAED,UAAU,SAAS;IACjB,OAAO,EAAE;QACP,yEAAyE;QACzE,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1B,QAAQ,CAAC,MAAM,EAAE;YACf,UAAU,EAAE,MAAM,CAAC;YACnB,YAAY,CAAC,EAAE,OAAO,CAAC;YACvB,aAAa,CAAC,EAAE,OAAO,CAAC;SACzB,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAAC;KACpC,CAAC;IACF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAyDD;;;;;;;;;;;GAWG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,EAAE,SAAkC,EAAE,OAA8B,EAAE;;;CAAK,GAC1E,OAAO,CAAC,SAAS,CAAC,CA2BpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACxB,YAAY,SAAQ,GACnB,OAAO,CAAC,CAAC,CAAC,CASZ;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,SAAS,kBAAkB,EAAE,GACpC,OAAO,CAAC,UAAU,EAAE,CAAC,CAgEvB;AAED,sEAAsE;AACtE,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,UAAU,EACf,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,UAAU,CAAC,CAOrB"}