@threenative/core 0.3.0 → 0.3.2

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 (39) hide show
  1. package/README.md +10 -0
  2. package/capabilities.json +1881 -131
  3. package/dist/assets-kyoF7JlJ.d.ts +103 -0
  4. package/dist/{audio-Dp2mXpD3.d.ts → audio-BFiGneTL.d.ts} +62 -0
  5. package/dist/canvas-layer-BLVijiUJ.d.ts +62 -0
  6. package/dist/{game-CYIaKhgl.d.ts → game-XGrTzapq.d.ts} +350 -164
  7. package/dist/gpu-readback-D2iRvoe9.d.ts +112 -0
  8. package/dist/hot.d.ts +5 -3
  9. package/dist/hot.js +5 -1
  10. package/dist/index.d.ts +813 -143
  11. package/dist/index.js +4548 -941
  12. package/dist/net.d.ts +65 -0
  13. package/dist/net.js +643 -0
  14. package/dist/playtest.d.ts +29 -5
  15. package/dist/playtest.js +181 -35
  16. package/dist/react.d.ts +4 -2
  17. package/dist/{canvas-layer-CtrZHgIh.d.ts → renderer-C6hqZpoG.d.ts} +237 -75
  18. package/dist/world.d.ts +203 -4
  19. package/dist/world.js +2536 -25
  20. package/gpl/LICENSE.GPL +117 -0
  21. package/gpl/convert.py +192 -0
  22. package/gpl/recipes/_common.py +169 -0
  23. package/gpl/recipes/bake_ao.py +111 -0
  24. package/gpl/recipes/decimate.py +64 -0
  25. package/gpl/recipes/retarget.py +131 -0
  26. package/gpl/recipes/unwrap.py +71 -0
  27. package/mcp/blender-server.mjs +632 -0
  28. package/mcp/blender.mjs +27 -0
  29. package/mcp/engine-server.mjs +271 -23
  30. package/mcp/engine.mjs +15 -7
  31. package/mcp/install.d.mts +37 -0
  32. package/mcp/install.mjs +94 -26
  33. package/mcp/servers.d.mts +34 -0
  34. package/mcp/servers.mjs +110 -9
  35. package/package.json +36 -8
  36. package/patches/three@0.185.1.patch +249 -14
  37. package/scripts/ensure-mcp.mjs +20 -13
  38. package/scripts/bundle-engine-mcp.mjs +0 -15
  39. package/scripts/generate-version.mjs +0 -13
