@eturnity/eturnity_3d 9.13.0-google3dTile.2 → 9.16.0

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/style.css DELETED
@@ -1 +0,0 @@
1
- .canvas3DContainer{height:100%;width:100%}.canvas3DContainer>canvas{height:100%;width:100%}
package/dist/vite.svg DELETED
@@ -1 +0,0 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
@@ -1,574 +0,0 @@
1
- /**
2
- * Google 3D Tiles Overlay
3
- *
4
- * Loads 3D Tiles from Google's Photorealistic 3D Tiles API and displays them
5
- * in the Three.js scene. The scene origin is at (centerLat, centerLon) at ground level,
6
- * with an ENU coordinate system: X = East, Y = North, Z = Up, in meters.
7
- *
8
- * Integrates with the existing Overlay system so it can be rendered via renderOnThreeJS
9
- * and updated every frame via userData.update on the mesh.
10
- * Extends ThreeDModelOverlay to reuse getProjectedPlanesOnOverlay for roof projection.
11
- */
12
-
13
- import ThreeDModelOverlay from './ThreeDModelOverlay'
14
- import * as THREE from 'three'
15
- import { TilesRenderer } from '3d-tiles-renderer'
16
- import {
17
- TilesFadePlugin,
18
- GoogleCloudAuthPlugin,
19
- ReorientationPlugin,
20
- TileCompressionPlugin,
21
- } from '3d-tiles-renderer/plugins'
22
-
23
- /**
24
- * Max screen-space error for tile refinement (3d-tiles-renderer).
25
- * Lower = finer meshes for tiles inside {@link Google3DTilesOverlay#_tilesCamera}'s frustum.
26
- * GoogleCloudAuthPlugin sets 20 for broad views; we override for this fixed ortho footprint.
27
- */
28
- const TILES_FRUSTUM_ERROR_TARGET = 4
29
-
30
- /**
31
- * Draw after merged base / roofs (renderOrder 10) and edges (15) so transparent
32
- * tiles blend with geometry already in the color buffer instead of hiding it.
33
- */
34
- const GOOGLE_TILES_RENDER_ORDER = 25
35
-
36
- /** Extra meters padded on each side of roof AABB for tile loading frustum */
37
- const ROOFS_BOUNDS_MARGIN_M = 5
38
-
39
- /** Same rhythm as ThreeDModelOverlay.animatePlaceholder (sin² on time) */
40
- function placeholderBounceScale(timeSeconds) {
41
- const baseRadius = 0.65
42
- const amplitude = 0.55
43
- return baseRadius + amplitude * Math.sin(timeSeconds * 0.7 * Math.PI) ** 2
44
- }
45
-
46
- export default class Google3DTilesOverlay extends ThreeDModelOverlay {
47
- constructor(overlay, emit, origin) {
48
- super(overlay, emit, origin || {}, null)
49
- this.hasToBeSavedInBE = false
50
- this.origin = origin || {}
51
- this.tilesData = null
52
- this._initPromise = null
53
- // Center for ReorientationPlugin: use settings or origin (degrees → radians)
54
- const lat = this.settings?.centerLat ?? this.origin?.lat
55
- const lon = this.settings?.centerLon ?? this.origin?.lng
56
- this._centerLatRad =
57
- lat != null ? lat * (Math.PI / 180) : 35.6586 * (Math.PI / 180)
58
- this._centerLonRad =
59
- lon != null ? lon * (Math.PI / 180) : 139.7454 * (Math.PI / 180)
60
- // Ground elevation in meters from Google Elevation API (used to offset tiles to ground level)
61
- this._groundElevation = this.settings?.groundElevation ?? null
62
- // Dedicated camera for tile loading and resolution so the user's camera does not affect which tiles load
63
- // Orthographic camera looking down (Z up), covering -50 to +50 meters in X and Y
64
- this._tilesCamera = new THREE.OrthographicCamera(
65
- -10,
66
- 10,
67
- 10,
68
- -10,
69
- 0.1,
70
- 10000
71
- )
72
- this._tilesCamera.position.set(0, 0, -100)
73
- this._tilesCamera.lookAt(0, 0, 0)
74
- this._tilesCamera.updateMatrixWorld(true)
75
- /** @type {{ xMin: number, xMax: number, yMin: number, yMax: number, zMin?: number, zMax?: number } | null} mm — same shape as Vuex getRoofsBounds (three-d-module) */
76
- this.roofsBound = null
77
- /** Padded roof-bounds center (m), same as tile camera look-at XY — placeholder sits at (cx, cy, 0) */
78
- this._placeholderCenterX = 0
79
- this._placeholderCenterY = 0
80
- this._rayDirDown = new THREE.Vector3(0, 0, 1)
81
- this._defaultTilesCamZ = -100
82
- this._defaultOrthoHalfExtentM = 10
83
- this.sphereMesh = null
84
- /** Transparent bouncing sphere at origin; removed once ground align settles */
85
- this._groundAlignPlaceholderMesh = null
86
- /** True when raycast tile bbox min.z is within ±10 after stick-to-ground */
87
- this.tilesFullyLoaded = false
88
- this.scene = null
89
- }
90
- getOverlayMeshForRaycast() {
91
- return this.tilesData?.tiles.group
92
- }
93
- async initialiseModel() {
94
- this.isReady = true
95
- return true
96
- }
97
-
98
- _roofsBoundsAreEqual(a, b) {
99
- if (a === b) return true
100
- if (!a || !b) return false
101
- return (
102
- a.xMin === b.xMin &&
103
- a.xMax === b.xMax &&
104
- a.yMin === b.yMin &&
105
- a.yMax === b.yMax
106
- )
107
- }
108
-
109
- /**
110
- * Store roof AABB (mm) and fit {@link #_tilesCamera} to it (ortho frustum in m).
111
- * Bounds shape matches Vuex `getRoofsBounds` in `three-d-module.js`.
112
- * Camera sits above the bounds center; left/right/top/bottom are set so the world XY
113
- * footprint matches [xMin,xMax]×[yMin,yMax] in meters (same convention as ThreeCanvas orthographic).
114
- *
115
- * @param {{ xMin: number, xMax: number, yMin: number, yMax: number, zMin?: number, zMax?: number } | null | undefined} boundsMm
116
- */
117
- updateRoofsBound(boundsMm) {
118
- this._tilesGroundAligned = false
119
- if (
120
- !boundsMm ||
121
- !Number.isFinite(boundsMm.xMin) ||
122
- boundsMm.xMin === Infinity
123
- ) {
124
- this.roofsBound = null
125
- const h = this._defaultOrthoHalfExtentM
126
- const cam = this._tilesCamera
127
- const z = this._defaultTilesCamZ
128
- cam.position.set(0, 0, z)
129
- cam.left = -h
130
- cam.right = h
131
- cam.top = h
132
- cam.bottom = -h
133
- cam.lookAt(0, 0, 0)
134
- cam.updateProjectionMatrix()
135
- cam.updateMatrixWorld(true)
136
- this._placeholderCenterX = 0
137
- this._placeholderCenterY = 0
138
- this._syncPlaceholderWorldXY()
139
- return
140
- }
141
-
142
- this.roofsBound = {
143
- xMin: boundsMm.xMin,
144
- xMax: boundsMm.xMax,
145
- yMin: boundsMm.yMin,
146
- yMax: boundsMm.yMax,
147
- zMin: boundsMm.zMin,
148
- zMax: boundsMm.zMax,
149
- }
150
-
151
- const m = ROOFS_BOUNDS_MARGIN_M
152
- const xMinM = boundsMm.xMin / 1000 - m
153
- const xMaxM = boundsMm.xMax / 1000 + m
154
- const yMinM = boundsMm.yMin / 1000 - m
155
- const yMaxM = boundsMm.yMax / 1000 + m
156
-
157
- const cx = (xMinM + xMaxM) / 2
158
- const cy = (yMinM + yMaxM) / 2
159
-
160
- let halfW = (xMaxM - xMinM) / 2
161
- let halfH = (yMaxM - yMinM) / 2
162
- const minHalf = 100
163
- if (halfW < minHalf) halfW = minHalf
164
- if (halfH < minHalf) halfH = minHalf
165
-
166
- const cam = this._tilesCamera
167
- const z = this._defaultTilesCamZ
168
- cam.position.set(cx, cy, z)
169
- cam.left = xMinM - cx
170
- cam.right = xMaxM - cx
171
- cam.top = yMaxM - cy
172
- cam.bottom = yMinM - cy
173
- cam.lookAt(cx, cy, 0)
174
- cam.updateProjectionMatrix()
175
- cam.updateMatrixWorld(true)
176
-
177
- this._placeholderCenterX = cx
178
- this._placeholderCenterY = cy
179
- this._syncPlaceholderWorldXY()
180
- }
181
-
182
- _syncPlaceholderWorldXY() {
183
- const mesh = this._groundAlignPlaceholderMesh
184
- if (!mesh) return
185
- mesh.position.x = this._placeholderCenterX
186
- mesh.position.y = this._placeholderCenterY
187
- }
188
-
189
- _getOrCreateTilesData() {
190
- if (this.tilesData) return this.tilesData
191
- const apiKey = process.env.VUE_APP_GOOGLE_MAP_API_KEY
192
- const tiles = new TilesRenderer()
193
- tiles.registerPlugin(
194
- new GoogleCloudAuthPlugin({
195
- apiToken: apiKey,
196
- sessionOptions: null,
197
- autoRefreshToken: true,
198
- useRecommendedSettings: true,
199
- })
200
- )
201
- tiles.registerPlugin(
202
- new ReorientationPlugin({
203
- lat: this._centerLatRad,
204
- lon: this._centerLonRad,
205
- })
206
- )
207
- tiles.registerPlugin(new TileCompressionPlugin())
208
- tiles.registerPlugin(new TilesFadePlugin({ maximumFadeOutTiles: 50 }))
209
-
210
- // After GoogleCloudAuthPlugin.init (errorTarget 20), tighten LOD for the ortho frustum only
211
- tiles.errorTarget = TILES_FRUSTUM_ERROR_TARGET
212
- // Prefer loading tiles that intersect _tilesCamera before prefetch / out-of-frustum work
213
- tiles.optimizedLoadStrategy = true
214
-
215
- tiles.lruCache.minSize = 400
216
- tiles.lruCache.maxSize = 800
217
- tiles.parseQueue.maxJobs = 4
218
-
219
- const tilesWrapper = new THREE.Group()
220
- tilesWrapper.name = 'Google3DTilesOverlay'
221
- tilesWrapper.renderOrder = GOOGLE_TILES_RENDER_ORDER
222
- tilesWrapper.rotation.x = Math.PI / 2
223
- tilesWrapper.rotation.y = Math.PI
224
- tilesWrapper.add(tiles.group)
225
- tilesWrapper.position.z = 0
226
- this.tilesData = { tiles, tilesWrapper }
227
-
228
- tiles.addEventListener('load-model', ({ scene, tile }) => {
229
- console.log('tile size loading', tiles.loadingTiles.size)
230
- this.tilesFullyLoaded = tiles.loadingTiles.size == 0
231
- if (this.tilesFullyLoaded) {
232
- this._applyGoogleTilesShadowProperty(tilesWrapper)
233
- this.stickObjectToTheGround(scene)
234
- }
235
- })
236
-
237
- return this.tilesData
238
- }
239
-
240
- _ensureGroundAlignPlaceholder(threeJSComponent) {
241
- if (this._tilesGroundAligned || !threeJSComponent?.scene) return
242
- const { scene } = threeJSComponent
243
- if (this._groundAlignPlaceholderMesh) {
244
- if (scene.getObjectById(this._groundAlignPlaceholderMesh.id)) return
245
- this._groundAlignPlaceholderMesh.geometry?.dispose()
246
- if (this._groundAlignPlaceholderMesh.material?.dispose) {
247
- this._groundAlignPlaceholderMesh.material.dispose()
248
- }
249
- this._groundAlignPlaceholderMesh = null
250
- }
251
- const geometry = new THREE.SphereGeometry(10, 32, 32)
252
- const material = new THREE.MeshBasicMaterial({
253
- color: 0xffffff,
254
- transparent: true,
255
- opacity: 0.2,
256
- depthWrite: false,
257
- })
258
- const mesh = new THREE.Mesh(geometry, material)
259
- mesh.name = 'Google3DTilesGroundAlignPlaceholder'
260
- mesh.userData.googleTilesGroundAlignPlaceholder = true
261
- mesh.position.set(this._placeholderCenterX, this._placeholderCenterY, 0)
262
- mesh.scale.setScalar(1)
263
- scene.add(mesh)
264
- this._groundAlignPlaceholderMesh = mesh
265
- this._tickGroundAlignPlaceholderAnimation()
266
- }
267
-
268
- _tickGroundAlignPlaceholderAnimation() {
269
- const mesh = this._groundAlignPlaceholderMesh
270
- if (!mesh?.material) return
271
-
272
- if (this.opacity === 0) {
273
- mesh.visible = false
274
- mesh.material.opacity = 0
275
- return
276
- }
277
-
278
- mesh.visible = true
279
- const t = performance.now() * 0.001
280
- const scale = placeholderBounceScale(t)
281
- mesh.scale.setScalar(scale)
282
- mesh.position.x = this._placeholderCenterX
283
- mesh.position.y = this._placeholderCenterY
284
- // Light Z bob so it reads as a bounce (Z up)
285
- mesh.position.z = 0.2 * Math.sin(t * 1.4 * Math.PI) ** 2
286
- mesh.material.opacity = 0.06 + 0.22 * Math.sin(t * 0.85 * Math.PI) ** 2
287
- }
288
-
289
- _removeGroundAlignPlaceholder(threeJSComponent) {
290
- const mesh = this._groundAlignPlaceholderMesh
291
- if (!mesh) return
292
- const scene = threeJSComponent?.scene
293
- if (scene && scene.getObjectById(mesh.id)) {
294
- scene.remove(mesh)
295
- } else {
296
- mesh.parent?.remove(mesh)
297
- }
298
- mesh.geometry?.dispose()
299
- if (mesh.material?.dispose) mesh.material.dispose()
300
- this._groundAlignPlaceholderMesh = null
301
- }
302
-
303
- _syncGroundAlignPlaceholder(threeJSComponent) {
304
- if (!threeJSComponent?.scene) return
305
- if (this.tilesFullyLoaded) {
306
- this._removeGroundAlignPlaceholder(threeJSComponent)
307
- } else {
308
- this._ensureGroundAlignPlaceholder(threeJSComponent)
309
- }
310
- }
311
- getBoundingBoxOfTiles(tileGroups) {
312
- let mergedBoundingBox = new THREE.Box3()
313
- tileGroups.forEach((tileGroup) => {
314
- const tileMesh = tileGroup.children[0]
315
- if (tileGroup.visible && tileMesh.geometry && tileMesh.visible) {
316
- //create random color
317
- const boundingBox = this.getBoundingBoxOfTile(tileMesh)
318
- //compute bounding box in world coordinates
319
- mergedBoundingBox.union(boundingBox)
320
- }
321
- })
322
- return mergedBoundingBox
323
- }
324
- stickObjectToTheGround(scene) {
325
- const { tiles, tilesWrapper } = this.tilesData || {}
326
- if (!tiles || !tilesWrapper) {
327
- this._tilesGroundAligned = false
328
- return
329
- }
330
-
331
- //merge all bounding boxes of the tiles
332
- const boundingBox = this.getBoundingBoxOfTiles(
333
- tilesWrapper.children[0].children
334
- )
335
- tilesWrapper.position.z -= boundingBox.min.z
336
- tilesWrapper.updateMatrixWorld(true)
337
- this._tilesGroundAligned = true
338
- }
339
- getBoundingBoxOfTile(tileMesh) {
340
- const extremePoints = []
341
- let minX = Infinity,
342
- maxX = -Infinity,
343
- minY = Infinity,
344
- maxY = -Infinity,
345
- minZ = Infinity,
346
- maxZ = -Infinity
347
- //use for instead of forEach as the array doesn't contain points but indices
348
- for (
349
- let i = 300;
350
- i < tileMesh.geometry.attributes.position.array.length;
351
- i += 3
352
- ) {
353
- const x = tileMesh.geometry.attributes.position.array[i]
354
- const y = tileMesh.geometry.attributes.position.array[i + 1]
355
- const z = tileMesh.geometry.attributes.position.array[i + 2]
356
- let point = new THREE.Vector3(x, y, z)
357
- point.applyMatrix4(tileMesh.matrixWorld)
358
- minX = Math.min(minX, point.x)
359
- maxX = Math.max(maxX, point.x)
360
- minY = Math.min(minY, point.y)
361
- maxY = Math.max(maxY, point.y)
362
- minZ = Math.min(minZ, point.z)
363
- maxZ = Math.max(maxZ, point.z)
364
- }
365
-
366
- extremePoints.push(new THREE.Vector3(maxX, maxY, maxZ))
367
- extremePoints.push(new THREE.Vector3(minX, maxY, minZ))
368
- extremePoints.push(new THREE.Vector3(maxX, minY, minZ))
369
- extremePoints.push(new THREE.Vector3(minX, maxY, maxZ))
370
- extremePoints.push(new THREE.Vector3(maxX, minY, maxZ))
371
- extremePoints.push(new THREE.Vector3(minX, minY, maxZ))
372
- extremePoints.push(new THREE.Vector3(maxX, maxY, minZ))
373
-
374
- const boundingBox = new THREE.Box3(
375
- new THREE.Vector3(minX, minY, minZ),
376
- new THREE.Vector3(maxX, maxY, maxZ)
377
- )
378
- return boundingBox
379
- }
380
-
381
- /**
382
- * Apply global overlay opacity to all tile mesh materials (base Overlay.setOpacity only updates state + emit).
383
- */
384
- /**
385
- * Replace MeshBasicMaterial with MeshPhongMaterial for lit/shadow rendering.
386
- * Textures are reused by reference. Caller must re-run TilesFadePlugin material prep after batch swap.
387
- */
388
- _convertGoogleTileBasicToPhong(basic) {
389
- const phong = new THREE.MeshPhongMaterial()
390
- //THREE.Material.prototype.copy.call(phong, basic)
391
- phong.color = new THREE.Color(0xffffff)
392
- phong.map = basic.map
393
- phong.side = THREE.DoubleSide
394
- phong.transparent = false
395
- phong.opacity = 1
396
- phong.shadowSide = THREE.DoubleSide
397
- phong.flatShading = true
398
- // phong.lightMap = basic.lightMap
399
- // phong.lightMapIntensity = basic.lightMapIntensity
400
- // phong.aoMap = basic.aoMap
401
- // phong.aoMapIntensity = basic.aoMapIntensity
402
- // phong.specularMap = basic.specularMap
403
- // phong.alphaMap = basic.alphaMap
404
- // phong.envMap = basic.envMap
405
- // phong.envMapRotation.copy(basic.envMapRotation)
406
- // phong.combine = basic.combine
407
- basic.dispose()
408
- return phong
409
- }
410
-
411
- /**
412
- * New materials after Basic→Phong swap must be wrapped for TilesFadePlugin dither fade.
413
- * Uses FADE_TILES_PLUGIN internals (prepareScene); coupled to 3d-tiles-renderer version.
414
- */
415
- _reregisterGoogleTilesFadeMaterials(wrapper) {
416
- const tiles = this.tilesData?.tiles
417
- const fadePlugin = tiles?.getPluginByName?.('FADE_TILES_PLUGIN')
418
- fadePlugin?._fadeMaterialManager?.prepareScene?.(wrapper)
419
- }
420
-
421
- _applyGoogleTilesOpacity(wrapper) {
422
- if (!wrapper) return
423
- const opacity = this.opacity
424
- const isTransparent = opacity < 1 - 1e-6
425
- wrapper.renderOrder = GOOGLE_TILES_RENDER_ORDER
426
- wrapper.visible = Boolean(this.isActive) && opacity > 0
427
- wrapper.traverse((object) => {
428
- if (!object.isMesh || !object.material) return
429
- object.renderOrder = GOOGLE_TILES_RENDER_ORDER
430
- const materials = Array.isArray(object.material)
431
- ? object.material
432
- : [object.material]
433
- for (const mat of materials) {
434
- if (mat) {
435
- mat.transparent = isTransparent
436
- mat.opacity = opacity
437
- // Avoid writing depth when semi-transparent so merged base (base.js) and
438
- // other geometry drawn earlier remain visible through the tiles.
439
- mat.depthWrite = !isTransparent
440
- }
441
- }
442
- })
443
- }
444
- _applyGoogleTilesShadowProperty(wrapper) {
445
- if (!wrapper) return
446
- wrapper.traverse((object) => {
447
- if (!object.isMesh || !object.material) return
448
- if (Array.isArray(object.material)) {
449
- object.material = object.material.map((mat) =>
450
- this._convertGoogleTileBasicToPhong(mat)
451
- )
452
- } else {
453
- object.material = this._convertGoogleTileBasicToPhong(object.material)
454
- }
455
- })
456
- // this._reregisterGoogleTilesFadeMaterials(wrapper)
457
- wrapper.traverse((object) => {
458
- if (!object.isMesh) return
459
- object.castShadow = true
460
- object.receiveShadow = true
461
- object.needsUpdate = true
462
- })
463
- }
464
- setOpacity(opacity) {
465
- super.setOpacity(opacity)
466
- const wrapper = this.overlayMesh || this.tilesData?.tilesWrapper
467
- if (wrapper) {
468
- this._applyGoogleTilesOpacity(wrapper)
469
- }
470
- }
471
-
472
- setIsActive(isActive) {
473
- this.isActive = Boolean(isActive)
474
- const wrapper = this.overlayMesh || this.tilesData?.tilesWrapper
475
- if (wrapper) {
476
- this._applyGoogleTilesOpacity(wrapper)
477
- }
478
- this.emit('item-updated', this)
479
- }
480
-
481
- async renderOnThreeJS(threeJSComponent) {
482
- const rb = threeJSComponent?.roofsBounds
483
- if (rb && !this._roofsBoundsAreEqual(this.roofsBound, rb)) {
484
- this.updateRoofsBound(rb)
485
- }
486
-
487
- if (!this.isActive) {
488
- this._removeGroundAlignPlaceholder(threeJSComponent)
489
- const tilesWrapper =
490
- this.tilesData?.tilesWrapper ||
491
- threeJSComponent.meshes.overlayMeshes[this.id]
492
- if (tilesWrapper) {
493
- tilesWrapper.visible = false
494
- threeJSComponent.meshes.overlayMeshes[this.id] = tilesWrapper
495
- this.overlayMesh = tilesWrapper
496
- }
497
- return tilesWrapper || null
498
- }
499
-
500
- const tilesData = this._getOrCreateTilesData()
501
- if (!tilesData) return null
502
-
503
- const { tiles, tilesWrapper } = tilesData
504
- const { renderer, scene } = threeJSComponent
505
- this.scene = scene
506
- tiles.setCamera(this._tilesCamera)
507
- tiles.setResolutionFromRenderer(this._tilesCamera, renderer)
508
-
509
- tilesWrapper.userData.type = 'overlayMeshes'
510
- tilesWrapper.userData.meshId = this.id
511
- tilesWrapper.userData.version = this.version
512
-
513
- this._syncGroundAlignPlaceholder(threeJSComponent)
514
- if (!this.tilesFullyLoaded) {
515
- this._tickGroundAlignPlaceholderAnimation()
516
- }
517
-
518
- tilesWrapper.userData.update = () => {
519
- if (!this.isActive || !tiles || !renderer) return
520
- tiles.errorTarget = TILES_FRUSTUM_ERROR_TARGET
521
- tiles.setCamera(this._tilesCamera)
522
- tiles.setResolutionFromRenderer(this._tilesCamera, renderer)
523
- tiles.update()
524
- this._syncGroundAlignPlaceholder(threeJSComponent)
525
- if (!this.tilesFullyLoaded) {
526
- this._tickGroundAlignPlaceholderAnimation()
527
- }
528
- }
529
-
530
- if (tilesWrapper.parent !== scene) {
531
- if (tilesWrapper.parent) tilesWrapper.parent.remove(tilesWrapper)
532
- scene.add(tilesWrapper)
533
- }
534
-
535
- threeJSComponent.meshes.overlayMeshes[this.id] = tilesWrapper
536
- this.overlayMesh = tilesWrapper
537
- this._applyGoogleTilesOpacity(tilesWrapper)
538
- return tilesWrapper
539
- }
540
-
541
- renderOnPaperJS() {
542
- // No 2D representation for 3D Tiles overlay
543
- }
544
-
545
- serializeSettings() {
546
- return {
547
- ...super.serializeSettings(),
548
- centerLat: this.origin?.lat ?? this.settings?.centerLat,
549
- centerLon: this.origin?.lng ?? this.settings?.centerLon,
550
- groundElevation: this._groundElevation,
551
- }
552
- }
553
-
554
- dispose() {
555
- if (this._groundAlignPlaceholderMesh) {
556
- this._groundAlignPlaceholderMesh.parent?.remove(
557
- this._groundAlignPlaceholderMesh
558
- )
559
- this._groundAlignPlaceholderMesh.geometry?.dispose()
560
- if (this._groundAlignPlaceholderMesh.material?.dispose) {
561
- this._groundAlignPlaceholderMesh.material.dispose()
562
- }
563
- this._groundAlignPlaceholderMesh = null
564
- }
565
- if (this.tilesData?.tiles) {
566
- this.tilesData.tiles.dispose()
567
- }
568
- this.tilesData = null
569
- this.overlayMesh = null
570
- this.roofsBound = null
571
- this._initPromise = null
572
- this._tilesGroundAligned = false
573
- }
574
- }