@drawcall/charta 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/loader.d.ts +5 -14
- package/dist/assets/loader.d.ts.map +1 -1
- package/dist/assets/loader.js +33 -64
- package/dist/place/index.d.ts +11 -18
- package/dist/place/index.d.ts.map +1 -1
- package/dist/place/index.js +47 -42
- package/package.json +1 -1
package/dist/assets/loader.d.ts
CHANGED
|
@@ -1,21 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LoadingManager, Loader } from 'three';
|
|
2
2
|
import { Interpreter } from '../interpreter.js';
|
|
3
|
-
export
|
|
4
|
-
mock
|
|
5
|
-
};
|
|
6
|
-
export declare class AssetLoader extends Group {
|
|
7
|
-
private interpreter;
|
|
8
|
-
private options;
|
|
9
|
-
private manager;
|
|
3
|
+
export declare class AssetLoader extends Loader<void, Interpreter> {
|
|
4
|
+
private readonly mock;
|
|
10
5
|
private textureLoader;
|
|
11
6
|
private gltfLoader;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
constructor(interpreter: Interpreter, options?: AssetLoaderOptions);
|
|
15
|
-
updateMatrixWorld(force?: boolean): void;
|
|
7
|
+
constructor(manager?: LoadingManager, mock?: boolean);
|
|
8
|
+
load(interpreter: Interpreter, onLoad: (data: void) => void, onProgress?: (event: ProgressEvent) => void, onError?: (err: unknown) => void): void;
|
|
16
9
|
private handleLoadTexture;
|
|
17
10
|
private handleLoadModel;
|
|
18
|
-
whenReady(): Promise<void>;
|
|
19
|
-
dispose(): void;
|
|
20
11
|
}
|
|
21
12
|
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/assets/loader.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/assets/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,cAAc,EAAqB,MAAM,EAAW,MAAM,OAAO,CAAA;AAEzG,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAU/C,qBAAa,WAAY,SAAQ,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC;IAIlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAH3D,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,UAAU,CAAY;gBAElB,OAAO,CAAC,EAAE,cAAc,EAAmB,IAAI,GAAE,OAAe;IAM5E,IAAI,CACF,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,EAC5B,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EAC3C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAC/B,IAAI;YAuBO,iBAAiB;YA8BjB,eAAe;CAuC9B"}
|
package/dist/assets/loader.js
CHANGED
|
@@ -1,79 +1,67 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Texture, TextureLoader, Object3D, Loader, Vector3 } from 'three';
|
|
2
2
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
3
3
|
import { ChartaError } from '../errors.js';
|
|
4
|
-
import { ObjectFactory } from '../place/index.js';
|
|
5
4
|
import { InstancedMeshGroup } from '../utils/instanced-mesh-group.js';
|
|
6
5
|
import { object, string } from 'zod';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import { measureObject, PrefabBatchBuilder } from '../place/index.js';
|
|
7
|
+
// Schemas
|
|
8
|
+
const basePathSchema = object({ path: string() });
|
|
9
|
+
const loadTextureSchema = object({ name: string(), path: string() });
|
|
10
|
+
const loadModelSchema = object({ name: string(), path: string() });
|
|
11
|
+
export class AssetLoader extends Loader {
|
|
12
|
+
mock;
|
|
11
13
|
textureLoader;
|
|
12
14
|
gltfLoader;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
this.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.textureLoader = new TextureLoader(this.manager);
|
|
21
|
-
this.gltfLoader = new GLTFLoader(this.manager);
|
|
22
|
-
const promises = [];
|
|
23
|
-
// Schemas
|
|
24
|
-
const basePathSchema = object({ path: string() });
|
|
25
|
-
const loadTextureSchema = object({ name: string(), path: string() });
|
|
26
|
-
const loadModelSchema = object({ name: string(), path: string() });
|
|
27
|
-
// Parse meta row calls
|
|
15
|
+
constructor(manager, mock = false) {
|
|
16
|
+
super(manager);
|
|
17
|
+
this.mock = mock;
|
|
18
|
+
this.textureLoader = new TextureLoader(manager);
|
|
19
|
+
this.gltfLoader = new GLTFLoader(manager);
|
|
20
|
+
}
|
|
21
|
+
load(interpreter, onLoad, onProgress, onError) {
|
|
28
22
|
const calls = interpreter.getCalls(undefined, {
|
|
29
23
|
basePath: basePathSchema,
|
|
30
24
|
loadTexture: loadTextureSchema,
|
|
31
25
|
loadModel: loadModelSchema,
|
|
32
26
|
});
|
|
27
|
+
const promises = [];
|
|
33
28
|
let basePath;
|
|
34
29
|
for (const [key, args, , location] of calls) {
|
|
35
30
|
if (key === 'basePath') {
|
|
36
31
|
basePath = args.path.length === 0 ? undefined : args.path;
|
|
37
32
|
}
|
|
38
33
|
else if (key === 'loadTexture') {
|
|
39
|
-
promises.push(this.handleLoadTexture(args.name, basePath, args.path, location));
|
|
34
|
+
promises.push(this.handleLoadTexture(interpreter, args.name, basePath, args.path, location));
|
|
40
35
|
}
|
|
41
36
|
else if (key === 'loadModel') {
|
|
42
|
-
promises.push(this.handleLoadModel(args.name, basePath, args.path, location));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
this._whenReady = Promise.all(promises).then(() => { });
|
|
46
|
-
}
|
|
47
|
-
updateMatrixWorld(force) {
|
|
48
|
-
if (this.pendingFinalizers.length > 0) {
|
|
49
|
-
for (const finalize of this.pendingFinalizers) {
|
|
50
|
-
finalize();
|
|
37
|
+
promises.push(this.handleLoadModel(interpreter, args.name, basePath, args.path, location));
|
|
51
38
|
}
|
|
52
|
-
this.pendingFinalizers.length = 0;
|
|
53
39
|
}
|
|
54
|
-
|
|
40
|
+
Promise.all(promises)
|
|
41
|
+
.then(() => onLoad())
|
|
42
|
+
.catch((reason) => onError?.(reason));
|
|
55
43
|
}
|
|
56
|
-
async handleLoadTexture(name, basePath, path, location) {
|
|
57
|
-
if (this.
|
|
44
|
+
async handleLoadTexture(interpreter, name, basePath, path, location) {
|
|
45
|
+
if (this.mock) {
|
|
58
46
|
const texture = new Texture();
|
|
59
47
|
texture.name = name;
|
|
60
|
-
|
|
48
|
+
interpreter.setAsset(`${name}BaseColorTexture`, texture);
|
|
61
49
|
return;
|
|
62
50
|
}
|
|
63
51
|
const fullPath = new URL(path, basePath).href;
|
|
64
52
|
try {
|
|
65
53
|
const texture = await this.textureLoader.loadAsync(fullPath);
|
|
66
54
|
texture.name = name;
|
|
67
|
-
|
|
55
|
+
interpreter.setAsset(`${name}BaseColorTexture`, texture);
|
|
68
56
|
}
|
|
69
57
|
catch (err) {
|
|
70
|
-
|
|
58
|
+
interpreter.reportError(new ChartaError(`Failed to load texture "${name}" at "${fullPath}". Is the url correct?`, interpreter.getSource(), location));
|
|
71
59
|
}
|
|
72
60
|
}
|
|
73
|
-
async handleLoadModel(name, basePath, path, location) {
|
|
74
|
-
if (this.
|
|
75
|
-
const
|
|
76
|
-
|
|
61
|
+
async handleLoadModel(interpreter, name, basePath, path, location) {
|
|
62
|
+
if (this.mock) {
|
|
63
|
+
const batchBuilder = new PrefabBatchBuilder(new Vector3(), () => new Object3D());
|
|
64
|
+
interpreter.setAsset(`${name}Prefab`, batchBuilder);
|
|
77
65
|
return;
|
|
78
66
|
}
|
|
79
67
|
const fullPath = new URL(path, basePath).href;
|
|
@@ -84,30 +72,11 @@ export class AssetLoader extends Group {
|
|
|
84
72
|
object.castShadow = true;
|
|
85
73
|
object.receiveShadow = true;
|
|
86
74
|
});
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
matrices.push(new Matrix4().compose(position, rotation, scale));
|
|
90
|
-
});
|
|
91
|
-
this.interpreter.setAsset(`${name}Factory`, factory);
|
|
92
|
-
this.pendingFinalizers.push(() => {
|
|
93
|
-
if (matrices.length > 0) {
|
|
94
|
-
this.add(new InstancedMeshGroup(scene, matrices.length, matrices));
|
|
95
|
-
}
|
|
96
|
-
});
|
|
75
|
+
const batchBuilder = new PrefabBatchBuilder(measureObject(scene), (matrices) => new InstancedMeshGroup(scene, matrices.length, matrices));
|
|
76
|
+
interpreter.setAsset(`${name}Prefab`, batchBuilder);
|
|
97
77
|
}
|
|
98
78
|
catch (err) {
|
|
99
|
-
|
|
79
|
+
interpreter.reportError(new ChartaError(`Failed to load model ${name} at ${fullPath}: ${err instanceof Error ? err.message : String(err)}`, interpreter.getSource(), location));
|
|
100
80
|
}
|
|
101
81
|
}
|
|
102
|
-
async whenReady() {
|
|
103
|
-
return this._whenReady;
|
|
104
|
-
}
|
|
105
|
-
dispose() {
|
|
106
|
-
this.traverse((child) => {
|
|
107
|
-
if (child instanceof InstancedMeshGroup) {
|
|
108
|
-
child.dispose();
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
this.clear();
|
|
112
|
-
}
|
|
113
82
|
}
|
package/dist/place/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Group, Material, Object3D, Quaternion, Vector3 } from 'three';
|
|
1
|
+
import { Group, Material, Matrix4, Object3D, Quaternion, Vector3 } from 'three';
|
|
2
2
|
import { Interpreter } from '../interpreter.js';
|
|
3
3
|
export type MeasureFunction = (target: Vector3) => void;
|
|
4
4
|
export type InstantiateFunction = (args: {
|
|
@@ -13,25 +13,18 @@ export type InstantiateFunction = (args: {
|
|
|
13
13
|
};
|
|
14
14
|
name: string;
|
|
15
15
|
}) => void;
|
|
16
|
-
export declare
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
scale: Vector3;
|
|
25
|
-
interpreter: Interpreter;
|
|
26
|
-
cell: {
|
|
27
|
-
row: number;
|
|
28
|
-
col: number;
|
|
29
|
-
center: [number, number];
|
|
30
|
-
};
|
|
31
|
-
name: string;
|
|
32
|
-
}): void;
|
|
16
|
+
export declare function measureObject(object: Object3D): Vector3;
|
|
17
|
+
export declare class PrefabBatchBuilder {
|
|
18
|
+
readonly prefabSize: Vector3;
|
|
19
|
+
private readonly buildFromMatrices;
|
|
20
|
+
private matrices;
|
|
21
|
+
constructor(prefabSize: Vector3, buildFromMatrices: (matrices: Array<Matrix4>) => Object3D);
|
|
22
|
+
add(matrix: Matrix4): this;
|
|
23
|
+
build(): Object3D;
|
|
33
24
|
}
|
|
34
25
|
export declare class PlaceGroup extends Group {
|
|
26
|
+
private batchBuilders;
|
|
35
27
|
constructor(interpreter: Interpreter, _materialFallback?: Material);
|
|
28
|
+
dispose(): void;
|
|
36
29
|
}
|
|
37
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/place/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/place/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAQ,MAAM,OAAO,CAAA;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAmC/C,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;AAEvD,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE;IACvC,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,UAAU,CAAA;IACpB,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,WAAW,CAAA;IACxB,IAAI,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KAAE,CAAA;IAC5D,IAAI,EAAE,MAAM,CAAA;CACb,KAAK,IAAI,CAAA;AAKV,wBAAgB,aAAa,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAOvD;AAED,qBAAa,kBAAkB;aAIX,UAAU,EAAE,OAAO;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAJpC,OAAO,CAAC,QAAQ,CAAqB;gBAGnB,UAAU,EAAE,OAAO,EAClB,iBAAiB,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,QAAQ;IAG5E,GAAG,CAAC,MAAM,EAAE,OAAO;IAKZ,KAAK,IAAI,QAAQ;CAKzB;AAED,qBAAa,UAAW,SAAQ,KAAK;IACnC,OAAO,CAAC,aAAa,CAAgC;gBAEzC,WAAW,EAAE,WAAW,EAAE,iBAAiB,CAAC,EAAE,QAAQ;IAqNlE,OAAO;CAOR"}
|
package/dist/place/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Group, Matrix4,
|
|
1
|
+
import { Group, Matrix4, Quaternion, Vector3, Box3 } from 'three';
|
|
2
2
|
import { TilesGeometry } from '../tiles/geometry.js';
|
|
3
3
|
import { coerce, object, string, enum as zodEnum } from 'zod';
|
|
4
4
|
import { createRng, hashNumbersToUint32, hashStringToUint32 } from '../utils/random.js';
|
|
@@ -30,28 +30,35 @@ const placeSchema = object({
|
|
|
30
30
|
sizeZ: coerce.number().optional(),
|
|
31
31
|
});
|
|
32
32
|
const boxHelper = new Box3();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
const matrixHelper = new Matrix4();
|
|
34
|
+
export function measureObject(object) {
|
|
35
|
+
const parent = object.parent;
|
|
36
|
+
object.parent = null;
|
|
37
|
+
const target = new Vector3();
|
|
38
|
+
boxHelper.setFromObject(object).getSize(target);
|
|
39
|
+
object.parent = parent;
|
|
40
|
+
return target;
|
|
41
|
+
}
|
|
42
|
+
export class PrefabBatchBuilder {
|
|
43
|
+
prefabSize;
|
|
44
|
+
buildFromMatrices;
|
|
45
|
+
matrices = [];
|
|
46
|
+
constructor(prefabSize, buildFromMatrices) {
|
|
47
|
+
this.prefabSize = prefabSize;
|
|
48
|
+
this.buildFromMatrices = buildFromMatrices;
|
|
39
49
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
this._measure.parent = null;
|
|
44
|
-
boxHelper.setFromObject(this._measure).getSize(target);
|
|
45
|
-
this._measure.parent = parent;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
this._measure(target);
|
|
50
|
+
add(matrix) {
|
|
51
|
+
this.matrices.push(matrix.clone());
|
|
52
|
+
return this;
|
|
49
53
|
}
|
|
50
|
-
|
|
51
|
-
this.
|
|
54
|
+
build() {
|
|
55
|
+
const batch = this.buildFromMatrices(this.matrices);
|
|
56
|
+
this.matrices = [];
|
|
57
|
+
return batch;
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
export class PlaceGroup extends Group {
|
|
61
|
+
batchBuilders = new Set();
|
|
55
62
|
constructor(interpreter, _materialFallback) {
|
|
56
63
|
super();
|
|
57
64
|
const rows = interpreter.getRows();
|
|
@@ -120,12 +127,13 @@ export class PlaceGroup extends Group {
|
|
|
120
127
|
// scatter: randomized distribution, density is count for now
|
|
121
128
|
for (const [, parsed, callIdx, loc] of scatterEntries) {
|
|
122
129
|
const layerIndex = interpreter.countCalls([z, x], (c) => c.name === 'ground' || c.name === 'ceiling', 0, callIdx) - 1;
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
if (!
|
|
130
|
+
const prefabName = `${parsed.model}Prefab`;
|
|
131
|
+
const batchBuilder = interpreter.getAsset(PrefabBatchBuilder, prefabName, loc);
|
|
132
|
+
if (!batchBuilder)
|
|
126
133
|
continue;
|
|
134
|
+
this.batchBuilders.add(batchBuilder);
|
|
127
135
|
const usualSize = new Vector3();
|
|
128
|
-
|
|
136
|
+
usualSize.copy(batchBuilder.prefabSize);
|
|
129
137
|
const base = hashStringToUint32(parsed.model);
|
|
130
138
|
const seed = hashNumbersToUint32(base, z, x);
|
|
131
139
|
const rng = createRng(seed);
|
|
@@ -168,14 +176,7 @@ export class PlaceGroup extends Group {
|
|
|
168
176
|
: minSizeZ ?? maxSizeZ;
|
|
169
177
|
const scale = computeScale(usualSize, sX, sZ);
|
|
170
178
|
scl.multiply(scale);
|
|
171
|
-
|
|
172
|
-
position: pos,
|
|
173
|
-
rotation: quat,
|
|
174
|
-
scale: scl,
|
|
175
|
-
interpreter,
|
|
176
|
-
cell: { row: z, col: x, center: [cx, cz] },
|
|
177
|
-
name: parsed.model,
|
|
178
|
-
});
|
|
179
|
+
batchBuilder.add(matrixHelper.compose(pos, quat, scl));
|
|
179
180
|
}
|
|
180
181
|
}
|
|
181
182
|
// place: exact in-cell placement
|
|
@@ -193,24 +194,28 @@ export class PlaceGroup extends Group {
|
|
|
193
194
|
fixedY: parsed.bottomY,
|
|
194
195
|
layerIndex,
|
|
195
196
|
});
|
|
196
|
-
const
|
|
197
|
-
const
|
|
198
|
-
if (!
|
|
197
|
+
const prefabName = `${parsed.model}Prefab`;
|
|
198
|
+
const batchBuilder = interpreter.getAsset(PrefabBatchBuilder, prefabName, loc);
|
|
199
|
+
if (!batchBuilder)
|
|
199
200
|
continue;
|
|
201
|
+
this.batchBuilders.add(batchBuilder);
|
|
200
202
|
const usualSize = new Vector3();
|
|
201
|
-
|
|
203
|
+
usualSize.copy(batchBuilder.prefabSize);
|
|
202
204
|
const scale = computeScale(usualSize, parsed.sizeX, parsed.sizeZ);
|
|
203
205
|
scl.multiply(scale);
|
|
204
|
-
|
|
205
|
-
position: pos,
|
|
206
|
-
rotation: quat,
|
|
207
|
-
scale: scl,
|
|
208
|
-
interpreter,
|
|
209
|
-
cell: { row: z, col: x, center: [cx, cz] },
|
|
210
|
-
name: parsed.model,
|
|
211
|
-
});
|
|
206
|
+
batchBuilder.add(matrixHelper.compose(pos, quat, scl));
|
|
212
207
|
}
|
|
213
208
|
}
|
|
214
209
|
}
|
|
210
|
+
for (const batchBuilder of this.batchBuilders) {
|
|
211
|
+
this.add(batchBuilder.build());
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
dispose() {
|
|
215
|
+
for (const child of this.children) {
|
|
216
|
+
if ('dispose' in child && typeof child.dispose === 'function') {
|
|
217
|
+
child.dispose();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
215
220
|
}
|
|
216
221
|
}
|