package/dist/world.d.ts CHANGED
@@ -1,4 +1,175 @@
1
- import { Vector3, BufferGeometry } from 'three';
1
+ import { Object3D, Mesh, LOD, Vector3, Group, BufferGeometry } from 'three';
2
+ import { I as IComputeDriven, a as IGPUReadbackSample } from './gpu-readback-D2iRvoe9.js';
3
+ import { I as IRendererLike } from './renderer-C6hqZpoG.js';
4
+ import { I as IAssetLoader } from './assets-kyoF7JlJ.js';
5
+ import 'three/webgpu';
6
+
7
+ interface IWorldErosionOptions {
8
+ readonly depositionRate: number;
9
+ readonly erosionRate: number;
10
+ readonly evaporation: number;
11
+ readonly iterations: number;
12
+ readonly rainfall: number;
13
+ readonly sedimentCapacity: number;
14
+ readonly timeStep: number;
15
+ }
16
+
17
+ type MeshSurface = NonNullable<ConstructorParameters<typeof Mesh>[1]>;
18
+ interface IWorldTileCollider {
19
+ dispose(): void;
20
+ }
21
+ interface IWorldTileColliderInput {
22
+ readonly field: Heightfield;
23
+ readonly key: string;
24
+ readonly object: Object3D;
25
+ readonly tileX: number;
26
+ readonly tileZ: number;
27
+ }
28
+ interface IWorldTile {
29
+ readonly bytes: number;
30
+ readonly collider: IWorldTileCollider;
31
+ readonly field: Heightfield;
32
+ readonly key: string;
33
+ readonly lod: LOD;
34
+ readonly lodLevel: number;
35
+ readonly object: Object3D;
36
+ readonly skirtVertexCount: number;
37
+ readonly tileX: number;
38
+ readonly tileZ: number;
39
+ }
40
+ interface IWorldTilesFollowPosition {
41
+ readonly x: number;
42
+ readonly z: number;
43
+ }
44
+ interface IWorldTilesTopologyObservation {
45
+ readonly columns: number;
46
+ readonly depth: number;
47
+ readonly origin: IHeightfieldOrigin;
48
+ readonly rows: number;
49
+ readonly width: number;
50
+ }
51
+ interface IWorldTilesOptions {
52
+ /** Releases a caller-supplied model key when its last tile reference is evicted. */
53
+ readonly assets?: Pick<IAssetLoader, "release">;
54
+ /** A game-owned, already-loaded logical model key, or a key resolver per tile. */
55
+ readonly assetKey?: string | ((tileX: number, tileZ: number) => string);
56
+ /** Creates the physics body from the field's explicit collider-order copy. */
57
+ readonly createCollider?: (input: IWorldTileColliderInput) => IWorldTileCollider;
58
+ /** TSL pass options are game supplied and are forwarded to each resident field. */
59
+ readonly worldPasses?: IHeightfieldWorldPassOptions;
60
+ /** Game-owned surface; this class never creates or mutates it. */
61
+ readonly surface: MeshSurface;
62
+ readonly residentByteBudget: number;
63
+ readonly residentTileBudget: number;
64
+ readonly sampleHeight: IHeightfieldSamplerOptions["sampleHeight"];
65
+ /** How deep each edge skirt extends below its surface. Defaults to one tile width. */
66
+ readonly skirtDepth?: number;
67
+ /** Square tile neighborhood to consider around the followed point. Defaults to 1. */
68
+ readonly streamRadius?: number;
69
+ readonly tileResolution: number;
70
+ readonly tileSize: number;
71
+ /** Vertex decimation factors. Defaults to 1, 2, and 4 over the same field. */
72
+ readonly lodFactors?: readonly number[];
73
+ /** Distances in world units at which the next LOD becomes active. */
74
+ readonly lodDistances?: readonly number[];
75
+ /** Explicit game-owned measurement region used by the topology evaluator. */
76
+ readonly topologyObservation?: IWorldTilesTopologyObservation;
77
+ }
78
+ /**
79
+ * Stream a bounded square of game-authored heightfields and keep their render and physics units
80
+ * together. The class composes ordinary THREE.LOD objects and leaves frustum/projection culling
81
+ * to the renderer's existing scene path.
82
+ *
83
+ * @situation stream terrain without cracks
84
+ * @situation keep generated terrain resident around a moving player
85
+ * @situation put a generated terrain tile into a game-owned physics world
86
+ * @alias stream terrain across chunks
87
+ * @constraint sampleHeight and surface are required game choices; no landform or surface preset is installed
88
+ * @constraint residentTileBudget and residentByteBudget are hard caps; a tile that cannot fit throws
89
+ * @override tileSize, tileResolution, lodFactors, lodDistances, skirtDepth, streamRadius, and budgets
90
+ * @example const tiles = new TerrainTiles({ sampleHeight, surface: gameSurface(), tileSize: 256, tileResolution: 129, residentTileBudget: 25, residentByteBudget: 32_000_000 });
91
+ */
92
+ declare class TerrainTiles extends Object3D implements IComputeDriven {
93
+ #private;
94
+ readonly residentTileBudget: number;
95
+ readonly residentByteBudget: number;
96
+ readonly skirtDepth: number;
97
+ readonly tileResolution: number;
98
+ readonly tileSize: number;
99
+ readonly processCadence: "render";
100
+ constructor(options: IWorldTilesOptions);
101
+ get released(): boolean;
102
+ get residentTileCount(): number;
103
+ get residentBytes(): number;
104
+ get peakResidentTileCount(): number;
105
+ get peakResidentBytes(): number;
106
+ get residentKeys(): readonly string[];
107
+ get residentColliderKeys(): readonly string[];
108
+ get lodLevelCount(): number;
109
+ get lodTransitions(): number;
110
+ /** Maximum per-render-frame displacement of the visible LOD surface during transitions. */
111
+ get maxLodPop(): number;
112
+ /** Maximum number of rendered frames during which an LOD transition remained observable. */
113
+ get maxLodTransitionFrames(): number;
114
+ /** Maximum visible edge gap observed across follow/process calls for this residency owner. */
115
+ get maxSeamGap(): number;
116
+ /** Maximum remaining visible gap after skirt or bridge coverage observed across follow/process calls. */
117
+ get maxVisualSeamGap(): number;
118
+ /** Number of mixed-LOD edge reconciliations observed during this residency lifetime. */
119
+ get stitchedEdgeCount(): number;
120
+ get warmupNodes(): readonly unknown[];
121
+ getTile(key: string): IWorldTile | undefined;
122
+ follow(position: IWorldTilesFollowPosition | Pick<Vector3, "x" | "z">): void;
123
+ heightAt(x: number, z: number): number;
124
+ normalAt(x: number, z: number, target?: Vector3): Vector3;
125
+ sample(channel: string, x: number, z: number): number;
126
+ attachRenderer(renderer: IRendererLike): void;
127
+ process(renderer?: IRendererLike | undefined): void;
128
+ debug(): Record<string, unknown>;
129
+ detach(): void;
130
+ dispose(): void;
131
+ }
132
+
133
+ type WorldGenerationPath = "gpu" | "cpu-fallback" | "unsupported";
134
+ interface IWorldComputeLimits {
135
+ readonly maxComputeInvocationsPerWorkgroup: number;
136
+ readonly maxComputeWorkgroupsPerDimension: number;
137
+ readonly maxStorageBufferBindingSize: number;
138
+ }
139
+ interface IWorldCapabilities {
140
+ readonly compute: boolean;
141
+ /** Whether the host exposed a GPU adapter, even when its limits cannot run the world pass. */
142
+ readonly gpu: boolean;
143
+ readonly generation: WorldGenerationPath;
144
+ readonly limits: IWorldComputeLimits;
145
+ readonly cpuFallbackIterations: number;
146
+ readonly reason?: string;
147
+ }
148
+ interface IWorldCapabilitiesOptions {
149
+ /** Explicitly supplied by a host that already probed its adapter. */
150
+ readonly gpuAvailable?: boolean;
151
+ readonly limits?: Partial<IWorldComputeLimits>;
152
+ readonly minimumWorkgroupsPerDimension?: number;
153
+ readonly minimumStorageBufferBindingSize?: number;
154
+ /** A positive value makes CPU generation an explicit, reduced fallback. */
155
+ readonly cpuFallbackIterations?: number;
156
+ }
157
+ /**
158
+ * Resolve the active world-generation path from host capability facts.
159
+ *
160
+ * The function accepts the adapter facts instead of reaching through a renderer-specific global,
161
+ * so browser and native hosts can report the same object. Missing limits are not treated as
162
+ * infinite: a host must either provide a valid GPU limit report or explicitly choose CPU fallback.
163
+ * GPU generation remains unavailable until a GPU readback can own the canonical field; a host
164
+ * adapter report therefore never upgrades a CPU fallback into a GPU generation claim.
165
+ *
166
+ * @situation decide whether generated terrain can use GPU compute
167
+ * @situation report why terrain generation is using a reduced CPU fallback
168
+ * @constraint unsupported is returned when compute limits are unknown or below the requirement; callers must not silently continue
169
+ * @override minimumWorkgroupsPerDimension, minimumStorageBufferBindingSize, and cpuFallbackIterations
170
+ * @example const capabilities = getWorldCapabilities({ limits: adapter.limits, cpuFallbackIterations: 8 });
171
+ */
172
+ declare function getWorldCapabilities(options?: IWorldCapabilitiesOptions): IWorldCapabilities;
2
173
 
