@eturnity/eturnity_3d 6.33.0-qa.0 → 6.33.0-qa.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_3d",
3
3
  "private": false,
4
- "version": "6.33.0-qa.0",
4
+ "version": "6.33.0-qa.2",
5
5
  "main": "dist/main.js",
6
6
  "scripts": {
7
7
  "dev": "vue-cli-service serve --skip-plugins @vue/cli-plugin-eslint",
@@ -31,7 +31,7 @@ export default {
31
31
  1000
32
32
  ),
33
33
  provider: null,
34
- cameraprojection: null,
34
+ cameraProjection: null,
35
35
  texture: null,
36
36
  renderer: new THREE.WebGLRenderer({
37
37
  antialias: true,
@@ -72,7 +72,7 @@ export default {
72
72
  await this.loadPanelsTexture()
73
73
  this.renderGeometry()
74
74
  this.onWindowResize()
75
- // this.updateProjectionMaterials()
75
+ this.updateProjectionMaterials()
76
76
  this.animate()
77
77
  this.$root.$on('on-roofSelected', (polygon) =>
78
78
  this.setCameraOrthogonalTo(polygon)
@@ -113,7 +113,7 @@ export default {
113
113
  })
114
114
  imageOverlayProjectionMaterial.userData = {}
115
115
  imageOverlayProjectionMaterial.userData.type = 'imageOverlayMaterial'
116
- imageOverlayProjectionMaterial.userData.priority = 2
116
+ imageOverlayProjectionMaterial.priority = 20
117
117
  imageOverlayProjectionMaterial.userData.url = this.imageOverlay.url
118
118
  resolve(imageOverlayProjectionMaterial)
119
119
  })
@@ -14,6 +14,7 @@ import mapProjection from './mapProjection'
14
14
  import texture from './texture'
15
15
  import projectionMaterial from './projectionMaterial'
16
16
  import tile from './tile'
17
+ import tileProjection from './tileProjection'
17
18
 
18
19
  export default {
19
20
  //mixins:[node,background,clear,edge,loader,margin,moduleField,obstacle,panel,roof,base]
@@ -33,6 +34,7 @@ export default {
33
34
  texture,
34
35
  mapProjection,
35
36
  projectionMaterial,
36
- tile
37
+ tile,
38
+ tileProjection
37
39
  ]
38
40
  }
@@ -35,7 +35,7 @@ export default {
35
35
  this.mapProjectionTexture = texture
36
36
  this.setMapProjectionCameraPosition()
37
37
  let mapProjectionMaterial = new ProjectedMaterial({
38
- camera: this.cameraprojection,
38
+ camera: this.cameraProjection,
39
39
  texture: texture,
40
40
  transparent: true,
41
41
  side: THREE.DoubleSide
@@ -63,12 +63,12 @@ export default {
63
63
  this.backgroundImagesizeInMm =
64
64
  this.layoutSettings.background_map_settings.sizeInMm
65
65
  if (this.backgroundImagesizeInMm) {
66
- this.cameraprojection.aspect =
66
+ this.cameraProjection.aspect =
67
67
  this.backgroundImagesizeInMm.width /
68
68
  this.backgroundImagesizeInMm.height
69
69
  let projectionAltitude =
70
70
  this.backgroundImagesizeInMm.height /
71
- (2 * Math.tan((this.cameraprojection.fov * Math.PI) / 360))
71
+ (2 * Math.tan((this.cameraProjection.fov * Math.PI) / 360))
72
72
 
73
73
  //set projection camera over background_map_center
74
74
  let cameraProjectionPosition = {
@@ -86,14 +86,14 @@ export default {
86
86
  cameraProjectionPosition.y = positionInMm.y / 1000
87
87
  }
88
88
 
89
- this.cameraprojection.position.set(
89
+ this.cameraProjection.position.set(
90
90
  cameraProjectionPosition.x,
91
91
  cameraProjectionPosition.y,
92
92
  projectionAltitude / 1000
93
93
  )
94
- this.cameraprojection.far = projectionAltitude * 1.5
95
- this.cameraprojection.near = projectionAltitude * 0.5
96
- this.cameraprojection.updateProjectionMatrix()
94
+ this.cameraProjection.far = projectionAltitude * 1.5
95
+ this.cameraProjection.near = projectionAltitude * 0.5
96
+ this.cameraProjection.updateProjectionMatrix()
97
97
  }
98
98
  }
99
99
  }
@@ -35,7 +35,6 @@ export default {
35
35
  this.material.roof[index].dispose()
36
36
  this.material.roof.splice(index, 1)
37
37
  this.material.roof = [...this.material.roof]
38
- this.reorderRoofMaterials()
39
38
  }
40
39
 
41
40
  index = this.material.roof.findIndex(
@@ -50,13 +49,11 @@ export default {
50
49
  ...this.material.roof,
51
50
  this.imageOverlayMaterial
52
51
  ]
53
- this.reorderRoofMaterials()
54
52
  }
55
53
  } else if (index >= 0) {
56
54
  this.material.roof[index].dispose()
57
55
  this.material.roof.splice(index, 1)
58
56
  this.material.roof = [...this.material.roof]
59
- this.reorderRoofMaterials()
60
57
  }
61
58
  this.renderImageOverlayOnBackground()
62
59
  this.applyTextureOnRoofs()
@@ -70,18 +70,19 @@ export default {
70
70
  return geometry
71
71
  },
72
72
 
73
- applyTextureOnRoofs() {
73
+ applyTextureOnRoofs(material = this.material.roof) {
74
+ this.reorderRoofMaterials()
74
75
  this.roofs.forEach((roof) => {
75
76
  //roofs
76
77
  let mesh = this.meshes.roofMeshes[roof.id]
77
- this.applyTextureOnMesh(this.material.roof, mesh)
78
+ this.applyTextureOnMesh(material, mesh)
78
79
  //obstacle on roof
79
80
  roof.holes
80
81
  .filter((p) => p.layer == 'obstacle')
81
82
  .forEach((obstacle) => {
82
83
  let meshObstacle =
83
84
  this.meshes.obstacleMeshes[obstacle.id + '-' + roof.id + '_top']
84
- this.applyTextureOnMesh(this.material.roof, meshObstacle)
85
+ this.applyTextureOnMesh(material, meshObstacle)
85
86
  })
86
87
  })
87
88
  },
@@ -9,12 +9,12 @@ import {
9
9
  tileToCorners
10
10
  } from '@eturnity/eturnity_maths'
11
11
 
12
- import {cancellablePromise} from '../../utils/cancellablePromise'
12
+ import { cancellablePromise } from '../../utils/cancellablePromise'
13
13
 
14
14
  export default {
15
15
  data() {
16
16
  return {
17
- pendingTiles: [],
17
+ pendingTiles: []
18
18
  }
19
19
  },
20
20
  methods: {
@@ -92,11 +92,11 @@ export default {
92
92
  let tileToRender = []
93
93
  for (let xTile = xTileMin; xTile <= xTileMax; xTile++) {
94
94
  for (let yTile = yTileMin; yTile <= yTileMax; yTile++) {
95
- tileToRender.push({ xTile, yTile, zoomLvl })
95
+ tileToRender.push({ xTile, yTile, zoomLvl, isTileOnRoofBound: true })
96
96
  }
97
97
  }
98
98
 
99
- for (let k = 0; k < 3; k++) {
99
+ while (zoomLvl > 16) {
100
100
  xTileMin = xTileMin / 2 - 1
101
101
  xTileMax = (xTileMax + 1) / 2
102
102
  yTileMin = yTileMin / 2 - 1
@@ -119,7 +119,12 @@ export default {
119
119
  yTile - yTileMin <= yMinOdd ||
120
120
  yTileMax - yTile <= yMaxEven
121
121
  ) {
122
- tileToRender.push({ xTile, yTile, zoomLvl })
122
+ tileToRender.push({
123
+ xTile,
124
+ yTile,
125
+ zoomLvl,
126
+ isTileOnRoofBound: false
127
+ })
123
128
  }
124
129
  }
125
130
  }
@@ -129,19 +134,22 @@ export default {
129
134
  let xTile = tileToRender[k].xTile
130
135
  let yTile = tileToRender[k].yTile
131
136
  zoomLvl = tileToRender[k].zoomLvl
132
- this.renderTile(xTile, yTile, zoomLvl)
137
+ let isTileOnRoofBound = tileToRender[k].isTileOnRoofBound
138
+ this.renderTile(xTile, yTile, zoomLvl, isTileOnRoofBound)
133
139
  }
134
140
  },
135
- removeTileFromPending(meshId,mapLayer){
141
+ removeTileFromPending(meshId, mapLayer) {
136
142
  this.pendingTiles = this.pendingTiles.filter(
137
143
  (t) => t.meshId != meshId || t.mapLayer != mapLayer
138
144
  )
139
145
  },
140
- async renderTile(x, y, zoomLvl) {
146
+ async renderTile(x, y, zoomLvl, isTileOnRoofBound = false) {
141
147
  const meshId = 'tile_' + x + '_' + y + '_' + zoomLvl
142
148
  const mapLayer = this.provider.mapLayer
143
149
  if (
144
- this.pendingTiles.find(t=>t.meshId==meshId && t.mapLayer==mapLayer)
150
+ this.pendingTiles.find(
151
+ (t) => t.meshId == meshId && t.mapLayer == mapLayer
152
+ )
145
153
  ) {
146
154
  return
147
155
  }
@@ -154,15 +162,19 @@ export default {
154
162
  const latitude = this.layoutSettings.layout_latitude
155
163
  const longitude = this.layoutSettings.layout_longitude
156
164
  let geometry, material
157
- const imagePromise=cancellablePromise(this.provider.fetchTile(zoomLvl, x, y))
158
- this.pendingTiles.push({ x, y, zoomLvl, mapLayer, meshId, imagePromise})
159
- imagePromise.then((image) =>{
160
-
165
+ const imagePromise = cancellablePromise(
166
+ this.provider.fetchTile(zoomLvl, x, y)
167
+ )
168
+ this.pendingTiles.push({ x, y, zoomLvl, mapLayer, meshId, imagePromise })
169
+ imagePromise.then((image) => {
161
170
  if (!image) {
162
- this.removeTileFromPending(meshId,mapLayer)
171
+ this.removeTileFromPending(meshId, mapLayer)
163
172
  return
164
173
  }
165
174
  const texture = new THREE.Texture(image)
175
+ if (isTileOnRoofBound) {
176
+ this.newTileMaterial(texture, x, y, zoomLvl, mapLayer)
177
+ }
166
178
  texture.generateMipmaps = false
167
179
  texture.format = THREE.RGBAFormat
168
180
  texture.magFilter = THREE.LinearFilter
@@ -190,7 +202,7 @@ export default {
190
202
  map: texture,
191
203
  color: 0xffffff,
192
204
  side: THREE.FrontSide,
193
- transparent: false
205
+ transparent: true
194
206
  })
195
207
  material.map = texture
196
208
  material.needsUpdate = true
@@ -205,10 +217,126 @@ export default {
205
217
  }
206
218
  }
207
219
  //image.parentNode.removeChild(image);
208
- this.removeTileFromPending(meshId,mapLayer)
220
+ this.removeTileFromPending(meshId, mapLayer)
209
221
  })
210
222
  },
211
- renderGoogleTiles() {
223
+ async renderGoogleTiles() {
224
+ this.clearByType('tileMeshes')
225
+ if (this.backgroundMap) {
226
+ this.backgroundMap.clear()
227
+ this.scene.remove(this.backgroundMap)
228
+ this.clearThreeObjects(this.backgroundMap)
229
+ }
230
+ this.backgroundMap = new THREE.Group()
231
+
232
+ let googleMapType = 'satellite'
233
+ switch (this.selectedMapLayer.key) {
234
+ case 'googleLayerRoadmap':
235
+ googleMapType = 'roadmap'
236
+ break
237
+ case 'googleLayer':
238
+ googleMapType = 'satellite'
239
+ break
240
+ case 'googleLayerTerrain':
241
+ googleMapType = 'terrain'
242
+ break
243
+ }
244
+
245
+ let roofsBoundZoomLvl = 19
246
+ let roofsBoundCenterMeter = {
247
+ x: (this.roofsBounds.xMax + this.roofsBounds.xMin) / 2000,
248
+ y: (this.roofsBounds.yMax + this.roofsBounds.yMin) / 2000
249
+ }
250
+ let deltaLatLng = distanceToDeltaLatLng(
251
+ roofsBoundCenterMeter.x,
252
+ roofsBoundCenterMeter.y,
253
+ this.layoutSettings.layout_latitude
254
+ )
255
+ let roofsBoundCenterLatLng = {
256
+ lat: this.layoutSettings.layout_latitude + deltaLatLng.lat,
257
+ lng: this.layoutSettings.layout_longitude + deltaLatLng.lng
258
+ }
259
+
260
+ let apiKey = process.env.VUE_APP_GOOGLE_MAP_API_KEY
261
+ let backgroundPlane = []
262
+ let size = 640
263
+ let planeGeometry = []
264
+ let planeMaterial = []
265
+ let texture = []
266
+ let zoomLevels = [
267
+ roofsBoundZoomLvl,
268
+ roofsBoundZoomLvl - 2,
269
+ roofsBoundZoomLvl - 4
270
+ ]
271
+
272
+ for (
273
+ let indexGoogleBackground = 0;
274
+ indexGoogleBackground < zoomLevels.length;
275
+ indexGoogleBackground++
276
+ ) {
277
+ let zoomLevel = zoomLevels[indexGoogleBackground]
278
+ let groundResolution =
279
+ (Math.cos((this.layoutSettings.layout_latitude * Math.PI) / 180) *
280
+ 2 *
281
+ Math.PI *
282
+ 6378137) /
283
+ (256 * Math.pow(2, zoomLevel))
284
+ let sizeInMeter = groundResolution * size
285
+ planeGeometry[indexGoogleBackground] = new THREE.PlaneGeometry(
286
+ sizeInMeter,
287
+ sizeInMeter*0.9
288
+ )
289
+
290
+ //to remove attribution in bottom of the image
291
+ var uvs = new Float32Array([
292
+ 0, 0.95,
293
+ 1, 0.95,
294
+ 0, 0.05,
295
+ 1, 0.05,
296
+ 0, 0.05,
297
+ 1, 0.95,
298
+ ])
299
+ planeGeometry[indexGoogleBackground].setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
300
+ planeGeometry[indexGoogleBackground].computeVertexNormals()
301
+
302
+ let googleBackgroundUrl = `https://maps.googleapis.com/maps/api/staticmap?center=${
303
+ roofsBoundCenterLatLng.lat + ',' + roofsBoundCenterLatLng.lng
304
+ }&maptype=${googleMapType}&zoom=${zoomLevel}&size=${size}x${size}&key=${apiKey}`
305
+
306
+ texture[indexGoogleBackground] = await this.loader.load(
307
+ googleBackgroundUrl
308
+ )
309
+ texture[indexGoogleBackground].wrapS = 1//THREE.RepeatWrapping
310
+ texture[indexGoogleBackground].wrapT = 1//THREE.RepeatWrapping
311
+ // texture[indexGoogleBackground].offset.y += 0.1
312
+
313
+ if (indexGoogleBackground == 0) {
314
+ this.newGoogleTileMaterial(
315
+ texture[indexGoogleBackground],
316
+ sizeInMeter,
317
+ roofsBoundCenterMeter,
318
+ googleMapType
319
+ )
320
+ }
321
+ planeMaterial[indexGoogleBackground] = new THREE.MeshBasicMaterial({
322
+ map: texture[indexGoogleBackground],
323
+ side: THREE.DoubleSide
324
+ })
325
+ backgroundPlane[indexGoogleBackground] = new THREE.Mesh(
326
+ planeGeometry[indexGoogleBackground],
327
+ planeMaterial[indexGoogleBackground]
328
+ )
329
+ backgroundPlane[indexGoogleBackground].position.x =
330
+ roofsBoundCenterMeter.x
331
+ backgroundPlane[indexGoogleBackground].position.y =
332
+ roofsBoundCenterMeter.y
333
+ backgroundPlane[indexGoogleBackground].position.z =
334
+ -indexGoogleBackground / 2
335
+ this.backgroundMap.add(backgroundPlane[indexGoogleBackground])
336
+ }
337
+ this.scene.add(this.backgroundMap)
338
+ },
339
+ async renderGoogleTilesCenter() {
212
340
  this.clearByType('tileMeshes')
213
341
  if (this.backgroundMap) {
214
342
  this.backgroundMap.clear()
@@ -237,6 +365,7 @@ export default {
237
365
  let planeMaterial = []
238
366
  let texture = []
239
367
  let zoomLevels = [19, 16]
368
+
240
369
  for (
241
370
  let indexGoogleBackground = 0;
242
371
  indexGoogleBackground < zoomLevels.length;
@@ -260,7 +389,16 @@ export default {
260
389
  this.layoutSettings.layout_longitude
261
390
  }&maptype=${googleMapType}&zoom=${zoomLevel}&size=${size}x${size}&key=${apiKey}`
262
391
 
263
- texture[indexGoogleBackground] = this.loader.load(googleBackgroundUrl)
392
+ texture[indexGoogleBackground] = await this.loader.load(
393
+ googleBackgroundUrl
394
+ )
395
+ if (indexGoogleBackground == 0) {
396
+ this.newGoogleTileMaterial(
397
+ texture[indexGoogleBackground],
398
+ sizeInMeter,
399
+ googleMapType
400
+ )
401
+ }
264
402
  planeMaterial[indexGoogleBackground] = new THREE.MeshBasicMaterial({
265
403
  map: texture[indexGoogleBackground],
266
404
  side: THREE.DoubleSide
@@ -276,16 +414,14 @@ export default {
276
414
  this.scene.add(this.backgroundMap)
277
415
  }
278
416
  },
279
- watch:{
280
- selectedMapLayer(newMapLayer){
281
- this.pendingTiles = this.pendingTiles.filter(
282
- (t) => {
283
- if(t.mapLayer != newMapLayer.key){
284
- t.imagePromise.cancel()
285
- return false
286
- }
417
+ watch: {
418
+ selectedMapLayer(newMapLayer) {
419
+ this.pendingTiles = this.pendingTiles.filter((t) => {
420
+ if (t.mapLayer != newMapLayer.key) {
421
+ t.imagePromise.cancel()
422
+ return false
287
423
  }
288
- )
424
+ })
289
425
  }
290
426
  }
291
427
  }
@@ -0,0 +1,124 @@
1
+ import * as THREE from 'three'
2
+ import ProjectedMaterial from 'three-projected-material'
3
+ import { tileToCorners } from '@eturnity/eturnity_maths'
4
+ import { earthRadius } from '../../config'
5
+ export default {
6
+ data() {
7
+ return {
8
+ tileProjectionTextures: [],
9
+ tileProjectionMaterials: []
10
+ }
11
+ },
12
+ methods: {
13
+ async newGoogleTileMaterial(texture, sizeInMeter, center, mapLayer) {
14
+ if (!this.material.roof) {
15
+ this.material.roof = []
16
+ }
17
+ const cameraProjection = new THREE.OrthographicCamera(
18
+ center.x - sizeInMeter / 2,
19
+ center.x + sizeInMeter / 2,
20
+ center.y + sizeInMeter / 2,
21
+ center.y - sizeInMeter / 2,
22
+ 100,
23
+ 10000
24
+ )
25
+ // cameraProjection.position.set(0, 0, 1)
26
+ // cameraProjection.up.set(0, 0, 1)
27
+ let tileProjectionMaterial = new ProjectedMaterial({
28
+ camera: cameraProjection,
29
+ texture: texture,
30
+ transparent: true,
31
+ side: THREE.DoubleSide
32
+ })
33
+ tileProjectionMaterial.userData = {}
34
+ tileProjectionMaterial.userData.type = 'tileProjectionMaterial'
35
+ tileProjectionMaterial.userData.materialId =
36
+ 'material_' +
37
+ sizeInMeter +
38
+ '_' +
39
+ center.x +
40
+ '_' +
41
+ center.y +
42
+ '_' +
43
+ mapLayer
44
+ tileProjectionMaterial.userData.mapLayer = mapLayer
45
+ tileProjectionMaterial.userData.priority = 10
46
+ this.material.roof.push(tileProjectionMaterial)
47
+ this.applyTextureOnRoofs()
48
+ },
49
+ async newTileMaterial(texture, x, y, zoom, mapLayer) {
50
+ if (!this.material.roof) {
51
+ this.material.roof = []
52
+ }
53
+ const cameraProjection = new THREE.OrthographicCamera(
54
+ -1,
55
+ 1,
56
+ -1,
57
+ 1,
58
+ 100,
59
+ 10000
60
+ )
61
+ cameraProjection.position.set(0, 0, 1)
62
+ cameraProjection.up.set(0, 0, 1)
63
+ let tileProjectionMaterial = new ProjectedMaterial({
64
+ camera: cameraProjection,
65
+ texture: texture,
66
+ transparent: true,
67
+ side: THREE.DoubleSide
68
+ })
69
+ tileProjectionMaterial.userData = {}
70
+ tileProjectionMaterial.userData.type = 'tileProjectionMaterial'
71
+ tileProjectionMaterial.userData.materialId =
72
+ 'material_' + x + '_' + y + '_' + zoom + '_' + mapLayer
73
+ tileProjectionMaterial.userData.mapLayer = mapLayer
74
+ tileProjectionMaterial.priority = 10
75
+ this.setTileCameraPosition(cameraProjection, x, y, zoom)
76
+ this.material.roof.push(tileProjectionMaterial)
77
+ this.applyTextureOnRoofs()
78
+ },
79
+ disposeTileMaterial(material) {
80
+ material.texture.dispose()
81
+ material.dispose()
82
+ },
83
+ disposeTileMaterialDifferentMapLayer(mapLayer) {
84
+ if (!this.material.roof) return
85
+ this.material.roof = this.material.roof.filter((m) => {
86
+ if (
87
+ m.userData.type == 'tileProjectionMaterial' &&
88
+ m.userData.mapLayer != mapLayer
89
+ ) {
90
+ this.disposeTileMaterial(m)
91
+ return false
92
+ }
93
+ return true
94
+ })
95
+ },
96
+ setTileCameraPosition(camera, x, y, zoom) {
97
+ const latitude = this.layoutSettings.layout_latitude
98
+ const longitude = this.layoutSettings.layout_longitude
99
+ let corners = tileToCorners(x, y, zoom, latitude, longitude)
100
+ let height, width, tileCenter
101
+ let numberOfTiles = Math.pow(2, zoom)
102
+ height =
103
+ (2000 * Math.PI * earthRadius * Math.cos((latitude * Math.PI) / 180)) /
104
+ numberOfTiles
105
+ width = height
106
+ tileCenter = {
107
+ x: (corners[0].x + corners[2].x) / 2,
108
+ y: (corners[0].y + corners[2].y) / 2
109
+ }
110
+
111
+ camera.left = corners[0].x / 1000
112
+ camera.right = corners[2].x / 1000
113
+ camera.bottom = corners[0].y / 1000
114
+ camera.top = corners[2].y / 1000
115
+
116
+ camera.updateProjectionMatrix()
117
+ }
118
+ },
119
+ watch: {
120
+ selectedMapLayer(newMapLayer) {
121
+ this.disposeTileMaterialDifferentMapLayer(newMapLayer.key)
122
+ }
123
+ }
124
+ }
@@ -355,7 +355,7 @@ export default {
355
355
  this.renderer = null
356
356
  this.scene = null
357
357
  this.camera = null
358
- this.cameraprojection = null
358
+ this.cameraProjection = null
359
359
  Object.values(this.material).forEach((m) => {
360
360
  if (m && m.dispose) m.dispose()
361
361
  })
@@ -43,16 +43,16 @@ export default {
43
43
  this.camera.position.set(0, -100, 50)
44
44
  this.camera.up.set(0, 0, 1)
45
45
 
46
- this.cameraprojection = new THREE.PerspectiveCamera(
46
+ this.cameraProjection = new THREE.PerspectiveCamera(
47
47
  1,
48
48
  300 / 300,
49
49
  100,
50
50
  1000
51
51
  )
52
- this.cameraprojection.position.set(0, 0, 24)
53
- this.cameraprojection.up.set(0, 0, 1)
52
+ this.cameraProjection.position.set(0, 0, 24)
53
+ this.cameraProjection.up.set(0, 0, 1)
54
54
 
55
- // const helper = new THREE.CameraHelper( this.cameraprojection );
55
+ // const helper = new THREE.CameraHelper( this.cameraProjection );
56
56
  // this.scene.add( helper );
57
57
 
58
58
  // const axesHelper = new THREE.AxesHelper( 20 );