itowns 2.44.3-next.4 → 2.44.3-next.40

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.
Files changed (109) hide show
  1. package/CODING.md +1 -1
  2. package/CONTRIBUTORS.md +1 -0
  3. package/dist/debug.js +1 -1
  4. package/dist/debug.js.map +1 -1
  5. package/dist/itowns.js +1 -1
  6. package/dist/itowns.js.LICENSE.txt +0 -2
  7. package/dist/itowns.js.map +1 -1
  8. package/dist/itowns_widgets.js +1 -1
  9. package/dist/itowns_widgets.js.map +1 -1
  10. package/examples/3dtiles_loader.html +123 -48
  11. package/examples/config.json +3 -10
  12. package/examples/copc_simple_loader.html +15 -5
  13. package/examples/effects_stereo.html +2 -2
  14. package/examples/entwine_3d_loader.html +3 -1
  15. package/examples/entwine_simple_loader.html +1 -1
  16. package/examples/images/itowns_logo.svg +123 -0
  17. package/examples/js/plugins/COGParser.js +1 -1
  18. package/examples/jsm/OGC3DTilesHelper.js +6 -1
  19. package/examples/layers/JSONLayers/GeoidMNT.json +3 -1
  20. package/examples/misc_collada.html +2 -2
  21. package/examples/source_file_geojson_3d.html +0 -1
  22. package/examples/source_file_kml_raster_usgs.html +0 -1
  23. package/examples/source_stream_wfs_raster.html +0 -7
  24. package/examples/vector_tile_mapbox_raster.html +91 -0
  25. package/examples/view_3d_map_webxr.html +3 -1
  26. package/examples/view_multi_25d.html +2 -2
  27. package/lib/Controls/GlobeControls.js +45 -28
  28. package/lib/Controls/StateControl.js +5 -2
  29. package/lib/Converter/Feature2Mesh.js +10 -4
  30. package/lib/Converter/Feature2Texture.js +6 -1
  31. package/lib/Converter/convertToTile.js +3 -8
  32. package/lib/Converter/textureConverter.js +4 -5
  33. package/lib/Core/Deprecated/Undeprecator.js +0 -1
  34. package/lib/Core/Feature.js +3 -4
  35. package/lib/Core/Geographic/Coordinates.js +143 -132
  36. package/lib/Core/Geographic/Crs.js +140 -145
  37. package/lib/Core/Geographic/Extent.js +221 -397
  38. package/lib/Core/Geographic/GeoidGrid.js +1 -1
  39. package/lib/Core/MainLoop.js +1 -3
  40. package/lib/Core/Math/Ellipsoid.js +62 -21
  41. package/lib/Core/Prefab/Globe/Atmosphere.js +4 -8
  42. package/lib/Core/Prefab/Globe/GlobeLayer.js +22 -15
  43. package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +111 -0
  44. package/lib/Core/Prefab/GlobeView.js +2 -7
  45. package/lib/Core/Prefab/Planar/PlanarLayer.js +17 -11
  46. package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +43 -43
  47. package/lib/Core/Prefab/TileBuilder.js +42 -40
  48. package/lib/Core/Prefab/computeBufferTileGeometry.js +195 -130
  49. package/lib/Core/Scheduler/Cache.js +1 -240
  50. package/lib/Core/Style.js +34 -495
  51. package/lib/Core/StyleOptions.js +486 -0
  52. package/lib/Core/Tile/Tile.js +207 -0
  53. package/lib/Core/Tile/TileGrid.js +49 -0
  54. package/lib/Core/TileGeometry.js +112 -28
  55. package/lib/Core/TileMesh.js +3 -3
  56. package/lib/Core/View.js +15 -8
  57. package/lib/Layer/C3DTilesLayer.js +20 -16
  58. package/lib/Layer/ColorLayer.js +35 -9
  59. package/lib/Layer/CopcLayer.js +7 -2
  60. package/lib/Layer/ElevationLayer.js +39 -7
  61. package/lib/Layer/EntwinePointTileLayer.js +14 -7
  62. package/lib/Layer/FeatureGeometryLayer.js +20 -6
  63. package/lib/Layer/GeometryLayer.js +42 -11
  64. package/lib/Layer/LabelLayer.js +45 -27
  65. package/lib/Layer/Layer.js +92 -61
  66. package/lib/Layer/OGC3DTilesLayer.js +212 -56
  67. package/lib/Layer/OrientedImageLayer.js +11 -5
  68. package/lib/Layer/PointCloudLayer.js +76 -30
  69. package/lib/Layer/Potree2Layer.js +9 -2
  70. package/lib/Layer/PotreeLayer.js +10 -3
  71. package/lib/Layer/RasterLayer.js +12 -2
  72. package/lib/Layer/TiledGeometryLayer.js +69 -13
  73. package/lib/Main.js +2 -2
  74. package/lib/Parser/GeoJsonParser.js +1 -1
  75. package/lib/Parser/VectorTileParser.js +42 -29
  76. package/lib/Parser/XbilParser.js +14 -2
  77. package/lib/Provider/Fetcher.js +5 -1
  78. package/lib/Provider/URLBuilder.js +22 -11
  79. package/lib/Renderer/Camera.js +1 -1
  80. package/lib/Renderer/Label2DRenderer.js +9 -7
  81. package/lib/Renderer/OBB.js +11 -13
  82. package/lib/Renderer/PointsMaterial.js +5 -5
  83. package/lib/Renderer/RasterTile.js +1 -2
  84. package/lib/Renderer/SphereHelper.js +0 -6
  85. package/lib/Source/CopcSource.js +13 -2
  86. package/lib/Source/EntwinePointTileSource.js +14 -4
  87. package/lib/Source/FileSource.js +9 -10
  88. package/lib/Source/OrientedImageSource.js +2 -2
  89. package/lib/Source/Source.js +26 -46
  90. package/lib/Source/TMSSource.js +10 -9
  91. package/lib/Source/VectorTilesSource.js +38 -34
  92. package/lib/Source/WFSSource.js +18 -13
  93. package/lib/Source/WMSSource.js +56 -18
  94. package/lib/Source/WMTSSource.js +13 -7
  95. package/lib/ThreeExtended/libs/ktx-parse.module.js +310 -274
  96. package/lib/ThreeExtended/loaders/DRACOLoader.js +3 -2
  97. package/lib/ThreeExtended/loaders/GLTFLoader.js +6 -3
  98. package/lib/ThreeExtended/loaders/KTX2Loader.js +144 -60
  99. package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
  100. package/lib/Utils/CameraUtils.js +1 -1
  101. package/lib/Utils/gui/C3DTilesStyle.js +2 -3
  102. package/lib/Utils/placeObjectOnGround.js +0 -1
  103. package/package.json +10 -8
  104. package/examples/3dtiles_25d.html +0 -120
  105. package/examples/3dtiles_basic.html +0 -94
  106. package/examples/3dtiles_batch_table.html +0 -86
  107. package/examples/3dtiles_ion.html +0 -126
  108. package/examples/3dtiles_pointcloud.html +0 -95
  109. package/lib/Core/Prefab/Globe/BuilderEllipsoidTile.js +0 -110
