itowns 2.45.1-next.0 → 2.45.1-next.1
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/455.js +2 -0
- package/dist/455.js.map +1 -0
- package/dist/debug.js +3 -0
- package/dist/debug.js.LICENSE.txt +13 -0
- package/dist/debug.js.map +1 -0
- package/dist/itowns.js +3 -0
- package/dist/itowns.js.LICENSE.txt +5 -0
- package/dist/itowns.js.map +1 -0
- 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 +2 -0
- package/dist/itowns_widgets.js.map +1 -0
- package/lib/Controls/FirstPersonControls.js +308 -0
- package/lib/Controls/FlyControls.js +175 -0
- package/lib/Controls/GlobeControls.js +1178 -0
- package/lib/Controls/PlanarControls.js +1025 -0
- package/lib/Controls/StateControl.js +432 -0
- package/lib/Controls/StreetControls.js +392 -0
- package/lib/Converter/Feature2Mesh.js +612 -0
- package/lib/Converter/Feature2Texture.js +174 -0
- package/lib/Converter/convertToTile.js +70 -0
- package/lib/Converter/textureConverter.js +43 -0
- package/lib/Core/3DTiles/C3DTBatchTable.js +131 -0
- package/lib/Core/3DTiles/C3DTBatchTableHierarchyExtension.js +96 -0
- package/lib/Core/3DTiles/C3DTBoundingVolume.js +156 -0
- package/lib/Core/3DTiles/C3DTExtensions.js +97 -0
- package/lib/Core/3DTiles/C3DTFeature.js +110 -0
- package/lib/Core/3DTiles/C3DTilesEnums.js +20 -0
- package/lib/Core/3DTiles/C3DTileset.js +99 -0
- package/lib/Core/3DTiles/utils/BinaryPropertyAccessor.js +100 -0
- package/lib/Core/AnimationPlayer.js +142 -0
- package/lib/Core/CopcNode.js +174 -0
- package/lib/Core/Deprecated/Undeprecator.js +74 -0
- package/lib/Core/EntwinePointTileNode.js +126 -0
- package/lib/Core/Feature.js +488 -0
- package/lib/Core/Geographic/GeoidGrid.js +108 -0
- package/lib/Core/Label.js +222 -0
- package/lib/Core/MainLoop.js +209 -0
- package/lib/Core/Picking.js +255 -0
- package/lib/Core/PointCloudNode.js +42 -0
- package/lib/Core/Potree2Node.js +206 -0
- package/lib/Core/Potree2PointAttributes.js +139 -0
- package/lib/Core/PotreeNode.js +101 -0
- package/lib/Core/Prefab/Globe/Atmosphere.js +293 -0
- package/lib/Core/Prefab/Globe/GlobeLayer.js +152 -0
- package/lib/Core/Prefab/Globe/GlobeTileBuilder.js +110 -0
- package/lib/Core/Prefab/Globe/SkyShader.js +78 -0
- package/lib/Core/Prefab/GlobeView.js +155 -0
- package/lib/Core/Prefab/Planar/PlanarLayer.js +59 -0
- package/lib/Core/Prefab/Planar/PlanarTileBuilder.js +71 -0
- package/lib/Core/Prefab/PlanarView.js +62 -0
- package/lib/Core/Prefab/TileBuilder.js +82 -0
- package/lib/Core/Prefab/computeBufferTileGeometry.js +248 -0
- package/lib/Core/Scheduler/Cache.js +17 -0
- package/lib/Core/Scheduler/CancelledCommandException.js +15 -0
- package/lib/Core/Scheduler/Scheduler.js +294 -0
- package/lib/Core/Style.js +660 -0
- package/lib/Core/StyleOptions.js +486 -0
- package/lib/Core/System/Capabilities.js +63 -0
- package/lib/Core/Tile/Tile.js +205 -0
- package/lib/Core/Tile/TileGrid.js +49 -0
- package/lib/Core/TileGeometry.js +124 -0
- package/lib/Core/TileMesh.js +108 -0
- package/lib/Core/View.js +1115 -0
- package/lib/Layer/C3DTilesLayer.js +459 -0
- package/lib/Layer/ColorLayer.js +154 -0
- package/lib/Layer/CopcLayer.js +63 -0
- package/lib/Layer/ElevationLayer.js +139 -0
- package/lib/Layer/EntwinePointTileLayer.js +71 -0
- package/lib/Layer/FeatureGeometryLayer.js +77 -0
- package/lib/Layer/GeoidLayer.js +80 -0
- package/lib/Layer/GeometryLayer.js +233 -0
- package/lib/Layer/InfoLayer.js +64 -0
- package/lib/Layer/LabelLayer.js +469 -0
- package/lib/Layer/Layer.js +335 -0
- package/lib/Layer/LayerUpdateState.js +89 -0
- package/lib/Layer/LayerUpdateStrategy.js +80 -0
- package/lib/Layer/OGC3DTilesLayer.js +543 -0
- package/lib/Layer/OrientedImageLayer.js +227 -0
- package/lib/Layer/PointCloudLayer.js +405 -0
- package/lib/Layer/Potree2Layer.js +171 -0
- package/lib/Layer/PotreeLayer.js +72 -0
- package/lib/Layer/RasterLayer.js +37 -0
- package/lib/Layer/ReferencingLayerProperties.js +62 -0
- package/lib/Layer/TiledGeometryLayer.js +459 -0
- package/lib/Loader/LASLoader.js +193 -0
- package/lib/Loader/Potree2BrotliLoader.js +261 -0
- package/lib/Loader/Potree2Loader.js +207 -0
- package/lib/Main.js +113 -0
- package/lib/MainBundle.js +4 -0
- package/lib/Parser/B3dmParser.js +174 -0
- package/lib/Parser/CameraCalibrationParser.js +94 -0
- package/lib/Parser/GDFParser.js +72 -0
- package/lib/Parser/GTXParser.js +75 -0
- package/lib/Parser/GeoJsonParser.js +212 -0
- package/lib/Parser/GpxParser.js +25 -0
- package/lib/Parser/ISGParser.js +71 -0
- package/lib/Parser/KMLParser.js +25 -0
- package/lib/Parser/LASParser.js +137 -0
- package/lib/Parser/MapBoxUrlParser.js +83 -0
- package/lib/Parser/PntsParser.js +131 -0
- package/lib/Parser/Potree2BinParser.js +92 -0
- package/lib/Parser/PotreeBinParser.js +106 -0
- package/lib/Parser/PotreeCinParser.js +29 -0
- package/lib/Parser/ShapefileParser.js +78 -0
- package/lib/Parser/VectorTileParser.js +215 -0
- package/lib/Parser/XbilParser.js +120 -0
- package/lib/Parser/deprecated/LegacyGLTFLoader.js +1386 -0
- package/lib/Parser/iGLTFLoader.js +168 -0
- package/lib/Process/3dTilesProcessing.js +304 -0
- package/lib/Process/FeatureProcessing.js +76 -0
- package/lib/Process/LayeredMaterialNodeProcessing.js +229 -0
- package/lib/Process/ObjectRemovalHelper.js +97 -0
- package/lib/Process/handlerNodeError.js +23 -0
- package/lib/Provider/3dTilesProvider.js +149 -0
- package/lib/Provider/DataSourceProvider.js +24 -0
- package/lib/Provider/Fetcher.js +233 -0
- package/lib/Provider/PointCloudProvider.js +45 -0
- package/lib/Provider/TileProvider.js +16 -0
- package/lib/Provider/URLBuilder.js +116 -0
- package/lib/Renderer/Camera.js +281 -0
- package/lib/Renderer/Color.js +56 -0
- package/lib/Renderer/ColorLayersOrdering.js +115 -0
- package/lib/Renderer/CommonMaterial.js +31 -0
- package/lib/Renderer/Label2DRenderer.js +192 -0
- package/lib/Renderer/LayeredMaterial.js +243 -0
- package/lib/Renderer/OBB.js +150 -0
- package/lib/Renderer/OrientedImageCamera.js +118 -0
- package/lib/Renderer/OrientedImageMaterial.js +167 -0
- package/lib/Renderer/PointsMaterial.js +485 -0
- package/lib/Renderer/RasterTile.js +243 -0
- package/lib/Renderer/RenderMode.js +31 -0
- package/lib/Renderer/Shader/ShaderChunk.js +160 -0
- package/lib/Renderer/Shader/ShaderUtils.js +47 -0
- package/lib/Renderer/SphereHelper.js +17 -0
- package/lib/Renderer/WebXR.js +51 -0
- package/lib/Renderer/c3DEngine.js +214 -0
- package/lib/Source/C3DTilesGoogleSource.js +74 -0
- package/lib/Source/C3DTilesIonSource.js +54 -0
- package/lib/Source/C3DTilesSource.js +30 -0
- package/lib/Source/CopcSource.js +126 -0
- package/lib/Source/EntwinePointTileSource.js +72 -0
- package/lib/Source/FileSource.js +188 -0
- package/lib/Source/OGC3DTilesGoogleSource.js +29 -0
- package/lib/Source/OGC3DTilesIonSource.js +34 -0
- package/lib/Source/OGC3DTilesSource.js +21 -0
- package/lib/Source/OrientedImageSource.js +59 -0
- package/lib/Source/Potree2Source.js +167 -0
- package/lib/Source/PotreeSource.js +82 -0
- package/lib/Source/Source.js +202 -0
- package/lib/Source/TMSSource.js +144 -0
- package/lib/Source/VectorTilesSource.js +182 -0
- package/lib/Source/WFSSource.js +170 -0
- package/lib/Source/WMSSource.js +167 -0
- package/lib/Source/WMTSSource.js +92 -0
- package/lib/ThreeExtended/capabilities/WebGL.js +69 -0
- package/lib/ThreeExtended/libs/ktx-parse.module.js +506 -0
- package/lib/ThreeExtended/libs/zstddec.module.js +29 -0
- package/lib/ThreeExtended/loaders/DDSLoader.js +200 -0
- package/lib/ThreeExtended/loaders/DRACOLoader.js +400 -0
- package/lib/ThreeExtended/loaders/GLTFLoader.js +2879 -0
- package/lib/ThreeExtended/loaders/KTX2Loader.js +709 -0
- package/lib/ThreeExtended/math/ColorSpaces.js +59 -0
- package/lib/ThreeExtended/utils/BufferGeometryUtils.js +846 -0
- package/lib/ThreeExtended/utils/WorkerPool.js +70 -0
- package/lib/Utils/CameraUtils.js +554 -0
- package/lib/Utils/DEMUtils.js +350 -0
- package/lib/Utils/FeaturesUtils.js +156 -0
- package/lib/Utils/Gradients.js +16 -0
- package/lib/Utils/ThreeUtils.js +115 -0
- package/lib/Utils/gui/C3DTilesStyle.js +218 -0
- package/lib/Utils/gui/Main.js +7 -0
- package/lib/Utils/gui/Minimap.js +152 -0
- package/lib/Utils/gui/Navigation.js +245 -0
- package/lib/Utils/gui/Scale.js +104 -0
- package/lib/Utils/gui/Searchbar.js +234 -0
- package/lib/Utils/gui/Widget.js +80 -0
- package/lib/Utils/placeObjectOnGround.js +136 -0
- package/lib/Worker/LASLoaderWorker.js +19 -0
- package/lib/Worker/Potree2Worker.js +21 -0
- package/package.json +2 -2
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { FEATURE_TYPES } from "../Core/Feature.js";
|
|
3
|
+
import { Extent, Coordinates } from '@itowns/geographic';
|
|
4
|
+
import Style, { StyleContext } from "../Core/Style.js";
|
|
5
|
+
const defaultStyle = new Style();
|
|
6
|
+
const context = new StyleContext();
|
|
7
|
+
let style;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Draw polygon (contour, line edge and fill) based on feature vertices into canvas
|
|
11
|
+
* using the given style(s). Several styles will re-draws the polygon each one with
|
|
12
|
+
* a different style.
|
|
13
|
+
* @param {CanvasRenderingContext2D} ctx - canvas' 2D rendering context.
|
|
14
|
+
* @param {Number[]} vertices - All the vertices of the Feature.
|
|
15
|
+
* @param {Object[]} indices - Contains the indices that define the geometry.
|
|
16
|
+
* Objects stored in this array have two properties, an `offset` and a `count`.
|
|
17
|
+
* The offset is related to the overall number of vertices in the Feature.
|
|
18
|
+
* @param {Number} size - The size of the feature.
|
|
19
|
+
* @param {Number} extent - The extent.
|
|
20
|
+
* @param {Number} invCtxScale - The ration to scale line width and radius circle.
|
|
21
|
+
* @param {Boolean} canBeFilled - true if feature.type == FEATURE_TYPES.POLYGON
|
|
22
|
+
*/
|
|
23
|
+
function drawPolygon(ctx, vertices) {
|
|
24
|
+
let indices = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [{
|
|
25
|
+
offset: 0,
|
|
26
|
+
count: 1
|
|
27
|
+
}];
|
|
28
|
+
let size = arguments.length > 3 ? arguments[3] : undefined;
|
|
29
|
+
let extent = arguments.length > 4 ? arguments[4] : undefined;
|
|
30
|
+
let invCtxScale = arguments.length > 5 ? arguments[5] : undefined;
|
|
31
|
+
let canBeFilled = arguments.length > 6 ? arguments[6] : undefined;
|
|
32
|
+
if (vertices.length === 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// build contour
|
|
36
|
+
const path = new Path2D();
|
|
37
|
+
for (const indice of indices) {
|
|
38
|
+
if (indice.extent && Extent.intersectsExtent(indice.extent, extent)) {
|
|
39
|
+
const offset = indice.offset * size;
|
|
40
|
+
const count = offset + indice.count * size;
|
|
41
|
+
path.moveTo(vertices[offset], vertices[offset + 1]);
|
|
42
|
+
for (let j = offset + size; j < count; j += size) {
|
|
43
|
+
path.lineTo(vertices[j], vertices[j + 1]);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
style.applyToCanvasPolygon(ctx, path, invCtxScale, canBeFilled);
|
|
48
|
+
}
|
|
49
|
+
function drawPoint(ctx, x, y, invCtxScale) {
|
|
50
|
+
ctx.beginPath();
|
|
51
|
+
const opacity = style.point.opacity == undefined ? 1.0 : style.point.opacity;
|
|
52
|
+
if (opacity !== ctx.globalAlpha) {
|
|
53
|
+
ctx.globalAlpha = opacity;
|
|
54
|
+
}
|
|
55
|
+
ctx.arc(x, y, (style.point.radius || 3.0) * invCtxScale, 0, 2 * Math.PI, false);
|
|
56
|
+
if (style.point.color) {
|
|
57
|
+
ctx.fillStyle = style.point.color;
|
|
58
|
+
ctx.fill();
|
|
59
|
+
}
|
|
60
|
+
if (style.point.line) {
|
|
61
|
+
ctx.lineWidth = (style.point.width || 1.0) * invCtxScale;
|
|
62
|
+
ctx.strokeStyle = style.point.line;
|
|
63
|
+
ctx.stroke();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const coord = new Coordinates('EPSG:4326', 0, 0, 0);
|
|
67
|
+
function drawFeature(ctx, feature, extent, invCtxScale) {
|
|
68
|
+
const extentDim = extent.planarDimensions();
|
|
69
|
+
const scaleRadius = extentDim.x / ctx.canvas.width;
|
|
70
|
+
for (const geometry of feature.geometries) {
|
|
71
|
+
if (Extent.intersectsExtent(geometry.extent, extent)) {
|
|
72
|
+
context.setGeometry(geometry);
|
|
73
|
+
if (style.zoom.min > style.context.zoom || style.zoom.max <= style.context.zoom) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (feature.type === FEATURE_TYPES.POINT && style.point) {
|
|
77
|
+
// cross multiplication to know in the extent system the real size of
|
|
78
|
+
// the point
|
|
79
|
+
const px = (Math.round(style.point.radius * invCtxScale) || 3 * invCtxScale) * scaleRadius;
|
|
80
|
+
for (const indice of geometry.indices) {
|
|
81
|
+
const offset = indice.offset * feature.size;
|
|
82
|
+
const count = offset + indice.count * feature.size;
|
|
83
|
+
for (let j = offset; j < count; j += feature.size) {
|
|
84
|
+
coord.setFromArray(feature.vertices, j);
|
|
85
|
+
if (extent.isPointInside(coord, px)) {
|
|
86
|
+
drawPoint(ctx, feature.vertices[j], feature.vertices[j + 1], invCtxScale);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
drawPolygon(ctx, feature.vertices, geometry.indices, feature.size, extent, invCtxScale, feature.type == FEATURE_TYPES.POLYGON);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const origin = new THREE.Vector3();
|
|
97
|
+
const dimension = new THREE.Vector3(0, 0, 1);
|
|
98
|
+
const scale = new THREE.Vector3();
|
|
99
|
+
const quaternion = new THREE.Quaternion();
|
|
100
|
+
const world2texture = new THREE.Matrix4();
|
|
101
|
+
const feature2texture = new THREE.Matrix4();
|
|
102
|
+
const worldTextureOrigin = new THREE.Vector3();
|
|
103
|
+
const featureExtent = new Extent('EPSG:4326', 0, 0, 0, 0);
|
|
104
|
+
export default {
|
|
105
|
+
// backgroundColor is a THREE.Color to specify a color to fill the texture
|
|
106
|
+
// with, given there is no feature passed in parameter
|
|
107
|
+
createTextureFromFeature(collection, extent, sizeTexture, layerStyle, backgroundColor) {
|
|
108
|
+
style = layerStyle || defaultStyle;
|
|
109
|
+
style.setContext(context);
|
|
110
|
+
let texture;
|
|
111
|
+
if (collection) {
|
|
112
|
+
// A texture is instancied drawn canvas
|
|
113
|
+
// origin and dimension are used to transform the feature's coordinates to canvas's space
|
|
114
|
+
extent.planarDimensions(dimension);
|
|
115
|
+
const c = document.createElement('canvas');
|
|
116
|
+
coord.crs = extent.crs;
|
|
117
|
+
c.width = sizeTexture;
|
|
118
|
+
c.height = sizeTexture;
|
|
119
|
+
const ctx = c.getContext('2d', {
|
|
120
|
+
willReadFrequently: true
|
|
121
|
+
});
|
|
122
|
+
if (backgroundColor) {
|
|
123
|
+
ctx.fillStyle = backgroundColor.getStyle();
|
|
124
|
+
ctx.fillRect(0, 0, sizeTexture, sizeTexture);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Documentation needed !!
|
|
128
|
+
ctx.globalCompositeOperation = layerStyle.globalCompositeOperation || 'source-over';
|
|
129
|
+
ctx.imageSmoothingEnabled = false;
|
|
130
|
+
ctx.lineJoin = 'round';
|
|
131
|
+
|
|
132
|
+
// transform extent to feature projection
|
|
133
|
+
extent.as(collection.crs, featureExtent);
|
|
134
|
+
// transform extent to local system
|
|
135
|
+
featureExtent.applyMatrix4(collection.matrixWorldInverse);
|
|
136
|
+
|
|
137
|
+
// compute matrix transformation `world2texture` to convert coordinates to texture coordinates
|
|
138
|
+
if (collection.isInverted) {
|
|
139
|
+
worldTextureOrigin.set(extent.west, extent.north, 0);
|
|
140
|
+
scale.set(ctx.canvas.width, -ctx.canvas.height, 1.0).divide(dimension);
|
|
141
|
+
} else {
|
|
142
|
+
worldTextureOrigin.set(extent.west, extent.south, 0);
|
|
143
|
+
scale.set(ctx.canvas.width, ctx.canvas.height, 1.0).divide(dimension);
|
|
144
|
+
}
|
|
145
|
+
world2texture.compose(worldTextureOrigin.multiply(scale).negate(), quaternion, scale);
|
|
146
|
+
|
|
147
|
+
// compute matrix transformation `feature2texture` to convert features coordinates to texture coordinates
|
|
148
|
+
feature2texture.multiplyMatrices(world2texture, collection.matrixWorld);
|
|
149
|
+
feature2texture.decompose(origin, quaternion, scale);
|
|
150
|
+
ctx.setTransform(scale.x, 0, 0, scale.y, origin.x, origin.y);
|
|
151
|
+
|
|
152
|
+
// to scale line width and radius circle
|
|
153
|
+
const invCtxScale = Math.abs(1 / scale.x);
|
|
154
|
+
context.setZoom(extent.zoom);
|
|
155
|
+
|
|
156
|
+
// Draw the canvas
|
|
157
|
+
for (const feature of collection.features) {
|
|
158
|
+
context.setFeature(feature);
|
|
159
|
+
drawFeature(ctx, feature, featureExtent, invCtxScale);
|
|
160
|
+
}
|
|
161
|
+
texture = new THREE.CanvasTexture(c);
|
|
162
|
+
texture.flipY = collection.isInverted;
|
|
163
|
+
} else if (backgroundColor) {
|
|
164
|
+
const data = new Uint8Array(3);
|
|
165
|
+
data[0] = backgroundColor.r * 255;
|
|
166
|
+
data[1] = backgroundColor.g * 255;
|
|
167
|
+
data[2] = backgroundColor.b * 255;
|
|
168
|
+
texture = new THREE.DataTexture(data, 1, 1, THREE.RGBAFormat);
|
|
169
|
+
} else {
|
|
170
|
+
texture = new THREE.Texture();
|
|
171
|
+
}
|
|
172
|
+
return texture;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import TileMesh from "../Core/TileMesh.js";
|
|
3
|
+
import LayeredMaterial from "../Renderer/LayeredMaterial.js";
|
|
4
|
+
import { newTileGeometry } from "../Core/Prefab/TileBuilder.js";
|
|
5
|
+
import ReferLayerProperties from "../Layer/ReferencingLayerProperties.js";
|
|
6
|
+
import { geoidLayerIsVisible } from "../Layer/GeoidLayer.js";
|
|
7
|
+
const dimensions = new THREE.Vector2();
|
|
8
|
+
function setTileFromTiledLayer(tile, tileLayer) {
|
|
9
|
+
if (tileLayer.diffuse) {
|
|
10
|
+
tile.material.diffuse = tileLayer.diffuse;
|
|
11
|
+
}
|
|
12
|
+
if (tileLayer.isGlobeLayer) {
|
|
13
|
+
// Computes a point used for horizon culling.
|
|
14
|
+
// If the point is below the horizon,
|
|
15
|
+
// the tile is guaranteed to be below the horizon as well.
|
|
16
|
+
tile.horizonCullingPoint = tile.extent.center().as('EPSG:4978').toVector3();
|
|
17
|
+
tile.extent.planarDimensions(dimensions).multiplyScalar(THREE.MathUtils.DEG2RAD);
|
|
18
|
+
|
|
19
|
+
// alpha is maximum angle between two points of tile
|
|
20
|
+
const alpha = dimensions.length();
|
|
21
|
+
const h = Math.abs(1.0 / Math.cos(alpha * 0.5));
|
|
22
|
+
tile.horizonCullingPoint.setLength(h * tile.horizonCullingPoint.length());
|
|
23
|
+
tile.horizonCullingPointElevationScaled = tile.horizonCullingPoint.clone();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export default {
|
|
27
|
+
convert(requester, extent, layer) {
|
|
28
|
+
const builder = layer.builder;
|
|
29
|
+
const parent = requester;
|
|
30
|
+
const level = parent !== undefined ? parent.level + 1 : 0;
|
|
31
|
+
const paramsGeometry = {
|
|
32
|
+
extent,
|
|
33
|
+
level,
|
|
34
|
+
segments: layer.segments || 16,
|
|
35
|
+
disableSkirt: layer.disableSkirt,
|
|
36
|
+
hideSkirt: layer.hideSkirt
|
|
37
|
+
};
|
|
38
|
+
return newTileGeometry(builder, paramsGeometry).then(result => {
|
|
39
|
+
// build tile mesh
|
|
40
|
+
result.geometry.increaseRefCount();
|
|
41
|
+
const crsCount = layer.tileMatrixSets.length;
|
|
42
|
+
const material = new LayeredMaterial(layer.materialOptions, crsCount);
|
|
43
|
+
ReferLayerProperties(material, layer);
|
|
44
|
+
const tile = new TileMesh(result.geometry, material, layer, extent, level);
|
|
45
|
+
if (parent && parent.isTileMesh) {
|
|
46
|
+
// get parent extent transformation
|
|
47
|
+
const pTrans = builder.computeShareableExtent(parent.extent);
|
|
48
|
+
// place relative to his parent
|
|
49
|
+
result.position.sub(pTrans.position).applyQuaternion(pTrans.quaternion.invert());
|
|
50
|
+
result.quaternion.premultiply(pTrans.quaternion);
|
|
51
|
+
}
|
|
52
|
+
tile.position.copy(result.position);
|
|
53
|
+
tile.quaternion.copy(result.quaternion);
|
|
54
|
+
tile.visible = false;
|
|
55
|
+
tile.updateMatrix();
|
|
56
|
+
setTileFromTiledLayer(tile, layer);
|
|
57
|
+
if (parent) {
|
|
58
|
+
tile.geoidHeight = parent.geoidHeight;
|
|
59
|
+
const geoidHeight = geoidLayerIsVisible(layer) ? tile.geoidHeight : 0;
|
|
60
|
+
tile.setBBoxZ({
|
|
61
|
+
min: parent.obb.z.min,
|
|
62
|
+
max: parent.obb.z.max,
|
|
63
|
+
geoidHeight
|
|
64
|
+
});
|
|
65
|
+
tile.material.geoidHeight = geoidHeight;
|
|
66
|
+
}
|
|
67
|
+
return tile;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import Feature2Texture from "./Feature2Texture.js";
|
|
3
|
+
import { Extent } from '@itowns/geographic';
|
|
4
|
+
const extentTexture = new Extent('EPSG:4326');
|
|
5
|
+
const textureLayer = (texture, layer) => {
|
|
6
|
+
texture.generateMipmaps = false;
|
|
7
|
+
texture.magFilter = layer.magFilter || THREE.LinearFilter;
|
|
8
|
+
texture.minFilter = layer.minFilter || THREE.LinearFilter;
|
|
9
|
+
return texture;
|
|
10
|
+
};
|
|
11
|
+
function textureColorLayer(texture, layer) {
|
|
12
|
+
texture.anisotropy = 16;
|
|
13
|
+
texture.premultiplyAlpha = layer.transparent;
|
|
14
|
+
return textureLayer(texture, layer);
|
|
15
|
+
}
|
|
16
|
+
export default {
|
|
17
|
+
convert(data, destinationTile, layer) {
|
|
18
|
+
let texture;
|
|
19
|
+
if (data.isFeatureCollection) {
|
|
20
|
+
const backgroundLayer = layer.source.backgroundLayer;
|
|
21
|
+
const backgroundColor = backgroundLayer && backgroundLayer.paint ? new THREE.Color(backgroundLayer.paint['background-color']) : undefined;
|
|
22
|
+
destinationTile.toExtent(layer.crs, extentTexture);
|
|
23
|
+
texture = Feature2Texture.createTextureFromFeature(data, extentTexture, layer.subdivisionThreshold, layer.style, backgroundColor);
|
|
24
|
+
texture.features = data;
|
|
25
|
+
texture.extent = destinationTile;
|
|
26
|
+
} else if (data.isTexture) {
|
|
27
|
+
texture = data;
|
|
28
|
+
} else {
|
|
29
|
+
throw new Error('Data type is not supported to convert into texture');
|
|
30
|
+
}
|
|
31
|
+
if (layer.isColorLayer) {
|
|
32
|
+
return textureColorLayer(texture, layer);
|
|
33
|
+
} else if (layer.isElevationLayer) {
|
|
34
|
+
if (texture.flipY) {
|
|
35
|
+
// DataTexture default to false, so make sure other Texture types
|
|
36
|
+
// do the same (eg image texture)
|
|
37
|
+
// See UV construction for more details
|
|
38
|
+
texture.flipY = false;
|
|
39
|
+
}
|
|
40
|
+
return textureLayer(texture, layer);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import binaryPropertyAccessor from "./utils/BinaryPropertyAccessor.js";
|
|
2
|
+
import { C3DTilesTypes } from "./C3DTilesEnums.js";
|
|
3
|
+
const utf8Decoder = new TextDecoder();
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A 3D Tiles
|
|
7
|
+
* [batch
|
|
8
|
+
* table](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification/TileFormats/BatchTable).
|
|
9
|
+
* @property {C3DTilesTypes} type - Used by 3D Tiles extensions
|
|
10
|
+
* (e.g. {@link C3DTBatchTableHierarchyExtension}) to know in which context
|
|
11
|
+
* (i.e. for which 3D Tiles class) the parsing of the extension should be done.
|
|
12
|
+
* @property {number} batchLength - the length of the batch.
|
|
13
|
+
* @property {object} content - the content of the batch table in the form:
|
|
14
|
+
* {property1: values[], property2: values[], ...}.
|
|
15
|
+
* @property {object} extensions - 3D Tiles extensions of the batch table
|
|
16
|
+
* stored in the following format:
|
|
17
|
+
* {extensioName1: extensionObject1, extensioName2: extensionObject2, ...}
|
|
18
|
+
*/
|
|
19
|
+
class C3DTBatchTable {
|
|
20
|
+
/**
|
|
21
|
+
* @param {ArrayBuffer} [buffer=new ArrayBuffer()] - batch table buffer to parse
|
|
22
|
+
* @param {number} [jsonLength=0] - batch table json part length
|
|
23
|
+
* @param {number} [binaryLength=0] - batch table binary part length
|
|
24
|
+
* @param {number} [batchLength=0] - the length of the batch.
|
|
25
|
+
* @param {Object} [registeredExtensions] - extensions registered to the layer
|
|
26
|
+
*/
|
|
27
|
+
constructor() {
|
|
28
|
+
let buffer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : new ArrayBuffer();
|
|
29
|
+
let jsonLength = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
30
|
+
let binaryLength = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
31
|
+
let batchLength = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
32
|
+
let registeredExtensions = arguments.length > 4 ? arguments[4] : undefined;
|
|
33
|
+
if (arguments.length === 4 && typeof batchLength === 'object' && !Array.isArray(batchLength) && batchLength !== null) {
|
|
34
|
+
console.warn('You most likely used a deprecated constructor of C3DTBatchTable.');
|
|
35
|
+
}
|
|
36
|
+
if (jsonLength + binaryLength !== buffer.byteLength) {
|
|
37
|
+
console.error('3DTiles batch table json length and binary length are not consistent with total buffer' + ' length. The batch table may be wrong.');
|
|
38
|
+
}
|
|
39
|
+
this.type = C3DTilesTypes.batchtable;
|
|
40
|
+
this.batchLength = batchLength;
|
|
41
|
+
const jsonBuffer = buffer.slice(0, jsonLength);
|
|
42
|
+
const decodedJsonBuffer = utf8Decoder.decode(new Uint8Array(jsonBuffer));
|
|
43
|
+
const jsonContent = decodedJsonBuffer === '' ? null : JSON.parse(decodedJsonBuffer);
|
|
44
|
+
if (binaryLength > 0) {
|
|
45
|
+
const binaryBuffer = buffer.slice(jsonLength, jsonLength + binaryLength);
|
|
46
|
+
for (const propKey in jsonContent) {
|
|
47
|
+
if (!Object.prototype.hasOwnProperty.call(jsonContent, propKey)) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const propVal = jsonContent[propKey];
|
|
51
|
+
// Batch table entries that have already been parsed from the JSON buffer have an array of values.
|
|
52
|
+
if (Array.isArray(propVal)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (typeof propVal?.byteOffset !== 'undefined' && typeof propVal?.componentType !== 'undefined' && typeof propVal?.type !== 'undefined') {
|
|
56
|
+
jsonContent[propKey] = binaryPropertyAccessor(binaryBuffer, this.batchLength, propVal.byteOffset, propVal.componentType, propVal.type);
|
|
57
|
+
} else {
|
|
58
|
+
console.error('Invalid 3D Tiles batch table property that is neither a JSON array nor a valid ' + 'accessor to a binary body');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Separate the content and the possible extensions
|
|
64
|
+
// When an extension is found, we call its parser and append the
|
|
65
|
+
// returned object to batchTable.extensions
|
|
66
|
+
// Extensions must be registered in the layer (see an example of this in
|
|
67
|
+
// 3dtiles_hierarchy.html)
|
|
68
|
+
if (jsonContent && jsonContent.extensions) {
|
|
69
|
+
this.extensions = registeredExtensions.parseExtensions(jsonContent.extensions, this.type);
|
|
70
|
+
delete jsonContent.extensions;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Store batch table json content
|
|
74
|
+
this.content = jsonContent;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates and returns a javascript object holding the displayable
|
|
79
|
+
* information from the batch table and from extensions of the batch table,
|
|
80
|
+
* for a given feature (identified with its batchID).
|
|
81
|
+
* @param {integer} batchID - id of the feature
|
|
82
|
+
* @returns {Object} - displayable information relative to the batch
|
|
83
|
+
* table and its extensions. Object is formatted as follow:
|
|
84
|
+
* {batchTable:
|
|
85
|
+
* {property1: value1
|
|
86
|
+
* property2: value2
|
|
87
|
+
* ...}
|
|
88
|
+
* extensions:
|
|
89
|
+
* {extension1:
|
|
90
|
+
* {property1: value1
|
|
91
|
+
* ...}
|
|
92
|
+
* extension2: {...}
|
|
93
|
+
* ...}
|
|
94
|
+
* }
|
|
95
|
+
*/
|
|
96
|
+
getInfoById(batchID) {
|
|
97
|
+
// Verify that the batch ID is valid
|
|
98
|
+
if (batchID < 0 && batchID < this.batchLength) {
|
|
99
|
+
throw new Error(`Batch Id (${batchID}) must be between 0 and
|
|
100
|
+
${this.batchLength} to access feature properties from the batch
|
|
101
|
+
table.`);
|
|
102
|
+
}
|
|
103
|
+
const featureDisplayableInfo = {};
|
|
104
|
+
featureDisplayableInfo.batchTable = {};
|
|
105
|
+
// Get properties from batch table content
|
|
106
|
+
for (const property in this.content) {
|
|
107
|
+
// check that the property is not inherited from prototype chain
|
|
108
|
+
if (Object.prototype.hasOwnProperty.call(this.content, property)) {
|
|
109
|
+
const val = this.content[property][batchID];
|
|
110
|
+
// Property value may be a threejs vector (see 3D Tiles spec and BinaryPropertyAccessor.js)
|
|
111
|
+
if (val && (val.isVector2 || val.isVector3 || val.isVector4)) {
|
|
112
|
+
featureDisplayableInfo.batchTable[property] = val.toArray();
|
|
113
|
+
} else {
|
|
114
|
+
featureDisplayableInfo.batchTable[property] = val;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Extensions
|
|
120
|
+
if (this.extensions) {
|
|
121
|
+
featureDisplayableInfo.extensions = {};
|
|
122
|
+
for (const extName in this.extensions) {
|
|
123
|
+
if (Object.prototype.hasOwnProperty.call(this.extensions, extName)) {
|
|
124
|
+
featureDisplayableInfo.extensions[extName] = this.extensions[extName].getInfoById(batchID);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return featureDisplayableInfo;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export default C3DTBatchTable;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch Table part of the 3D Tiles
|
|
3
|
+
* [Batch Table Hierarchy Extension](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy)
|
|
4
|
+
* @property {object} classes - The classes as defined in the specification.
|
|
5
|
+
* @property {object} inverseHierarchy - InverseHierarchy contains for each
|
|
6
|
+
* instance (i.e. georgraphic feature e.g. building, roof, etc.) an array of the
|
|
7
|
+
* indexes of its parents. For example, the parents of the instance 0 can be
|
|
8
|
+
* found using inverseHierarchy[0].
|
|
9
|
+
* @property {number[]} instancesIdxs - For each instance of the extension,
|
|
10
|
+
* contains a javascript object with classId and instanceIdx. classId is the id
|
|
11
|
+
* of the class (from this.classes) of the instance. instanceIdx is the index of
|
|
12
|
+
* the instance in this class. Goal: Ease the retrieval of the properties of an
|
|
13
|
+
* instance.
|
|
14
|
+
*/
|
|
15
|
+
class C3DTBatchTableHierarchyExtension {
|
|
16
|
+
/**
|
|
17
|
+
* Constructor of the C3DTBatchTableHierarchyExtension class.
|
|
18
|
+
* @param {Object} json - The parsed json of the batch table part of the 3D
|
|
19
|
+
* Tiles [Batch Table Hierarchy Extension](https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy)
|
|
20
|
+
*/
|
|
21
|
+
constructor(json) {
|
|
22
|
+
this.classes = json.classes;
|
|
23
|
+
this.inverseHierarchy = {};
|
|
24
|
+
this.instancesIdxs = [];
|
|
25
|
+
|
|
26
|
+
// Counts the number of instances of a class
|
|
27
|
+
const classCounter = {};
|
|
28
|
+
let parentIdsCounter = 0;
|
|
29
|
+
|
|
30
|
+
// if omitted, parentCounts is an array of length instancesLength,
|
|
31
|
+
// where all values are 1 (cf. spec)
|
|
32
|
+
let parentCounts = json.parentCounts;
|
|
33
|
+
if (parentCounts === undefined) {
|
|
34
|
+
parentCounts = new Array(json.instancesLength);
|
|
35
|
+
parentCounts.fill(1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// for each instance
|
|
39
|
+
for (let i = 0; i < json.instancesLength; i++) {
|
|
40
|
+
// for each parent of the current instance
|
|
41
|
+
for (let j = 0; j < parentCounts[i]; j++) {
|
|
42
|
+
// When an instance's parentId points to itself, then it has no
|
|
43
|
+
// parent" (cf. spec)
|
|
44
|
+
if (i !== json.parentIds[parentIdsCounter]) {
|
|
45
|
+
if (this.inverseHierarchy[i] === undefined) {
|
|
46
|
+
this.inverseHierarchy[i] = [];
|
|
47
|
+
}
|
|
48
|
+
this.inverseHierarchy[i].push(json.parentIds[parentIdsCounter]);
|
|
49
|
+
parentIdsCounter++;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const classId = json.classIds[i];
|
|
53
|
+
if (classCounter[classId] === undefined) {
|
|
54
|
+
classCounter[classId] = 0;
|
|
55
|
+
}
|
|
56
|
+
this.instancesIdxs[i] = {
|
|
57
|
+
classId,
|
|
58
|
+
instanceIdx: classCounter[classId]
|
|
59
|
+
};
|
|
60
|
+
classCounter[classId]++;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Creates and returns a javascript object holding the displayable
|
|
66
|
+
* information relative to this extension for a given feature.
|
|
67
|
+
* @param {integer} featureId - id of the feature
|
|
68
|
+
* @returns {Object} - displayable information relative to this
|
|
69
|
+
* extension, for the feature with id=featureId and for its parents
|
|
70
|
+
*/
|
|
71
|
+
getInfoById(featureId) {
|
|
72
|
+
const instanceProperties = {};
|
|
73
|
+
// get feature class name
|
|
74
|
+
const instanceClassId = this.instancesIdxs[featureId].classId;
|
|
75
|
+
const featureClass = this.classes[instanceClassId].name;
|
|
76
|
+
// get feature properties and values
|
|
77
|
+
const instanceIdx = this.instancesIdxs[featureId].instanceIdx;
|
|
78
|
+
const instances = this.classes[instanceClassId].instances;
|
|
79
|
+
for (const key in instances) {
|
|
80
|
+
if (Object.prototype.hasOwnProperty.call(instances, key)) {
|
|
81
|
+
instanceProperties[key] = instances[key][instanceIdx];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// create return object: className: {featureProperties and values}
|
|
85
|
+
const pickingInfo = {};
|
|
86
|
+
pickingInfo[featureClass] = instanceProperties;
|
|
87
|
+
// If this feature has parent(s), recurse on them
|
|
88
|
+
if (this.inverseHierarchy && this.inverseHierarchy[featureId]) {
|
|
89
|
+
for (const parentID of this.inverseHierarchy[featureId]) {
|
|
90
|
+
Object.assign(pickingInfo, this.getInfoById(parentID));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return pickingInfo;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export default C3DTBatchTableHierarchyExtension;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import { Ellipsoid, Coordinates } from '@itowns/geographic';
|
|
3
|
+
import { C3DTilesTypes, C3DTilesBoundingVolumeTypes } from "./C3DTilesEnums.js";
|
|
4
|
+
const ellipsoid = new Ellipsoid();
|
|
5
|
+
|
|
6
|
+
// bounding box scratch variables
|
|
7
|
+
const boxSize = new THREE.Vector3();
|
|
8
|
+
const boxCenter = new THREE.Vector3();
|
|
9
|
+
|
|
10
|
+
// Bounding region scratch variables
|
|
11
|
+
const southEastUpCarto = new Coordinates('EPSG:4326');
|
|
12
|
+
const southEastUpVec3 = new THREE.Vector3();
|
|
13
|
+
const northWestBottomCarto = new Coordinates('EPSG:4326');
|
|
14
|
+
const northWestBottomVec3 = new THREE.Vector3();
|
|
15
|
+
const radiusScratch = new THREE.Vector3();
|
|
16
|
+
|
|
17
|
+
// Culling scratch value
|
|
18
|
+
const worldCoordinateCenter = new THREE.Vector3();
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Bounding region is converted to a bounding sphere to simplify and speed computation and culling. This function
|
|
22
|
+
* computes a sphere enclosing the bounding region.
|
|
23
|
+
* @param {Object} region - the parsed json from the tile representing the region
|
|
24
|
+
* @param {THREE.Matrix4} tileMatrixInverse - the inverse transformation matrix of the tile to transform the produced
|
|
25
|
+
* sphere from a global to a reference local to the tile
|
|
26
|
+
* @return {THREE.Sphere} a sphere enclosing the given region
|
|
27
|
+
*/
|
|
28
|
+
function initFromRegion(region, tileMatrixInverse) {
|
|
29
|
+
const east = region[2];
|
|
30
|
+
const west = region[0];
|
|
31
|
+
const south = region[1];
|
|
32
|
+
const north = region[3];
|
|
33
|
+
const minHeight = region[4];
|
|
34
|
+
const maxHeight = region[5];
|
|
35
|
+
const eastDeg = THREE.MathUtils.radToDeg(east);
|
|
36
|
+
const westDeg = THREE.MathUtils.radToDeg(west);
|
|
37
|
+
const southDeg = THREE.MathUtils.radToDeg(south);
|
|
38
|
+
const northDeg = THREE.MathUtils.radToDeg(north);
|
|
39
|
+
northWestBottomCarto.setFromValues(westDeg, northDeg, minHeight);
|
|
40
|
+
ellipsoid.cartographicToCartesian(northWestBottomCarto, northWestBottomVec3);
|
|
41
|
+
southEastUpCarto.setFromValues(eastDeg, southDeg, maxHeight);
|
|
42
|
+
ellipsoid.cartographicToCartesian(southEastUpCarto, southEastUpVec3);
|
|
43
|
+
const regionCenter = new THREE.Vector3();
|
|
44
|
+
regionCenter.lerpVectors(northWestBottomVec3, southEastUpVec3, 0.5);
|
|
45
|
+
const radius = radiusScratch.subVectors(northWestBottomVec3, southEastUpVec3).length() / 2;
|
|
46
|
+
const sphere = new THREE.Sphere(regionCenter, radius);
|
|
47
|
+
sphere.applyMatrix4(tileMatrixInverse);
|
|
48
|
+
return sphere;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Create a bounding box from a json describing a box in a 3D Tiles tile.
|
|
53
|
+
* @param {Object} box - the parsed json from the tile representing the box
|
|
54
|
+
* @return {THREE.Box3} the bounding box of the tile
|
|
55
|
+
*/
|
|
56
|
+
function initFromBox(box) {
|
|
57
|
+
// box[0], box[1], box[2] = center of the box
|
|
58
|
+
// box[3], box[4], box[5] = x axis direction and half-length
|
|
59
|
+
// box[6], box[7], box[8] = y axis direction and half-length
|
|
60
|
+
// box[9], box[10], box[11] = z axis direction and half-length
|
|
61
|
+
boxCenter.set(box[0], box[1], box[2]);
|
|
62
|
+
boxSize.set(box[3], box[7], box[11]).multiplyScalar(2);
|
|
63
|
+
const box3 = new THREE.Box3();
|
|
64
|
+
box3.setFromCenterAndSize(boxCenter, boxSize);
|
|
65
|
+
return box3;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Creats a bounding sphere from a json describing a sphere in a 3D Tiles tile.
|
|
70
|
+
* @param {Object} sphere - the parsed json from the tile representing the sphere
|
|
71
|
+
* @returns {THREE.Sphere} the bounding sphere of the tile
|
|
72
|
+
*/
|
|
73
|
+
function initFromSphere(sphere) {
|
|
74
|
+
const sphereCenter = new THREE.Vector3();
|
|
75
|
+
sphereCenter.set(sphere[0], sphere[1], sphere[2]);
|
|
76
|
+
return new THREE.Sphere(sphereCenter, sphere[3]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* [bounding volume](https://github.com/AnalyticalGraphicsInc/3d-tiles/blob/master/specification/schema/boundingVolume.schema.json)
|
|
81
|
+
* Used to represent bounding volumes and viewer request volumes. The input bounding volume (from the dataset) can be a
|
|
82
|
+
* box, a sphere or a region. Regions are transformed to spheres internally for simplification of parsing and to speed
|
|
83
|
+
* up computations such as culling.
|
|
84
|
+
* @property {C3DTilesTypes} type - Used by 3D Tiles extensions
|
|
85
|
+
* (e.g. {@link C3DTBatchTableHierarchyExtension}) to know in which context
|
|
86
|
+
* (i.e. for which 3D Tiles class) the parsing of the extension should be done.
|
|
87
|
+
* @property {String} initialVolumeType - the initial volume type to be able to dissociate spheres
|
|
88
|
+
* and regions if needed since both are converted to spheres (one of {@link C3DTilesBoundingVolumeTypes})
|
|
89
|
+
* @property {THREE.Box3|THREE.Sphere} volume - The 3D bounding volume created. Can be a THREE.Box3 for bounding volumes
|
|
90
|
+
* of types box or a THREE.Sphere for bounding volumes of type sphere or region.
|
|
91
|
+
* @property {object} extensions - 3D Tiles extensions of the bounding volume
|
|
92
|
+
* stored in the following format:
|
|
93
|
+
* {extensioName1: extensionObject1, extensioName2: extensionObject2, ...}
|
|
94
|
+
*/
|
|
95
|
+
class C3DTBoundingVolume {
|
|
96
|
+
constructor(json, tileMatrixInverse, registeredExtensions) {
|
|
97
|
+
this.type = C3DTilesTypes.boundingVolume;
|
|
98
|
+
if (json.region) {
|
|
99
|
+
this.initialVolumeType = C3DTilesBoundingVolumeTypes.region;
|
|
100
|
+
this.volume = initFromRegion(json.region, tileMatrixInverse);
|
|
101
|
+
} else if (json.box) {
|
|
102
|
+
this.initialVolumeType = C3DTilesBoundingVolumeTypes.box;
|
|
103
|
+
this.volume = initFromBox(json.box);
|
|
104
|
+
} else if (json.sphere) {
|
|
105
|
+
this.initialVolumeType = C3DTilesBoundingVolumeTypes.sphere;
|
|
106
|
+
this.volume = initFromSphere(json.sphere);
|
|
107
|
+
} else {
|
|
108
|
+
throw new Error(`Unknown bounding volume type: ${json}. 3D Tiles nodes must have a bounding volume of type
|
|
109
|
+
region, box or sphere.`);
|
|
110
|
+
}
|
|
111
|
+
if (json.extensions) {
|
|
112
|
+
this.extensions = registeredExtensions.parseExtensions(json.extensions, this.type);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Performs camera frustum culling on bounding volumes.
|
|
118
|
+
* @param {Camera} camera - the camera to perform culling for
|
|
119
|
+
* @param {THREE.Matrix4} tileMatrixWorld - the world matrix of the tile
|
|
120
|
+
* @returns {boolean} true if the tile should be culled out (bounding volume not in camera frustum), false otherwise.
|
|
121
|
+
*/
|
|
122
|
+
boundingVolumeCulling(camera, tileMatrixWorld) {
|
|
123
|
+
if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.box) {
|
|
124
|
+
return !camera.isBox3Visible(this.volume, tileMatrixWorld);
|
|
125
|
+
} else if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.sphere || this.initialVolumeType === C3DTilesBoundingVolumeTypes.region) {
|
|
126
|
+
return !camera.isSphereVisible(this.volume, tileMatrixWorld);
|
|
127
|
+
} else {
|
|
128
|
+
throw new Error('Unknown bounding volume type.');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Checks if the camera is inside the [viewer request volumes](https://github.com/CesiumGS/3d-tiles/tree/main/specification#viewer-request-volume).
|
|
134
|
+
* @param {Camera} camera - the camera to perform culling for
|
|
135
|
+
* @param {THREE.Matrix4} tileMatrixWorld - the world matrix of the tile
|
|
136
|
+
* @returns {boolean} true if the camera is outside the viewer request volume, false otherwise.
|
|
137
|
+
*/
|
|
138
|
+
viewerRequestVolumeCulling(camera, tileMatrixWorld) {
|
|
139
|
+
if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.region) {
|
|
140
|
+
console.warn('Region viewerRequestVolume not yet supported');
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.box) {
|
|
144
|
+
console.warn('Bounding box viewerRequestVolume not yet supported');
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
if (this.initialVolumeType === C3DTilesBoundingVolumeTypes.sphere) {
|
|
148
|
+
worldCoordinateCenter.copy(this.volume.center);
|
|
149
|
+
worldCoordinateCenter.applyMatrix4(tileMatrixWorld);
|
|
150
|
+
// To check the distance between the center sphere and the camera
|
|
151
|
+
return !(camera.camera3D.position.distanceTo(worldCoordinateCenter) <= this.volume.radius);
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export default C3DTBoundingVolume;
|