3
174
  interface IHeightfieldOrigin {
4
175
  readonly x: number;
@@ -11,11 +182,24 @@ interface IHeightfieldOptions {
11
182
  readonly origin: IHeightfieldOrigin;
12
183
  readonly rows: number;
13
184
  readonly width: number;
185
+ readonly worldPasses?: IHeightfieldWorldPassOptions;
186
+ }
187
+ interface IHeightfieldWorldPassOptions {
188
+ /** Maximum TSL compute dispatches submitted by one rendered frame. */
189
+ readonly dispatchBudget: number;
190
+ /** Reserved GPU path; true is rejected until GPU readback owns the canonical field. */
191
+ readonly gpu?: boolean;
192
+ /** Every physical coefficient is game supplied; core owns no terrain preset. */
193
+ readonly erosion: IWorldErosionOptions;
14
194
  }
15
195
  interface IHeightfieldSamplerOptions extends Omit<IHeightfieldOptions, "heights"> {
16
196
  /** Game-owned terrain function. It is evaluated once and never retained. */
17
197
  readonly sampleHeight: (x: number, z: number) => number;
18
198
  }
199
+ interface IStoredHeightfieldChannels {
200
+ readonly flow?: Float32Array;
201
+ readonly moisture?: Float32Array;
202
+ }
19
203
  /**
20
204
  * One height buffer shared by world queries, rendered geometry, and a physics heightfield.
21
205
  *
@@ -25,25 +209,40 @@ interface IHeightfieldSamplerOptions extends Omit<IHeightfieldOptions, "heights"
25
209
  * again.
26
210
  *
27
211
  * @situation build terrain geometry and collision from one game-authored height function
212
+ * @situation generate a terrain a player can walk across
28
213
  * @situation query the same ground height or normal that a player sees and collides with
214
+ * @situation ask how high the ground is here
29
215
  * @situation build islands and coastlines from terrain
30
216
  * @constraint sampleHeight owns the terrain shape and stays in game source; the framework stores and interpolates its output
31
217
  * @constraint rows and columns are vertex counts; geometry is row-major z-then-x and collider export transposes once into Rapier's column-major matrix order
32
218
  * @override rows, columns, width, depth, origin, and sampleHeight are explicit on every field
33
219
  * @example const field = Heightfield.fromSampler({ rows: 65, columns: 65, width: 64, depth: 64, origin: { x: 0, z: 0 }, sampleHeight: terrainHeight });
34
220
  */
35
- declare class Heightfield {
221
+ declare class Heightfield extends Group implements IComputeDriven {
36
222
  #private;
37
223
  readonly columns: number;
38
224
  readonly depth: number;
39
225
  readonly origin: IHeightfieldOrigin;
40
226
  readonly rows: number;
41
227
  readonly width: number;
42
- constructor(options: IHeightfieldOptions);
228
+ readonly processCadence: "render";
229
+ readonly warmupNodes: readonly unknown[];
230
+ constructor(options: IHeightfieldOptions & IStoredHeightfieldChannels);
43
231
  static fromSampler(options: IHeightfieldSamplerOptions): Heightfield;
44
232
  sample(channel: string, x: number, z: number): number;
233
+ get released(): boolean;
234
+ get generationComplete(): boolean;
235
+ get gpuHeightSample(): IGPUReadbackSample | undefined;
236
+ attachRenderer(renderer: IRendererLike): void;
237
+ process(renderer?: IRendererLike | undefined): void;
238
+ debug(): Record<string, unknown>;
239
+ detach(): void;
45
240
  /** A copy of the canonical row-major samples, safe for game-side analysis. */
46
241
  get heights(): Float32Array;
242
+ /** A copy of the normalized routed-flow channel, when world passes were requested. */
243
+ get flow(): Float32Array | undefined;
244
+ /** Bytes retained by this field's CPU channels and its conservative GPU allowance. */
245
+ get memoryBytes(): number;
47
246
  heightAt(x: number, z: number): number;
48
247
  normalAt(x: number, z: number, target?: Vector3): Vector3;
49
248
  /** The same values transposed once into Rapier's column-major height-matrix order. */
@@ -52,4 +251,4 @@ declare class Heightfield {
52
251
  toGeometry(): BufferGeometry;
53
252
  }
54
253
 
55
- export { Heightfield, type IHeightfieldOptions, type IHeightfieldOrigin, type IHeightfieldSamplerOptions };
254
+ export { Heightfield, type IHeightfieldOptions, type IHeightfieldOrigin, type IHeightfieldSamplerOptions, type IHeightfieldWorldPassOptions, type IWorldCapabilities, type IWorldTileColliderInput, type IWorldTilesTopologyObservation, TerrainTiles, getWorldCapabilities };