@jdultra/threedtiles 11.1.10 → 11.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +1 -1
  2. package/dist/index.html +1 -1
  3. package/dist/threedtiles.min.js +1 -1
  4. package/dist/threedtiles.min.js.map +1 -1
  5. package/package.json +1 -1
  6. package/dist/docs/InstancedOGC3DTile.html +0 -3
  7. package/dist/docs/InstancedTile.html +0 -3
  8. package/dist/docs/InstancedTileLoader.html +0 -3
  9. package/dist/docs/OGC3DTile.html +0 -3
  10. package/dist/docs/OGC3DTile.js.html +0 -1451
  11. package/dist/docs/OcclusionCullingService.html +0 -3
  12. package/dist/docs/OcclusionCullingService.js.html +0 -84
  13. package/dist/docs/TileLoader.html +0 -3
  14. package/dist/docs/TileLoader.js.html +0 -550
  15. package/dist/docs/data/search.json +0 -1
  16. package/dist/docs/fonts/Inconsolata-Regular.ttf +0 -0
  17. package/dist/docs/fonts/OpenSans-Regular.ttf +0 -0
  18. package/dist/docs/fonts/WorkSans-Bold.ttf +0 -0
  19. package/dist/docs/global.html +0 -3
  20. package/dist/docs/index.html +0 -338
  21. package/dist/docs/instanced_InstancedOGC3DTile.js.html +0 -106
  22. package/dist/docs/instanced_InstancedTile.js.html +0 -701
  23. package/dist/docs/instanced_InstancedTileLoader.js.html +0 -497
  24. package/dist/docs/scripts/core.js +0 -726
  25. package/dist/docs/scripts/core.min.js +0 -23
  26. package/dist/docs/scripts/resize.js +0 -90
  27. package/dist/docs/scripts/search.js +0 -265
  28. package/dist/docs/scripts/search.min.js +0 -6
  29. package/dist/docs/scripts/third-party/Apache-License-2.0.txt +0 -202
  30. package/dist/docs/scripts/third-party/fuse.js +0 -9
  31. package/dist/docs/scripts/third-party/hljs-line-num-original.js +0 -369
  32. package/dist/docs/scripts/third-party/hljs-line-num.js +0 -1
  33. package/dist/docs/scripts/third-party/hljs-original.js +0 -5171
  34. package/dist/docs/scripts/third-party/hljs.js +0 -1
  35. package/dist/docs/scripts/third-party/popper.js +0 -5
  36. package/dist/docs/scripts/third-party/tippy.js +0 -1
  37. package/dist/docs/scripts/third-party/tocbot.js +0 -672
  38. package/dist/docs/scripts/third-party/tocbot.min.js +0 -1
  39. package/dist/docs/styles/clean-jsdoc-theme-base.css +0 -1159
  40. package/dist/docs/styles/clean-jsdoc-theme-dark.css +0 -412
  41. package/dist/docs/styles/clean-jsdoc-theme-light.css +0 -482
  42. package/dist/docs/styles/clean-jsdoc-theme-scrollbar.css +0 -30
  43. package/dist/docs/styles/clean-jsdoc-theme-without-scrollbar.min.css +0 -1
  44. package/dist/docs/styles/clean-jsdoc-theme.min.css +0 -1