@@ -1,19 +1,28 @@
1
1
  import * as THREE from 'three';
2
- import TileGeometry from "../TileGeometry.js";
3
- import Cache from "../Scheduler/Cache.js";
4
- import computeBuffers from "./computeBufferTileGeometry.js";
2
+ import { TileGeometry } from "../TileGeometry.js";
3
+ import { LRUCache } from 'lru-cache';
4
+ import { computeBuffers } from "./computeBufferTileGeometry.js";
5
5
  import OBB from "../../Renderer/OBB.js";
6
6
  const cacheBuffer = new Map();
7
- const cacheTile = new Cache();
8
- export default function newTileGeometry(builder, params) {
7
+ const cacheTile = new LRUCache({
8
+ max: 500
9
+ });
10
+
11
+ /**
12
+ * Reference to a tile's extent with rigid transformations.
13
+ * Enables reuse of geometry, saving a bit of memory.
14
+ */
15
+
16
+ export function newTileGeometry(builder, params) {
9
17
  const {
10
- sharableExtent,
18
+ shareableExtent,
11
19
  quaternion,
12
20
  position
13
- } = builder.computeSharableExtent(params.extent);
14
- const south = sharableExtent.south.toFixed(6);
21
+ } = builder.computeShareableExtent(params.extent);
22
+ const south = shareableExtent.south.toFixed(6);
15
23
  const bufferKey = `${builder.crs}_${params.disableSkirt ? 0 : 1}_${params.segments}`;
16
- let promiseGeometry = cacheTile.get(south, params.level, bufferKey);
24
+ const key = `s${south}l${params.level}bK${bufferKey}`;
25
+ let promiseGeometry = cacheTile.get(key);
17
26
 
18
27
  // build geometry if doesn't exist
19
28
  if (!promiseGeometry) {
@@ -21,50 +30,43 @@ export default function newTileGeometry(builder, params) {
21
30
  promiseGeometry = new Promise(r => {
22
31
  resolve = r;
23
32
  });
24
- cacheTile.set(promiseGeometry, south, params.level, bufferKey);
25
- params.extent = sharableExtent;
33
+ cacheTile.set(key, promiseGeometry);
34
+ params.extent = shareableExtent;
26
35
  params.center = builder.center(params.extent).clone();
27
- // Read previously cached values (index and uv.wgs84 only depend on the # of triangles)
36
+ // Read previously cached values (index and uv.wgs84 only
37
+ // depend on the # of triangles)
28
38
  let cachedBuffers = cacheBuffer.get(bufferKey);
29
- params.buildIndexAndUv_0 = !cachedBuffers;
30
- params.builder = builder;
31
39
  let buffers;
32
40
  try {
33
- buffers = computeBuffers(params);
41
+ buffers = computeBuffers(builder, params, cachedBuffers !== undefined ? {
42
+ index: cachedBuffers.index.array,
43
+ uv: cachedBuffers.uv.array
44
+ } : undefined);
34
45
  } catch (e) {
35
46
  return Promise.reject(e);
36
47
  }
37
48
  if (!cachedBuffers) {
38
- cachedBuffers = {};
39
- cachedBuffers.index = new THREE.BufferAttribute(buffers.index, 1);
40
- cachedBuffers.uv = new THREE.BufferAttribute(buffers.uvs[0], 2);
49
+ // We know the fields will exist due to the condition
50
+ // matching with the one for buildIndexAndUv_0.
51
+ // TODO: Make this brain-based check compiler-based.
52
+
53
+ cachedBuffers = {
54
+ index: new THREE.BufferAttribute(buffers.index, 1),
55
+ uv: new THREE.BufferAttribute(buffers.uvs[0], 2)
56
+ };
41
57
 
42
58
  // Update cacheBuffer
43
59
  cacheBuffer.set(bufferKey, cachedBuffers);
44
60
  }
45
- buffers.index = cachedBuffers.index;
46
- buffers.uvs[0] = cachedBuffers.uv;
47
- buffers.position = new THREE.BufferAttribute(buffers.position, 3);
48
- buffers.normal = new THREE.BufferAttribute(buffers.normal, 3);
49
- if (params.builder.uvCount > 1) {
50
- buffers.uvs[1] = new THREE.BufferAttribute(buffers.uvs[1], 1);
51
- }
52
- const geometry = new TileGeometry(params, buffers);
53
- geometry.OBB = new OBB(geometry.boundingBox.min, geometry.boundingBox.max);
54
- geometry._count = 0;
55
- geometry.dispose = () => {
56
- geometry._count--;
57
- if (geometry._count <= 0) {
58
- // To avoid remove index buffer and attribute buffer uv
59
- // error un-bound buffer in webgl with VAO rendering.
60
- // Could be removed if the attribute buffer deleting is
61
- // taken into account in the buffer binding state (in THREE.WebGLBindingStates code).
62
- geometry.index = null;
63
- delete geometry.attributes.uv;
64
- THREE.BufferGeometry.prototype.dispose.call(geometry);
65
- cacheTile.delete(south, params.level, bufferKey);
66
- }
61
+ const gpuBuffers = {
62
+ index: cachedBuffers.index,
63
+ uvs: [cachedBuffers.uv, ...(buffers.uvs[1] !== undefined ? [new THREE.BufferAttribute(buffers.uvs[1], 1)] : [])],
64
+ position: new THREE.BufferAttribute(buffers.position, 3),
65
+ normal: new THREE.BufferAttribute(buffers.normal, 3)
67
66
  };
67
+ const geometry = new TileGeometry(builder, params, gpuBuffers);
68
+ geometry.OBB = new OBB(geometry.boundingBox.min, geometry.boundingBox.max);
69
+ geometry.initRefCount(cacheTile, key);
68
70
  resolve(geometry);
69
71
  return Promise.resolve({
70
72
  geometry,
@@ -3,14 +3,55 @@ export function getBufferIndexSize(segments, noSkirt) {
3
3
  const triangles = segments * segments * 2 + (noSkirt ? 0 : 4 * segments * 2);
4
4
  return triangles * 3;
5
5
  }
6
- export default function computeBuffers(params) {
7
- // Create output buffers.
8
- const outBuffers = {
9
- index: null,
10
- position: null,
11
- normal: null,
12
- // 2 UV set per tile: wgs84 (uv[0]) and pm (uv[1])
13
- // - wgs84: 1 texture per tile because tiles are using wgs84 projection
6
+ function getUintArrayConstructor(highestValue) {
7
+ let picked = null;
8
+ if (highestValue < 2 ** 8) {
9
+ picked = Uint8Array;
10
+ } else if (highestValue < 2 ** 16) {
11
+ picked = Uint16Array;
12
+ } else if (highestValue < 2 ** 32) {
13
+ picked = Uint32Array;
14
+ } else {
15
+ throw new Error('Value is too high');
16
+ }
17
+ return picked;
18
+ }
19
+ function allocateIndexBuffer(nVertex, nSeg, params, cache) {
20
+ const indexBufferSize = getBufferIndexSize(nSeg, params.disableSkirt);
21
+ const indexConstructor = getUintArrayConstructor(nVertex);
22
+ const tileLen = indexBufferSize;
23
+ const skirtLen = 4 * nSeg;
24
+ if (cache !== undefined) {
25
+ return {
26
+ index: cache,
27
+ skirt: cache.subarray(tileLen, tileLen + skirtLen)
28
+ };
29
+ }
30
+ const indexBuffer = new ArrayBuffer((
31
+ // Tile
32
+ tileLen
33
+ // Skirt
34
+ + (params.disableSkirt ? 0 : skirtLen)) * indexConstructor.BYTES_PER_ELEMENT);
35
+ const index = new indexConstructor(indexBuffer);
36
+ const skirt = !params.disableSkirt ? index.subarray(tileLen, tileLen + skirtLen) : undefined;
37
+ return {
38
+ index,
39
+ skirt
40
+ };
41
+ }
42
+ function allocateBuffers(nVertex, nSeg, builder, params, cache) {
43
+ const {
44
+ index,
45
+ skirt
46
+ } = allocateIndexBuffer(nVertex, nSeg, params, cache?.index);
47
+ return {
48
+ index,
49
+ skirt,
50
+ position: new Float32Array(nVertex * 3),
51
+ normal: new Float32Array(nVertex * 3),
52
+ // 2 UV set per tile: wgs84 (uv[0]) and pseudo-mercator (pm, uv[1])
53
+ // - wgs84: 1 texture per tile because tiles are using wgs84
54
+ // projection
14
55
  // - pm: use multiple textures per tile.
15
56
  // +-------------------------+
16
57
  // | |
@@ -24,142 +65,160 @@ export default function computeBuffers(params) {
24
65
  // +-------------------------+
25
66
  // * u = wgs84.u
26
67
  // * v = textureid + v in builder texture
27
- uvs: []
68
+ uvs: [cache?.uv ?? new Float32Array(nVertex * 2), builder.computeExtraOffset !== undefined ? new Float32Array(nVertex) : undefined]
69
+ };
70
+ }
71
+ function computeUv0(uv, id, u, v) {
72
+ uv[id * 2 + 0] = u;
73
+ uv[id * 2 + 1] = v;
74
+ }
75
+ function initComputeUv1(value) {
76
+ return (uv, id) => {
77
+ uv[id] = value;
28
78
  };
29
- const computeUvs = [];
30
- const builder = params.builder;
31
- const nSeg = params.segments;
32
- // segments count :
33
- // Tile : (nSeg + 1) * (nSeg + 1)
34
- // Skirt : 8 * (nSeg - 1)
35
- const nVertex = (nSeg + 1) * (nSeg + 1) + (params.disableSkirt ? 0 : 4 * nSeg);
36
- if (nVertex > 2 ** 32) {
79
+ }
80
+ /** Compute buffers describing a tile according to a builder and its params. */
81
+ // TODO: Split this even further into subfunctions
82
+ export function computeBuffers(builder, params, cache) {
83
+ // n seg, n+1 vert + <- skirt, n verts per side
84
+ // <---------------> / |
85
+ // +---+---+---+---+ |
86
+ // | / | / | / | / | | Vertices:
87
+ // +---+---+---+---+ - + tile = (n + 1)^2
88
+ // | / | / | / | / | | skirt = 4n
89
+ // +---+---+---+---+ - +
90
+ // | / | / | / | / | | Segments:
91
+ // +---+---+---+---+ - + tile = 2 * n * (n + 1) + n^2
92
+ // | / | / | / | / | | skirt = 2n * 4
93
+ // +---+---+---+---+ |
94
+ const nSeg = Math.max(2, params.segments);
95
+ const nVertex = nSeg + 1;
96
+ const nTileVertex = nVertex ** 2;
97
+ const nSkirtVertex = params.disableSkirt ? 0 : 4 * nSeg;
98
+ const nTotalVertex = nTileVertex + nSkirtVertex;
99
+
100
+ // Computer should combust before this happens
101
+ if (nTotalVertex > 2 ** 32) {
37
102
  throw new Error('Tile segments count is too big');
38
103
  }
39
- outBuffers.position = new Float32Array(nVertex * 3);
40
- outBuffers.normal = new Float32Array(nVertex * 3);
41
- const uvCount = params.builder.uvCount;
42
- if (uvCount > 1) {
43
- outBuffers.uvs[1] = new Float32Array(nVertex);
44
- }
45
- computeUvs[0] = () => {};
46
- const bufferIndexSize = getBufferIndexSize(nSeg, params.disableSkirt);
47
- if (params.buildIndexAndUv_0) {
48
- if (nVertex < 2 ** 8) {
49
- outBuffers.index = new Uint8Array(bufferIndexSize);
50
- } else if (nVertex < 2 ** 16) {
51
- outBuffers.index = new Uint16Array(bufferIndexSize);
52
- } else if (nVertex < 2 ** 32) {
53
- outBuffers.index = new Uint32Array(bufferIndexSize);
54
- }
55
- outBuffers.uvs[0] = new Float32Array(nVertex * 2);
56
- computeUvs[0] = (id, u, v) => {
57
- outBuffers.uvs[0][id * 2 + 0] = u;
58
- outBuffers.uvs[0][id * 2 + 1] = v;
59
- };
60
- }
61
- const widthSegments = Math.max(2, Math.floor(nSeg) || 2);
62
- const heightSegments = Math.max(2, Math.floor(nSeg) || 2);
63
- let idVertex = 0;
64
- const vertices = [];
65
- let skirt = [];
66
- const skirtEnd = [];
67
- builder.prepare(params);
68
- for (let y = 0; y <= heightSegments; y++) {
69
- const verticesRow = [];
70
- const v = y / heightSegments;
71
- builder.vProjecte(v, params);
72
- if (uvCount > 1) {
73
- const u = builder.computeUvs[1](params);
74
- computeUvs[1] = id => {
75
- outBuffers.uvs[1][id] = u;
76
- };
104
+ const outBuffers = allocateBuffers(nTotalVertex, nSeg, builder, params, cache);
105
+ const computeUvs = [cache === undefined ? computeUv0 : () => {}];
106
+ params = builder.prepare(params);
107
+ for (let y = 0; y <= nSeg; y++) {
108
+ const v = y / nSeg;
109
+ params.coordinates.y = builder.vProject(v, params.extent);
110
+ if (builder.computeExtraOffset !== undefined) {
111
+ computeUvs[1] = initComputeUv1(builder.computeExtraOffset(params));
77
112
  }
78
- for (let x = 0; x <= widthSegments; x++) {
79
- const u = x / widthSegments;
80
- const id_m3 = idVertex * 3;
81
- builder.uProjecte(u, params);
82
- const vertex = builder.vertexPosition(params, params.projected);
83
- const normal = builder.vertexNormal(params);
113
+ for (let x = 0; x <= nSeg; x++) {
114
+ const u = x / nSeg;
115
+ const id_m3 = (y * nVertex + x) * 3;
116
+ params.coordinates.x = builder.uProject(u, params.extent);
117
+ const vertex = builder.vertexPosition(params.coordinates);
118
+ const normal = builder.vertexNormal();
84
119
 
85
120
  // move geometry to center world
86
121
  vertex.sub(params.center);
87
122
 
88
123
  // align normal to z axis
89
- if (params.quatNormalToZ) {
90
- vertex.applyQuaternion(params.quatNormalToZ);
91
- normal.applyQuaternion(params.quatNormalToZ);
124
+ // HACK: this check style is not great
125
+ if ('quatNormalToZ' in params) {
126
+ const quat = params.quatNormalToZ;
127
+ vertex.applyQuaternion(quat);
128
+ normal.applyQuaternion(quat);
92
129
  }
93
130
  vertex.toArray(outBuffers.position, id_m3);
94
131
  normal.toArray(outBuffers.normal, id_m3);
95
- for (const computeUv of computeUvs) {
96
- computeUv(idVertex, u, v);
97
- }
98
- if (!params.disableSkirt) {
99
- if (y !== 0 && y !== heightSegments) {
100
- if (x === widthSegments) {
101
- skirt.push(idVertex);
102
- } else if (x === 0) {
103
- skirtEnd.push(idVertex);
104
- }
132
+ for (const [index, computeUv] of computeUvs.entries()) {
133
+ if (computeUv !== undefined) {
134
+ computeUv(outBuffers.uvs[index], y * nVertex + x, u, v);
105
135
  }
106
136
  }
107
- verticesRow.push(idVertex);
108
- idVertex++;
109
- }
110
- vertices.push(verticesRow);
111
- if (y === 0) {
112
- skirt = skirt.concat(verticesRow);
113
- } else if (y === heightSegments) {
114
- skirt = skirt.concat(verticesRow.slice().reverse());
115
137
  }
116
138
  }
117
- if (!params.disableSkirt) {
118
- skirt = skirt.concat(skirtEnd.reverse());
139
+
140
+ // Fill skirt index buffer
141
+ if (cache === undefined && !params.disableSkirt) {
142
+ for (let x = 0; x < nVertex; x++) {
143
+ // -------->
144
+ // 0---1---2
145
+ // | / | / | [0-9] = assign order
146
+ // +---+---+
147
+ // | / | / |
148
+ // +---+---+
149
+ outBuffers.skirt[x] = x;
150
+ // +---+---+
151
+ // | / | / | [0-9] = assign order
152
+ // +---+---x x = skipped for now
153
+ // | / | / |
154
+ // 0---1---2
155
+ // <--------
156
+ outBuffers.skirt[2 * nVertex - 2 + x] = nVertex ** 2 - (x + 1);
157
+ }
158
+ for (let y = 1; y < nVertex - 1; y++) {
159
+ // +---+---s |
160
+ // | / | / | | o = stored vertices
161
+ // +---+---o | s = already stored
162
+ // | / | / | |
163
+ // +---+---s v
164
+ outBuffers.skirt[nVertex - 1 + y] = y * nVertex + (nVertex - 1);
165
+ // ^ s---+---+
166
+ // | | / | / | o = stored vertices
167
+ // | o---+---+ s = already stored
168
+ // | | / | / |
169
+ // | s---+---+
170
+ outBuffers.skirt[3 * nVertex - 3 + y] = nVertex * (nVertex - 1 - y);
171
+ }
119
172
  }
120
- function bufferize(va, vb, vc, idVertex) {
121
- outBuffers.index[idVertex + 0] = va;
122
- outBuffers.index[idVertex + 1] = vb;
123
- outBuffers.index[idVertex + 2] = vc;
124
- return idVertex + 3;
173
+
174
+ /** Copy passed indices at the desired index of the output index buffer. */
175
+ function bufferizeTri(id, va, vb, vc) {
176
+ outBuffers.index[id + 0] = va;
177
+ outBuffers.index[id + 1] = vb;
178
+ outBuffers.index[id + 2] = vc;
125
179
  }
126
- let idVertex2 = 0;
127
- if (params.buildIndexAndUv_0) {
128
- for (let y = 0; y < heightSegments; y++) {
129
- for (let x = 0; x < widthSegments; x++) {
130
- const v1 = vertices[y][x + 1];
131
- const v2 = vertices[y][x];
132
- const v3 = vertices[y + 1][x];
133
- const v4 = vertices[y + 1][x + 1];
134
- idVertex2 = bufferize(v4, v2, v1, idVertex2);
135
- idVertex2 = bufferize(v4, v3, v2, idVertex2);
180
+ if (cache === undefined) {
181
+ for (let y = 0; y < nSeg; y++) {
182
+ for (let x = 0; x < nSeg; x++) {
183
+ const v1 = y * nVertex + (x + 1);
184
+ const v2 = y * nVertex + x;
185
+ const v3 = (y + 1) * nVertex + x;
186
+ const v4 = (y + 1) * nVertex + (x + 1);
187
+ const id = (y * nSeg + x) * 6;
188
+ bufferizeTri(id, /**/v4, v2, v1);
189
+ bufferizeTri(id + 3, v4, v3, v2);
136
190
  }
137
191
  }
138
192
  }
139
- const iStart = idVertex;
140
193
 
141
- // TODO: WARNING beware skirt's size influences performance
142
- // The size of the skirt is now a ratio of the size of the tile.
143
- // To be perfect it should depend on the real elevation delta but too heavy to compute
194
+ // PERF: Beware skirt's size influences performance
195
+ // INFO: The size of the skirt is now a ratio of the size of the tile.
196
+ // To be perfect it should depend on the real elevation delta but too heavy
197
+ // to compute
144
198
  if (!params.disableSkirt) {
145
- // We compute the actual size of tile segment to use later for the skirt.
199
+ // We compute the actual size of tile segment to use later for
200
+ // the skirt.
146
201
  const segmentSize = new THREE.Vector3().fromArray(outBuffers.position).distanceTo(new THREE.Vector3().fromArray(outBuffers.position, 3));
147
- let buildIndexSkirt = function () {};
148
- let buildUVSkirt = function () {};
149
- if (params.buildIndexAndUv_0) {
150
- buildIndexSkirt = function (id, v1, v2, v3, v4) {
151
- id = bufferize(v1, v2, v3, id);
152
- id = bufferize(v1, v3, v4, id);
153
- return id;
154
- };
155
- buildUVSkirt = function (id) {
156
- outBuffers.uvs[0][idVertex * 2 + 0] = outBuffers.uvs[0][id * 2 + 0];
157
- outBuffers.uvs[0][idVertex * 2 + 1] = outBuffers.uvs[0][id * 2 + 1];
158
- };
159
- }
160
- for (let i = 0; i < skirt.length; i++) {
161
- const id = skirt[i];
162
- const id_m3 = idVertex * 3;
202
+ const buildSkirt = cache === undefined ? {
203
+ index: (id, v1, v2, v3, v4) => {
204
+ bufferizeTri(id, v1, v2, v3);
205
+ bufferizeTri(id + 3, v1, v3, v4);
206
+ return id + 6;
207
+ },
208
+ uv: (buf, idTo, idFrom) => {
209
+ buf[idTo * 2 + 0] = buf[idFrom * 2 + 0];
210
+ buf[idTo * 2 + 1] = buf[idFrom * 2 + 1];
211
+ }
212
+ } : {
213
+ index: () => {},
214
+ uv: () => {}
215
+ };
216
+
217
+ // Alias for readability
218
+ const start = nTileVertex;
219
+ for (let i = 0; i < outBuffers.skirt.length; i++) {
220
+ const id = outBuffers.skirt[i];
221
+ const id_m3 = (start + i) * 3;
163
222
  const id2_m3 = id * 3;
164
223
  outBuffers.position[id_m3 + 0] = outBuffers.position[id2_m3 + 0] - outBuffers.normal[id2_m3 + 0] * segmentSize;
165
224
  outBuffers.position[id_m3 + 1] = outBuffers.position[id2_m3 + 1] - outBuffers.normal[id2_m3 + 1] * segmentSize;
@@ -167,17 +226,23 @@ export default function computeBuffers(params) {
167
226
  outBuffers.normal[id_m3 + 0] = outBuffers.normal[id2_m3 + 0];
168
227
  outBuffers.normal[id_m3 + 1] = outBuffers.normal[id2_m3 + 1];
169
228
  outBuffers.normal[id_m3 + 2] = outBuffers.normal[id2_m3 + 2];
170
- buildUVSkirt(id);
171
- if (uvCount > 1) {
172
- outBuffers.uvs[1][idVertex] = outBuffers.uvs[1][id];
229
+ buildSkirt.uv(outBuffers.uvs[0], start + i, id);
230
+ if (outBuffers.uvs[1] !== undefined) {
231
+ outBuffers.uvs[1][start + i] = outBuffers.uvs[1][id];
173
232
  }
174
- const idf = (i + 1) % skirt.length;
175
- const v2 = idVertex;
176
- const v3 = idf === 0 ? iStart : idVertex + 1;
177
- const v4 = skirt[idf];
178
- idVertex2 = buildIndexSkirt(idVertex2, id, v2, v3, v4);
179
- idVertex++;
233
+ const idf = (i + 1) % outBuffers.skirt.length;
234
+ const v2 = start + i;
235
+ const v3 = idf === 0 ? start : start + i + 1;
236
+ const v4 = outBuffers.skirt[idf];
237
+ buildSkirt.index(6 * nSeg ** 2 + i * 6, id, v2, v3, v4);
180
238
  }
181
239
  }
182
- return outBuffers;
240
+
241
+ // Dropping skirt view
242
+ return {
243
+ index: outBuffers.index,
244
+ position: outBuffers.position,
245
+ uvs: outBuffers.uvs,
246
+ normal: outBuffers.normal
247
+ };
183
248
  }