@treasuryspatial/map-kit 0.1.3 → 0.1.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/mapThreeLayer.d.ts +1 -0
- package/dist/mapThreeLayer.d.ts.map +1 -1
- package/dist/mapThreeLayer.js +120 -22
- package/package.json +1 -1
package/dist/mapThreeLayer.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export type MapThreeLayerOptions = {
|
|
|
13
13
|
id: string;
|
|
14
14
|
zOffsetMeters?: number;
|
|
15
15
|
onInit?: (scene: THREE.Scene, renderer: THREE.WebGLRenderer, camera: THREE.Camera) => void;
|
|
16
|
+
debug?: boolean;
|
|
16
17
|
};
|
|
17
18
|
export declare function createMapThreeLayer(options: MapThreeLayerOptions): MapThreeLayer;
|
|
18
19
|
//# sourceMappingURL=mapThreeLayer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapThreeLayer.d.ts","sourceRoot":"","sources":["../src/mapThreeLayer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,SAAS,EAAE,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"mapThreeLayer.d.ts","sourceRoot":"","sources":["../src/mapThreeLayer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,QAAQ,CAAC,oBAAoB,CAAC;IACrC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C,SAAS,EAAE,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,KAAK,IAAI,CAAC;IACjE,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC;IAC3F,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CA+OhF"}
|
package/dist/mapThreeLayer.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import mapboxgl from 'mapbox-gl';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
3
|
export function createMapThreeLayer(options) {
|
|
4
|
-
const { id, zOffsetMeters = 0.02, onInit } = options;
|
|
4
|
+
const { id, zOffsetMeters = 0.02, onInit, debug = false } = options;
|
|
5
5
|
let mapRef = null;
|
|
6
6
|
let scene = null;
|
|
7
7
|
let camera = null;
|
|
@@ -18,6 +18,55 @@ export function createMapThreeLayer(options) {
|
|
|
18
18
|
let zOffset = zOffsetMeters;
|
|
19
19
|
let targetWidth = 0;
|
|
20
20
|
let targetHeight = 0;
|
|
21
|
+
let renderDisabled = false;
|
|
22
|
+
let errorCount = 0;
|
|
23
|
+
let hasRenderable = false;
|
|
24
|
+
const log = (...args) => {
|
|
25
|
+
if (!debug)
|
|
26
|
+
return;
|
|
27
|
+
console.info(`[map-kit:${id}]`, ...args);
|
|
28
|
+
};
|
|
29
|
+
const logError = (message, err) => {
|
|
30
|
+
console.error(`[map-kit:${id}] ${message}`, err);
|
|
31
|
+
};
|
|
32
|
+
const logGlError = (gl, label) => {
|
|
33
|
+
if (!debug)
|
|
34
|
+
return;
|
|
35
|
+
const error = gl.getError();
|
|
36
|
+
if (error !== gl.NO_ERROR) {
|
|
37
|
+
log(`GL error (${label})`, error);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const checkFramebuffer = (gl, label) => {
|
|
41
|
+
if (!debug)
|
|
42
|
+
return;
|
|
43
|
+
const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
|
44
|
+
if (status !== gl.FRAMEBUFFER_COMPLETE) {
|
|
45
|
+
log(`Framebuffer incomplete (${label})`, status);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const updateRenderable = (group) => {
|
|
49
|
+
if (!group) {
|
|
50
|
+
hasRenderable = false;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let found = false;
|
|
54
|
+
group.traverse((child) => {
|
|
55
|
+
if (found)
|
|
56
|
+
return;
|
|
57
|
+
const mesh = child;
|
|
58
|
+
if (!mesh.isMesh)
|
|
59
|
+
return;
|
|
60
|
+
if (mesh.visible === false)
|
|
61
|
+
return;
|
|
62
|
+
const geometry = mesh.geometry;
|
|
63
|
+
const position = geometry?.getAttribute?.('position');
|
|
64
|
+
if (position && position.count > 0) {
|
|
65
|
+
found = true;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
hasRenderable = found;
|
|
69
|
+
};
|
|
21
70
|
const layer = {
|
|
22
71
|
id,
|
|
23
72
|
type: 'custom',
|
|
@@ -46,6 +95,7 @@ export function createMapThreeLayer(options) {
|
|
|
46
95
|
});
|
|
47
96
|
renderTarget.texture.colorSpace = THREE.SRGBColorSpace;
|
|
48
97
|
renderTarget.texture.premultiplyAlpha = true;
|
|
98
|
+
log('renderTarget', { width: targetWidth, height: targetHeight });
|
|
49
99
|
screenScene = new THREE.Scene();
|
|
50
100
|
screenCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
|
|
51
101
|
screenMaterial = new THREE.MeshBasicMaterial({
|
|
@@ -66,41 +116,89 @@ export function createMapThreeLayer(options) {
|
|
|
66
116
|
onInit(scene, renderer, camera);
|
|
67
117
|
},
|
|
68
118
|
prerender: (_gl, matrix) => {
|
|
119
|
+
if (renderDisabled)
|
|
120
|
+
return;
|
|
69
121
|
if (!renderer || !scene || !camera || !rootGroup || !renderTarget)
|
|
70
122
|
return;
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
123
|
+
if (!hasRenderable)
|
|
124
|
+
return;
|
|
125
|
+
try {
|
|
126
|
+
camera.projectionMatrix = new THREE.Matrix4().fromArray(matrix);
|
|
127
|
+
if (mercatorOrigin) {
|
|
128
|
+
const translate = new THREE.Matrix4().makeTranslation(mercatorOrigin.x, mercatorOrigin.y, (mercatorOrigin.z ?? 0) + zOffset * meterScale);
|
|
129
|
+
const scale = new THREE.Matrix4().makeScale(meterScale, -meterScale, meterScale);
|
|
130
|
+
rootGroup.matrix = new THREE.Matrix4().multiplyMatrices(translate, scale);
|
|
131
|
+
rootGroup.matrixWorldNeedsUpdate = true;
|
|
132
|
+
}
|
|
133
|
+
const canvas = mapRef?.getCanvas();
|
|
134
|
+
if (canvas && (canvas.width !== targetWidth || canvas.height !== targetHeight)) {
|
|
135
|
+
targetWidth = canvas.width;
|
|
136
|
+
targetHeight = canvas.height;
|
|
137
|
+
renderTarget.setSize(targetWidth, targetHeight);
|
|
138
|
+
log('renderTarget resized', { width: targetWidth, height: targetHeight });
|
|
139
|
+
}
|
|
140
|
+
renderer.setRenderTarget(renderTarget);
|
|
141
|
+
renderer.setClearColor(0x000000, 0);
|
|
142
|
+
renderer.setClearAlpha(0);
|
|
143
|
+
renderer.clear(true, true, true);
|
|
144
|
+
const gl = renderer.getContext();
|
|
145
|
+
checkFramebuffer(gl, 'prerender');
|
|
146
|
+
renderer.render(scene, camera);
|
|
147
|
+
logGlError(gl, 'prerender');
|
|
148
|
+
renderer.setRenderTarget(null);
|
|
77
149
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
150
|
+
catch (err) {
|
|
151
|
+
errorCount += 1;
|
|
152
|
+
logError('prerender failed', err);
|
|
153
|
+
if (errorCount > 2) {
|
|
154
|
+
renderDisabled = true;
|
|
155
|
+
log('render disabled after repeated errors');
|
|
156
|
+
}
|
|
83
157
|
}
|
|
84
|
-
renderer.setRenderTarget(renderTarget);
|
|
85
|
-
renderer.clear(true, true, true);
|
|
86
|
-
renderer.render(scene, camera);
|
|
87
|
-
renderer.setRenderTarget(null);
|
|
88
158
|
},
|
|
89
159
|
render: (gl) => {
|
|
160
|
+
if (renderDisabled)
|
|
161
|
+
return;
|
|
90
162
|
if (!renderer || !screenScene || !screenCamera)
|
|
91
163
|
return;
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
164
|
+
if (!hasRenderable)
|
|
165
|
+
return;
|
|
166
|
+
try {
|
|
167
|
+
renderer.resetState();
|
|
168
|
+
gl.disable(gl.DEPTH_TEST);
|
|
169
|
+
gl.depthMask(false);
|
|
170
|
+
gl.disable(gl.STENCIL_TEST);
|
|
171
|
+
gl.disable(gl.SCISSOR_TEST);
|
|
172
|
+
gl.colorMask(true, true, true, true);
|
|
173
|
+
gl.enable(gl.BLEND);
|
|
174
|
+
gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
175
|
+
const canvas = mapRef?.getCanvas();
|
|
176
|
+
if (canvas) {
|
|
177
|
+
renderer.setViewport(0, 0, canvas.width, canvas.height);
|
|
178
|
+
}
|
|
179
|
+
renderer.render(screenScene, screenCamera);
|
|
180
|
+
logGlError(gl, 'render');
|
|
181
|
+
renderer.resetState();
|
|
182
|
+
mapRef?.triggerRepaint();
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
errorCount += 1;
|
|
186
|
+
logError('render failed', err);
|
|
187
|
+
if (errorCount > 2) {
|
|
188
|
+
renderDisabled = true;
|
|
189
|
+
log('render disabled after repeated errors');
|
|
190
|
+
}
|
|
191
|
+
}
|
|
98
192
|
},
|
|
99
193
|
};
|
|
100
194
|
return {
|
|
101
195
|
layer,
|
|
102
196
|
setGroup: (group) => {
|
|
103
197
|
meshGroup = group;
|
|
198
|
+
updateRenderable(group);
|
|
199
|
+
if (debug) {
|
|
200
|
+
log('group set', { hasRenderable });
|
|
201
|
+
}
|
|
104
202
|
if (rootGroup) {
|
|
105
203
|
rootGroup.clear();
|
|
106
204
|
if (meshGroup)
|