@jdultra/threedtiles 3.3.2 → 4.0.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/README.md +5 -5
- package/index.html +1 -1
- package/package.json +14 -13
- package/src/decoder/B3DMDecoder.js +63 -64
- package/src/index.js +139 -33
- package/src/tileset/OGC3DTile.js +2 -2
- package/src/tileset/TileLoader.js +0 -9
- package/src/tileset/instanced/InstancedOGC3DTile.js +45 -0
- package/src/tileset/instanced/InstancedTile.js +510 -0
- package/src/tileset/instanced/InstancedTileLoader.js +322 -0
- package/src/tileset/instanced/JsonTile.js +41 -0
- package/src/tileset/instanced/MeshTile.js +75 -0
- package/webpack.config.js +117 -107
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
The fastest 3DTiles viewer for three.js
|
|
6
6
|
|
|
7
|
-
Photogrametry
|
|
7
|
+
[Photogrametry (OBJ conversion)](https://ebeaufay.github.io/ThreedTilesViewer.github.io/)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
[PBR material (GlTF conversion)](https://www.jdultra.com/pbr/)
|
|
10
10
|
|
|
11
|
-
Occlusion culling
|
|
11
|
+
[Occlusion culling (IFC conversion)](https://www.jdultra.com/occlusion/index.html)
|
|
12
12
|
|
|
13
13
|
Adding a tileset to a scene is as easy as :
|
|
14
14
|
|
|
@@ -140,8 +140,8 @@ ogc3DTile.rotateOnAxis(new THREE.Vector3(1,0,0), -Math.PI*0.5);
|
|
|
140
140
|
### Occlusion culling
|
|
141
141
|
Occlusion culling prevents the refinment of data that is hidden by other data, like a wall. It can have a big impact on frame-rate and loading speed for interior scenes.
|
|
142
142
|
|
|
143
|
-
A word of warning: activating occlusion culling
|
|
144
|
-
It will be most beneficial on interior scenes where most of the data is occluded by walls. All the tiles that don't need to be downloaded or drawn will balance out the cost of the
|
|
143
|
+
A word of warning: activating occlusion culling has an impact on frame-rate.
|
|
144
|
+
It will be most beneficial on interior scenes where most of the data is occluded by walls. All the tiles that don't need to be downloaded or drawn will balance out the cost of the occlusion logic.
|
|
145
145
|
|
|
146
146
|
|
|
147
147
|
First, instantiate an OcclusionCullingService:
|
package/index.html
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<body>
|
|
49
49
|
<div id="screen"></div>
|
|
50
50
|
<div style="position: absolute; top: 1%; z-index: 100; right:1%; ">
|
|
51
|
-
<input type="range" min="0.0" max="0
|
|
51
|
+
<input type="range" min="0.0" max="1.0" value="1.0", step="0.001" class="slider" id="lodMultiplier" >
|
|
52
52
|
<p style="color: #0439aa;">LOD multiplier: <span id="multiplierValue"></span></p>
|
|
53
53
|
</div>
|
|
54
54
|
</body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jdultra/threedtiles",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"description": "An OGC 3DTiles viewer for Three.js",
|
|
5
5
|
"main": "tileset.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,29 +23,30 @@
|
|
|
23
23
|
"author": "Emeric Beaufays",
|
|
24
24
|
"license": "MIT",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"gltf-validator": "
|
|
26
|
+
"gltf-validator": "^2.0.0-dev.3.9",
|
|
27
27
|
"js-utils-z": "1.2.1",
|
|
28
28
|
"lodash": ">=4.17.20",
|
|
29
|
-
"lru-cache": "^7.
|
|
30
|
-
"mnemonist": "^0.39.
|
|
29
|
+
"lru-cache": "^7.14.1",
|
|
30
|
+
"mnemonist": "^0.39.5",
|
|
31
31
|
"path-browserify": "^1.0.1",
|
|
32
|
-
"regenerator-runtime": "
|
|
32
|
+
"regenerator-runtime": "^0.13.11",
|
|
33
33
|
"set-interval-async": "^2.0.3",
|
|
34
|
-
"three": "0.
|
|
34
|
+
"three": "0.146.0",
|
|
35
35
|
"uuid": "^8.3.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@babel/core": "^7.
|
|
39
|
-
"@babel/preset-env": "^7.
|
|
40
|
-
"babel-loader": "^8.
|
|
38
|
+
"@babel/core": "^7.20.2",
|
|
39
|
+
"@babel/preset-env": "^7.20.2",
|
|
40
|
+
"babel-loader": "^8.3.0",
|
|
41
41
|
"copy-webpack-plugin": "^6.3.2",
|
|
42
|
-
"core-js": "^3.
|
|
42
|
+
"core-js": "^3.26.1",
|
|
43
43
|
"html-loader": "^1.3.2",
|
|
44
44
|
"html-webpack-plugin": "^4.5.0",
|
|
45
|
-
"mini-css-extract-plugin": "^1.
|
|
46
|
-
"webpack": "^5.
|
|
45
|
+
"mini-css-extract-plugin": "^1.6.2",
|
|
46
|
+
"webpack": "^5.75.0",
|
|
47
47
|
"webpack-cli": "4.9.1",
|
|
48
|
-
"webpack-dev-server": "^4.
|
|
48
|
+
"webpack-dev-server": "^4.11.1",
|
|
49
|
+
"webpack-glsl-loader": "^1.0.1",
|
|
49
50
|
"whatwg-fetch": "^3.5.0"
|
|
50
51
|
}
|
|
51
52
|
}
|
|
@@ -1,92 +1,91 @@
|
|
|
1
1
|
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
2
2
|
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
|
|
3
|
-
|
|
3
|
+
import * as THREE from 'three';
|
|
4
4
|
|
|
5
5
|
const gltfLoader = new GLTFLoader();
|
|
6
6
|
const dracoLoader = new DRACOLoader();
|
|
7
|
-
dracoLoader.setDecoderPath(
|
|
8
|
-
gltfLoader.setDRACOLoader(
|
|
7
|
+
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.4.3/');
|
|
8
|
+
gltfLoader.setDRACOLoader(dracoLoader);
|
|
9
|
+
const dummy = new THREE.Object3D();
|
|
9
10
|
//const legacyGLTFLoader = new LegacyGLTFLoader();
|
|
10
|
-
const B3DMDecoder = {
|
|
11
|
-
parseB3DM: (arrayBuffer, meshCallback) => {
|
|
12
|
-
const dataView = new DataView(arrayBuffer);
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
String.fromCharCode(dataView.getUint8(1)) +
|
|
17
|
-
String.fromCharCode(dataView.getUint8(2)) +
|
|
18
|
-
String.fromCharCode(dataView.getUint8(3));
|
|
19
|
-
console.assert(magic === 'b3dm');
|
|
12
|
+
function parseB3DM(arrayBuffer, meshCallback) {
|
|
13
|
+
const dataView = new DataView(arrayBuffer);
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const magic =
|
|
16
|
+
String.fromCharCode(dataView.getUint8(0)) +
|
|
17
|
+
String.fromCharCode(dataView.getUint8(1)) +
|
|
18
|
+
String.fromCharCode(dataView.getUint8(2)) +
|
|
19
|
+
String.fromCharCode(dataView.getUint8(3));
|
|
20
|
+
console.assert(magic === 'b3dm');
|
|
23
21
|
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
const version = dataView.getUint32(4, true);
|
|
23
|
+
console.assert(version === 1);
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
const batchTableJSONByteLength = dataView.getUint32(20, true);
|
|
30
|
-
const batchTableBinaryByteLength = dataView.getUint32(24, true);
|
|
25
|
+
const byteLength = dataView.getUint32(8, true);
|
|
26
|
+
console.assert(byteLength === arrayBuffer.byteLength);
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const featureTableJSONByteLength = dataView.getUint32(12, true);
|
|
29
|
+
const featureTableBinaryByteLength = dataView.getUint32(16, true);
|
|
30
|
+
const batchTableJSONByteLength = dataView.getUint32(20, true);
|
|
31
|
+
const batchTableBinaryByteLength = dataView.getUint32(24, true);
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
const featureTableStart = 28;
|
|
34
|
+
//const featureTable = new FeatureTable( arrayBuffer, featureTableStart, featureTableJSONByteLength, featureTableBinaryByteLength );
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const batchTableStart = featureTableStart + featureTableJSONByteLength + featureTableBinaryByteLength;
|
|
37
|
+
//const batchTable = new BatchTable( arrayBuffer, featureTable.getData( 'BATCH_LENGTH' ), batchTableStart, batchTableJSONByteLength, batchTableBinaryByteLength );
|
|
40
38
|
|
|
39
|
+
const glbStart = batchTableStart + batchTableJSONByteLength + batchTableBinaryByteLength;
|
|
40
|
+
const glbBytes = new Uint8Array(arrayBuffer, glbStart, byteLength - glbStart);
|
|
41
41
|
|
|
42
|
-
const gltfBuffer = glbBytes.slice().buffer;
|
|
43
42
|
|
|
43
|
+
const gltfBuffer = glbBytes.slice().buffer;
|
|
44
44
|
|
|
45
|
-
return new Promise((resolve, reject) => {
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
//model.batchTable = b3dm.batchTable;
|
|
51
|
-
//model.featureTable = b3dm.featureTable;
|
|
48
|
+
gltfLoader.parse(gltfBuffer, null, model => {
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
////TODO
|
|
51
|
+
//model.batchTable = b3dm.batchTable;
|
|
52
|
+
//model.featureTable = b3dm.featureTable;
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (o.isMesh) {
|
|
59
|
-
if (!!meshCallback) {
|
|
60
|
-
meshCallback(o);
|
|
61
|
-
}
|
|
54
|
+
//model.scene.batchTable = b3dm.batchTable;
|
|
55
|
+
//model.scene.featureTable = b3dm.featureTable;
|
|
62
56
|
|
|
57
|
+
//const scene = mergeColoredObject(model.scene);
|
|
58
|
+
model.scene.traverse((o) => {
|
|
59
|
+
if (o.isMesh) {
|
|
60
|
+
if (!!meshCallback) {
|
|
61
|
+
meshCallback(o);
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}, error=>{
|
|
67
|
-
console.error(error);
|
|
68
|
-
/* legacyGLTFLoader.parse(gltfBuffer, model => {
|
|
69
|
-
|
|
70
|
-
////TODO
|
|
71
|
-
//model.batchTable = b3dm.batchTable;
|
|
72
|
-
//model.featureTable = b3dm.featureTable;
|
|
73
|
-
|
|
74
|
-
//model.scene.batchTable = b3dm.batchTable;
|
|
75
|
-
//model.scene.featureTable = b3dm.featureTable;
|
|
76
|
-
|
|
77
|
-
//const scene = mergeColoredObject(model.scene);
|
|
78
|
-
model.scene.traverse((o) => {
|
|
79
|
-
if (o.isMesh) {
|
|
80
|
-
if (!!meshCallback) {
|
|
81
|
-
meshCallback(o);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
resolve(model.scene);
|
|
87
|
-
}, null); */
|
|
63
|
+
|
|
64
|
+
}
|
|
88
65
|
});
|
|
66
|
+
resolve(model.scene);
|
|
67
|
+
}, error => {
|
|
68
|
+
console.error(error);
|
|
89
69
|
});
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const B3DMDecoder = {
|
|
74
|
+
parseB3DM: parseB3DM,
|
|
75
|
+
parseB3DMInstanced: (arrayBuffer, meshCallback, maxCount) => { // expects GLTF with one node level
|
|
76
|
+
|
|
77
|
+
return parseB3DM(arrayBuffer, meshCallback).then(mesh => {
|
|
78
|
+
let instancedMesh;
|
|
79
|
+
mesh.traverse(child => {
|
|
80
|
+
if (child.isMesh) {
|
|
81
|
+
instancedMesh = new THREE.InstancedMesh(child.geometry, child.material, maxCount);
|
|
82
|
+
instancedMesh.baseMatrix = child.matrix;
|
|
83
|
+
//console.log(child.matrix.elements[12])
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return instancedMesh;
|
|
87
|
+
});
|
|
88
|
+
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
91
|
|
package/src/index.js
CHANGED
|
@@ -6,33 +6,86 @@ import { TileLoader } from "./tileset/TileLoader";
|
|
|
6
6
|
import { MapControls, OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
|
7
7
|
import { setIntervalAsync } from 'set-interval-async/dynamic';
|
|
8
8
|
import { OcclusionCullingService } from "./tileset/OcclusionCullingService";
|
|
9
|
+
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
|
|
10
|
+
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js';
|
|
11
|
+
import { UnrealBloomPass } from 'three/examples/jsm/postprocessing/UnrealBloomPass.js';
|
|
12
|
+
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
|
9
13
|
|
|
14
|
+
import { InstancedOGC3DTile } from "./tileset/instanced/InstancedOGC3DTile.js"
|
|
15
|
+
import { InstancedTileLoader } from "./tileset/instanced/InstancedTileLoader.js"
|
|
16
|
+
|
|
17
|
+
import { B3DMDecoder } from "./decoder/B3DMDecoder";
|
|
10
18
|
|
|
11
19
|
const occlusionCullingService = new OcclusionCullingService();
|
|
12
20
|
occlusionCullingService.setSide(THREE.DoubleSide);
|
|
13
21
|
const scene = initScene();
|
|
22
|
+
|
|
14
23
|
const domContainer = initDomContainer("screen");
|
|
15
24
|
const camera = initCamera();
|
|
16
|
-
const ogc3DTiles = initTileset(scene);
|
|
17
|
-
|
|
25
|
+
//const ogc3DTiles = initTileset(scene);
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
const instancedTileLoader = createInstancedTileLoader(scene);
|
|
29
|
+
initInstancedTilesets(instancedTileLoader);
|
|
30
|
+
|
|
18
31
|
const controller = initController(camera, domContainer);
|
|
19
32
|
|
|
20
33
|
const stats = initStats(domContainer);
|
|
21
34
|
const renderer = initRenderer(camera, domContainer);
|
|
35
|
+
const composer = initComposer(scene, camera, renderer);
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
/* fetch("https://storage.googleapis.com/ogc-3d-tiles/droneship/1/2007.b3dm").then(result => {
|
|
39
|
+
|
|
40
|
+
if (!result.ok) {
|
|
41
|
+
console.error("could not load tile with path : " + path)
|
|
42
|
+
throw new Error(`couldn't load "${path}". Request failed with status ${result.status} : ${result.statusText}`);
|
|
43
|
+
}
|
|
44
|
+
return result.arrayBuffer();
|
|
45
|
+
|
|
46
|
+
})
|
|
47
|
+
.then(resultArrayBuffer=>{
|
|
48
|
+
return B3DMDecoder.parseB3DMInstanced(resultArrayBuffer, self.meshCallback, 1);
|
|
49
|
+
})
|
|
50
|
+
.then(mesh=>{
|
|
51
|
+
scene.add(mesh)
|
|
52
|
+
|
|
53
|
+
}) */
|
|
22
54
|
|
|
23
55
|
|
|
24
56
|
animate();
|
|
25
57
|
|
|
58
|
+
|
|
59
|
+
function initComposer(scene, camera, renderer) {
|
|
60
|
+
const renderScene = new RenderPass(scene, camera);
|
|
61
|
+
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 0.4, 0.5, 0);
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const composer = new EffectComposer(renderer);
|
|
65
|
+
composer.addPass(renderScene);
|
|
66
|
+
composer.addPass(bloomPass);
|
|
67
|
+
return composer;
|
|
68
|
+
}
|
|
26
69
|
function initScene() {
|
|
27
70
|
const scene = new THREE.Scene();
|
|
28
71
|
scene.matrixAutoUpdate = false;
|
|
29
|
-
scene.background = new THREE.Color(
|
|
30
|
-
scene.add(new THREE.AmbientLight(0xFFFFFF, 0.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
scene.
|
|
72
|
+
scene.background = new THREE.Color(0x000000);
|
|
73
|
+
scene.add(new THREE.AmbientLight(0xFFFFFF, 0.2));
|
|
74
|
+
|
|
75
|
+
const light = new THREE.PointLight(0xbbbbff, 2, 5000);
|
|
76
|
+
const sphere = new THREE.SphereGeometry(2, 16, 8);
|
|
77
|
+
light.add(new THREE.Mesh(sphere, new THREE.MeshBasicMaterial({ color: 0xbbbbff })));
|
|
78
|
+
scene.add(light);
|
|
79
|
+
light.position.set(200, 200, 200);
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
const light2 = new THREE.PointLight(0xffbbbb, 2, 5000);
|
|
83
|
+
const sphere2 = new THREE.SphereGeometry(2, 16, 8);
|
|
84
|
+
light2.add(new THREE.Mesh(sphere2, new THREE.MeshBasicMaterial({ color: 0xffbbbb })));
|
|
85
|
+
scene.add(light2);
|
|
86
|
+
light2.position.set(200, 100, -100);
|
|
87
|
+
|
|
88
|
+
scene.matrixWorldAutoUpdate = true;
|
|
36
89
|
return scene;
|
|
37
90
|
}
|
|
38
91
|
|
|
@@ -51,6 +104,8 @@ function initRenderer(camera, dom) {
|
|
|
51
104
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
52
105
|
renderer.setSize(dom.offsetWidth, dom.offsetHeight);
|
|
53
106
|
renderer.outputEncoding = THREE.sRGBEncoding;
|
|
107
|
+
//renderer.toneMapping = THREE.ReinhardToneMapping;
|
|
108
|
+
//renderer.toneMappingExposure = Math.pow(0.8, 4.0);
|
|
54
109
|
renderer.autoClear = false;
|
|
55
110
|
|
|
56
111
|
dom.appendChild(renderer.domElement);
|
|
@@ -77,8 +132,8 @@ function initStats(dom) {
|
|
|
77
132
|
|
|
78
133
|
|
|
79
134
|
function initCamera() {
|
|
80
|
-
const camera = new THREE.PerspectiveCamera(40, window.offsetWidth / window.offsetHeight,
|
|
81
|
-
camera.position.set(
|
|
135
|
+
const camera = new THREE.PerspectiveCamera(40, window.offsetWidth / window.offsetHeight, 1, 100000);
|
|
136
|
+
camera.position.set(100, 10, 100);
|
|
82
137
|
camera.matrixAutoUpdate = true;
|
|
83
138
|
return camera;
|
|
84
139
|
}
|
|
@@ -88,36 +143,36 @@ function initTileset(scene) {
|
|
|
88
143
|
const tileLoader = new TileLoader(mesh => {
|
|
89
144
|
//// Insert code to be called on every newly decoded mesh e.g.:
|
|
90
145
|
mesh.material.wireframe = false;
|
|
91
|
-
mesh.material.side = THREE.
|
|
146
|
+
mesh.material.side = THREE.FrontSide;
|
|
92
147
|
}, 1000)
|
|
93
148
|
const ogc3DTile = new OGC3DTile({
|
|
94
|
-
|
|
95
|
-
url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
|
|
96
|
-
geometricErrorMultiplier: 0
|
|
149
|
+
url: "https://storage.googleapis.com/ogc-3d-tiles/droneship/tileset.json",
|
|
150
|
+
//url: "https://storage.googleapis.com/ogc-3d-tiles/berlinTileset/tileset.json",
|
|
151
|
+
geometricErrorMultiplier: 1.0,
|
|
97
152
|
loadOutsideView: false,
|
|
98
153
|
tileLoader: tileLoader,
|
|
99
154
|
//occlusionCullingService: occlusionCullingService,
|
|
100
155
|
static: false,
|
|
101
|
-
|
|
156
|
+
|
|
102
157
|
});
|
|
103
|
-
|
|
104
158
|
|
|
105
159
|
|
|
106
|
-
|
|
160
|
+
|
|
161
|
+
|
|
107
162
|
//// The OGC3DTile object is a threejs Object3D so you may do all the usual opperations like transformations e.g.:
|
|
108
|
-
ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
|
|
163
|
+
//ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5) // Z-UP to Y-UP
|
|
109
164
|
//// If the OGC3DTile object is marked as "static" (constructorParameter), these operations will not work.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
113
168
|
//// It's up to the user to call updates on the tileset. You might call them whenever the camera moves or at regular time intervals like here
|
|
114
169
|
|
|
115
170
|
|
|
116
|
-
|
|
171
|
+
|
|
117
172
|
var interval;
|
|
118
173
|
document.addEventListener('keyup', (e) => {
|
|
119
174
|
console.log(camera.position)
|
|
120
|
-
if (!!e.key && e.key !== "p"){
|
|
175
|
+
if (!!e.key && e.key !== "p") {
|
|
121
176
|
|
|
122
177
|
if (!!interval) {
|
|
123
178
|
clearInterval(interval);
|
|
@@ -126,18 +181,18 @@ function initTileset(scene) {
|
|
|
126
181
|
startInterval();
|
|
127
182
|
}
|
|
128
183
|
}
|
|
129
|
-
if (!!e.key && e.key !== "l"){
|
|
184
|
+
if (!!e.key && e.key !== "l") {
|
|
130
185
|
|
|
131
186
|
console.log("new THREE.Vector3(" + camera.position.x + "," + camera.position.y + "," + camera.position.z + ")");
|
|
132
|
-
|
|
187
|
+
console.log("new THREE.Quaternion(" + camera.quaternion.x + "," + camera.quaternion.y + "," + camera.quaternion.z + "," + camera.quaternion.w + ")");
|
|
133
188
|
|
|
134
189
|
}
|
|
135
|
-
|
|
190
|
+
|
|
136
191
|
});
|
|
137
192
|
function startInterval() {
|
|
138
193
|
interval = setIntervalAsync(function () {
|
|
139
194
|
ogc3DTile.update(camera);
|
|
140
|
-
|
|
195
|
+
|
|
141
196
|
}, 20);
|
|
142
197
|
}
|
|
143
198
|
startInterval();
|
|
@@ -146,13 +201,63 @@ function initTileset(scene) {
|
|
|
146
201
|
return ogc3DTile;
|
|
147
202
|
}
|
|
148
203
|
|
|
149
|
-
function
|
|
204
|
+
function createInstancedTileLoader(scene) {
|
|
205
|
+
return new InstancedTileLoader(scene, mesh => {
|
|
206
|
+
//// Insert code to be called on every newly decoded mesh e.g.:
|
|
207
|
+
mesh.material.wireframe = false;
|
|
208
|
+
mesh.material.side = THREE.FrontSide;
|
|
209
|
+
}, 1000, 1000);
|
|
210
|
+
}
|
|
211
|
+
function initInstancedTilesets(instancedTileLoader) {
|
|
212
|
+
|
|
213
|
+
const instancedTilesets = [];
|
|
214
|
+
|
|
215
|
+
for (let x = 0; x < 10; x++) {
|
|
216
|
+
for (let y = 0; y < 10; y++) {
|
|
217
|
+
for (let z = 0; z < 10; z++) {
|
|
218
|
+
const tileset = new InstancedOGC3DTile({
|
|
219
|
+
url: "https://storage.googleapis.com/ogc-3d-tiles/droneship/tileset.json",
|
|
220
|
+
//url: "http://localhost:8080/tileset.json",
|
|
221
|
+
geometricErrorMultiplier: 0.5,
|
|
222
|
+
loadOutsideView: false,
|
|
223
|
+
tileLoader: instancedTileLoader,
|
|
224
|
+
static: false,
|
|
225
|
+
});
|
|
226
|
+
tileset.rotateOnAxis(new THREE.Vector3(0, 0, 1), 50 * z)
|
|
227
|
+
tileset.translateOnAxis(new THREE.Vector3(1, 0, 0), 50 * x)
|
|
228
|
+
tileset.translateOnAxis(new THREE.Vector3(0, 1, 0), 50 * y)
|
|
229
|
+
tileset.translateOnAxis(new THREE.Vector3(0, 0, 1), 50 * z)
|
|
230
|
+
scene.add(tileset);
|
|
231
|
+
instancedTilesets.push(tileset);
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
idleCallback();
|
|
239
|
+
|
|
240
|
+
function idleCallback() {
|
|
241
|
+
instancedTilesets.forEach(tileset=>{
|
|
242
|
+
tileset.update(camera);
|
|
243
|
+
})
|
|
244
|
+
setTimeout(() => {
|
|
245
|
+
window.requestIdleCallback(idleCallback, { timeout: 50 })
|
|
246
|
+
}, 20)
|
|
247
|
+
|
|
248
|
+
}
|
|
249
|
+
initLODMultiplierSlider(instancedTilesets);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function initLODMultiplierSlider(instancedTilesets) {
|
|
150
253
|
var slider = document.getElementById("lodMultiplier");
|
|
151
254
|
var output = document.getElementById("multiplierValue");
|
|
152
255
|
output.innerHTML = slider.value;
|
|
153
256
|
|
|
154
257
|
slider.oninput = () => {
|
|
155
|
-
|
|
258
|
+
instancedTilesets.forEach(tileset => {
|
|
259
|
+
tileset.setGeometricErrorMultiplier(slider.value)
|
|
260
|
+
})
|
|
156
261
|
output.innerHTML = slider.value;
|
|
157
262
|
}
|
|
158
263
|
}
|
|
@@ -161,8 +266,8 @@ function initController(camera, dom) {
|
|
|
161
266
|
const controller = new OrbitControls(camera, dom);
|
|
162
267
|
|
|
163
268
|
controller.target.set(0, 0, 0);
|
|
164
|
-
controller.minDistance =
|
|
165
|
-
controller.maxDistance =
|
|
269
|
+
controller.minDistance = 0.01;
|
|
270
|
+
controller.maxDistance = 100000;
|
|
166
271
|
controller.update();
|
|
167
272
|
return controller;
|
|
168
273
|
}
|
|
@@ -170,7 +275,8 @@ function initController(camera, dom) {
|
|
|
170
275
|
|
|
171
276
|
function animate() {
|
|
172
277
|
requestAnimationFrame(animate);
|
|
173
|
-
|
|
278
|
+
instancedTileLoader.update();
|
|
279
|
+
composer.render();
|
|
174
280
|
//occlusionCullingService.update(scene, renderer, camera)
|
|
175
281
|
stats.update();
|
|
176
282
|
}
|
package/src/tileset/OGC3DTile.js
CHANGED
|
@@ -192,7 +192,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
192
192
|
if(self.static){
|
|
193
193
|
o.matrixAutoUpdate = false;
|
|
194
194
|
}
|
|
195
|
-
o.material.visible = false;
|
|
195
|
+
//o.material.visible = false;
|
|
196
196
|
}
|
|
197
197
|
});
|
|
198
198
|
|
|
@@ -450,7 +450,7 @@ class OGC3DTile extends THREE.Object3D {
|
|
|
450
450
|
return true;
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
-
return
|
|
453
|
+
return false;
|
|
454
454
|
|
|
455
455
|
}
|
|
456
456
|
|
|
@@ -26,12 +26,6 @@ class TileLoader {
|
|
|
26
26
|
const self = this;
|
|
27
27
|
setIntervalAsync(() => {
|
|
28
28
|
self.download();
|
|
29
|
-
/* const start = Date.now();
|
|
30
|
-
let uploaded = 0;
|
|
31
|
-
do{
|
|
32
|
-
uploaded = download();
|
|
33
|
-
}while(uploaded > 0 && (Date.now() - start)<= 2 ) */
|
|
34
|
-
|
|
35
29
|
}, 10);
|
|
36
30
|
setIntervalAsync(() => {
|
|
37
31
|
const start = Date.now();
|
|
@@ -57,9 +51,6 @@ class TileLoader {
|
|
|
57
51
|
nextDownload.doDownload();
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
54
|
return;
|
|
64
55
|
}
|
|
65
56
|
meshReceived(cache, register, key, distanceFunction, getSiblings, level, uuid) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
import {InstancedTile} from "./InstancedTile.js"
|
|
3
|
+
|
|
4
|
+
class InstancedOGC3DTile extends THREE.Object3D {
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* @param {
|
|
9
|
+
* json: optional,
|
|
10
|
+
* url: optional,
|
|
11
|
+
* rootPath: optional,
|
|
12
|
+
* parentGeometricError: optional,
|
|
13
|
+
* parentBoundingVolume: optional,
|
|
14
|
+
* parentRefinement: optional,
|
|
15
|
+
* geometricErrorMultiplier: Double,
|
|
16
|
+
* loadOutsideView: Boolean,
|
|
17
|
+
* tileLoader : InstancedTileLoader,
|
|
18
|
+
* meshCallback: function,
|
|
19
|
+
* cameraOnLoad: camera,
|
|
20
|
+
* parentTile: OGC3DTile,
|
|
21
|
+
* onLoadCallback: function,
|
|
22
|
+
* static: Boolean
|
|
23
|
+
* } properties
|
|
24
|
+
*/
|
|
25
|
+
constructor(properties) {
|
|
26
|
+
super();
|
|
27
|
+
properties.master = this;
|
|
28
|
+
this.geometricErrorMultiplier = properties.geometricErrorMultiplier? properties.geometricErrorMultiplier:1.0;
|
|
29
|
+
this.tileset = new InstancedTile(properties);
|
|
30
|
+
if (properties.static) {
|
|
31
|
+
this.matrixAutoUpdate = false;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
update(camera){
|
|
36
|
+
const frustum = new THREE.Frustum();
|
|
37
|
+
frustum.setFromProjectionMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
|
|
38
|
+
this.tileset._update(camera, frustum);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setGeometricErrorMultiplier(geometricErrorMultiplier) {
|
|
42
|
+
this.geometricErrorMultiplier = geometricErrorMultiplier?geometricErrorMultiplier:1.0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export { InstancedOGC3DTile };
|