itowns 2.43.2-next.2 → 2.43.2-next.20
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/558.js +2 -0
- package/dist/558.js.map +1 -0
- package/dist/debug.js +1 -1
- package/dist/debug.js.map +1 -1
- package/dist/itowns.js +1 -1
- package/dist/itowns.js.map +1 -1
- package/dist/itowns_lasparser.js +2 -0
- package/dist/itowns_lasparser.js.map +1 -0
- package/dist/itowns_lasworker.js +2 -0
- package/dist/itowns_lasworker.js.map +1 -0
- package/dist/itowns_potree2worker.js +2 -0
- package/dist/itowns_potree2worker.js.map +1 -0
- package/dist/itowns_widgets.js +1 -1
- package/dist/itowns_widgets.js.map +1 -1
- package/examples/3dtiles_25d.html +1 -1
- package/examples/3dtiles_basic.html +2 -2
- package/examples/3dtiles_batch_table.html +1 -3
- package/examples/3dtiles_pointcloud.html +9 -15
- package/examples/config.json +1 -0
- package/examples/copc_simple_loader.html +1 -1
- package/examples/entwine_3d_loader.html +1 -1
- package/examples/entwine_simple_loader.html +1 -1
- package/examples/js/plugins/COGParser.js +84 -50
- package/examples/js/plugins/COGSource.js +7 -4
- package/examples/layers/JSONLayers/OPENSM.json +1 -1
- package/examples/potree2_25d_map.html +127 -0
- package/examples/potree_25d_map.html +1 -1
- package/examples/potree_3d_map.html +1 -1
- package/examples/source_file_cog.html +22 -5
- package/lib/Controls/FirstPersonControls.js +0 -1
- package/lib/Controls/FlyControls.js +0 -1
- package/lib/Converter/Feature2Mesh.js +2 -4
- package/lib/Converter/textureConverter.js +1 -1
- package/lib/Core/3DTiles/C3DTBatchTable.js +1 -1
- package/lib/Core/3DTiles/C3DTFeature.js +6 -7
- package/lib/Core/Feature.js +1 -2
- package/lib/Core/Geographic/CoordStars.js +0 -1
- package/lib/Core/Label.js +0 -1
- package/lib/Core/MainLoop.js +0 -1
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +0 -4
- package/lib/Core/Prefab/Globe/GlobeLayer.js +3 -3
- package/lib/Core/Scheduler/Scheduler.js +1 -1
- package/lib/Core/Style.js +54 -53
- package/lib/Core/View.js +2 -4
- package/lib/Layer/C3DTilesLayer.js +8 -6
- package/lib/Layer/ElevationLayer.js +2 -3
- package/lib/Layer/GeoidLayer.js +1 -2
- package/lib/Layer/LabelLayer.js +8 -17
- package/lib/Layer/Layer.js +4 -2
- package/lib/Layer/PointCloudLayer.js +5 -8
- package/lib/Layer/Potree2Layer.js +165 -0
- package/lib/Layer/ReferencingLayerProperties.js +8 -3
- package/lib/Layer/TiledGeometryLayer.js +6 -4
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +2 -0
- package/lib/Parser/GeoJsonParser.js +2 -3
- package/lib/Parser/LASParser.js +49 -18
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1 -2
- package/lib/Process/3dTilesProcessing.js +2 -1
- package/lib/Process/FeatureProcessing.js +1 -2
- package/lib/Process/LayeredMaterialNodeProcessing.js +3 -9
- package/lib/Process/ObjectRemovalHelper.js +1 -2
- package/lib/Provider/3dTilesProvider.js +3 -2
- package/lib/Renderer/ColorLayersOrdering.js +1 -2
- package/lib/Renderer/Label2DRenderer.js +1 -4
- package/lib/Renderer/PointsMaterial.js +135 -100
- package/lib/Renderer/RenderMode.js +0 -1
- package/lib/Source/FileSource.js +1 -1
- package/lib/Source/Potree2Source.js +172 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +11 -1
- package/lib/ThreeExtended/loaders/DRACOLoader.js +0 -1
- package/lib/ThreeExtended/loaders/GLTFLoader.js +1 -0
- package/lib/Utils/DEMUtils.js +2 -2
- package/lib/Utils/OrientationUtils.js +0 -1
- package/lib/Utils/gui/Searchbar.js +1 -2
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- package/package.json +11 -8
- /package/lib/{Parser → Loader}/LASLoader.js +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/*
|
|
2
|
+
============
|
|
3
|
+
== POTREE ==
|
|
4
|
+
============
|
|
5
|
+
|
|
6
|
+
http://potree.org
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2011-2020, Markus Schütz
|
|
9
|
+
All rights reserved.
|
|
10
|
+
|
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
|
12
|
+
modification, are permitted provided that the following conditions are met:
|
|
13
|
+
|
|
14
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
15
|
+
list of conditions and the following disclaimer.
|
|
16
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
17
|
+
this list of conditions and the following disclaimer in the documentation
|
|
18
|
+
and/or other materials provided with the distribution.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
21
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
22
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
24
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
25
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
26
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
27
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
28
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
29
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
30
|
+
|
|
31
|
+
The views and conclusions contained in the software and documentation are those
|
|
32
|
+
of the authors and should not be interpreted as representing official policies,
|
|
33
|
+
either expressed or implied, of the FreeBSD Project.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { PointAttribute, PointAttributeTypes } from "../Core/Potree2PointAttributes.js";
|
|
37
|
+
const typedArrayMapping = {
|
|
38
|
+
int8: Int8Array,
|
|
39
|
+
int16: Int16Array,
|
|
40
|
+
int32: Int32Array,
|
|
41
|
+
int64: Float64Array,
|
|
42
|
+
uint8: Uint8Array,
|
|
43
|
+
uint16: Uint16Array,
|
|
44
|
+
uint32: Uint32Array,
|
|
45
|
+
uint64: Float64Array,
|
|
46
|
+
float: Float32Array,
|
|
47
|
+
double: Float64Array
|
|
48
|
+
};
|
|
49
|
+
export default function load(buffer, options) {
|
|
50
|
+
const {
|
|
51
|
+
pointAttributes,
|
|
52
|
+
scale,
|
|
53
|
+
min,
|
|
54
|
+
size,
|
|
55
|
+
offset,
|
|
56
|
+
numPoints
|
|
57
|
+
} = options;
|
|
58
|
+
const view = new DataView(buffer);
|
|
59
|
+
const attributeBuffers = {};
|
|
60
|
+
let attributeOffset = 0;
|
|
61
|
+
let bytesPerPoint = 0;
|
|
62
|
+
for (const pointAttribute of pointAttributes.attributes) {
|
|
63
|
+
bytesPerPoint += pointAttribute.byteSize;
|
|
64
|
+
}
|
|
65
|
+
const gridSize = 32;
|
|
66
|
+
const grid = new Uint32Array(gridSize ** 3);
|
|
67
|
+
const toIndex = (x, y, z) => {
|
|
68
|
+
// min is already subtracted
|
|
69
|
+
const dx = gridSize * x / size.x;
|
|
70
|
+
const dy = gridSize * y / size.y;
|
|
71
|
+
const dz = gridSize * z / size.z;
|
|
72
|
+
const ix = Math.min(parseInt(dx, 10), gridSize - 1);
|
|
73
|
+
const iy = Math.min(parseInt(dy, 10), gridSize - 1);
|
|
74
|
+
const iz = Math.min(parseInt(dz, 10), gridSize - 1);
|
|
75
|
+
return ix + iy * gridSize + iz * gridSize * gridSize;
|
|
76
|
+
};
|
|
77
|
+
let numOccupiedCells = 0;
|
|
78
|
+
for (const pointAttribute of pointAttributes.attributes) {
|
|
79
|
+
if (['POSITION_CARTESIAN', 'position'].includes(pointAttribute.name)) {
|
|
80
|
+
const buff = new ArrayBuffer(numPoints * 4 * 3);
|
|
81
|
+
const positions = new Float32Array(buff);
|
|
82
|
+
for (let j = 0; j < numPoints; j++) {
|
|
83
|
+
const pointOffset = j * bytesPerPoint;
|
|
84
|
+
const x = view.getInt32(pointOffset + attributeOffset + 0, true) * scale[0] + offset[0] - min.x;
|
|
85
|
+
const y = view.getInt32(pointOffset + attributeOffset + 4, true) * scale[1] + offset[1] - min.y;
|
|
86
|
+
const z = view.getInt32(pointOffset + attributeOffset + 8, true) * scale[2] + offset[2] - min.z;
|
|
87
|
+
const index = toIndex(x, y, z);
|
|
88
|
+
const count = grid[index]++;
|
|
89
|
+
if (count === 0) {
|
|
90
|
+
numOccupiedCells++;
|
|
91
|
+
}
|
|
92
|
+
positions[3 * j + 0] = x;
|
|
93
|
+
positions[3 * j + 1] = y;
|
|
94
|
+
positions[3 * j + 2] = z;
|
|
95
|
+
}
|
|
96
|
+
attributeBuffers[pointAttribute.name] = {
|
|
97
|
+
buffer: buff,
|
|
98
|
+
attribute: pointAttribute
|
|
99
|
+
};
|
|
100
|
+
} else if (['RGBA', 'rgba'].includes(pointAttribute.name)) {
|
|
101
|
+
const buff = new ArrayBuffer(numPoints * 4);
|
|
102
|
+
const colors = new Uint8Array(buff);
|
|
103
|
+
for (let j = 0; j < numPoints; j++) {
|
|
104
|
+
const pointOffset = j * bytesPerPoint;
|
|
105
|
+
const r = view.getUint16(pointOffset + attributeOffset + 0, true);
|
|
106
|
+
const g = view.getUint16(pointOffset + attributeOffset + 2, true);
|
|
107
|
+
const b = view.getUint16(pointOffset + attributeOffset + 4, true);
|
|
108
|
+
colors[4 * j + 0] = r > 255 ? r / 256 : r;
|
|
109
|
+
colors[4 * j + 1] = g > 255 ? g / 256 : g;
|
|
110
|
+
colors[4 * j + 2] = b > 255 ? b / 256 : b;
|
|
111
|
+
}
|
|
112
|
+
attributeBuffers[pointAttribute.name] = {
|
|
113
|
+
buffer: buff,
|
|
114
|
+
attribute: pointAttribute
|
|
115
|
+
};
|
|
116
|
+
} else {
|
|
117
|
+
const buff = new ArrayBuffer(numPoints * 4);
|
|
118
|
+
const f32 = new Float32Array(buff);
|
|
119
|
+
const TypedArray = typedArrayMapping[pointAttribute.type.name];
|
|
120
|
+
const preciseBuffer = new TypedArray(numPoints);
|
|
121
|
+
let [offset, scale] = [0, 1];
|
|
122
|
+
const getterMap = {
|
|
123
|
+
int8: view.getInt8,
|
|
124
|
+
int16: view.getInt16,
|
|
125
|
+
int32: view.getInt32,
|
|
126
|
+
uint8: view.getUint8,
|
|
127
|
+
uint16: view.getUint16,
|
|
128
|
+
uint32: view.getUint32,
|
|
129
|
+
float: view.getFloat32,
|
|
130
|
+
double: view.getFloat64
|
|
131
|
+
};
|
|
132
|
+
const getter = getterMap[pointAttribute.type.name].bind(view);
|
|
133
|
+
|
|
134
|
+
// compute offset and scale to pack larger types into 32 bit floats
|
|
135
|
+
if (pointAttribute.type.size > 4) {
|
|
136
|
+
const [amin, amax] = pointAttribute.range;
|
|
137
|
+
offset = amin;
|
|
138
|
+
scale = 1 / (amax - amin);
|
|
139
|
+
}
|
|
140
|
+
for (let j = 0; j < numPoints; j++) {
|
|
141
|
+
const pointOffset = j * bytesPerPoint;
|
|
142
|
+
const value = getter(pointOffset + attributeOffset, true);
|
|
143
|
+
f32[j] = (value - offset) * scale;
|
|
144
|
+
preciseBuffer[j] = value;
|
|
145
|
+
}
|
|
146
|
+
attributeBuffers[pointAttribute.name] = {
|
|
147
|
+
buffer: buff,
|
|
148
|
+
preciseBuffer,
|
|
149
|
+
attribute: pointAttribute,
|
|
150
|
+
offset,
|
|
151
|
+
scale
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
attributeOffset += pointAttribute.byteSize;
|
|
155
|
+
}
|
|
156
|
+
const occupancy = parseInt(numPoints / numOccupiedCells, 10);
|
|
157
|
+
{
|
|
158
|
+
// add indices
|
|
159
|
+
const buff = new ArrayBuffer(numPoints * 4);
|
|
160
|
+
const indices = new Uint32Array(buff);
|
|
161
|
+
for (let i = 0; i < numPoints; i++) {
|
|
162
|
+
indices[i] = i;
|
|
163
|
+
}
|
|
164
|
+
attributeBuffers.INDICES = {
|
|
165
|
+
buffer: buff,
|
|
166
|
+
attribute: PointAttribute.INDICES
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
{
|
|
170
|
+
// handle attribute vectors
|
|
171
|
+
const vectors = pointAttributes.vectors;
|
|
172
|
+
for (const vector of vectors) {
|
|
173
|
+
const {
|
|
174
|
+
name,
|
|
175
|
+
attributes
|
|
176
|
+
} = vector;
|
|
177
|
+
const numVectorElements = attributes.length;
|
|
178
|
+
const buffer = new ArrayBuffer(numVectorElements * numPoints * 4);
|
|
179
|
+
const f32 = new Float32Array(buffer);
|
|
180
|
+
let iElement = 0;
|
|
181
|
+
for (const sourceName of attributes) {
|
|
182
|
+
const sourceBuffer = attributeBuffers[sourceName];
|
|
183
|
+
const {
|
|
184
|
+
offset,
|
|
185
|
+
scale
|
|
186
|
+
} = sourceBuffer;
|
|
187
|
+
const view = new DataView(sourceBuffer.buffer);
|
|
188
|
+
const getter = view.getFloat32.bind(view);
|
|
189
|
+
for (let j = 0; j < numPoints; j++) {
|
|
190
|
+
const value = getter(j * 4, true);
|
|
191
|
+
f32[j * numVectorElements + iElement] = value / scale + offset;
|
|
192
|
+
}
|
|
193
|
+
iElement++;
|
|
194
|
+
}
|
|
195
|
+
const vecAttribute = new PointAttribute(name, PointAttributeTypes.DATA_TYPE_FLOAT, 3);
|
|
196
|
+
attributeBuffers[name] = {
|
|
197
|
+
buffer,
|
|
198
|
+
attribute: vecAttribute
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
buffer,
|
|
204
|
+
attributeBuffers,
|
|
205
|
+
density: occupancy
|
|
206
|
+
};
|
|
207
|
+
}
|
package/lib/Main.js
CHANGED
|
@@ -51,6 +51,7 @@ export { default as GeometryLayer } from "./Layer/GeometryLayer.js";
|
|
|
51
51
|
export { default as FeatureGeometryLayer } from "./Layer/FeatureGeometryLayer.js";
|
|
52
52
|
export { default as PointCloudLayer } from "./Layer/PointCloudLayer.js";
|
|
53
53
|
export { default as PotreeLayer } from "./Layer/PotreeLayer.js";
|
|
54
|
+
export { default as Potree2Layer } from "./Layer/Potree2Layer.js";
|
|
54
55
|
export { default as C3DTilesLayer, C3DTILES_LAYER_EVENTS } from "./Layer/C3DTilesLayer.js";
|
|
55
56
|
export { default as TiledGeometryLayer } from "./Layer/TiledGeometryLayer.js";
|
|
56
57
|
export { default as OrientedImageLayer } from "./Layer/OrientedImageLayer.js";
|
|
@@ -75,6 +76,7 @@ export { default as WMTSSource } from "./Source/WMTSSource.js";
|
|
|
75
76
|
export { default as VectorTilesSource } from "./Source/VectorTilesSource.js";
|
|
76
77
|
export { default as OrientedImageSource } from "./Source/OrientedImageSource.js";
|
|
77
78
|
export { default as PotreeSource } from "./Source/PotreeSource.js";
|
|
79
|
+
export { default as Potree2Source } from "./Source/Potree2Source.js";
|
|
78
80
|
export { default as C3DTilesSource } from "./Source/C3DTilesSource.js";
|
|
79
81
|
export { default as C3DTilesIonSource } from "./Source/C3DTilesIonSource.js";
|
|
80
82
|
export { default as C3DTilesGoogleSource } from "./Source/C3DTilesGoogleSource.js";
|
|
@@ -132,8 +132,7 @@ function toFeatureType(jsonType) {
|
|
|
132
132
|
const keyProperties = ['type', 'geometry', 'properties'];
|
|
133
133
|
const firstCoordinates = a => a === undefined || Array.isArray(a) && !isNaN(a[0]) ? a : firstCoordinates(a[0]);
|
|
134
134
|
function jsonFeatureToFeature(crsIn, json, collection) {
|
|
135
|
-
|
|
136
|
-
if (!((_json$geometry = json.geometry) !== null && _json$geometry !== void 0 && _json$geometry.type)) {
|
|
135
|
+
if (!json.geometry?.type) {
|
|
137
136
|
console.warn('No geometry provided');
|
|
138
137
|
return null;
|
|
139
138
|
}
|
|
@@ -142,7 +141,7 @@ function jsonFeatureToFeature(crsIn, json, collection) {
|
|
|
142
141
|
const feature = collection.requestFeatureByType(featureType);
|
|
143
142
|
const coordinates = jsonType != 'point' ? json.geometry.coordinates : [json.geometry.coordinates];
|
|
144
143
|
const properties = json.properties || {};
|
|
145
|
-
feature.hasRawElevationData =
|
|
144
|
+
feature.hasRawElevationData = firstCoordinates(coordinates)?.length === 3;
|
|
146
145
|
|
|
147
146
|
// copy other properties
|
|
148
147
|
for (const key of Object.keys(json)) {
|
package/lib/Parser/LASParser.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import { spawn, Thread, Transfer } from 'threads';
|
|
3
|
+
let _lazPerf;
|
|
4
|
+
let _thread;
|
|
5
|
+
function workerInstance() {
|
|
6
|
+
return new Worker( /* webpackChunkName: "itowns_lasparser" */
|
|
7
|
+
new URL('../Worker/LASLoaderWorker.js', import.meta.url), {
|
|
8
|
+
type: 'module'
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async function loader() {
|
|
12
|
+
if (_thread) {
|
|
13
|
+
return _thread;
|
|
14
|
+
}
|
|
15
|
+
_thread = await spawn(workerInstance());
|
|
16
|
+
if (_lazPerf) {
|
|
17
|
+
_thread.lazPerf(_lazPerf);
|
|
18
|
+
}
|
|
19
|
+
return _thread;
|
|
20
|
+
}
|
|
4
21
|
function buildBufferGeometry(attributes) {
|
|
5
22
|
const geometry = new THREE.BufferGeometry();
|
|
6
23
|
const positionBuffer = new THREE.BufferAttribute(attributes.position, 3);
|
|
@@ -42,7 +59,16 @@ export default {
|
|
|
42
59
|
if (!path) {
|
|
43
60
|
throw new Error('Path to laz-perf is mandatory');
|
|
44
61
|
}
|
|
45
|
-
|
|
62
|
+
_lazPerf = path;
|
|
63
|
+
},
|
|
64
|
+
/**
|
|
65
|
+
* Terminate all worker instances.
|
|
66
|
+
* @returns {Promise<void>}
|
|
67
|
+
*/
|
|
68
|
+
terminate() {
|
|
69
|
+
const currentThread = _thread;
|
|
70
|
+
_thread = undefined;
|
|
71
|
+
return Thread.terminate(currentThread);
|
|
46
72
|
},
|
|
47
73
|
/**
|
|
48
74
|
* Parses a chunk of a LAS or LAZ (LASZip) and returns the corresponding
|
|
@@ -66,13 +92,18 @@ export default {
|
|
|
66
92
|
* @return {Promise<THREE.BufferGeometry>} A promise resolving with a
|
|
67
93
|
* `THREE.BufferGeometry`.
|
|
68
94
|
*/
|
|
69
|
-
parseChunk(data) {
|
|
95
|
+
async parseChunk(data) {
|
|
70
96
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
97
|
+
const lasLoader = await loader();
|
|
98
|
+
const parsedData = await lasLoader.parseChunk(Transfer(data), {
|
|
99
|
+
pointCount: options.in.pointCount,
|
|
100
|
+
header: options.in.header,
|
|
101
|
+
eb: options.eb,
|
|
102
|
+
colorDepth: options.in.colorDepth
|
|
75
103
|
});
|
|
104
|
+
const geometry = buildBufferGeometry(parsedData.attributes);
|
|
105
|
+
geometry.computeBoundingBox();
|
|
106
|
+
return geometry;
|
|
76
107
|
},
|
|
77
108
|
/**
|
|
78
109
|
* Parses a LAS file or a LAZ (LASZip) file and return the corresponding
|
|
@@ -88,19 +119,19 @@ export default {
|
|
|
88
119
|
* @return {Promise} A promise resolving with a `THREE.BufferGeometry`. The
|
|
89
120
|
* header of the file is contained in `userData`.
|
|
90
121
|
*/
|
|
91
|
-
parse(data) {
|
|
92
|
-
var _options$out, _options$in;
|
|
122
|
+
async parse(data) {
|
|
93
123
|
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
94
|
-
if (
|
|
124
|
+
if (options.out?.skip) {
|
|
95
125
|
console.warn("Warning: options 'skip' not supported anymore");
|
|
96
126
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
geometry.userData.header = parsedData.header;
|
|
102
|
-
geometry.computeBoundingBox();
|
|
103
|
-
return geometry;
|
|
127
|
+
const input = options.in;
|
|
128
|
+
const lasLoader = await loader();
|
|
129
|
+
const parsedData = await lasLoader.parseFile(Transfer(data), {
|
|
130
|
+
colorDepth: input?.colorDepth
|
|
104
131
|
});
|
|
132
|
+
const geometry = buildBufferGeometry(parsedData.attributes);
|
|
133
|
+
geometry.userData.header = parsedData.header;
|
|
134
|
+
geometry.computeBoundingBox();
|
|
135
|
+
return geometry;
|
|
105
136
|
}
|
|
106
137
|
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { spawn, Thread, Transfer } from 'threads';
|
|
3
|
+
let _thread;
|
|
4
|
+
function workerInstance() {
|
|
5
|
+
return new Worker( /* webpackChunkName: "itowns_potree2worker" */
|
|
6
|
+
new URL('../Worker/Potree2Worker.js', import.meta.url), {
|
|
7
|
+
type: 'module'
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
async function loader() {
|
|
11
|
+
if (_thread) {
|
|
12
|
+
return _thread;
|
|
13
|
+
}
|
|
14
|
+
_thread = await spawn(workerInstance());
|
|
15
|
+
return _thread;
|
|
16
|
+
}
|
|
17
|
+
function decoder(w, metadata) {
|
|
18
|
+
return metadata.encoding === 'BROTLI' ? w.parseBrotli : w.parse;
|
|
19
|
+
}
|
|
20
|
+
export default {
|
|
21
|
+
/**
|
|
22
|
+
* @return {Promise<void>}
|
|
23
|
+
*/
|
|
24
|
+
terminate() {
|
|
25
|
+
const currentThread = _thread;
|
|
26
|
+
_thread = undefined;
|
|
27
|
+
return Thread.terminate(currentThread);
|
|
28
|
+
},
|
|
29
|
+
/** @module Potree2BinParser */
|
|
30
|
+
/** Parse .bin PotreeConverter 2.0 format and convert to a THREE.BufferGeometry
|
|
31
|
+
* @function parse
|
|
32
|
+
* @param {ArrayBuffer} buffer - the bin buffer.
|
|
33
|
+
* @param {Object} options
|
|
34
|
+
* @param {string[]} options.in.pointAttributes - the point attributes information contained in metadata.js
|
|
35
|
+
* @return {Promise} - a promise that resolves with a THREE.BufferGeometry.
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
parse: async function (buffer, options) {
|
|
39
|
+
const metadata = options.in.source.metadata;
|
|
40
|
+
const layer = options.out;
|
|
41
|
+
const pointAttributes = layer.pointAttributes;
|
|
42
|
+
const scale = metadata.scale;
|
|
43
|
+
const box = options.in.bbox;
|
|
44
|
+
const min = box.min;
|
|
45
|
+
const size = box.max.clone().sub(box.min);
|
|
46
|
+
const max = box.max;
|
|
47
|
+
const offset = metadata.offset;
|
|
48
|
+
const numPoints = options.in.numPoints;
|
|
49
|
+
const potreeLoader = await loader();
|
|
50
|
+
const decode = decoder(potreeLoader, metadata);
|
|
51
|
+
const data = await decode(Transfer(buffer), {
|
|
52
|
+
pointAttributes,
|
|
53
|
+
scale,
|
|
54
|
+
min,
|
|
55
|
+
max,
|
|
56
|
+
size,
|
|
57
|
+
offset,
|
|
58
|
+
numPoints
|
|
59
|
+
});
|
|
60
|
+
const buffers = data.attributeBuffers;
|
|
61
|
+
const geometry = new THREE.BufferGeometry();
|
|
62
|
+
Object.keys(buffers).forEach(property => {
|
|
63
|
+
const buffer = buffers[property].buffer;
|
|
64
|
+
if (property === 'position') {
|
|
65
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(buffer), 3));
|
|
66
|
+
} else if (property === 'rgba') {
|
|
67
|
+
geometry.setAttribute('color', new THREE.BufferAttribute(new Uint8Array(buffer), 4, true));
|
|
68
|
+
} else if (property === 'NORMAL') {
|
|
69
|
+
geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(buffer), 3));
|
|
70
|
+
} else if (property === 'INDICES') {
|
|
71
|
+
const bufferAttribute = new THREE.BufferAttribute(new Uint8Array(buffer), 4);
|
|
72
|
+
bufferAttribute.normalized = true;
|
|
73
|
+
geometry.setAttribute('indices', bufferAttribute);
|
|
74
|
+
} else {
|
|
75
|
+
const bufferAttribute = new THREE.BufferAttribute(new Float32Array(buffer), 1);
|
|
76
|
+
const batchAttribute = buffers[property].attribute;
|
|
77
|
+
bufferAttribute.potree = {
|
|
78
|
+
offset: buffers[property].offset,
|
|
79
|
+
scale: buffers[property].scale,
|
|
80
|
+
preciseBuffer: buffers[property].preciseBuffer,
|
|
81
|
+
range: batchAttribute.range
|
|
82
|
+
};
|
|
83
|
+
geometry.setAttribute(property, bufferAttribute);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
geometry.computeBoundingBox();
|
|
87
|
+
return {
|
|
88
|
+
geometry,
|
|
89
|
+
density: data.density
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
};
|
|
@@ -321,7 +321,6 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
321
321
|
1029: THREE.FrontSide // Culling back
|
|
322
322
|
//1032: THREE.NoSide // Culling front and back, what to do?
|
|
323
323
|
};
|
|
324
|
-
|
|
325
324
|
var WEBGL_DEPTH_FUNCS = {
|
|
326
325
|
512: THREE.NeverDepth,
|
|
327
326
|
513: THREE.LessDepth,
|
|
@@ -355,7 +354,6 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
355
354
|
//32771: CONSTANT_ALPHA,
|
|
356
355
|
//32772: ONE_MINUS_CONSTANT_COLOR
|
|
357
356
|
};
|
|
358
|
-
|
|
359
357
|
var WEBGL_TYPE_SIZES = {
|
|
360
358
|
'SCALAR': 1,
|
|
361
359
|
'VEC2': 2,
|
|
@@ -1116,6 +1114,7 @@ threeExamples.LegacyGLTFLoader = function () {
|
|
|
1116
1114
|
|
|
1117
1115
|
// According to COLLADA spec...
|
|
1118
1116
|
// aspectRatio = xfov / yfov
|
|
1117
|
+
|
|
1119
1118
|
var _camera = new THREE.PerspectiveCamera(THREE.MathUtils.radToDeg(yfov * aspectRatio), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6);
|
|
1120
1119
|
if (camera.name !== undefined) _camera.name = camera.name;
|
|
1121
1120
|
if (camera.extras) _camera.userData = camera.extras;
|
|
@@ -160,10 +160,11 @@ function cleanup3dTileset(layer, n) {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
// this is a layer
|
|
163
|
-
export function pre3dTilesUpdate() {
|
|
163
|
+
export function pre3dTilesUpdate(context) {
|
|
164
164
|
if (!this.visible) {
|
|
165
165
|
return [];
|
|
166
166
|
}
|
|
167
|
+
this.scale = context.camera._preSSE;
|
|
167
168
|
|
|
168
169
|
// Elements removed are added in the layer._cleanableTiles list.
|
|
169
170
|
// Since we simply push in this array, the first item is always
|
|
@@ -17,9 +17,8 @@ export default {
|
|
|
17
17
|
if (node.layerUpdateState[layer.id] === undefined) {
|
|
18
18
|
node.layerUpdateState[layer.id] = new LayerUpdateState();
|
|
19
19
|
} else if (!node.layerUpdateState[layer.id].canTryUpdate()) {
|
|
20
|
-
var _node$link$layer$id;
|
|
21
20
|
// toggle visibility features
|
|
22
|
-
|
|
21
|
+
node.link[layer.id]?.forEach(f => {
|
|
23
22
|
f.layer.object3d.add(f);
|
|
24
23
|
f.meshes.position.z = geoidLayerIsVisible(layer.parent) ? node.geoidHeight : 0;
|
|
25
24
|
f.meshes.updateMatrixWorld();
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { chooseNextLevelToFetch } from "../Layer/LayerUpdateStrategy.js";
|
|
2
2
|
import LayerUpdateState from "../Layer/LayerUpdateState.js";
|
|
3
3
|
import handlingError from "./handlerNodeError.js";
|
|
4
|
-
export const SIZE_TEXTURE_TILE = 256;
|
|
5
|
-
export const SIZE_DIAGONAL_TEXTURE = (2 * (SIZE_TEXTURE_TILE * SIZE_TEXTURE_TILE)) ** 0.5;
|
|
6
4
|
function materialCommandQueuePriorityFunction(material) {
|
|
7
5
|
// We know that 'node' is visible because commands can only be
|
|
8
6
|
// issued for visible nodes.
|
|
@@ -62,14 +60,12 @@ export function updateLayeredMaterialNodeImagery(context, layer, node, parent) {
|
|
|
62
60
|
return;
|
|
63
61
|
} // ok, we're going to inherit our parent's texture
|
|
64
62
|
}
|
|
65
|
-
|
|
66
63
|
if (!nodeLayer) {
|
|
67
|
-
var _parent$material;
|
|
68
64
|
// Create new raster node
|
|
69
65
|
nodeLayer = layer.setupRasterNode(node);
|
|
70
66
|
|
|
71
67
|
// Init the node by parent
|
|
72
|
-
const parentLayer =
|
|
68
|
+
const parentLayer = parent.material?.getLayer(layer.id);
|
|
73
69
|
nodeLayer.initFromParent(parentLayer, extentsDestination);
|
|
74
70
|
}
|
|
75
71
|
|
|
@@ -158,9 +154,8 @@ export function updateLayeredMaterialNodeElevation(context, layer, node, parent)
|
|
|
158
154
|
nodeLayer = layer.setupRasterNode(node);
|
|
159
155
|
}
|
|
160
156
|
if (node.layerUpdateState[layer.id] === undefined) {
|
|
161
|
-
var _parent$material2;
|
|
162
157
|
node.layerUpdateState[layer.id] = new LayerUpdateState();
|
|
163
|
-
const parentLayer =
|
|
158
|
+
const parentLayer = parent.material?.getLayer(layer.id);
|
|
164
159
|
nodeLayer.initFromParent(parentLayer, extentsDestination);
|
|
165
160
|
if (nodeLayer.level >= layer.source.zoom.min) {
|
|
166
161
|
context.view.notifyChange(node, false);
|
|
@@ -210,8 +205,7 @@ export function removeLayeredMaterialNodeLayer(layerId) {
|
|
|
210
205
|
* @param {TileMesh} node - The node to udpate.
|
|
211
206
|
*/
|
|
212
207
|
return function (node) {
|
|
213
|
-
|
|
214
|
-
if ((_node$material = node.material) !== null && _node$material !== void 0 && _node$material.removeLayer) {
|
|
208
|
+
if (node.material?.removeLayer) {
|
|
215
209
|
if (node.material.elevationLayerIds.indexOf(layerId) > -1) {
|
|
216
210
|
node.setBBoxZ({
|
|
217
211
|
min: 0,
|
|
@@ -28,7 +28,6 @@ export default {
|
|
|
28
28
|
// see https://github.com/iTowns/itowns/issues/869
|
|
29
29
|
// obj.geometry = null;
|
|
30
30
|
}
|
|
31
|
-
|
|
32
31
|
if (obj.material) {
|
|
33
32
|
if (Array.isArray(obj.material)) {
|
|
34
33
|
for (const material of obj.material) {
|
|
@@ -82,7 +81,7 @@ export default {
|
|
|
82
81
|
// of the objects which have their own removal logic
|
|
83
82
|
let toRemove = obj.children.filter(c => c.layer && c.layer.id === layer.id);
|
|
84
83
|
const linked = obj.link && obj.link[layer.id];
|
|
85
|
-
if (linked
|
|
84
|
+
if (linked?.children.length) {
|
|
86
85
|
toRemove = toRemove.concat(linked.children);
|
|
87
86
|
delete obj.link[layer.id];
|
|
88
87
|
}
|
|
@@ -35,10 +35,10 @@ function gltfToMesh(data, layer, url) {
|
|
|
35
35
|
function pntsParse(data, layer) {
|
|
36
36
|
return PntsParser.parse(data, layer.registeredExtensions).then(result => {
|
|
37
37
|
const material = layer.material ? layer.material.clone() : new PointsMaterial({
|
|
38
|
-
size:
|
|
38
|
+
size: 1,
|
|
39
39
|
mode: layer.pntsMode,
|
|
40
40
|
shape: layer.pntsShape,
|
|
41
|
-
|
|
41
|
+
classificationScheme: layer.classification,
|
|
42
42
|
sizeMode: layer.pntsSizeMode,
|
|
43
43
|
minAttenuatedSize: layer.pntsMinAttenuatedSize,
|
|
44
44
|
maxAttenuatedSize: layer.pntsMaxAttenuatedSize
|
|
@@ -114,6 +114,7 @@ function executeCommand(command) {
|
|
|
114
114
|
} else if (magic == 'b3dm') {
|
|
115
115
|
func = supportedFormats.b3dm;
|
|
116
116
|
} else if (magic == 'pnts') {
|
|
117
|
+
layer.hasPnts = true;
|
|
117
118
|
func = supportedFormats.pnts;
|
|
118
119
|
} else if (magic == 'glTF') {
|
|
119
120
|
func = supportedFormats.gltf;
|
|
@@ -2,8 +2,7 @@ import { ImageryLayers } from "../Layer/Layer.js";
|
|
|
2
2
|
function updateLayersOrdering(geometryLayer, imageryLayers) {
|
|
3
3
|
const sequence = ImageryLayers.getColorLayersIdOrderedBySequence(imageryLayers);
|
|
4
4
|
const cO = function (object) {
|
|
5
|
-
|
|
6
|
-
if ((_object$material = object.material) !== null && _object$material !== void 0 && _object$material.setSequence) {
|
|
5
|
+
if (object.material?.setSequence) {
|
|
7
6
|
object.material.setSequence(sequence);
|
|
8
7
|
}
|
|
9
8
|
};
|
|
@@ -157,10 +157,7 @@ class Label2DRenderer {
|
|
|
157
157
|
}
|
|
158
158
|
});
|
|
159
159
|
labelLayers.forEach(labelLayer => {
|
|
160
|
-
labelLayer.toHide.children.forEach(labelsNode =>
|
|
161
|
-
var _labelsNode$domElemen;
|
|
162
|
-
return (_labelsNode$domElemen = labelsNode.domElements) === null || _labelsNode$domElemen === void 0 ? void 0 : _labelsNode$domElemen.labels.hide();
|
|
163
|
-
});
|
|
160
|
+
labelLayer.toHide.children.forEach(labelsNode => labelsNode.domElements?.labels.hide());
|
|
164
161
|
labelLayer.toHide.clear();
|
|
165
162
|
});
|
|
166
163
|
}
|