@@ -1,1451 +0,0 @@
1
- <!DOCTYPE html><html lang="en" style="font-size:16px"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Source: OGC3DTile.js</title><!--[if lt IE 9]>
2
- <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
3
- <![endif]--><script src="scripts/third-party/hljs.js" defer="defer"></script><script src="scripts/third-party/hljs-line-num.js" defer="defer"></script><script src="scripts/third-party/popper.js" defer="defer"></script><script src="scripts/third-party/tippy.js" defer="defer"></script><script src="scripts/third-party/tocbot.min.js"></script><script>var baseURL="/",locationPathname="";baseURL=(locationPathname=document.location.pathname).substr(0,locationPathname.lastIndexOf("/")+1)</script><link rel="stylesheet" href="styles/clean-jsdoc-theme.min.css"><svg aria-hidden="true" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none"><defs><symbol id="copy-icon" viewbox="0 0 488.3 488.3"><g><path d="M314.25,85.4h-227c-21.3,0-38.6,17.3-38.6,38.6v325.7c0,21.3,17.3,38.6,38.6,38.6h227c21.3,0,38.6-17.3,38.6-38.6V124 C352.75,102.7,335.45,85.4,314.25,85.4z M325.75,449.6c0,6.4-5.2,11.6-11.6,11.6h-227c-6.4,0-11.6-5.2-11.6-11.6V124 c0-6.4,5.2-11.6,11.6-11.6h227c6.4,0,11.6,5.2,11.6,11.6V449.6z"/><path d="M401.05,0h-227c-21.3,0-38.6,17.3-38.6,38.6c0,7.5,6,13.5,13.5,13.5s13.5-6,13.5-13.5c0-6.4,5.2-11.6,11.6-11.6h227 c6.4,0,11.6,5.2,11.6,11.6v325.7c0,6.4-5.2,11.6-11.6,11.6c-7.5,0-13.5,6-13.5,13.5s6,13.5,13.5,13.5c21.3,0,38.6-17.3,38.6-38.6 V38.6C439.65,17.3,422.35,0,401.05,0z"/></g></symbol><symbol id="search-icon" viewBox="0 0 512 512"><g><g><path d="M225.474,0C101.151,0,0,101.151,0,225.474c0,124.33,101.151,225.474,225.474,225.474 c124.33,0,225.474-101.144,225.474-225.474C450.948,101.151,349.804,0,225.474,0z M225.474,409.323 c-101.373,0-183.848-82.475-183.848-183.848S124.101,41.626,225.474,41.626s183.848,82.475,183.848,183.848 S326.847,409.323,225.474,409.323z"/></g></g><g><g><path d="M505.902,476.472L386.574,357.144c-8.131-8.131-21.299-8.131-29.43,0c-8.131,8.124-8.131,21.306,0,29.43l119.328,119.328 c4.065,4.065,9.387,6.098,14.715,6.098c5.321,0,10.649-2.033,14.715-6.098C514.033,497.778,514.033,484.596,505.902,476.472z"/></g></g></symbol><symbol id="font-size-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11.246 15H4.754l-2 5H.6L7 4h2l6.4 16h-2.154l-2-5zm-.8-2L8 6.885 5.554 13h4.892zM21 12.535V12h2v8h-2v-.535a4 4 0 1 1 0-6.93zM19 18a2 2 0 1 0 0-4 2 2 0 0 0 0 4z"/></symbol><symbol id="add-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M11 11V5h2v6h6v2h-6v6h-2v-6H5v-2z"/></symbol><symbol id="minus-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M5 11h14v2H5z"/></symbol><symbol id="dark-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z"/></symbol><symbol id="light-theme-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z"/></symbol><symbol id="reset-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M18.537 19.567A9.961 9.961 0 0 1 12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10c0 2.136-.67 4.116-1.81 5.74L17 12h3a8 8 0 1 0-2.46 5.772l.997 1.795z"/></symbol><symbol id="down-icon" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M12.7803 6.21967C13.0732 6.51256 13.0732 6.98744 12.7803 7.28033L8.53033 11.5303C8.23744 11.8232 7.76256 11.8232 7.46967 11.5303L3.21967 7.28033C2.92678 6.98744 2.92678 6.51256 3.21967 6.21967C3.51256 5.92678 3.98744 5.92678 4.28033 6.21967L8 9.93934L11.7197 6.21967C12.0126 5.92678 12.4874 5.92678 12.7803 6.21967Z"></path></symbol><symbol id="codepen-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M16.5 13.202L13 15.535v3.596L19.197 15 16.5 13.202zM14.697 12L12 10.202 9.303 12 12 13.798 14.697 12zM20 10.869L18.303 12 20 13.131V10.87zM19.197 9L13 4.869v3.596l3.5 2.333L19.197 9zM7.5 10.798L11 8.465V4.869L4.803 9 7.5 10.798zM4.803 15L11 19.131v-3.596l-3.5-2.333L4.803 15zM4 13.131L5.697 12 4 10.869v2.262zM2 9a1 1 0 0 1 .445-.832l9-6a1 1 0 0 1 1.11 0l9 6A1 1 0 0 1 22 9v6a1 1 0 0 1-.445.832l-9 6a1 1 0 0 1-1.11 0l-9-6A1 1 0 0 1 2 15V9z"/></symbol><symbol id="close-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z"/></symbol><symbol id="menu-icon" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M3 4h18v2H3V4zm0 7h18v2H3v-2zm0 7h18v2H3v-2z"/></symbol></defs></svg></head><body data-theme="dark"><div class="sidebar-container"><div class="sidebar" id="sidebar"><div class="sidebar-items-container"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="InstancedOGC3DTile.html">InstancedOGC3DTile</a></div><div class="sidebar-section-children"><a href="InstancedTile.html">InstancedTile</a></div><div class="sidebar-section-children"><a href="InstancedTileLoader.html">InstancedTileLoader</a></div><div class="sidebar-section-children"><a href="OGC3DTile.html">OGC3DTile</a></div><div class="sidebar-section-children"><a href="OcclusionCullingService.html">OcclusionCullingService</a></div><div class="sidebar-section-children"><a href="TileLoader.html">TileLoader</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#getOGC3DTilesCopyrightInfo">getOGC3DTilesCopyrightInfo</a></div></div></div></div></div><div class="navbar-container" id="VuAckcnZhf"><nav class="navbar"><div class="navbar-left-items"></div><div class="navbar-right-items"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div><nav></nav></nav></div><div class="toc-container"><div class="toc-content"><span class="bold">On this page</span><div id="eed4d2a0bfd64539bb9df78095dec881"></div></div></div><div class="body-wrapper"><div class="main-content"><div class="main-wrapper"><section id="source-page" class="source-page"><header><h1 id="title" class="has-anchor">OGC3DTile.js</h1></header><article><pre class="prettyprint source lang-js"><code>import * as THREE from 'three';
4
- import { OBB } from "../geometry/obb";
5
- import { TileLoader } from "./TileLoader";
6
- import { v4 as uuidv4 } from "uuid";
7
- import * as path from "path-browserify"
8
- import { resolveImplicite } from './implicit/ImplicitTileResolver.js';
9
- var averageTime = 0;
10
-
11
- var copyrightDiv;
12
- const tempSphere = new THREE.Sphere(new THREE.Vector3(0, 0, 0), 1);
13
- const tempBox3 = new THREE.Box3();
14
- const tempVec1 = new THREE.Vector3(0, 0, 0);
15
- const tempVec2 = new THREE.Vector3(0, 0, 0);
16
- const upVector = new THREE.Vector3(0, 1, 0);
17
-
18
- const tempQuaternion = new THREE.Quaternion();
19
- const copyright = {};
20
-
21
- /**
22
- * @returns a list of vendors that are required by copyright to be displayed in the app.
23
- */
24
- function getOGC3DTilesCopyrightInfo() {
25
- var list = [];
26
- for (let key in copyright) {
27
- if (copyright.hasOwnProperty(key) &amp;&amp; copyright[key] > 0) { // This checks if the key is actually part of the object and not its prototype.
28
- list.push(key);
29
- }
30
- }
31
- return list;
32
-
33
- }
34
-
35
-
36
- /**
37
- * class representing a tiled and multileveled mesh or point-cloud according to the OGC3DTiles 1.1 spec
38
- * @class
39
- * @extends {THREE.Object3D}
40
- */
41
- class OGC3DTile extends THREE.Object3D {
42
-
43
- /**
44
- * @param {Object} [properties] - the properties for this tileset
45
- * @param {String} [properties.url] - the url to the parent tileset.json
46
- * @param {Object} [properties.queryParams] - optional, path params to add to individual tile urls
47
- * @param {Number} [properties.geometricErrorMultiplier] - the geometric error of the parent. 1.0 by default corresponds to a maxScreenSpaceError of 16
48
- * @param {Boolean} [properties.loadOutsideView] - if truthy, tiles otside the camera frustum will be loaded with the least possible amount of detail
49
- * @param {TileLoader} [properties.tileLoader] - A tile loader that can be shared among tilesets in order to share a common cache.
50
- * @param {Function} [properties.meshCallback] - A callback function that will be called on every mesh
51
- * @param {Function} [properties.pointsCallback] - A callback function that will be called on every points
52
- * @param {Function} [properties.onLoadCallback] - A callback function that will be called when the root tile has been loaded
53
- * @param {OcclusionCullingService} [properties.occlusionCullingService] - A service that handles occlusion culling
54
- * @param {Boolean} [properties.centerModel] - If true, the tileset will be centered on 0,0,0 and in the case of georeferenced tilesets that use the "region" bounding volume, it will also be rotated so that the up axis matched the world y axis.
55
- * @param {Boolean} [properties.static] - If true, the tileset is considered static which improves performance but the matrices aren't automatically updated
56
- * @param {String} [properties.rootPath] - optional the root path for fetching children
57
- * @param {String} [properties.json] - optional json object representing the tileset sub-tree
58
- * @param {Number} [properties.parentGeometricError] - optional geometric error of the parent
59
- * @param {Object} [properties.parentBoundingVolume] - optional bounding volume of the parent
60
- * @param {String} [properties.parentRefine] - optional refine strategy of the parent of the parent
61
- * @param {THREE.Camera} [properties.cameraOnLoad] - optional the camera used when loading this particular sub-tile
62
- * @param {OGC3DTile} [properties.parentTile] - optional the OGC3DTile object that loaded this tile as a child
63
- * @param {String} [properties.proxy] - optional the url to a proxy service. Instead of fetching tiles via a GET request, a POST will be sent to the proxy url with the real tile address in the body of the request.
64
- * @param {Boolean} [properties.displayErrors] - optional value indicating that errors should be shown on screen.
65
- * @param {THREE.Renderer} [properties.renderer] - optional the renderer used to display the tileset. Used to infer render resolution at runtime and to instantiate a ktx2loader on the fly if not provided.
66
- * @param {Number} [properties.domWidth] - optional the canvas width (used to calculate geometric error). If a renderer is provided, it'll be used instead, else a default value is used.
67
- * @param {Number} [properties.domHeight] - optional the canvas height (used to calculate geometric error). If a renderer is provided, it'll be used instead, else a default value is used.
68
- * @param {DracoLoader} [properties.dracoLoader] - optional a draco loader (three/addons).
69
- * @param {KTX2Loader} [properties.ktx2Loader] - optional a ktx2 loader (three/addons).
70
- * @param {Number} [properties.distanceBias] - optional a bias that allows loading more or less detail closer to the camera relative to far away. The value should be a positive number. A value below 1 loads less detail near the camera and a value above 1 loads more detail near the camera. This needs to be compensated by the geometricErrorMultiplier in order to load a reasonable number of tiles.
71
- * @param {String} [properties.loadingStrategy] - optional a strategy for loading tiles "INCREMENTAL" loads intermediate LODs while "IMMEDIATE" skips intermediate LODs.
72
- * @param {String} [properties.drawBoundingVolume] - optional draws the bounding volume (may cause flickering)
73
- */
74
- constructor(properties) {
75
- super();
76
- const self = this;
77
-
78
- this.contentURL = [];
79
- if (!!properties.domWidth &amp;&amp; !!properties.domHeight) {
80
- this.rendererSize = new THREE.Vector2(properties.domWidth, properties.domHeight);
81
- } else {
82
- this.rendererSize = new THREE.Vector2(1000, 1000);
83
- }
84
- this.loadingStrategy = properties.loadingStrategy ? properties.loadingStrategy.toUpperCase() : "INCREMENTAL";
85
- this.distanceBias = Math.max(0.0001, properties.distanceBias ? properties.distanceBias : 1);
86
- this.proxy = properties.proxy;
87
- this.drawBoundingVolume = properties.drawBoundingVolume ? properties.drawBoundingVolume : false;
88
- this.displayErrors = properties.displayErrors;
89
- this.displayCopyright = properties.displayCopyright;
90
- if (properties.queryParams) {
91
- this.queryParams = { ...properties.queryParams };
92
- }
93
- this.uuid = uuidv4();
94
- if (!!properties.tileLoader) {
95
- this.tileLoader = properties.tileLoader;
96
- } else {
97
- const tileLoaderOptions = {};
98
- tileLoaderOptions.meshCallback = !properties.meshCallback ? (mesh, geometricError) => {
99
- mesh.material.wireframe = false;
100
- mesh.material.side = THREE.DoubleSide;
101
- } : properties.meshCallback;
102
- tileLoaderOptions.pointsCallback = !properties.pointsCallback ? (points, geometricError) => {
103
- points.material.size = Math.pow(geometricError, 0.33);
104
- points.material.sizeAttenuation = true;
105
- } : properties.pointsCallback;
106
- tileLoaderOptions.proxy = this.proxy;
107
- tileLoaderOptions.renderer = properties.renderer;
108
- tileLoaderOptions.dracoLoader = properties.dracoLoader;
109
- tileLoaderOptions.ktx2Loader = properties.ktx2Loader;
110
- this.tileLoader = new TileLoader(tileLoaderOptions);
111
- this.update = (camera) => {
112
- this.update(camera);
113
- this.tileLoader.update();
114
- }
115
- }
116
- this.displayCopyright = !!properties.displayCopyright;
117
- // set properties general to the entire tileset
118
- this.geometricErrorMultiplier = !!properties.geometricErrorMultiplier ? properties.geometricErrorMultiplier : 1.0;
119
-
120
-
121
- this.renderer = properties.renderer;
122
- this.meshCallback = properties.meshCallback;
123
- this.loadOutsideView = properties.loadOutsideView;
124
- this.cameraOnLoad = properties.cameraOnLoad;
125
- this.parentTile = properties.parentTile;
126
- this.occlusionCullingService = properties.occlusionCullingService;
127
- this.static = properties.static;
128
- if (this.occlusionCullingService) {
129
- this.color = new THREE.Color();
130
- this.color.setHex(Math.random() * 0xffffff);
131
- this.colorID = THREE.MathUtils.clamp(self.color.r * 255, 0, 255) &lt;&lt; 16 ^ THREE.MathUtils.clamp(self.color.g * 255, 0, 255) &lt;&lt; 8 ^ THREE.MathUtils.clamp(self.color.b * 255, 0, 255) &lt;&lt; 0;
132
- }
133
- if (this.static) {
134
- this.matrixAutoUpdate = false;
135
- this.matrixWorldAutoUpdate = false;
136
- }
137
-
138
- // declare properties specific to the tile for clarity
139
- this.childrenTiles = [];
140
- this.meshContent = [];
141
- this.tileContent;
142
- this.refine; // defaults to "REPLACE"
143
- this.rootPath;
144
- this.geometricError;
145
- this.boundingVolume;
146
- this.json; // the json corresponding to this tile
147
- this.materialVisibility = false;
148
- this.level = properties.level ? properties.level : 0;
149
- this.hasMeshContent = 0; // true when the provided json has a content field pointing to a B3DM file
150
- this.hasUnloadedJSONContent = 0; // true when the provided json has a content field pointing to a JSON file that is not yet loaded
151
- this.centerModel = properties.centerModel;
152
- this.abortController = new AbortController();
153
-
154
- this.onLoadCallback = properties.onLoadCallback;
155
- //this.layers.disable(0);
156
- //this.octree = new Octree();
157
-
158
- if (!!properties.json) { // If this tile is created as a child of another tile, properties.json is not null
159
-
160
- self._setup(properties);
161
-
162
-
163
- } else if (properties.url) { // If only the url to the tileset.json is provided
164
- var url = properties.url;
165
- if (self.queryParams) {
166
- var props = "";
167
- for (let key in self.queryParams) {
168
- if (self.queryParams.hasOwnProperty(key)) {
169
- props += "&amp;" + key + "=" + self.queryParams[key];
170
- }
171
- }
172
- if (url.includes("?")) {
173
- url += props;
174
- } else {
175
- url += "?" + props.substring(1);
176
- }
177
- }
178
-
179
-
180
- var fetchFunction;
181
- if (self.proxy) {
182
- fetchFunction = () => {
183
- return fetch(self.proxy,
184
- {
185
- method: 'POST',
186
- body: url,
187
- signal: self.abortController.signal
188
- }
189
- );
190
- }
191
- } else {
192
- fetchFunction = () => {
193
- return fetch(url, { signal: self.abortController.signal });
194
- }
195
- }
196
- fetchFunction().then(result => {
197
- if (!result.ok) {
198
- throw new Error(`couldn't load "${properties.url}". Request failed with status ${result.status} : ${result.statusText}`);
199
- }
200
- result.json().then(json => { return resolveImplicite(json, url) }).then(json => {
201
- self._setup({ rootPath: path.dirname(properties.url), json: json });
202
- });
203
- }).catch(e => { if (self.displayErrors) _showError(e) });
204
- }
205
- }
206
-
207
- /**
208
- * Manually updates all the matrices of the tileset.
209
- * To be called after transforming a {@link OGC3DTile tileset} instantiated with the "static" option
210
- */
211
- updateMatrices(){
212
- this.updateMatrix();
213
- if(this.static){
214
- this.traverse(o=>{
215
- if(o.isObject3D) o.matrixWorldAutoUpdate = true;
216
- });
217
- }
218
- this.updateMatrixWorld(true);
219
- if(this.static){
220
- this.traverse(o=>{
221
- if(o.isObject3D) o.matrixWorldAutoUpdate = false;
222
- });
223
- }
224
- }
225
- /**
226
- * Call this to specify the canvas width/height when it changes (used to compute tiles geometric error that controls tile refinement).
227
- * It's unnecessary to call this when the {@link OGC3DTile} is instantiated with the renderer.
228
- *
229
- * @param {Number} width
230
- * @param {Number} height
231
- */
232
- setCanvasSize(width, height) {
233
- this.rendererSize.set(width, height);
234
- }
235
-
236
- async _setup(properties) {
237
- const self = this;
238
- if (!!properties.json.root) {
239
- self.json = properties.json.root;
240
- if (!self.json.refine) self.json.refine = properties.json.refine;
241
- if (!self.json.geometricError) self.json.geometricError = properties.json.geometricError;
242
- if (!self.json.transform) self.json.transform = properties.json.transform;
243
- if (!self.json.boundingVolume) self.json.boundingVolume = properties.json.boundingVolume;
244
- } else {
245
- self.json = properties.json;
246
- }
247
-
248
- if (!self.json.children) {
249
- if (self.json.getChildren) {
250
- self.json.children = await self.json.getChildren();
251
- } else {
252
- self.json.children = [];
253
- }
254
- }
255
- self.rootPath = !!properties.json.rootPath ? properties.json.rootPath : properties.rootPath;
256
-
257
- // decode refine
258
- if (!!self.json.refine) {
259
- self.refine = self.json.refine;
260
- } else {
261
- self.refine = properties.parentRefine;
262
- }
263
- // decode geometric error
264
- if (!!self.json.geometricError) {
265
- self.geometricError = self.json.geometricError;
266
- } else {
267
- self.geometricError = properties.parentGeometricError;
268
- }
269
-
270
-
271
- // decode transform
272
- if (!!self.json.transform) {
273
- let mat = new THREE.Matrix4();
274
- mat.elements = self.json.transform;
275
- self.applyMatrix4(mat);
276
-
277
- }
278
-
279
- /* self.matrixWorldNeedsUpdate = true;
280
- //self.updateMatrix();
281
- if (self.parentTile) {
282
- self.parentTile.updateMatrixWorld(true);
283
- //self.parentTile.updateWorldMatrix(true, true);
284
- } */
285
-
286
- // decode volume
287
- if (!!self.json.boundingVolume) {
288
- if (!!self.json.boundingVolume.box) {
289
- self.boundingVolume = new OBB(self.json.boundingVolume.box);
290
- } else if (!!self.json.boundingVolume.region) {
291
- const region = self.json.boundingVolume.region;
292
- self._transformWGS84ToCartesian(region[0], region[1], region[4], tempVec1);
293
- self._transformWGS84ToCartesian(region[2], region[3], region[5], tempVec2);
294
- tempVec1.lerp(tempVec2, 0.5);
295
- self.boundingVolume = new THREE.Sphere(new THREE.Vector3(tempVec1.x, tempVec1.y, tempVec1.z), tempVec1.distanceTo(tempVec2));
296
- } else if (!!self.json.boundingVolume.sphere) {
297
- const sphere = self.json.boundingVolume.sphere;
298
- self.boundingVolume = new THREE.Sphere(new THREE.Vector3(sphere[0], sphere[1], sphere[2]), sphere[3]);
299
- } else {
300
- self.boundingVolume = properties.parentBoundingVolume;
301
- }
302
- } else {
303
- self.boundingVolume = properties.parentBoundingVolume;
304
- }
305
-
306
-
307
-
308
-
309
-
310
- function _checkContent(e) {
311
- if (!!e.uri &amp;&amp; e.uri.includes("json")) {
312
- self.hasUnloadedJSONContent++;
313
- } else if (!!e.url &amp;&amp; e.url.includes("json")) {
314
- self.hasUnloadedJSONContent++;
315
- } else {
316
- self.hasMeshContent++;
317
- }
318
- }
319
- if (!!self.json.content) { //if there is a content, json or otherwise, schedule it to be loaded
320
- _checkContent(self.json.content);
321
-
322
- switch (self.loadingStrategy) {
323
- case "IMMEDIATE": self._load(true, false); break;
324
- default: self._load();
325
- }
326
-
327
- } else if (!!self.json.contents) { //if there is a content, json or otherwise, schedule it to be loaded
328
- self.json.contents.forEach(e => _checkContent(e))
329
-
330
- switch (self.loadingStrategy) {
331
- case "IMMEDIATE": self._load(true, false); break;
332
- default: self._load();
333
- }
334
- //scheduleLoadTile(this);
335
- }
336
-
337
-
338
- if (!!self.centerModel) {
339
- const tempSphere = new THREE.Sphere();
340
- if (self.boundingVolume instanceof OBB) {
341
- // box
342
- tempSphere.copy(self.boundingVolume.sphere);
343
- } else if (self.boundingVolume instanceof THREE.Sphere) {
344
- //sphere
345
- tempSphere.copy(self.boundingVolume);
346
- }
347
-
348
- //tempSphere.applyMatrix4(self.matrixWorld);
349
- if (!!this.json.boundingVolume.region) {
350
- this._transformWGS84ToCartesian(
351
- (this.json.boundingVolume.region[0] + this.json.boundingVolume.region[2]) * 0.5,
352
- (this.json.boundingVolume.region[1] + this.json.boundingVolume.region[3]) * 0.5,
353
- (this.json.boundingVolume.region[4] + this.json.boundingVolume.region[5]) * 0.5,
354
- tempVec1);
355
-
356
- tempQuaternion.setFromUnitVectors(tempVec1.normalize(), upVector.normalize());
357
- self.applyQuaternion(tempQuaternion);
358
- }
359
- tempSphere.center.applyMatrix4(self.matrix);
360
- self.position.sub(tempSphere.center);
361
-
362
- self.updateMatrices();
363
- //self.updateMatrixWorld(true);
364
- }
365
- if (properties.onLoadCallback) self.onLoadCallback(self);
366
- self.isSetup = true;
367
-
368
-
369
- if (self.level > 0 &amp;&amp; self.drawBoundingVolume) {
370
- if (self.bbox) {
371
- console.log("double setup")
372
- }
373
- if(this.boundingVolume.aabb){
374
- let box = this.boundingVolume.aabb.clone();
375
- box.applyMatrix4(this.matrixWorld);
376
- self.bbox = new THREE.Box3Helper(box, 0xffff00);
377
- self.add(self.bbox);
378
- self.bbox.material.visible = false;
379
- }
380
- }
381
-
382
- }
383
- _assembleURL(root, relative) {
384
- // Append a slash to the root URL if it doesn't already have one
385
- if (!root.endsWith('/')) {
386
- root += '/';
387
- }
388
-
389
- const rootUrl = new URL(root);
390
- let rootParts = rootUrl.pathname.split('/').filter(p => p !== '');
391
- let relativeParts = relative.split('/').filter(p => p !== '');
392
-
393
- for (let i = 1; i &lt;= rootParts.length; i++) {
394
- if (i >= relativeParts.length) break;
395
- const rootToken = rootParts.slice(rootParts.length - i, rootParts.length).join('/');
396
- const relativeToken = relativeParts.slice(0, i).join('/');
397
- if (rootToken === relativeToken) {
398
- for (let j = 0; j &lt; i; j++) {
399
- rootParts.pop();
400
- }
401
- break;
402
- }
403
- }
404
-
405
-
406
- while (relativeParts.length > 0 &amp;&amp; relativeParts[0] === '..') {
407
- rootParts.pop();
408
- relativeParts.shift();
409
- }
410
-
411
- return `${rootUrl.protocol}//${rootUrl.host}/${[...rootParts, ...relativeParts].join('/')}`;
412
- }
413
-
414
- _extractQueryParams(url, params) {
415
- const urlObj = new URL(url);
416
-
417
- // Iterate over all the search parameters
418
- for (let [key, value] of urlObj.searchParams) {
419
- params[key] = value;
420
- }
421
-
422
- // Remove the query string
423
- urlObj.search = '';
424
- return urlObj.toString();
425
- }
426
- async _load(loadJson = true, loadMesh = true) {
427
- var self = this;
428
- if (self.deleted) return;
429
- if (!!self.json.content) {
430
- await loadContent(self.json.content, null, loadJson, loadMesh);
431
- } else if (!!self.json.contents) {
432
- let promises = self.json.contents.map((content, index) => loadContent(content, index, loadJson, loadMesh));
433
-
434
- Promise.all(promises)
435
- //self.json.contents.forEach(content=> loadContent(content, i))
436
- }
437
-
438
- async function loadContent(content, contentIndex, loadJson, loadMesh) {
439
- let url;
440
- if (!!content.uri) {
441
- url = content.uri;
442
- } else if (!!content.url) {
443
- url = content.url;
444
- }
445
- const urlRegex = /^(?:http|https|ftp|tcp|udp):\/\/\S+/;
446
-
447
- if (urlRegex.test(self.rootPath)) { // url
448
-
449
- if (!urlRegex.test(url)) {
450
- url = self._assembleURL(self.rootPath, url);
451
- }
452
- } else { //path
453
- if (path.isAbsolute(self.rootPath)) {
454
- url = self.rootPath + path.sep + url;
455
- }
456
- }
457
- url = self._extractQueryParams(url, self.queryParams);
458
- if (self.queryParams) {
459
- var props = "";
460
- for (let key in self.queryParams) {
461
- if (self.queryParams.hasOwnProperty(key)) { // This check is necessary to skip properties from the object's prototype chain
462
- props += "&amp;" + key + "=" + self.queryParams[key];
463
- }
464
- }
465
- if (url.includes("?")) {
466
- url += props;
467
- } else {
468
- url += "?" + props.substring(1);
469
- }
470
- }
471
-
472
- if (!!url) {
473
- if (loadMesh &amp;&amp; (url.includes(".b3dm") || url.includes(".glb") || url.includes(".gltf"))) {
474
- self.contentURL.push(url);
475
- try {
476
-
477
- self.tileLoader.get(self.abortController, self.uuid, url, mesh => {
478
-
479
- if (!!self.deleted) {
480
- return;
481
- }
482
- if (mesh.asset &amp;&amp; mesh.asset.copyright) {
483
- mesh.asset.copyright.split(';').forEach(s => {
484
- if (!!copyright[s]) {
485
- copyright[s]++;
486
- } else {
487
- copyright[s] = 1;
488
- }
489
- });
490
- if (self.displayCopyright) {
491
- _updateCopyrightLabel();
492
- }
493
- }
494
-
495
- mesh.traverse((o) => {
496
- if (o.isMesh || o.isPoints) {
497
- o.layers.disable(0);
498
-
499
- //if(o.material.transparent) o.layers.enable(31);
500
- }
501
- if (o.isMesh) {
502
-
503
- if (self.occlusionCullingService) {
504
- const position = o.geometry.attributes.position;
505
- const colors = [];
506
- for (let i = 0; i &lt; position.count; i++) {
507
- colors.push(self.color.r, self.color.g, self.color.b);
508
- }
509
- o.geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
510
- }
511
-
512
- //o.material.visible = false;
513
- }
514
- });
515
-
516
- //self.octree.fromGraphNode( mesh );
517
- /*averageTime*=numTiles;
518
- averageTime+=Date.now()-s;
519
- numTiles++;
520
- averageTime/=numTiles;
521
- console.log(averageTime);*/
522
- self.add(mesh);
523
- /* mesh.matrixWorldNeedsUpdate = true;
524
- self.matrixWorldNeedsUpdate = true;
525
- //self.updateMatrix();
526
- if (self.parentTile) {
527
- self.parentTile.updateMatrixWorld(true);
528
- //self.parentTile.updateWorldMatrix(true, true);
529
- } */
530
-
531
-
532
-
533
- // mesh.layers.disable(0);
534
- self.meshContent.push(mesh);
535
-
536
- }, !self.cameraOnLoad ? () => 0 : () => {
537
- let multiplier = 1;
538
- if ((self.metric &amp;&amp; self.metric &lt; 0) || self.deleted) multiplier = 2;
539
- return self._calculateDistanceToCamera(self.cameraOnLoad) * multiplier * self.level;
540
- }, () => self._getSiblings(),
541
- self.level,
542
- !!self.json.boundingVolume.region ? false : true,
543
- !!self.json.boundingVolume.region,
544
- self.geometricError
545
- );
546
- } catch (e) {
547
- if (self.displayErrors) _showError(e)
548
- }
549
-
550
-
551
- } else if (loadJson &amp;&amp; url.includes(".json")) {
552
- self.jsonRequested = url;
553
- self.tileLoader.get(self.abortController, self.uuid, url, async json => {
554
- if (!!self.deleted) return;
555
-
556
- json.rootPath = path.dirname(url);
557
- self.json.children.push(json);
558
- if (contentIndex == null) {
559
- delete self.json.content;
560
- } else {
561
- delete self.json.contents.splice(contentIndex, 1);
562
- }
563
-
564
- self.hasUnloadedJSONContent--;
565
- /* self.matrixWorldNeedsUpdate = true;
566
- self.updateMatrix();
567
- if (self.parentTile) {
568
- self.parentTile.updateMatrixWorld(true);
569
- //self.parentTile.updateWorldMatrix(true, true);
570
- } */
571
- });
572
-
573
- }
574
-
575
-
576
- /* self.matrixWorldNeedsUpdate = true;
577
- self.updateMatrix();
578
- if (self.parentTile) {
579
- self.parentTile.updateMatrixWorld(true);
580
- //self.parentTile.updateWorldMatrix(true, true);
581
- } */
582
- }
583
- }
584
- }
585
-
586
- /**
587
- * Disposes of all the resources used by the tileset.
588
- */
589
- dispose() {
590
-
591
- const self = this;
592
-
593
- self.meshContent.forEach(mc => {
594
- if (!!mc &amp;&amp; !!mc.asset &amp;&amp; mc.asset.copyright) {
595
- mc.asset.copyright.split(';').forEach(s => {
596
- if (!!copyright[s]) {
597
- copyright[s]--;
598
- }
599
- });
600
- if (self.displayCopyright) {
601
- _updateCopyrightLabel();
602
- }
603
- }
604
- })
605
-
606
- if (self.bbox) self.bbox.dispose();
607
-
608
-
609
- self.childrenTiles.forEach(tile => tile.dispose());
610
- self.deleted = true;
611
-
612
- if (!!self.contentURL) {
613
- self.contentURL.forEach(url => {
614
- self.tileLoader.invalidate(url, self.uuid);
615
- })
616
- self.contentURL = [];
617
- }
618
-
619
- if (!!self.abortController) { // abort tile request
620
- self.abortController.abort("tile not needed");
621
- }
622
- this.parent = null;
623
- this.parentTile = null;
624
- this.dispatchEvent({ type: 'removed' });
625
- }
626
- _disposeMeshContent() {
627
- const self = this;
628
- if(!!self.deleted) return;
629
- self.deleted = true;
630
- if (!!self.abortController) { // abort tile request
631
- self.abortController.abort("tile not needed");
632
- self.abortController = new AbortController();
633
- }
634
- for (let i = self.meshContent.length - 1; i >= 0; i--) {
635
- const mc = self.meshContent[i];
636
- if (!!mc &amp;&amp; !!mc.asset &amp;&amp; mc.asset.copyright) {
637
- mc.asset.copyright.split(';').forEach(s => {
638
- if (!!copyright[s]) {
639
- copyright[s]--;
640
- }
641
- });
642
- if (self.displayCopyright) {
643
- _updateCopyrightLabel();
644
- }
645
- }
646
-
647
- self.remove(mc);
648
- }
649
- self.meshContent = [];
650
- self.contentURL.forEach(url => {
651
- //console.log(url)
652
- self.tileLoader.invalidate(url, self.uuid);
653
- })
654
- self.contentURL = [];
655
-
656
- }
657
- _disposeChildren() {
658
- var self = this;
659
-
660
- self.childrenTiles.forEach(tile => {
661
- tile.dispose();
662
- self.remove(tile)
663
- });
664
- self.childrenTiles = [];
665
- /* self.children = [];
666
- if (self.meshContent.length > 0) {
667
- self.meshContent.forEach(mc => {
668
- self.children.push(mc);
669
- });
670
- } */
671
- }
672
-
673
- /**
674
- * To be called in the render loop.
675
- * @param {THREE.Camera} camera a camera that the tileset will be rendered with.
676
- * @returns {{numTilesLoaded: number, numTilesRendered: number, maxLOD: number, percentageLoaded: number}} An object containing describing the current state of the loaded tileset.
677
- */
678
- update(camera) {
679
-
680
- const frustum = new THREE.Frustum();
681
- frustum.setFromProjectionMatrix(new THREE.Matrix4().multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse));
682
- let numTiles = [0];
683
- let numTilesRendered = [0];
684
- let maxLOD = [0];
685
- let percentageLoaded = [0];
686
- if (this.refine == "REPLACE") {
687
- switch (this.loadingStrategy) {
688
- case "IMMEDIATE": this._updateImmediate(camera, frustum); this._statsImmediate(maxLOD, numTiles, percentageLoaded, numTilesRendered); break;
689
- default: this._update(camera, frustum); this._stats(maxLOD, numTiles, percentageLoaded, numTilesRendered);
690
- }
691
- } else {
692
- this._update(camera, frustum);
693
- this._stats(maxLOD, numTiles, percentageLoaded, numTilesRendered);
694
- }
695
-
696
- if (numTiles > 0) {
697
- percentageLoaded[0] /= numTiles[0];
698
- }
699
- //console.log(maxLOD);
700
- return { numTilesLoaded: numTiles[0], numTilesRendered: numTilesRendered[0], maxLOD: maxLOD[0], percentageLoaded: percentageLoaded[0] }
701
- }
702
-
703
- _updateImmediate(camera, frustum) {
704
- this._computeMetricRecursive(camera, frustum);
705
- this._updateNodeVisibilityImmediate();
706
- this._expandTreeImmediate(camera);
707
- this.shouldBeVisible = this.metric > 0 ? true : !!this.loadOutsideView;
708
- this._shouldBeVisibleUpdateImmediate();
709
- this._trimTreeImmediate();
710
- this._loadMeshImmediate();
711
-
712
-
713
- }
714
-
715
-
716
- _statsImmediate(maxLOD, numTiles, percentageLoaded, numTilesRendered) {
717
- maxLOD[0] = Math.max(maxLOD[0], this.level);
718
- if (this.shouldBeVisible || !!this.materialVisibility) {
719
- numTiles[0]++;
720
- if (!!this.materialVisibility) percentageLoaded[0]++;
721
- }
722
- if (!!this.materialVisibility) numTilesRendered[0]++;
723
-
724
-
725
- this.childrenTiles.forEach(child => {
726
- child._statsImmediate(maxLOD, numTiles, percentageLoaded, numTilesRendered);
727
- })
728
- }
729
- _stats(maxLOD, numTiles, percentageLoaded, numTilesRendered) {
730
- maxLOD[0] = Math.max(maxLOD[0], this.level);
731
- if (this.hasMeshContent) {
732
- numTiles[0]++;
733
- if (this.meshContent.length == this.hasMeshContent) percentageLoaded[0]++;
734
- if (!!this.materialVisibility) numTilesRendered[0]++;
735
- }
736
-
737
-
738
- this.childrenTiles.forEach(child => {
739
- child._stats(maxLOD, numTiles, percentageLoaded, numTilesRendered);
740
- })
741
- }
742
-
743
-
744
-
745
- _trimTreeImmediate() {
746
- if (this.metric == undefined) return;
747
-
748
- else if (this.hasMeshContent &amp;&amp; ((this.shouldBeVisible &amp;&amp; this.materialVisibility))) {
749
- this._disposeChildren();
750
- } else {
751
- this.childrenTiles.forEach(child => {
752
- child._trimTreeImmediate();
753
- })
754
- }
755
-
756
- }
757
- _updateNodeVisibilityImmediate(parentDisplaysMesh = false) {
758
- //updateNodeVisibilityCount++;
759
-
760
- const self = this;
761
- if (!self.hasMeshContent) {
762
- self.childrenTiles.forEach(child => {
763
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
764
- })
765
- return;
766
- }
767
-
768
- if (self.shouldBeVisible) {
769
- if (self.meshContent.length == self.hasMeshContent) {
770
- if (!self.materialVisibility) {
771
- self._changeContentVisibility(true);
772
- self.childrenTiles.forEach(child => {
773
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
774
- })
775
- } else {
776
- self.childrenTiles.forEach(child => {
777
- child._updateNodeVisibilityImmediate(true);
778
- })
779
- }
780
-
781
- } else {
782
- self.childrenTiles.forEach(child => {
783
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
784
- })
785
- }
786
- } else {
787
- if (!self.loadOutsideView &amp;&amp; self.metric &lt; 0) {
788
- self._changeContentVisibility(false);
789
- if (self.meshContent.length > 0) self._disposeMeshContent();
790
- self.childrenTiles.forEach(child => {
791
- child._updateNodeVisibilityImmediate(true);
792
- })
793
- return;
794
- }
795
-
796
- if (self.materialVisibility) {
797
-
798
- if (parentDisplaysMesh) {
799
- self._changeContentVisibility(false);
800
- if (self.meshContent.length > 0) self._disposeMeshContent();
801
- self.childrenTiles.forEach(child => {
802
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
803
- })
804
- } else {
805
- let allChildrenReady = true;
806
- self.childrenTiles.every(child => {
807
-
808
- if (!child._isReadyImmediate()) {
809
- allChildrenReady = false;
810
- return false;
811
- }
812
- return true;
813
- });
814
- if (allChildrenReady &amp;&amp; self.childrenTiles.length > 0) {
815
- self._changeContentVisibility(false);
816
- if (self.meshContent.length > 0) self._disposeMeshContent();
817
- self.childrenTiles.forEach(child => {
818
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
819
- })
820
- } else {
821
-
822
- self.childrenTiles.forEach(child => {
823
- child._updateNodeVisibilityImmediate(true);
824
- })
825
- }
826
- }
827
-
828
- } else {
829
-
830
- self.childrenTiles.forEach(child => {
831
- child._updateNodeVisibilityImmediate(parentDisplaysMesh);
832
- })
833
- }
834
- }
835
-
836
-
837
-
838
- }
839
- _shouldBeVisibleUpdateImmediate() {
840
- const self = this;
841
- if (!self.hasMeshContent) {
842
-
843
- self.childrenTiles.forEach(child => {
844
- child.shouldBeVisible = true;
845
- child._shouldBeVisibleUpdateImmediate();
846
- })
847
- self.shouldBeVisible = false;
848
-
849
- }
850
- else if (self.metric == undefined) {
851
- self.shouldBeVisible = false;
852
- }
853
- else if (self.metric &lt; 0) {
854
- self.shouldBeVisible = !!self.loadOutsideView;
855
- self.childrenTiles.forEach(child => {
856
- child._setShouldNotBeVisibleRecursive();
857
- });
858
- }
859
- else if (self.metric &lt; self.geometricErrorMultiplier * self.geometricError) {
860
- if (self.hasUnloadedJSONContent) {
861
- //self.shouldBeVisible = true;
862
-
863
- } else {
864
- if (!!self.json &amp;&amp; !!self.json.children &amp;&amp; self.json.children.length > 0) {
865
- self.shouldBeVisible = false;
866
- self.childrenTiles.forEach(child => {
867
- child.shouldBeVisible = true;
868
- child._shouldBeVisibleUpdateImmediate();
869
- })
870
-
871
- } else {
872
- self.shouldBeVisible = true;
873
-
874
- }
875
- }
876
-
877
- } else {
878
-
879
- self.childrenTiles.forEach(child => {
880
- child._setShouldNotBeVisibleRecursive();
881
- });
882
- }
883
- }
884
-
885
- _setShouldNotBeVisibleRecursive() {
886
- const self = this;
887
- self.shouldBeVisible = false;
888
- self.childrenTiles.forEach(child => {
889
- child._setShouldNotBeVisibleRecursive();
890
- })
891
- }
892
- _loadMeshImmediate() {
893
- const self = this;
894
- if (!self.hasMeshContent) {
895
- self.childrenTiles.forEach(child => {
896
- child._loadMeshImmediate();
897
- });
898
- return;
899
- }
900
- if (self.shouldBeVisible) {
901
- if (self.meshContent.length &lt; self.hasMeshContent &amp;&amp;
902
- self.contentURL.length == 0) {
903
-
904
- self.deleted = false;
905
-
906
- self._load(false, true);
907
- }
908
- } else {
909
- self.childrenTiles.forEach(child => {
910
- child._loadMeshImmediate();
911
- })
912
- }
913
-
914
- }
915
-
916
- _computeMetricRecursive(camera, frustum) {
917
- const self = this;
918
- self.metric = -1;
919
- if (!self.isSetup) return;
920
-
921
- if (!!self.boundingVolume &amp;&amp; !!self.geometricError) {
922
- self.metric = self._calculateUpdateMetric(camera, frustum);
923
- }
924
- self.childrenTiles.forEach(child => child._computeMetricRecursive(camera, frustum));
925
-
926
-
927
- }
928
-
929
-
930
- _expandTreeImmediate(camera) {
931
- const self = this;
932
-
933
- if (!self.hasUnloadedJSONContent) {
934
- if (!self.hasMeshContent) {
935
- if (!!self.json &amp;&amp; !!self.json.children &amp;&amp; self.childrenTiles.length &lt; self.json.children.length) {
936
- self._loadJsonChildren(camera);
937
-
938
- }
939
- } else {
940
- if (self.occlusionCullingService &amp;&amp; self.hasMeshContent &amp;&amp; !self.occlusionCullingService.hasID(self.colorID)) {
941
- // don't load children
942
- } else {
943
- if (self.metric >= 0 &amp;&amp; self.metric &lt; self.geometricErrorMultiplier * self.geometricError &amp;&amp;
944
- !!self.json &amp;&amp; !!self.json.children &amp;&amp; self.childrenTiles.length &lt; self.json.children.length
945
- ) {
946
- self._loadJsonChildren(camera);
947
- }
948
- }
949
- }
950
-
951
- }
952
-
953
- self.childrenTiles.forEach(child => child._expandTreeImmediate(camera));
954
- }
955
-
956
-
957
- _update(camera, frustum) {
958
- const self = this;
959
-
960
- if (!self.isSetup) return;
961
- // let dist = self.boundingVolume.distanceToPoint(new THREE.Vector3(3980, 4980.416656099139, 3.2851604304346775));
962
- // if (dist&lt; 1) {
963
- // self._changeContentVisibility(false);
964
- // console.log(dist+" "+self.level)
965
- // }
966
- const visibilityBeforeUpdate = self.materialVisibility;
967
-
968
- if (!!self.boundingVolume &amp;&amp; !!self.geometricError) {
969
- self.metric = self._calculateUpdateMetric(camera, frustum);
970
- }
971
- self.childrenTiles.forEach(child => child._update(camera, frustum));
972
-
973
- _updateNodeVisibility(self.metric);
974
- _updateTree(self.metric);
975
- _trimTree(self.metric, visibilityBeforeUpdate);
976
-
977
-
978
-
979
- function _updateTree(metric) {
980
- // If this tile does not have mesh content but it has children
981
- if (metric &lt; 0 &amp;&amp; self.hasMeshContent) return;
982
- if (self.occlusionCullingService &amp;&amp; self.hasMeshContent &amp;&amp; !self.occlusionCullingService.hasID(self.colorID)) {
983
- return;
984
- }
985
- if (!self.hasMeshContent || (metric &lt;= self.geometricErrorMultiplier * self.geometricError &amp;&amp; self.meshContent.length > 0)) {
986
- if (!!self.json &amp;&amp; !!self.json.children &amp;&amp; self.childrenTiles.length != self.json.children.length) {
987
- self._loadJsonChildren(camera);
988
- return;
989
- }
990
- }
991
- }
992
-
993
-
994
- function _updateNodeVisibility(metric) {
995
-
996
- //doesn't have a mesh content
997
- if (!self.hasMeshContent) return;
998
-
999
- // mesh content not yet loaded
1000
- if (self.meshContent.length &lt; self.hasMeshContent) {
1001
- return;
1002
- }
1003
-
1004
-
1005
- // outside frustum
1006
- if (metric &lt; 0) {
1007
- self.inFrustum = false;
1008
- self._changeContentVisibility(!!self.loadOutsideView);
1009
- return;
1010
- } else {
1011
- self.inFrustum = true;
1012
- }
1013
-
1014
- // has no children
1015
- if (self.childrenTiles.length == 0) {
1016
- self._changeContentVisibility(true);
1017
- return;
1018
- }
1019
-
1020
- // has children
1021
- if (metric >= self.geometricErrorMultiplier * self.geometricError) { // Ideal LOD or before this lod
1022
-
1023
- self._changeContentVisibility(true);
1024
- } else if (metric &lt; self.geometricErrorMultiplier * self.geometricError) { // Ideal LOD is past this one
1025
- // if children are visible and have been displayed, can be hidden
1026
- if (self.refine == "REPLACE") {
1027
- let allChildrenReady = true;
1028
- self.childrenTiles.every(child => {
1029
-
1030
- if (!child._isReady()) {
1031
- allChildrenReady = false;
1032
- return false;
1033
- }
1034
- return true;
1035
- });
1036
- if (allChildrenReady) {
1037
- self._changeContentVisibility(false);
1038
- }
1039
- else {
1040
- self._changeContentVisibility(true);
1041
- }
1042
- }
1043
-
1044
-
1045
- }
1046
- }
1047
-
1048
-
1049
-
1050
- function _trimTree(metric, visibilityBeforeUpdate) {
1051
- if (!self.hasMeshContent) return;
1052
- if (!self.inFrustum) { // outside frustum
1053
- self._disposeChildren();
1054
- //_updateNodeVisibility(metric);
1055
- return;
1056
- }
1057
- if (self.occlusionCullingService &amp;&amp;
1058
- !visibilityBeforeUpdate &amp;&amp;
1059
- self.hasMeshContent &amp;&amp;
1060
- self.meshContent.length > 0 &amp;&amp;
1061
- self.materialVisibility &amp;&amp;
1062
- self._areAllChildrenLoadedAndHidden()) {
1063
-
1064
- self._disposeChildren();
1065
- //_updateNodeVisibility(metric);
1066
- return;
1067
- }
1068
- if (metric >= self.geometricErrorMultiplier * self.geometricError) {
1069
- self._disposeChildren();
1070
- //_updateNodeVisibility(metric);
1071
- return;
1072
- }
1073
-
1074
- }
1075
-
1076
-
1077
-
1078
- }
1079
-
1080
- _loadJsonChildren(camera) {
1081
- const self = this;
1082
- for (let i = self.json.children.length - 1; i >= 0; i--) {
1083
- if (!self.json.children[i].root &amp;&amp; !self.json.children[i].children &amp;&amp; !self.json.children[i].getChildren &amp;&amp; !self.json.children[i].content &amp;&amp; !self.json.children[i].contents) {
1084
- self.json.children.splice(i, 1);
1085
- }
1086
- }
1087
- self.json.children.forEach(childJSON => {
1088
-
1089
- let childTile = new OGC3DTile({
1090
- parentTile: self,
1091
- queryParams: self.queryParams,
1092
- parentGeometricError: self.geometricError,
1093
- parentBoundingVolume: self.boundingVolume,
1094
- parentRefine: self.refine,
1095
- json: childJSON,
1096
- rootPath: self.rootPath,
1097
- geometricErrorMultiplier: self.geometricErrorMultiplier,
1098
- loadOutsideView: self.loadOutsideView,
1099
- level: self.level + 1,
1100
- tileLoader: self.tileLoader,
1101
- cameraOnLoad: camera,
1102
- occlusionCullingService: self.occlusionCullingService,
1103
- renderer: self.renderer,
1104
- static: self.static,
1105
- centerModel: false,
1106
- displayErrors: self.displayErrors,
1107
- displayCopyright: self.displayCopyright,
1108
- distanceBias: self.distanceBias,
1109
- loadingStrategy: self.loadingStrategy,
1110
- drawBoundingVolume: self.drawBoundingVolume
1111
- });
1112
- self.childrenTiles.push(childTile);
1113
- self.add(childTile);
1114
- });
1115
- self.updateMatrices(true);
1116
- }
1117
-
1118
- _areAllChildrenLoadedAndHidden() {
1119
- let allLoadedAndHidden = true;
1120
- const self = this;
1121
- this.childrenTiles.every(child => {
1122
- if (child.hasMeshContent) {
1123
- if (child.childrenTiles.length > 0) {
1124
- allLoadedAndHidden = false;
1125
- return false;
1126
- }
1127
- if (!child.metric &lt; 0) {
1128
- return true;
1129
- };
1130
- if (child.materialVisibility) {
1131
- allLoadedAndHidden = false;
1132
- return false;
1133
- } else if (self.occlusionCullingService.hasID(child.colorID)) {
1134
- allLoadedAndHidden = false;
1135
- return false;
1136
- }
1137
- } else {
1138
- if (!child._areAllChildrenLoadedAndHidden()) {
1139
- allLoadedAndHidden = false;
1140
- return false;
1141
- }
1142
- }
1143
- return true;
1144
- });
1145
- return allLoadedAndHidden;
1146
- }
1147
-
1148
- /**
1149
- * Node is ready if it is outside frustum, if it was drawn at least once or if all it's children are ready
1150
- * @returns true if ready
1151
- */
1152
- _isReady() {
1153
-
1154
- // if outside frustum
1155
- if (this.metric == undefined) {
1156
- return false;
1157
- }
1158
- if (this.metric &lt; 0) {
1159
- return true;
1160
- }
1161
- // if json is not done loading
1162
- if (this.hasUnloadedJSONContent) {
1163
- return false;
1164
- }
1165
- // if empty tile
1166
- if(!this.hasMeshContent &amp;&amp; this.json.children.length == 0 &amp;&amp; !this.hasUnloadedJSONContent){
1167
- return true;
1168
- }
1169
- // if this tile has no mesh content or if it's marked as visible false, look at children
1170
- if ((!this.hasMeshContent || this.meshContent.length == 0 || !this.materialVisibility)) {
1171
- if (this.children.length > 0) {
1172
- var allChildrenReady = true;
1173
- this.childrenTiles.every(child => {
1174
- if (!child._isReady()) {
1175
- allChildrenReady = false;
1176
- return false;
1177
- }
1178
- return true;
1179
- });
1180
- return allChildrenReady;
1181
- } else {
1182
- return false
1183
- }
1184
-
1185
- }
1186
-
1187
-
1188
- // if this tile has no mesh content
1189
- if (!this.hasMeshContent) {
1190
- return true;
1191
- }
1192
- // if mesh content not yet loaded
1193
- if (this.meshContent.length &lt; this.hasMeshContent) {
1194
- return false;
1195
- }
1196
-
1197
- // if this tile has been marked to hide it's content
1198
- if (this.materialVisibility) {
1199
- return true;
1200
- }
1201
-
1202
-
1203
-
1204
- return false;
1205
-
1206
- }
1207
-
1208
- _isReadyImmediate() {
1209
-
1210
- if (!!this.materialVisibility || (!this.loadOutsideView &amp;&amp; this.metric&lt;0)) {
1211
- return true;
1212
- } else {
1213
- if (this.childrenTiles.length > 0) {
1214
- var allChildrenReady = true;
1215
- this.childrenTiles.every(child => {
1216
- if (!child._isReadyImmediate()) {
1217
- allChildrenReady = false;
1218
- return false;
1219
- }
1220
- return true;
1221
- });
1222
- return allChildrenReady;
1223
- } else {
1224
- return false
1225
- }
1226
- }
1227
-
1228
-
1229
- }
1230
-
1231
-
1232
- _changeContentVisibility(visibility) {
1233
- const self = this;
1234
- if (self.bbox) {
1235
-
1236
- self.bbox.material.visible = visibility;
1237
- }
1238
- if (self.hasMeshContent &amp;&amp; self.meshContent.length > 0) {
1239
- if (visibility) {
1240
- self.meshContent.forEach(mc => {
1241
- mc.traverse((o) => {
1242
- if (o.isMesh || o.isPoints) {
1243
- o.layers.enable(0);
1244
- }
1245
- });
1246
- })
1247
-
1248
- } else {
1249
- self.meshContent.forEach(mc => {
1250
- mc.traverse((o) => {
1251
- if (o.isMesh || o.isPoints) {
1252
- o.layers.disable(0);
1253
- }
1254
- });
1255
- })
1256
-
1257
- }
1258
- }
1259
-
1260
- if (self.materialVisibility == visibility) {
1261
- return;
1262
- }
1263
- self.materialVisibility = visibility
1264
-
1265
-
1266
-
1267
- }
1268
- _calculateUpdateMetric(camera, frustum) {
1269
- ////// return -1 if not in frustum
1270
- let distance = 0;
1271
- if (this.boundingVolume instanceof OBB) {
1272
- // box
1273
- tempBox3.copy(this.boundingVolume.aabb);
1274
- tempBox3.applyMatrix4(this.matrixWorld);
1275
- if (!frustum.intersectsBox(tempBox3)) return -1;
1276
- distance = Math.max(0, tempBox3.distanceToPoint(camera.position) - camera.near);
1277
-
1278
- /* tempSphere.copy(this.boundingVolume.sphere);
1279
- tempSphere.applyMatrix4(this.matrixWorld);
1280
- if (!frustum.intersectsSphere(tempSphere)) return -1;
1281
- distance = Math.max(0, camera.position.distanceTo(tempSphere.center) - tempSphere.radius); */
1282
- } else if (this.boundingVolume instanceof THREE.Sphere) {
1283
- //sphere
1284
- tempSphere.copy(this.boundingVolume);
1285
- tempSphere.applyMatrix4(this.matrixWorld);
1286
- if (!frustum.intersectsSphere(tempSphere)) return -1;
1287
- distance = Math.max(0, camera.position.distanceTo(tempSphere.center) - tempSphere.radius - camera.near);
1288
- } else {
1289
- console.error("unsupported shape");
1290
- return -1
1291
-
1292
- }
1293
-
1294
- /////// Apply the bias factor to the distance
1295
- distance = Math.pow(distance, this.distanceBias);
1296
- /////// return metric based on geometric error and distance
1297
-
1298
-
1299
- if (distance == 0) {
1300
- return 0;
1301
- }
1302
- const scale = this.matrixWorld.getMaxScaleOnAxis();
1303
- if (!!this.renderer) {
1304
- this.renderer.getDrawingBufferSize(this.rendererSize);
1305
- }
1306
- let s = this.rendererSize.y;
1307
- let fov = camera.fov;
1308
- if (camera.aspect &lt; 1) {
1309
- fov *= camera.aspect;
1310
- s = this.rendererSize.x;
1311
- }
1312
-
1313
- let lambda = 2.0 * Math.tan(0.5 * fov * 0.01745329251994329576923690768489) * distance;
1314
-
1315
- return (window.devicePixelRatio * 16 * lambda) / (s * scale);
1316
- }
1317
-
1318
- _getSiblings() {
1319
- const self = this;
1320
- const tiles = [];
1321
- if (!self.parentTile) return tiles;
1322
- let p = self.parentTile;
1323
- while (!p.hasMeshContent &amp;&amp; !!p.parentTile) {
1324
- p = p.parentTile;
1325
- }
1326
- p.childrenTiles.forEach(child => {
1327
- if (!!child &amp;&amp; child != self) {
1328
- while (!child.hasMeshContent &amp;&amp; !!child.childrenTiles[0]) {
1329
- child = child.childrenTiles[0];
1330
- }
1331
- tiles.push(child);
1332
- }
1333
- });
1334
- return tiles;
1335
- }
1336
- _calculateDistanceToCamera(camera) {
1337
- if (this.boundingVolume instanceof OBB) {
1338
- // box
1339
- tempSphere.copy(this.boundingVolume.sphere);
1340
- tempSphere.applyMatrix4(this.matrixWorld);
1341
- //if (!frustum.intersectsSphere(tempSphere)) return -1;
1342
- } else if (this.boundingVolume instanceof THREE.Sphere) {
1343
- //sphere
1344
- tempSphere.copy(this.boundingVolume);
1345
- tempSphere.applyMatrix4(this.matrixWorld);
1346
- //if (!frustum.intersectsSphere(tempSphere)) return -1;
1347
- }
1348
- else {
1349
- console.error("unsupported shape")
1350
- }
1351
- return Math.max(0, camera.position.distanceTo(tempSphere.center) - tempSphere.radius);
1352
- }
1353
-
1354
- /**
1355
- * Set the Geometric Error Multiplier for the tileset.
1356
- * the {@param geometricErrorMultiplier} can be a number between 1 and infinity.
1357
- * A {@param geometricErrorMultiplier} of 1 (default) corresponds to a max ScreenSpace error (MSE) of 16.
1358
- * A lower {@param geometricErrorMultiplier} loads less detail (higher MSE) and a higher {@param geometricErrorMultiplier} loads more detail (lower MSE)
1359
- *
1360
- * @param {Number} geometricErrorMultiplier set the LOD multiplier for the entire tileset
1361
- */
1362
- setGeometricErrorMultiplier(geometricErrorMultiplier) {
1363
- this.geometricErrorMultiplier = geometricErrorMultiplier;
1364
- this.childrenTiles.forEach(child => child.setGeometricErrorMultiplier(geometricErrorMultiplier));
1365
- }
1366
-
1367
- /**
1368
- * Set the Distance Bias for the tileset.
1369
- * the {@param distanceBias} can be a number between 0 and infinity.
1370
- * A {@param distanceBias} is applied as an exponent to camera-to-tile distance.
1371
- * the {@link geometricErrorMultiplier} should be used to balance out the amount of detail loaded
1372
- *
1373
- * @param {Number} distanceBias set the distance bias for the entire tileset
1374
- */
1375
- setDistanceBias(distanceBias) {
1376
- this.distanceBias = distanceBias;
1377
- this.childrenTiles.forEach(child => child.setDistanceBias(distanceBias));
1378
- }
1379
-
1380
- _transformWGS84ToCartesian(lon, lat, h, sfct) {
1381
- const a = 6378137.0;
1382
- const e = 0.006694384442042;
1383
- const N = a / (Math.sqrt(1.0 - (e * Math.pow(Math.sin(lat), 2))));
1384
- const cosLat = Math.cos(lat);
1385
- const cosLon = Math.cos(lon);
1386
- const sinLat = Math.sin(lat);
1387
- const sinLon = Math.sin(lon);
1388
- const nPh = (N + h);
1389
- const x = nPh * cosLat * cosLon;
1390
- const y = nPh * cosLat * sinLon;
1391
- const z = (0.993305615557957 * N + h) * sinLat;
1392
-
1393
- sfct.set(x, y, z);
1394
- }
1395
- }
1396
- export { OGC3DTile, getOGC3DTilesCopyrightInfo };
1397
-
1398
- function _showError(error) {
1399
- // Create a new div element
1400
- var errorDiv = document.createElement("div");
1401
-
1402
- // Set its text content
1403
- errorDiv.textContent = error;
1404
-
1405
- // Set styles
1406
- errorDiv.style.position = 'fixed'; // Fix position to the viewport
1407
- errorDiv.style.top = '10px'; // Set top position
1408
- errorDiv.style.left = '50%'; // Center horizontally
1409
- errorDiv.style.transform = 'translateX(-50%)'; // Make sure it's centered accurately
1410
- errorDiv.style.padding = '10px'; // Add some padding
1411
- errorDiv.style.backgroundColor = '#ff8800'; // Set a background color
1412
- errorDiv.style.color = '#ffffff'; // Set a text color
1413
- errorDiv.style.zIndex = '9999'; // Make sure it's on top of other elements
1414
-
1415
- // Append the new div to the body
1416
- document.body.appendChild(errorDiv);
1417
-
1418
- // After 3 seconds, remove the error message
1419
- setTimeout(function () {
1420
- errorDiv.remove();
1421
- }, 8000);
1422
- }
1423
-
1424
- function _updateCopyrightLabel() {
1425
- // Create a new div
1426
- if (!copyrightDiv) {
1427
- copyrightDiv = document.createElement('div');
1428
- copyrightDiv.style.position = 'fixed';
1429
- copyrightDiv.style.bottom = '20px';
1430
- copyrightDiv.style.left = '20px';
1431
- copyrightDiv.style.color = 'white';
1432
- copyrightDiv.style.textShadow = '2px 2px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000';
1433
- copyrightDiv.style.padding = '10px';
1434
- copyrightDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.1)'; // semi-transparent black background
1435
-
1436
- // Append the div to the body of the document
1437
- document.body.appendChild(copyrightDiv);
1438
- }
1439
-
1440
- // Set the text content of the div
1441
- const list = getOGC3DTilesCopyrightInfo();
1442
- let listString = "";
1443
- list.forEach(item=>{
1444
- listString += item + ", ";
1445
- });
1446
- listString =listString.slice(0, -2);
1447
-
1448
- copyrightDiv.textContent = listString
1449
- // Style the div
1450
-
1451
- }</code></pre></article></section></div></div></div><div class="search-container" id="PkfLWpAbet" style="display:none"><div class="wrapper" id="iCxFxjkHbP"><button class="icon-button search-close-button" id="VjLlGakifb" aria-label="close search"><svg><use xlink:href="#close-icon"></use></svg></button><div class="search-box-c"><svg><use xlink:href="#search-icon"></use></svg> <input type="text" id="vpcKVYIppa" class="search-input" placeholder="Search..." autofocus></div><div class="search-result-c" id="fWwVHRuDuN"><span class="search-result-c-text">Type anything to view search result</span></div></div></div><div class="mobile-menu-icon-container"><button class="icon-button" id="mobile-menu" data-isopen="false" aria-label="menu"><svg><use xlink:href="#menu-icon"></use></svg></button></div><div id="mobile-sidebar" class="mobile-sidebar-container"><div class="mobile-sidebar-wrapper"><div class="mobile-nav-links"></div><div class="mobile-sidebar-items-c"><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-classes"><div>Classes</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="InstancedOGC3DTile.html">InstancedOGC3DTile</a></div><div class="sidebar-section-children"><a href="InstancedTile.html">InstancedTile</a></div><div class="sidebar-section-children"><a href="InstancedTileLoader.html">InstancedTileLoader</a></div><div class="sidebar-section-children"><a href="OGC3DTile.html">OGC3DTile</a></div><div class="sidebar-section-children"><a href="OcclusionCullingService.html">OcclusionCullingService</a></div><div class="sidebar-section-children"><a href="TileLoader.html">TileLoader</a></div></div><div class="sidebar-section-title with-arrow" data-isopen="false" id="sidebar-global"><div>Global</div><svg><use xlink:href="#down-icon"></use></svg></div><div class="sidebar-section-children-container"><div class="sidebar-section-children"><a href="global.html#getOGC3DTilesCopyrightInfo">getOGC3DTilesCopyrightInfo</a></div></div></div><div class="mobile-navbar-actions"><div class="navbar-right-item"><button class="icon-button search-button" aria-label="open-search"><svg><use xlink:href="#search-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button theme-toggle" aria-label="toggle-theme"><svg><use class="theme-svg-use" xlink:href="#light-theme-icon"></use></svg></button></div><div class="navbar-right-item"><button class="icon-button font-size" aria-label="change-font-size"><svg><use xlink:href="#font-size-icon"></use></svg></button></div></div></div></div><script type="text/javascript" src="scripts/core.min.js"></script><script src="scripts/search.min.js" defer="defer"></script><script src="scripts/third-party/fuse.js" defer="defer"></script><script type="text/javascript">var tocbotInstance=tocbot.init({tocSelector:"#eed4d2a0bfd64539bb9df78095dec881",contentSelector:".main-content",headingSelector:"h1, h2, h3",hasInnerContainers:!0,scrollContainer:".main-content",headingsOffset:130,onClick:bringLinkToView})</script></body></html>