@navaramap/three 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/fontWorker-OwvKiQ8o.js +2 -0
- package/dist/assets/fontWorker-OwvKiQ8o.js.map +1 -0
- package/dist/assets/{index-ywHSGImj.js → index-TKhRxurv.js} +2 -2
- package/dist/assets/index-TKhRxurv.js.map +1 -0
- package/dist/assets/{navara_wasm_font_worker_bg-Du9nb2Pn.wasm → navara_wasm_font_worker_bg-Kk06ArRB.wasm} +0 -0
- package/dist/assets/{navara_wasm_worker_bg-Xadu67fw.wasm → navara_wasm_worker_bg-BZjLKf4i.wasm} +0 -0
- package/dist/index.d.ts +349 -282
- package/dist/index.js +5394 -5470
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +287 -235
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +12 -12
- package/src/atmosphere.test.ts +227 -28
- package/src/atmosphere.ts +219 -55
- package/src/constants/assets.ts +63 -13
- package/src/declutter/types.ts +1 -1
- package/src/evaluations/FeatureEvaluator.test.ts +152 -0
- package/src/evaluations/FeatureEvaluator.ts +73 -2
- package/src/event/features/billboard.ts +1 -0
- package/src/event/features/point.ts +1 -0
- package/src/index.ts +7 -9
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/index.ts +10 -7
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.test.ts +74 -81
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/mutates.ts +18 -85
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/shader.test.ts +77 -0
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/shader.ts +9 -1
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.test.ts +15 -19
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/state.ts +0 -13
- package/src/material/enhancer/sdfText/sdfTextBaseEnhancer/types.ts +46 -48
- package/src/mesh/constants.ts +22 -0
- package/src/mesh/index.ts +1 -1
- package/src/mesh/model.ts +6 -0
- package/src/mesh/polygon.ts +6 -0
- package/src/mesh/polyline.ts +6 -0
- package/src/mesh/sdfText/batchedSdfText.ts +1223 -0
- package/src/mesh/sdfText/glyphBuffers.ts +222 -0
- package/src/mesh/sdfText/glyphSlots.test.ts +151 -0
- package/src/mesh/sdfText/glyphSlots.ts +98 -0
- package/src/mesh/sdfText/index.ts +10 -0
- package/src/mesh/sdfText/labelData.test.ts +178 -0
- package/src/mesh/sdfText/labelData.ts +187 -0
- package/src/mesh/{sdfText.test.ts → sdfText/layout.test.ts} +1 -1
- package/src/mesh/sdfText/layout.ts +306 -0
- package/src/mesh/sprite/instancedSprite.ts +32 -0
- package/dist/assets/fontWorker-wz61edjR.js +0 -2
- package/dist/assets/fontWorker-wz61edjR.js.map +0 -1
- package/dist/assets/index-ywHSGImj.js.map +0 -1
- package/src/mesh/batchedSdfText.ts +0 -708
- package/src/mesh/sdfText.ts +0 -1189
- /package/dist/{draco_decoder.wasm → assets/draco_decoder-C32yEggz.wasm} +0 -0
- /package/dist/{draco_decoder2.wasm → assets/draco_decoder-Z1_iN-Ht.wasm} +0 -0
|
@@ -14,7 +14,7 @@ import { BufferGeometry, Mesh, Object3D } from "three";
|
|
|
14
14
|
import type { NormalBufferAttributes } from "three";
|
|
15
15
|
|
|
16
16
|
import { Color } from "../Color";
|
|
17
|
-
import type { FeatureHandler } from "../event";
|
|
17
|
+
import type { FeatureHandler } from "../event/context";
|
|
18
18
|
import {
|
|
19
19
|
InstancedMesh,
|
|
20
20
|
isFeatureMesh,
|
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
type BatchedAttributeName,
|
|
26
26
|
InstancedSpriteMesh,
|
|
27
27
|
BatchedSdfTextMesh,
|
|
28
|
+
type GeometryType,
|
|
29
|
+
VALID_GEOMETRY_TYPES,
|
|
28
30
|
} from "../mesh";
|
|
29
31
|
|
|
30
32
|
type AvailableMaterialProperty = ExtractProperties<
|
|
@@ -86,6 +88,13 @@ export type EvaluatedValue = {
|
|
|
86
88
|
[K in EvaluatableMaterialPropertyKey]: EvaluatedMaterialProperty[K];
|
|
87
89
|
};
|
|
88
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Re-export GeometryType from mesh constants for convenience.
|
|
93
|
+
* Geometry type for feature evaluation context.
|
|
94
|
+
* Tells the evaluator which geometry type is being rendered.
|
|
95
|
+
*/
|
|
96
|
+
export type { GeometryType };
|
|
97
|
+
|
|
89
98
|
/**
|
|
90
99
|
* Information about a feature batch, passed to evaluation callbacks.
|
|
91
100
|
*/
|
|
@@ -93,6 +102,8 @@ export type FeatureInfo = {
|
|
|
93
102
|
batchId: number;
|
|
94
103
|
properties: Record<string, unknown> | undefined;
|
|
95
104
|
layerId: LayerId | undefined;
|
|
105
|
+
/** Mesh geometry type (e.g., "billboard", "text"). Not GeoJSON geometry ("Point", "Polygon"). */
|
|
106
|
+
meshGeomType?: GeometryType;
|
|
96
107
|
};
|
|
97
108
|
|
|
98
109
|
/**
|
|
@@ -185,6 +196,49 @@ export class FeatureEvaluator {
|
|
|
185
196
|
this.obj = obj;
|
|
186
197
|
}
|
|
187
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Track objects we've already warned about to avoid log spam.
|
|
201
|
+
* Uses WeakSet so objects can be garbage collected.
|
|
202
|
+
*/
|
|
203
|
+
private static readonly warnedObjects = new WeakSet<Object3D>();
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Type guard to check if an Object3D has a geometryType getter.
|
|
207
|
+
*/
|
|
208
|
+
private hasGeometryType(
|
|
209
|
+
obj: Object3D,
|
|
210
|
+
): obj is Object3D & { geometryType: unknown } {
|
|
211
|
+
return "geometryType" in obj;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Determine geometry type from the mesh object.
|
|
216
|
+
* Reads geometryType getter if available on the mesh.
|
|
217
|
+
* Validates that the returned value is a valid GeometryType literal.
|
|
218
|
+
*/
|
|
219
|
+
private determineGeometryType(obj: Object3D): GeometryType | undefined {
|
|
220
|
+
if (this.hasGeometryType(obj)) {
|
|
221
|
+
const value = obj.geometryType;
|
|
222
|
+
|
|
223
|
+
// Runtime validation: ensure the returned value is a valid GeometryType
|
|
224
|
+
if (
|
|
225
|
+
typeof value === "string" &&
|
|
226
|
+
VALID_GEOMETRY_TYPES.includes(value as GeometryType)
|
|
227
|
+
) {
|
|
228
|
+
return value as GeometryType;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Invalid value from geometryType - warn once per object to avoid log spam
|
|
232
|
+
if (!FeatureEvaluator.warnedObjects.has(obj)) {
|
|
233
|
+
FeatureEvaluator.warnedObjects.add(obj);
|
|
234
|
+
console.warn(
|
|
235
|
+
`Invalid geometry type returned from geometryType getter: "${value}". Expected one of: ${VALID_GEOMETRY_TYPES.join(", ")}`,
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
|
|
188
242
|
/**
|
|
189
243
|
* Gets the unique identifier of this feature set.
|
|
190
244
|
*/
|
|
@@ -214,6 +268,9 @@ export class FeatureEvaluator {
|
|
|
214
268
|
* ```
|
|
215
269
|
*/
|
|
216
270
|
readFeatureProperties(f: (info: FeatureInfo, batchIndex: number) => void) {
|
|
271
|
+
// Read geometry type dynamically to handle cases where it changes after evaluator creation
|
|
272
|
+
const meshGeomType = this.determineGeometryType(this.obj);
|
|
273
|
+
|
|
217
274
|
if (this.cachedBatchedProperties) {
|
|
218
275
|
for (const [batchIdx, properties] of this.cachedBatchedProperties) {
|
|
219
276
|
f(
|
|
@@ -221,6 +278,7 @@ export class FeatureEvaluator {
|
|
|
221
278
|
layerId: this.layerId,
|
|
222
279
|
batchId: this.batchIds[batchIdx],
|
|
223
280
|
properties,
|
|
281
|
+
meshGeomType,
|
|
224
282
|
},
|
|
225
283
|
batchIdx,
|
|
226
284
|
);
|
|
@@ -241,6 +299,7 @@ export class FeatureEvaluator {
|
|
|
241
299
|
layerId: this.layerId,
|
|
242
300
|
batchId,
|
|
243
301
|
properties,
|
|
302
|
+
meshGeomType,
|
|
244
303
|
},
|
|
245
304
|
batchIdx,
|
|
246
305
|
);
|
|
@@ -267,6 +326,9 @@ export class FeatureEvaluator {
|
|
|
267
326
|
keys: string[],
|
|
268
327
|
f: (info: FeatureInfo, batchIndex: number) => void,
|
|
269
328
|
) {
|
|
329
|
+
// Read geometry type dynamically to handle cases where it changes after evaluator creation
|
|
330
|
+
const meshGeomType = this.determineGeometryType(this.obj);
|
|
331
|
+
|
|
270
332
|
const cacheKey = keys.join("|");
|
|
271
333
|
if (this.filterCacheKey === cacheKey && this.cachedFilteredProperties) {
|
|
272
334
|
for (const [batchIndex, filtered] of this.cachedFilteredProperties) {
|
|
@@ -275,6 +337,7 @@ export class FeatureEvaluator {
|
|
|
275
337
|
layerId: this.layerId,
|
|
276
338
|
batchId: this.batchIds[batchIndex],
|
|
277
339
|
properties: filtered,
|
|
340
|
+
meshGeomType,
|
|
278
341
|
},
|
|
279
342
|
batchIndex,
|
|
280
343
|
);
|
|
@@ -293,7 +356,15 @@ export class FeatureEvaluator {
|
|
|
293
356
|
}
|
|
294
357
|
this.cachedFilteredProperties?.set(batchIndex, properties);
|
|
295
358
|
this.batchIds[batchIndex] = batchId;
|
|
296
|
-
f(
|
|
359
|
+
f(
|
|
360
|
+
{
|
|
361
|
+
layerId: this.layerId,
|
|
362
|
+
batchId,
|
|
363
|
+
properties,
|
|
364
|
+
meshGeomType,
|
|
365
|
+
},
|
|
366
|
+
batchIndex,
|
|
367
|
+
);
|
|
297
368
|
},
|
|
298
369
|
);
|
|
299
370
|
}
|
package/src/index.ts
CHANGED
|
@@ -1044,6 +1044,9 @@ export default class ThreeView<
|
|
|
1044
1044
|
this._camera,
|
|
1045
1045
|
);
|
|
1046
1046
|
this._atmosphere.on("needsUpdate", this.forceUpdate);
|
|
1047
|
+
// Textures load lazily, kicked off by the first consumer registering via
|
|
1048
|
+
// onTexturesReady(); re-render whenever they arrive.
|
|
1049
|
+
this._atmosphere.on("textureLoaded", this.forceUpdate);
|
|
1047
1050
|
|
|
1048
1051
|
this.on("layer", (e, id, ...args) => {
|
|
1049
1052
|
this.layersManager.emitById(e, id, ...args);
|
|
@@ -1327,14 +1330,9 @@ export default class ThreeView<
|
|
|
1327
1330
|
budgets.maxWorkerHeapBytes,
|
|
1328
1331
|
});
|
|
1329
1332
|
|
|
1330
|
-
//
|
|
1331
|
-
//
|
|
1332
|
-
|
|
1333
|
-
() => this.forceUpdate(),
|
|
1334
|
-
(e) => console.error("Failed to load atmosphere textures:", e),
|
|
1335
|
-
);
|
|
1336
|
-
|
|
1337
|
-
// 2. Fetch WASM resources.
|
|
1333
|
+
// Fetch WASM resources. Atmosphere textures are not fetched here: they
|
|
1334
|
+
// load lazily once a consumer (sky, sun light, aerial perspective, ...)
|
|
1335
|
+
// registers via atmosphere.onTexturesReady().
|
|
1338
1336
|
await Promise.all([initCore(), initNavaraApi()]);
|
|
1339
1337
|
|
|
1340
1338
|
this._core = new Core(newId());
|
|
@@ -1480,7 +1478,7 @@ export default class ThreeView<
|
|
|
1480
1478
|
|
|
1481
1479
|
this.viewContext._setRenderPass(this.renderPass);
|
|
1482
1480
|
|
|
1483
|
-
//
|
|
1481
|
+
// Warm up workers. Non-blocking: warms one worker, the rest follow
|
|
1484
1482
|
// in the background off the HTTP cache; tasks dispatched to a still-cold
|
|
1485
1483
|
// worker just await WASM inside the task.
|
|
1486
1484
|
warmUpWorkerPool().catch((e) =>
|
|
@@ -21,15 +21,18 @@ import type {
|
|
|
21
21
|
/**
|
|
22
22
|
* Factory function to create an sdfText base enhancer.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* -
|
|
24
|
+
* One enhancer drives the whole tile-layer batch, so it owns only batch-wide
|
|
25
|
+
* state:
|
|
26
|
+
* - Anchor centering, outline (width, color, opacity)
|
|
27
27
|
* - Background quad (color, border)
|
|
28
|
-
* -
|
|
29
|
-
* - Picking
|
|
28
|
+
* - Depth offset and picking mode
|
|
30
29
|
* - RTE (Relative-To-Eye) support for high-precision coordinates
|
|
31
30
|
* - Billboard scaling by distance
|
|
32
|
-
* - SDF atlas texture management
|
|
31
|
+
* - SDF atlas and per-label data texture management
|
|
32
|
+
*
|
|
33
|
+
* Per-label values (position, colour, opacity, font size, height, block
|
|
34
|
+
* metrics, batch id, declutter fade) are not here — they live in the label
|
|
35
|
+
* data texture the mesh owns.
|
|
33
36
|
*
|
|
34
37
|
* Supports ShaderMaterial with custom sdfText shaders.
|
|
35
38
|
*
|
|
@@ -71,7 +74,7 @@ export function createSdfTextBaseEnhancer(
|
|
|
71
74
|
};
|
|
72
75
|
state = updateState(mergedProps, initialState);
|
|
73
76
|
// Create mutates (refs are created inside with default values)
|
|
74
|
-
mutates = createBaseMutates(mergedProps.
|
|
77
|
+
mutates = createBaseMutates(mergedProps.rtcCenter);
|
|
75
78
|
mutates.update(state);
|
|
76
79
|
|
|
77
80
|
// Set atlas texture external ref if provided
|
|
@@ -19,11 +19,8 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
19
19
|
it("should sync core refs from state", () => {
|
|
20
20
|
const state: SdfTextBaseState = {
|
|
21
21
|
...DEFAULT_BASE_STATE,
|
|
22
|
-
color: new Color(0xff0000),
|
|
23
|
-
fontSize: 24,
|
|
24
22
|
center: [0.5, 0.5],
|
|
25
23
|
sizeInMeters: true,
|
|
26
|
-
addHeight: 50,
|
|
27
24
|
offsetDepth: false,
|
|
28
25
|
outlineWidth: 0.1,
|
|
29
26
|
outlineColor: new Color(0x00ff00),
|
|
@@ -34,18 +31,15 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
34
31
|
backgroundOutlineWidth: 0.2,
|
|
35
32
|
pickable: true,
|
|
36
33
|
};
|
|
37
|
-
const mutates = createBaseMutates(
|
|
34
|
+
const mutates = createBaseMutates();
|
|
38
35
|
mutates.update(state);
|
|
39
36
|
|
|
40
37
|
const uniforms: ShaderUniforms = {};
|
|
41
38
|
mutates.updateUniforms(uniforms, state);
|
|
42
39
|
|
|
43
|
-
expect(uniforms.uColor?.value.getHex()).toBe(0xff0000);
|
|
44
|
-
expect(uniforms.uFontSize?.value).toBe(24);
|
|
45
40
|
expect(uniforms.uCenter?.value.x).toBe(0.5);
|
|
46
41
|
expect(uniforms.uCenter?.value.y).toBe(0.5);
|
|
47
42
|
expect(uniforms.uSizeInMeters?.value).toBe(true);
|
|
48
|
-
expect(uniforms.uAddHeight?.value).toBe(50);
|
|
49
43
|
expect(uniforms.uOffsetDepth?.value).toBe(false);
|
|
50
44
|
expect(uniforms.uOutlineWidth?.value).toBe(0.1);
|
|
51
45
|
expect(uniforms.uOutlineColor?.value.getHex()).toBe(0x00ff00);
|
|
@@ -61,7 +55,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
61
55
|
describe("RTC center", () => {
|
|
62
56
|
it("should initialize uRTCCenter from constructor args", () => {
|
|
63
57
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
64
|
-
const mutates = createBaseMutates(
|
|
58
|
+
const mutates = createBaseMutates([10, 20, 30]);
|
|
65
59
|
mutates.update(state);
|
|
66
60
|
|
|
67
61
|
const uniforms: ShaderUniforms = {};
|
|
@@ -73,41 +67,60 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
73
67
|
});
|
|
74
68
|
});
|
|
75
69
|
|
|
76
|
-
describe("
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
70
|
+
describe("per-label state is not uniform state", () => {
|
|
71
|
+
// Anchors used to be uRTEPositionHIGH/LOW (RTE) or uRTCPosition (RTC) —
|
|
72
|
+
// one material per label. Batched, every label's anchor is a texel in
|
|
73
|
+
// uLabelData, so these uniforms must not come back: a single one would
|
|
74
|
+
// silently place the whole batch at one point.
|
|
75
|
+
it.each([true, false])(
|
|
76
|
+
"exposes no position uniforms (useRTE=%s)",
|
|
77
|
+
(useRTE) => {
|
|
78
|
+
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE, useRTE };
|
|
79
|
+
const mutates = createBaseMutates();
|
|
80
|
+
mutates.update(state);
|
|
81
|
+
|
|
82
|
+
const uniforms: ShaderUniforms = {};
|
|
83
|
+
mutates.updateUniforms(uniforms, state);
|
|
84
|
+
|
|
85
|
+
expect(uniforms.uRTEPositionLOW).toBeUndefined();
|
|
86
|
+
expect(uniforms.uRTEPositionHIGH).toBeUndefined();
|
|
87
|
+
expect(uniforms.uRTCPosition).toBeUndefined();
|
|
88
|
+
// The batch-wide RTC origin does stay a uniform.
|
|
89
|
+
expect(uniforms.uRTCCenter).toBeDefined();
|
|
90
|
+
expect(uniforms.uLabelData).toBeDefined();
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
it("exposes no per-label style or batch-id uniforms", () => {
|
|
94
95
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
95
|
-
const mutates = createBaseMutates(
|
|
96
|
+
const mutates = createBaseMutates();
|
|
96
97
|
mutates.update(state);
|
|
97
98
|
|
|
98
99
|
const uniforms: ShaderUniforms = {};
|
|
99
100
|
mutates.updateUniforms(uniforms, state);
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
for (const name of [
|
|
103
|
+
"uColor",
|
|
104
|
+
"uOpacity",
|
|
105
|
+
"uFontSize",
|
|
106
|
+
"uAddHeight",
|
|
107
|
+
"uTextWidth",
|
|
108
|
+
"uTextHeight",
|
|
109
|
+
"uBgYBounds",
|
|
110
|
+
"uDeclutterHide",
|
|
111
|
+
"nvr_uBatchId",
|
|
112
|
+
]) {
|
|
113
|
+
expect(uniforms).not.toHaveProperty(name);
|
|
114
|
+
}
|
|
115
|
+
// Pick mode is still batch-wide.
|
|
116
|
+
expect(uniforms.nvr_uPickable).toBeDefined();
|
|
104
117
|
});
|
|
105
118
|
});
|
|
106
119
|
|
|
107
120
|
describe("atlas texture ref", () => {
|
|
108
121
|
it("should update uAtlas value without replacing uniform ref", () => {
|
|
109
122
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
110
|
-
const mutates = createBaseMutates(
|
|
123
|
+
const mutates = createBaseMutates();
|
|
111
124
|
mutates.update(state);
|
|
112
125
|
|
|
113
126
|
const uniforms: ShaderUniforms = {};
|
|
@@ -130,7 +143,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
130
143
|
describe("updateAtlasSizes", () => {
|
|
131
144
|
it("should sync uSdfAtlasSize and uColorAtlasSize from bound texture images", () => {
|
|
132
145
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
133
|
-
const mutates = createBaseMutates(
|
|
146
|
+
const mutates = createBaseMutates();
|
|
134
147
|
mutates.update(state);
|
|
135
148
|
|
|
136
149
|
const sdfTex = {
|
|
@@ -155,7 +168,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
155
168
|
|
|
156
169
|
it("should pick up new dimensions after the atlas grows", () => {
|
|
157
170
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
158
|
-
const mutates = createBaseMutates(
|
|
171
|
+
const mutates = createBaseMutates();
|
|
159
172
|
mutates.update(state);
|
|
160
173
|
|
|
161
174
|
const sdfTex = {
|
|
@@ -184,7 +197,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
184
197
|
|
|
185
198
|
it("should leave atlas size uniforms unchanged when textures are null", () => {
|
|
186
199
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
187
|
-
const mutates = createBaseMutates(
|
|
200
|
+
const mutates = createBaseMutates();
|
|
188
201
|
mutates.update(state);
|
|
189
202
|
|
|
190
203
|
// Both uAtlas and uColorAtlas default to null.
|
|
@@ -202,7 +215,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
202
215
|
|
|
203
216
|
it("should leave atlas size uniforms unchanged when image has zero dimensions", () => {
|
|
204
217
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
205
|
-
const mutates = createBaseMutates(
|
|
218
|
+
const mutates = createBaseMutates();
|
|
206
219
|
mutates.update(state);
|
|
207
220
|
|
|
208
221
|
const sdfTex = {
|
|
@@ -222,7 +235,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
222
235
|
describe("updatePerFrame", () => {
|
|
223
236
|
it("should update camera uniforms", () => {
|
|
224
237
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
225
|
-
const mutates = createBaseMutates(
|
|
238
|
+
const mutates = createBaseMutates();
|
|
226
239
|
mutates.update(state);
|
|
227
240
|
|
|
228
241
|
mutates.updatePerFrame(1.5, 1080, 10000, 0, 0, 0, new Matrix4(), state);
|
|
@@ -240,7 +253,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
240
253
|
...DEFAULT_BASE_STATE,
|
|
241
254
|
useRTE: true,
|
|
242
255
|
};
|
|
243
|
-
const mutates = createBaseMutates(
|
|
256
|
+
const mutates = createBaseMutates();
|
|
244
257
|
mutates.update(state);
|
|
245
258
|
|
|
246
259
|
mutates.updatePerFrame(
|
|
@@ -268,7 +281,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
268
281
|
|
|
269
282
|
it("should not update RTE eye uniforms when useRTE=false", () => {
|
|
270
283
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
271
|
-
const mutates = createBaseMutates(
|
|
284
|
+
const mutates = createBaseMutates();
|
|
272
285
|
mutates.update(state);
|
|
273
286
|
|
|
274
287
|
mutates.updatePerFrame(
|
|
@@ -292,7 +305,7 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
292
305
|
|
|
293
306
|
it("should transform the RTC center into view space when useRTE=false", () => {
|
|
294
307
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
295
|
-
const mutates = createBaseMutates(
|
|
308
|
+
const mutates = createBaseMutates([6_400_000, 0, 0]);
|
|
296
309
|
mutates.update(state);
|
|
297
310
|
|
|
298
311
|
// View matrix cancels the center's large X so it lands near the origin.
|
|
@@ -308,74 +321,54 @@ describe("sdfTextBaseEnhancer/mutates", () => {
|
|
|
308
321
|
});
|
|
309
322
|
});
|
|
310
323
|
|
|
311
|
-
describe("
|
|
312
|
-
it("should
|
|
324
|
+
describe("setLabelDataTexture", () => {
|
|
325
|
+
it("should bind the texture and its dimensions", () => {
|
|
313
326
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
314
|
-
const mutates = createBaseMutates(
|
|
315
|
-
mutates.update(state);
|
|
316
|
-
|
|
317
|
-
mutates.updateTextDimensions(5.0, 1.0, -0.2, 0.8);
|
|
318
|
-
|
|
319
|
-
const uniforms: ShaderUniforms = {};
|
|
320
|
-
mutates.updateUniforms(uniforms, state);
|
|
321
|
-
|
|
322
|
-
expect(uniforms.uTextWidth?.value).toBe(5.0);
|
|
323
|
-
expect(uniforms.uTextHeight?.value).toBe(1.0);
|
|
324
|
-
expect(uniforms.uBgYBounds?.value.x).toBe(-0.2);
|
|
325
|
-
expect(uniforms.uBgYBounds?.value.y).toBe(0.8);
|
|
326
|
-
});
|
|
327
|
-
});
|
|
328
|
-
|
|
329
|
-
describe("setPosition", () => {
|
|
330
|
-
it("should set RTE position uniforms", () => {
|
|
331
|
-
const state: SdfTextBaseState = {
|
|
332
|
-
...DEFAULT_BASE_STATE,
|
|
333
|
-
useRTE: true,
|
|
334
|
-
};
|
|
335
|
-
const mutates = createBaseMutates(true);
|
|
327
|
+
const mutates = createBaseMutates();
|
|
336
328
|
mutates.update(state);
|
|
337
329
|
|
|
338
|
-
const
|
|
339
|
-
|
|
340
|
-
mutates.setPosition({ high, low }, true);
|
|
330
|
+
const tex = { isDataTexture: true } as unknown as DataTexture;
|
|
331
|
+
mutates.setLabelDataTexture(tex, 64, 5);
|
|
341
332
|
|
|
342
333
|
const uniforms: ShaderUniforms = {};
|
|
343
334
|
mutates.updateUniforms(uniforms, state);
|
|
344
335
|
|
|
345
|
-
expect(uniforms.
|
|
346
|
-
expect(uniforms.
|
|
336
|
+
expect(uniforms.uLabelData?.value).toBe(tex);
|
|
337
|
+
expect(uniforms.uLabelTexSize?.value.x).toBe(64);
|
|
338
|
+
expect(uniforms.uLabelTexSize?.value.y).toBe(5);
|
|
347
339
|
});
|
|
348
340
|
|
|
349
|
-
|
|
341
|
+
// The shader does `i % size.x` and `i / size.x`; a zero would divide by
|
|
342
|
+
// zero before the mesh has bound anything.
|
|
343
|
+
it("should never expose a zero dimension", () => {
|
|
350
344
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
351
|
-
const mutates = createBaseMutates(
|
|
345
|
+
const mutates = createBaseMutates();
|
|
352
346
|
mutates.update(state);
|
|
353
347
|
|
|
354
|
-
|
|
355
|
-
mutates.setPosition(pos, false, [100, 200, 300]);
|
|
348
|
+
mutates.setLabelDataTexture(null, 0, 0);
|
|
356
349
|
|
|
357
350
|
const uniforms: ShaderUniforms = {};
|
|
358
351
|
mutates.updateUniforms(uniforms, state);
|
|
359
352
|
|
|
360
|
-
expect(uniforms.
|
|
361
|
-
expect(uniforms.
|
|
362
|
-
expect(uniforms.uRTCCenter?.value.x).toBe(100);
|
|
363
|
-
expect(uniforms.uRTCCenter?.value.y).toBe(200);
|
|
353
|
+
expect(uniforms.uLabelTexSize?.value.x).toBe(1);
|
|
354
|
+
expect(uniforms.uLabelTexSize?.value.y).toBe(1);
|
|
364
355
|
});
|
|
365
356
|
});
|
|
366
357
|
|
|
367
|
-
describe("
|
|
368
|
-
it("should update
|
|
358
|
+
describe("setRtcCenter", () => {
|
|
359
|
+
it("should update uRTCCenter after a transform change", () => {
|
|
369
360
|
const state: SdfTextBaseState = { ...DEFAULT_BASE_STATE };
|
|
370
|
-
const mutates = createBaseMutates(
|
|
361
|
+
const mutates = createBaseMutates([1, 2, 3]);
|
|
371
362
|
mutates.update(state);
|
|
372
363
|
|
|
373
|
-
mutates.
|
|
364
|
+
mutates.setRtcCenter([100, 200, 300]);
|
|
374
365
|
|
|
375
366
|
const uniforms: ShaderUniforms = {};
|
|
376
367
|
mutates.updateUniforms(uniforms, state);
|
|
377
368
|
|
|
378
|
-
expect(uniforms.
|
|
369
|
+
expect(uniforms.uRTCCenter?.value.x).toBe(100);
|
|
370
|
+
expect(uniforms.uRTCCenter?.value.y).toBe(200);
|
|
371
|
+
expect(uniforms.uRTCCenter?.value.z).toBe(300);
|
|
379
372
|
});
|
|
380
373
|
});
|
|
381
374
|
});
|