@shapediver/viewer.rendering-engine.rendering-engine-threejs 3.15.11 → 3.16.0

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 (78) hide show
  1. package/dist/RenderingEngine.d.ts +4 -2
  2. package/dist/RenderingEngine.d.ts.map +1 -1
  3. package/dist/RenderingEngine.js +4 -0
  4. package/dist/RenderingEngine.js.map +1 -1
  5. package/dist/index.d.ts +4 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +7 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/interfaces/IRenderingEngine.d.ts +2 -1
  10. package/dist/interfaces/IRenderingEngine.d.ts.map +1 -1
  11. package/dist/loaders/GeometryLoader.d.ts +6 -4
  12. package/dist/loaders/GeometryLoader.d.ts.map +1 -1
  13. package/dist/loaders/GeometryLoader.js +162 -108
  14. package/dist/loaders/GeometryLoader.js.map +1 -1
  15. package/dist/loaders/HTMLElementAnchorLoader.d.ts +1 -2
  16. package/dist/loaders/HTMLElementAnchorLoader.d.ts.map +1 -1
  17. package/dist/loaders/HTMLElementAnchorLoader.js.map +1 -1
  18. package/dist/loaders/LightLoader.d.ts +4 -3
  19. package/dist/loaders/LightLoader.d.ts.map +1 -1
  20. package/dist/loaders/LightLoader.js +8 -0
  21. package/dist/loaders/LightLoader.js.map +1 -1
  22. package/dist/loaders/MaterialLoader.d.ts +15 -2
  23. package/dist/loaders/MaterialLoader.d.ts.map +1 -1
  24. package/dist/loaders/MaterialLoader.js +124 -61
  25. package/dist/loaders/MaterialLoader.js.map +1 -1
  26. package/dist/managers/CameraManager.d.ts +2 -2
  27. package/dist/managers/CameraManager.d.ts.map +1 -1
  28. package/dist/managers/CameraManager.js +25 -5
  29. package/dist/managers/CameraManager.js.map +1 -1
  30. package/dist/managers/EnvironmentGeometryManager.d.ts.map +1 -1
  31. package/dist/managers/EnvironmentGeometryManager.js +6 -19
  32. package/dist/managers/EnvironmentGeometryManager.js.map +1 -1
  33. package/dist/managers/PostProcessingManager.d.ts.map +1 -1
  34. package/dist/managers/PostProcessingManager.js +18 -1
  35. package/dist/managers/PostProcessingManager.js.map +1 -1
  36. package/dist/managers/RenderingManager.d.ts.map +1 -1
  37. package/dist/managers/RenderingManager.js +6 -1
  38. package/dist/managers/RenderingManager.js.map +1 -1
  39. package/dist/managers/SceneTracingManager.d.ts.map +1 -1
  40. package/dist/managers/SceneTracingManager.js +2 -0
  41. package/dist/managers/SceneTracingManager.js.map +1 -1
  42. package/dist/managers/SceneTreeManager.d.ts +40 -11
  43. package/dist/managers/SceneTreeManager.d.ts.map +1 -1
  44. package/dist/managers/SceneTreeManager.js +304 -247
  45. package/dist/managers/SceneTreeManager.js.map +1 -1
  46. package/dist/managers/environmentGeometry/ContactShadow.d.ts.map +1 -1
  47. package/dist/managers/environmentGeometry/ContactShadow.js +2 -2
  48. package/dist/managers/environmentGeometry/ContactShadow.js.map +1 -1
  49. package/dist/managers/environmentGeometry/Grid.d.ts.map +1 -1
  50. package/dist/managers/environmentGeometry/Grid.js +2 -2
  51. package/dist/managers/environmentGeometry/Grid.js.map +1 -1
  52. package/dist/managers/environmentGeometry/GroundPlane.d.ts.map +1 -1
  53. package/dist/managers/environmentGeometry/GroundPlane.js +4 -3
  54. package/dist/managers/environmentGeometry/GroundPlane.js.map +1 -1
  55. package/dist/managers/environmentGeometry/GroundPlaneShadow.d.ts.map +1 -1
  56. package/dist/managers/environmentGeometry/GroundPlaneShadow.js +4 -4
  57. package/dist/managers/environmentGeometry/GroundPlaneShadow.js.map +1 -1
  58. package/dist/managers/sceneTree/SDTFUtils.d.ts +2 -2
  59. package/dist/managers/sceneTree/SDTFUtils.d.ts.map +1 -1
  60. package/dist/managers/sceneTree/SDTFUtils.js +6 -6
  61. package/dist/managers/sceneTree/SDTFUtils.js.map +1 -1
  62. package/dist/managers/sceneTree/SceenTreeManagerUtils.d.ts +3 -5
  63. package/dist/managers/sceneTree/SceenTreeManagerUtils.d.ts.map +1 -1
  64. package/dist/managers/sceneTree/SceenTreeManagerUtils.js +24 -32
  65. package/dist/managers/sceneTree/SceenTreeManagerUtils.js.map +1 -1
  66. package/dist/objects/SDObject.d.ts +15 -1
  67. package/dist/objects/SDObject.d.ts.map +1 -1
  68. package/dist/objects/SDObject.js +26 -4
  69. package/dist/objects/SDObject.js.map +1 -1
  70. package/package.json +17 -17
  71. package/dist/objects/SDBone.d.ts +0 -13
  72. package/dist/objects/SDBone.d.ts.map +0 -1
  73. package/dist/objects/SDBone.js +0 -75
  74. package/dist/objects/SDBone.js.map +0 -1
  75. package/dist/objects/SDData.d.ts +0 -19
  76. package/dist/objects/SDData.d.ts.map +0 -1
  77. package/dist/objects/SDData.js +0 -48
  78. package/dist/objects/SDData.js.map +0 -1
@@ -24,44 +24,36 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.SceneTreeManager = void 0;
27
+ const THREE = __importStar(require("three"));
27
28
  const viewer_rendering_engine_camera_engine_1 = require("@shapediver/viewer.rendering-engine.camera-engine");
28
29
  const viewer_rendering_engine_light_engine_1 = require("@shapediver/viewer.rendering-engine.light-engine");
29
30
  const viewer_shared_math_1 = require("@shapediver/viewer.shared.math");
30
31
  const viewer_shared_node_tree_1 = require("@shapediver/viewer.shared.node-tree");
31
- const viewer_shared_services_1 = require("@shapediver/viewer.shared.services");
32
32
  const viewer_shared_types_1 = require("@shapediver/viewer.shared.types");
33
+ const viewer_shared_services_1 = require("@shapediver/viewer.shared.services");
33
34
  const gl_matrix_1 = require("gl-matrix");
34
- const THREE = __importStar(require("three"));
35
- const SDBone_1 = require("../objects/SDBone");
36
- const SDData_1 = require("../objects/SDData");
37
35
  const SDObject_1 = require("../objects/SDObject");
38
36
  const ThreejsData_1 = require("../types/ThreejsData");
39
37
  const SceenTreeManagerUtils_1 = require("./sceneTree/SceenTreeManagerUtils");
40
38
  const SDTFUtils_1 = require("./sceneTree/SDTFUtils");
41
39
  const ThreeJsDataUtils_1 = require("./sceneTree/ThreeJsDataUtils");
42
- // #endregion Type aliases (1)
43
- // #region Classes (1)
44
40
  class SceneTreeManager {
45
- // #endregion Properties (12)
46
- // #region Constructors (1)
47
41
  constructor(_renderingEngine) {
48
42
  this._renderingEngine = _renderingEngine;
49
- // #region Properties (12)
50
43
  this._eventEngine = viewer_shared_services_1.EventEngine.instance;
51
- this._inputValidator = viewer_shared_services_1.InputValidator.instance;
44
+ this._performanceEvaluator = viewer_shared_services_1.PerformanceEvaluator.instance;
52
45
  this._scene = new THREE.Scene();
53
46
  this._stateEngine = viewer_shared_services_1.StateEngine.instance;
54
47
  this._tree = viewer_shared_node_tree_1.Tree.instance;
55
48
  this._boundingBox = new viewer_shared_math_1.Box();
56
- this._boundingBoxSensitiveData = [];
49
+ this._directionalLightData = [];
57
50
  this._hiddenCamera = new THREE.PerspectiveCamera();
58
51
  this._lastRendererType = viewer_shared_types_1.RENDERER_TYPE.STANDARD;
59
52
  this._lastRootVersion = "";
53
+ this._newRendererType = false;
60
54
  this._suspendSceneUpdates = false;
61
55
  this._scene.background = new THREE.Color("#ffffff");
62
56
  }
63
- // #endregion Constructors (1)
64
- // #region Public Getters And Setters (4)
65
57
  get boundingBox() {
66
58
  return this._boundingBox;
67
59
  }
@@ -72,7 +64,7 @@ class SceneTreeManager {
72
64
  return this._lastRootVersion;
73
65
  }
74
66
  get mainNode() {
75
- return this._mainNode;
67
+ return this._mainConvertedObject;
76
68
  }
77
69
  get scene() {
78
70
  return this._scene;
@@ -83,8 +75,6 @@ class SceneTreeManager {
83
75
  set suspendSceneUpdates(value) {
84
76
  this._suspendSceneUpdates = value;
85
77
  }
86
- // #endregion Public Getters And Setters (4)
87
- // #region Public Methods (6)
88
78
  init() { }
89
79
  /**
90
80
  * Convert the data of the scene graph node into the format of the implementation.
@@ -92,248 +82,165 @@ class SceneTreeManager {
92
82
  * @param data the data element
93
83
  * @param obj the corresponding type node
94
84
  */
95
- updateData(node, obj, data, filter, isVisibleInHierarchy, skeleton) {
85
+ updateData(treeNodeData, treeNode, convertedObject, filter = { transformationOnly: false }, isVisibleInHierarchy = true) {
96
86
  var _a;
97
- let dataChild = (obj.children.find((oc) => oc.SDid === data.id &&
98
- oc.SDversion === data.version));
99
- let newChild = false;
100
- if (!dataChild) {
101
- newChild = true;
102
- dataChild = new SDData_1.SDData(data.id, data.version);
103
- obj.add(dataChild);
104
- }
87
+ let dataChild;
105
88
  if (this._renderingEngine.type === viewer_shared_types_1.RENDERER_TYPE.ATTRIBUTES) {
106
- (0, SDTFUtils_1.injectAttributeData)(this._renderingEngine, this._currentSDTFOverview, node, data);
89
+ if (treeNodeData instanceof viewer_shared_node_tree_1.GeometryData) {
90
+ (0, SDTFUtils_1.injectAttributeData)(this._renderingEngine, this._currentSDTFOverview, treeNode, treeNodeData);
91
+ }
107
92
  }
108
93
  else {
109
- const sdtfTransform = node.getTransformation("sdtf");
94
+ const sdtfTransform = treeNode.getTransformation("sdtf");
110
95
  if (sdtfTransform)
111
- node.removeTransformation(sdtfTransform);
112
- if (data instanceof viewer_shared_types_1.GeometryData)
113
- data.attributeMaterial = null;
96
+ treeNode.removeTransformation(sdtfTransform);
97
+ if (treeNodeData instanceof viewer_shared_node_tree_1.GeometryData)
98
+ treeNodeData.attributeMaterial = null;
114
99
  }
115
100
  switch (true) {
116
- case data instanceof viewer_shared_types_1.GeometryData:
101
+ case treeNodeData instanceof viewer_shared_node_tree_1.GeometryData:
117
102
  {
118
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.GEOMETRY;
119
103
  // We search for the instance matrices data in the parent of our current node
120
104
  // We are currently at the primitive level and the instance matrices are stored at the mesh level
121
- const instanceTransformationData = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.data.find((d) => d instanceof viewer_shared_types_1.InstanceData);
122
- if (filter.transformationOnly === false)
123
- this._renderingEngine.geometryLoader.load(data, dataChild, newChild, skeleton, instanceTransformationData);
105
+ const instanceTransformationData = (_a = treeNode.parent) === null || _a === void 0 ? void 0 : _a.data.find((d) => d instanceof viewer_shared_node_tree_1.InstanceData);
106
+ if (filter.transformationOnly === false) {
107
+ dataChild = this._renderingEngine.geometryLoader.load(treeNodeData, instanceTransformationData);
108
+ // Three.js Object3Ds can only have one parent. If the
109
+ // same GeometryData is referenced by multiple tree nodes,
110
+ // the cache returns the same mesh each time. Adding it to
111
+ // a second node silently removes it from the first. Clone
112
+ // only when this would happen (different existing parent).
113
+ if (dataChild.parent !== null &&
114
+ dataChild.parent !== convertedObject) {
115
+ dataChild = dataChild.clone();
116
+ }
117
+ dataChild.userData.SDtype = SDObject_1.SD_DATA_TYPE.GEOMETRY;
118
+ dataChild.userData.SDid = treeNodeData.id;
119
+ dataChild.userData.SDversion = treeNodeData.version;
120
+ convertedObject.add(dataChild);
121
+ }
124
122
  }
125
123
  break;
126
- case data instanceof ThreejsData_1.ThreejsData:
124
+ case treeNodeData instanceof ThreejsData_1.ThreejsData:
127
125
  {
128
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.THREEJS;
129
- dataChild.add(data.obj);
126
+ dataChild = treeNodeData.obj;
127
+ treeNodeData.obj.userData.SDtype =
128
+ SDObject_1.SD_DATA_TYPE.THREEJS;
129
+ treeNodeData.obj.userData.SDid =
130
+ treeNodeData.id;
131
+ treeNodeData.obj.userData.SDversion =
132
+ treeNodeData.version;
133
+ convertedObject.add(dataChild);
130
134
  // set the currently used environment map
131
- (0, ThreeJsDataUtils_1.assignEnvironmentMapForThreeJsDataObject)(data, this._renderingEngine.environmentMapLoader
135
+ (0, ThreeJsDataUtils_1.assignEnvironmentMapForThreeJsDataObject)(treeNodeData, this._renderingEngine.environmentMapLoader
132
136
  .environmentMap, this._renderingEngine.environmentMapLoader.type, this._renderingEngine.environmentMapIntensity, this._renderingEngine.environmentMapRotation);
133
137
  }
134
138
  break;
135
- case data instanceof viewer_shared_types_1.AbstractMaterialData:
136
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.MATERIAL;
137
- break;
138
- case data instanceof viewer_rendering_engine_light_engine_1.AbstractLight:
139
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.LIGHT;
140
- if (filter.transformationOnly === false)
141
- this._renderingEngine.lightLoader.load(data, dataChild);
142
- if (data instanceof viewer_rendering_engine_light_engine_1.DirectionalLight &&
143
- data.useNodeData === false)
144
- this._boundingBoxSensitiveData.push({
145
- data: data,
146
- dataChild,
147
- });
148
- break;
149
- case data instanceof viewer_rendering_engine_camera_engine_1.AbstractCamera:
150
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.CAMERA;
151
- if (filter.transformationOnly === false)
152
- this._renderingEngine.cameraManager.load(data, dataChild);
139
+ case treeNodeData instanceof viewer_rendering_engine_light_engine_1.AbstractLight:
140
+ if (filter.transformationOnly === false) {
141
+ const threeLight = this._renderingEngine.lightLoader.load(treeNodeData, convertedObject);
142
+ if (threeLight) {
143
+ dataChild = threeLight;
144
+ dataChild.userData.SDtype = SDObject_1.SD_DATA_TYPE.LIGHT;
145
+ dataChild.userData.SDid = treeNodeData.id;
146
+ dataChild.userData.SDversion = treeNodeData.version;
147
+ }
148
+ }
149
+ if (treeNodeData instanceof viewer_rendering_engine_light_engine_1.DirectionalLight &&
150
+ treeNodeData.useNodeData === false)
151
+ this._directionalLightData.push(treeNodeData);
153
152
  break;
154
- case data instanceof viewer_shared_types_1.HTMLElementAnchorData:
155
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.HTML_ELEMENT_ANCHOR;
156
- if (filter.transformationOnly === false)
157
- this._renderingEngine.htmlElementAnchorLoader.load(node, data, isVisibleInHierarchy);
153
+ case treeNodeData instanceof viewer_rendering_engine_camera_engine_1.AbstractCamera:
154
+ if (filter.transformationOnly === false) {
155
+ const threeCamera = this._renderingEngine.cameraManager.load(treeNodeData, convertedObject);
156
+ if (threeCamera) {
157
+ dataChild = threeCamera;
158
+ dataChild.userData.SDtype = SDObject_1.SD_DATA_TYPE.CAMERA;
159
+ dataChild.userData.SDid = treeNodeData.id;
160
+ dataChild.userData.SDversion = treeNodeData.version;
161
+ }
162
+ }
158
163
  break;
159
- case data instanceof viewer_shared_types_1.AnimationData:
160
- dataChild.SDtype = SDData_1.SD_DATA_TYPE.ANIMATION;
164
+ case treeNodeData instanceof viewer_shared_node_tree_1.HTMLElementAnchorData:
165
+ if (filter.transformationOnly === false) {
166
+ this._renderingEngine.htmlElementAnchorLoader.load(treeNode, treeNodeData, isVisibleInHierarchy);
167
+ const existingAnchor = convertedObject.children.find((o) => !(o instanceof SDObject_1.SDObject) &&
168
+ o.userData.SDtype ===
169
+ SDObject_1.SD_DATA_TYPE.HTML_ELEMENT_ANCHOR &&
170
+ o.userData.SDid === treeNodeData.id &&
171
+ o.userData.SDversion === treeNodeData.version);
172
+ if (!existingAnchor) {
173
+ const dataChild = new THREE.Object3D();
174
+ dataChild.userData.SDtype =
175
+ SDObject_1.SD_DATA_TYPE.HTML_ELEMENT_ANCHOR;
176
+ dataChild.userData.SDid = treeNodeData.id;
177
+ dataChild.userData.SDversion = treeNodeData.version;
178
+ convertedObject.add(dataChild);
179
+ }
180
+ }
161
181
  break;
162
182
  default:
163
- // if there is no valid conversion here, call the convertData of the implementation
164
183
  break;
165
184
  }
166
- (0, SceenTreeManagerUtils_1.assignBoundingBox)(node, data, this._renderingEngine.id, dataChild, skeleton !== undefined);
185
+ if (dataChild)
186
+ (0, SceenTreeManagerUtils_1.assignBoundingBox)(treeNode, treeNodeData, this._renderingEngine.id, dataChild);
167
187
  }
168
188
  /**
169
189
  * Update the current node via the scene graph node.
170
190
  * Convert the data if needed.
171
191
  *
172
- * @param node the scene graph node
192
+ * @param treeNode the scene graph node
173
193
  * @param obj the current type object
174
194
  */
175
- updateNode(node = this._tree.root, obj, filter = { transformationOnly: false }, visibleInHierarchy = true, skeleton) {
195
+ updateNode(treeNode = this._tree.root, obj, filter = { transformationOnly: false }, visibleInHierarchy = true) {
196
+ // Resolve the converted object if not provided
176
197
  if (obj === undefined) {
177
- // check if there is a converted object
178
- if (node.convertedObject[this._renderingEngine.id]) {
179
- obj = node.convertedObject[this._renderingEngine.id];
180
- }
181
- else {
182
- // the node has not been converted yet
183
- // go up the hierarchy until a converted object is found
184
- let parent = node.parent;
185
- while (parent) {
186
- if (parent.convertedObject[this._renderingEngine.id]) {
187
- this.updateNode(parent, parent.convertedObject[this._renderingEngine.id], filter, visibleInHierarchy, skeleton);
188
- return;
189
- }
190
- else {
191
- parent = parent.parent;
192
- }
193
- }
194
- // no converted object found in the hierarchy
195
- // update the whole scene tree
196
- this.updateSceneTree(this._tree.root);
198
+ obj = this.resolveConvertedObject(treeNode, filter, visibleInHierarchy);
199
+ if (!obj)
197
200
  return;
198
- }
199
201
  }
200
202
  const convertedObject = obj;
201
- // reset the general bounding box of the current node
202
- // it will be recomputed in the following steps
203
- node.boundingBox.reset();
204
- // create the specific BB if it doesn't exist yet
205
- if (!node.boundingBoxViewport[this._renderingEngine.id])
206
- node.boundingBoxViewport[this._renderingEngine.id] = new viewer_shared_math_1.Box();
207
- // reset the specific bounding box of the current node
208
- // it will be recomputed in the following steps
209
- node.boundingBoxViewport[this._renderingEngine.id].reset();
203
+ // reset bounding boxes
204
+ this.resetBoundingBoxes(treeNode);
205
+ // cleanup obsolete data and children
210
206
  if (filter.transformationOnly === false) {
211
- // remove all data items that do not exist anymore
212
- const dataIds = node.data.map((d) => d.id);
213
- const dataToRemove = convertedObject.children.filter((oc) => {
214
- if (oc instanceof SDData_1.SDData) {
215
- if (dataIds.includes(oc.SDid)) {
216
- const data = node.data.find((d) => d.id === oc.SDid);
217
- if (data && data.version !== oc.SDversion) {
218
- // version is different
219
- return true;
220
- }
221
- else {
222
- return false;
223
- }
224
- }
225
- else {
226
- // id not included anymore
227
- return true;
228
- }
229
- }
230
- else {
231
- return false;
232
- }
233
- });
234
- dataToRemove.forEach((dTR) => {
235
- (0, SceenTreeManagerUtils_1.removeData)(this._renderingEngine, dTR);
236
- convertedObject.remove(dTR);
237
- });
238
- // remove all child nodes in the transformed object that do not exist anymore
239
- // the filter goes also through the data items as they were already added
240
- const nodeIds = node.children
241
- .filter((d) => !d.excludeViewports.includes(this._renderingEngine.id))
242
- .map((d) => d.id);
243
- const childrenToRemove = convertedObject.children.filter((oc) => {
244
- if (oc instanceof SDObject_1.SDObject && !(oc instanceof SDData_1.SDData)) {
245
- if (nodeIds.includes(oc.SDid)) {
246
- return false;
247
- }
248
- else {
249
- // id not included anymore
250
- return true;
251
- }
252
- }
253
- else {
254
- return false;
255
- }
256
- });
257
- childrenToRemove.forEach((cTR) => {
258
- cTR.traverse((o) => {
259
- if (o instanceof SDData_1.SDData)
260
- (0, SceenTreeManagerUtils_1.removeData)(this._renderingEngine, o);
261
- });
262
- convertedObject.remove(cTR);
263
- });
264
- }
265
- // create the skeleton if the node is marked as the skin node (root node of the skeleton)
266
- if (node.skinNode === true) {
267
- const bones = [];
268
- for (let i = 0; i < node.bones.length; i++)
269
- bones.push((0, SceenTreeManagerUtils_1.getBone)(this._mainNode, node.bones[i]));
270
- const boneInverses = [];
271
- for (let i = 0; i < node.boneInverses.length; i++)
272
- boneInverses.push(new THREE.Matrix4().fromArray(node.boneInverses[i]));
273
- skeleton = new THREE.Skeleton(bones, boneInverses);
207
+ this.cleanupObsoleteData(treeNode, convertedObject);
208
+ this.cleanupObsoleteChildren(treeNode, convertedObject);
274
209
  }
275
- const isVisible = node.visible &&
276
- !node.excludeViewports.includes(this._renderingEngine.id) &&
277
- !(node.restrictViewports.length > 0 &&
278
- !node.restrictViewports.includes(this._renderingEngine.id));
210
+ const isVisible = this.isNodeVisible(treeNode);
279
211
  const isVisibleInHierarchy = visibleInHierarchy && isVisible;
280
212
  // convert all data items of the current node
281
213
  // old versions will be replaced by new ones
282
- for (let i = 0, len = node.data.length; i < len; i++) {
283
- const convertedObjectData = (convertedObject.children.find((oc) => oc.SDid === node.data[i].id &&
284
- oc.SDversion === node.data[i].version));
285
- if (!convertedObjectData) {
286
- this.updateData(node, convertedObject, node.data[i], filter, isVisibleInHierarchy, skeleton);
287
- }
288
- else {
289
- (0, SceenTreeManagerUtils_1.assignBoundingBox)(node, node.data[i], this._renderingEngine.id, convertedObjectData, skeleton !== undefined);
214
+ // Create a lookup map for efficient access to converted children
215
+ const convertedChildrenMap = new Map();
216
+ for (const child of convertedObject.children) {
217
+ if (child instanceof SDObject_1.SDObject) {
218
+ convertedChildrenMap.set(child.SDid, child);
290
219
  }
291
220
  }
292
- // add new children and update the ones that have a different version
293
- for (let i = 0, len = node.children.length; i < len; i++) {
294
- const nodeChild = node.children[i];
295
- const objChild = (convertedObject.children.find((oc) => oc.SDid === nodeChild.id));
296
- if (!objChild) {
297
- const newChild = node.data.find((d) => d instanceof viewer_shared_types_1.BoneData)
298
- ? new SDBone_1.SDBone(nodeChild.id, nodeChild.version)
299
- : new SDObject_1.SDObject(nodeChild.id, nodeChild.version);
300
- const oldChild = nodeChild.convertedObject[this._renderingEngine.id];
301
- nodeChild.convertedObject[this._renderingEngine.id] = newChild;
302
- if (nodeChild.updateCallbackConvertedObject)
303
- nodeChild.updateCallbackConvertedObject(newChild, oldChild, this._renderingEngine.id);
304
- convertedObject.add(newChild);
305
- this.updateNode(nodeChild, newChild, filter, isVisibleInHierarchy, skeleton);
306
- }
307
- else if (objChild.SDversion !== nodeChild.version) {
308
- // if the version is different, update the child
309
- this.updateNode(nodeChild, objChild, filter, isVisibleInHierarchy, skeleton);
310
- objChild.SDversion = nodeChild.version;
221
+ for (let i = 0, len = treeNode.data.length; i < len; i++) {
222
+ const dataItem = treeNode.data[i];
223
+ const convertedObjectData = convertedChildrenMap.get(dataItem.id);
224
+ if (!convertedObjectData ||
225
+ convertedObjectData.SDversion !== dataItem.version ||
226
+ this._newRendererType) {
227
+ this.updateData(dataItem, treeNode, convertedObject, filter, isVisibleInHierarchy);
311
228
  }
312
229
  else {
313
- this.updateNode(nodeChild, objChild, filter, isVisibleInHierarchy, skeleton);
314
- }
315
- // adjust the general BB
316
- if (!nodeChild.boundingBox.isEmpty())
317
- node.boundingBox.union(nodeChild.boundingBox);
318
- // adjust the specific BB
319
- if (nodeChild.boundingBoxViewport[this._renderingEngine.id] &&
320
- !nodeChild.boundingBoxViewport[this._renderingEngine.id].isEmpty()) {
321
- // only do this if the node is
322
- // 1. visible
323
- // 2. no included in the "excludeViewports"
324
- // 3. if there are "restrictViewports", it needs to be in them
325
- if (isVisible)
326
- node.boundingBoxViewport[this._renderingEngine.id].union(nodeChild.boundingBoxViewport[this._renderingEngine.id]);
230
+ (0, SceenTreeManagerUtils_1.assignBoundingBox)(treeNode, dataItem, this._renderingEngine.id, convertedObjectData);
327
231
  }
328
232
  }
329
- convertedObject.visible =
330
- node.visible &&
331
- !node.excludeViewports.includes(this._renderingEngine.id) &&
332
- !(node.restrictViewports.length > 0 &&
333
- !node.restrictViewports.includes(this._renderingEngine.id));
334
- convertedObject.applyTransformation(node.nodeMatrix);
233
+ // Update or create child nodes
234
+ for (let i = 0, len = treeNode.children.length; i < len; i++) {
235
+ const treeNodeChild = treeNode.children[i];
236
+ const childConvertedObject = convertedChildrenMap.get(treeNodeChild.id);
237
+ this.processChildTreeNode(treeNodeChild, convertedObject, childConvertedObject, filter, isVisibleInHierarchy);
238
+ this.unionChildBoundingBoxes(treeNode, treeNodeChild, isVisible);
239
+ }
240
+ convertedObject.visible = isVisible;
241
+ convertedObject.applyTransformation(treeNode.nodeMatrix);
335
242
  }
336
- updateSceneTree(root) {
243
+ updateSceneTree(rootTreeNode) {
337
244
  var _a, _b;
338
245
  // check if we currently have the same root version
339
246
  if (this._tree.root.version === this._lastRootVersion &&
@@ -343,48 +250,45 @@ class SceneTreeManager {
343
250
  if (this._suspendSceneUpdates)
344
251
  return;
345
252
  this._lastRootVersion = this._tree.root.version;
346
- if (this._renderingEngine.type !== this._lastRendererType) {
347
- root.traverseData((data) => {
348
- if (data instanceof viewer_shared_types_1.GeometryData) {
349
- data.updateVersion();
350
- }
351
- });
352
- }
253
+ this._newRendererType =
254
+ this._renderingEngine.type !== this._lastRendererType;
353
255
  this._lastRendererType = this._renderingEngine.type;
354
256
  if (this._renderingEngine.closed)
355
257
  return;
258
+ this._performanceEvaluator.startSection("sceneTreeUpdate." + this._lastRootVersion);
356
259
  const oldBB = this._boundingBox.clone();
357
260
  this._boundingBox = new viewer_shared_math_1.Box();
358
261
  this._renderingEngine.lightLoader.shadowMapCount = 0;
359
- // directional lights need to be updated every time
360
- // as they are sensitive to the bounding box
361
- root.traverseData((data) => {
362
- if (data instanceof viewer_rendering_engine_light_engine_1.DirectionalLight) {
363
- data.updateVersion();
364
- }
365
- });
366
- if (!this._mainNode) {
367
- this._mainNode = new SDObject_1.SDObject(root.id, root.version);
368
- const oldObj = root.convertedObject[this._renderingEngine.id];
369
- root.convertedObject[this._renderingEngine.id] = this._mainNode;
370
- if (root.updateCallbackConvertedObject)
371
- root.updateCallbackConvertedObject(this._mainNode, oldObj, this._renderingEngine.id);
372
- this._scene.add(this._mainNode);
262
+ if (!this._mainConvertedObject) {
263
+ this._mainConvertedObject = new SDObject_1.SDObject(rootTreeNode.id, rootTreeNode.version);
264
+ const oldObj = rootTreeNode.convertedObject[this._renderingEngine.id];
265
+ rootTreeNode.convertedObject[this._renderingEngine.id] =
266
+ this._mainConvertedObject;
267
+ if (rootTreeNode.updateCallbackConvertedObject)
268
+ rootTreeNode.updateCallbackConvertedObject(this._mainConvertedObject, oldObj, this._renderingEngine.id);
269
+ this._scene.add(this._mainConvertedObject);
373
270
  }
374
- this._boundingBoxSensitiveData = [];
375
- this._currentSDTFOverview = (0, SDTFUtils_1.createSDTFOverview)(root);
376
- this.updateNode(root, this._mainNode);
271
+ this._currentSDTFOverview = (0, SDTFUtils_1.createSDTFOverview)(rootTreeNode);
272
+ this.updateNode(rootTreeNode, this._mainConvertedObject);
377
273
  this._boundingBox =
378
- root.boundingBoxViewport[this._renderingEngine.id].clone();
379
- for (let i = 0; i < this._boundingBoxSensitiveData.length; i++) {
380
- this._renderingEngine.lightLoader.adjustToBoundingBox(this._boundingBoxSensitiveData[i].data, this._boundingBoxSensitiveData[i].dataChild, this._boundingBox);
381
- }
382
- if (!(this._boundingBox.min[0] === oldBB.min[0] &&
383
- this._boundingBox.min[1] === oldBB.min[1] &&
384
- this._boundingBox.min[2] === oldBB.min[2] &&
385
- this._boundingBox.max[0] === oldBB.max[0] &&
386
- this._boundingBox.max[1] === oldBB.max[1] &&
387
- this._boundingBox.max[2] === oldBB.max[2])) {
274
+ rootTreeNode.boundingBoxViewport[this._renderingEngine.id].clone();
275
+ // directional lights need to be with the bounding box
276
+ this._directionalLightData.forEach((dl) => {
277
+ var _a;
278
+ // check if the data has stored converted object
279
+ const convertedObject = ((_a = ((dl.convertedObject[this._renderingEngine.id]))) === null || _a === void 0 ? void 0 : _a.parent);
280
+ if (!convertedObject)
281
+ return;
282
+ this._renderingEngine.lightLoader.adjustToBoundingBox(dl, convertedObject, this._boundingBox);
283
+ });
284
+ this._directionalLightData = [];
285
+ const bbChanged = this._boundingBox.min[0] !== oldBB.min[0] ||
286
+ this._boundingBox.min[1] !== oldBB.min[1] ||
287
+ this._boundingBox.min[2] !== oldBB.min[2] ||
288
+ this._boundingBox.max[0] !== oldBB.max[0] ||
289
+ this._boundingBox.max[1] !== oldBB.max[1] ||
290
+ this._boundingBox.max[2] !== oldBB.max[2];
291
+ if (bbChanged) {
388
292
  if (!((_a = this._stateEngine.viewportEngines[this._renderingEngine.id]) === null || _a === void 0 ? void 0 : _a.boundingBoxCreated.resolved) &&
389
293
  !this._boundingBox.isEmpty())
390
294
  (_b = this._stateEngine.viewportEngines[this._renderingEngine.id]) === null || _b === void 0 ? void 0 : _b.boundingBoxCreated.resolve(true);
@@ -427,8 +331,161 @@ class SceneTreeManager {
427
331
  }
428
332
  // we compile the shaders
429
333
  this._renderingEngine.renderer.compile(this._renderingEngine.scene, this._hiddenCamera);
334
+ this._performanceEvaluator.endSection("sceneTreeUpdate." + this._lastRootVersion);
335
+ }
336
+ /**
337
+ * Remove obsolete child nodes from the converted object
338
+ */
339
+ cleanupObsoleteChildren(treeNode, convertedObject) {
340
+ // remove all child nodes in the transformed object that do not exist anymore
341
+ // the filter goes also through the data items as they were already added
342
+ const nodeIds = new Set(treeNode.children
343
+ .filter((d) => !d.excludeViewports.includes(this._renderingEngine.id))
344
+ .map((d) => d.id));
345
+ const childrenToRemove = convertedObject.children.filter((oc) => {
346
+ if (oc instanceof SDObject_1.SDObject && oc.SDtype === SDObject_1.SD_DATA_TYPE.OBJECT) {
347
+ return !nodeIds.has(oc.SDid);
348
+ }
349
+ else {
350
+ return false;
351
+ }
352
+ });
353
+ childrenToRemove.forEach((cTR) => {
354
+ cTR.traverse((o) => {
355
+ if (o instanceof SDObject_1.SDObject && o.SDtype !== SDObject_1.SD_DATA_TYPE.OBJECT) {
356
+ (0, SceenTreeManagerUtils_1.removeData)(this._renderingEngine, o);
357
+ }
358
+ else if (!(o instanceof SDObject_1.SDObject) &&
359
+ o.userData.SDtype !== undefined) {
360
+ (0, SceenTreeManagerUtils_1.removeData)(this._renderingEngine, o);
361
+ }
362
+ });
363
+ convertedObject.remove(cTR);
364
+ });
365
+ }
366
+ /**
367
+ * Remove obsolete data items from the converted object
368
+ */
369
+ cleanupObsoleteData(treeNode, convertedObject) {
370
+ // remove all data items that do not exist anymore
371
+ const dataMap = new Map(treeNode.data.map((d) => [d.id, d.version]));
372
+ const dataToRemove = convertedObject.children.filter((oc) => {
373
+ if (!(oc instanceof SDObject_1.SDObject)) {
374
+ const version = dataMap.get(oc.userData.SDid);
375
+ if (version !== undefined) {
376
+ if (version !== oc.userData.SDversion) {
377
+ // version is different
378
+ return true;
379
+ }
380
+ else {
381
+ return false;
382
+ }
383
+ }
384
+ else {
385
+ // id not included anymore
386
+ return true;
387
+ }
388
+ }
389
+ else {
390
+ return false;
391
+ }
392
+ });
393
+ dataToRemove.forEach((dTR) => {
394
+ (0, SceenTreeManagerUtils_1.removeData)(this._renderingEngine, dTR);
395
+ convertedObject.remove(dTR);
396
+ });
397
+ }
398
+ /**
399
+ * Check if a node is visible in the current viewport
400
+ */
401
+ isNodeVisible(treeNode) {
402
+ return (treeNode.visible &&
403
+ !treeNode.excludeViewports.includes(this._renderingEngine.id) &&
404
+ !(treeNode.restrictViewports.length > 0 &&
405
+ !treeNode.restrictViewports.includes(this._renderingEngine.id)));
406
+ }
407
+ /**
408
+ * Process a child node by creating it if needed, updating it, and syncing bounding boxes
409
+ */
410
+ processChildTreeNode(treeNodeChild, convertedObject, childConvertedObject, filter, isVisibleInHierarchy) {
411
+ if (!childConvertedObject) {
412
+ const newChild = new SDObject_1.SDObject(treeNodeChild.id, treeNodeChild.version);
413
+ const oldChild = treeNodeChild.convertedObject[this._renderingEngine.id];
414
+ treeNodeChild.convertedObject[this._renderingEngine.id] = newChild;
415
+ if (treeNodeChild.updateCallbackConvertedObject)
416
+ treeNodeChild.updateCallbackConvertedObject(newChild, oldChild, this._renderingEngine.id);
417
+ convertedObject.add(newChild);
418
+ this.updateNode(treeNodeChild, newChild, filter, isVisibleInHierarchy);
419
+ }
420
+ else if (childConvertedObject.SDversion !== treeNodeChild.version ||
421
+ this._newRendererType) {
422
+ // if the version is different, update the child
423
+ this.updateNode(treeNodeChild, childConvertedObject, filter, isVisibleInHierarchy);
424
+ childConvertedObject.SDversion = treeNodeChild.version;
425
+ }
426
+ else {
427
+ this.updateNode(treeNodeChild, childConvertedObject, filter, isVisibleInHierarchy);
428
+ }
429
+ }
430
+ /**
431
+ * Reset and initialize bounding boxes for a node
432
+ */
433
+ resetBoundingBoxes(treeNode) {
434
+ // reset the general bounding box of the current node
435
+ // it will be recomputed in the following steps
436
+ treeNode.boundingBox.reset();
437
+ // create the specific BB if it doesn't exist yet
438
+ if (!treeNode.boundingBoxViewport[this._renderingEngine.id])
439
+ treeNode.boundingBoxViewport[this._renderingEngine.id] = new viewer_shared_math_1.Box();
440
+ // reset the specific bounding box of the current node
441
+ // it will be recomputed in the following steps
442
+ treeNode.boundingBoxViewport[this._renderingEngine.id].reset();
443
+ }
444
+ /**
445
+ * Resolves the converted object for a node, handling cases where it doesn't exist
446
+ */
447
+ resolveConvertedObject(treeNode, filter, visibleInHierarchy) {
448
+ // check if there is a converted object
449
+ if (treeNode.convertedObject[this._renderingEngine.id]) {
450
+ return treeNode.convertedObject[this._renderingEngine.id];
451
+ }
452
+ else {
453
+ // the node has not been converted yet
454
+ // go up the hierarchy until a converted object is found
455
+ let parent = treeNode.parent;
456
+ while (parent) {
457
+ if (parent.convertedObject[this._renderingEngine.id]) {
458
+ this.updateNode(parent, parent.convertedObject[this._renderingEngine.id], filter, visibleInHierarchy);
459
+ return;
460
+ }
461
+ else {
462
+ parent = parent.parent;
463
+ }
464
+ }
465
+ // no converted object found in the hierarchy
466
+ // update the whole scene tree
467
+ this.updateSceneTree(this._tree.root);
468
+ return;
469
+ }
470
+ }
471
+ /**
472
+ * Union child bounding boxes with parent bounding boxes
473
+ */
474
+ unionChildBoundingBoxes(treeNode, treeNodeChild, isVisible) {
475
+ // adjust the general BB
476
+ if (!treeNodeChild.boundingBox.isEmpty())
477
+ treeNode.boundingBox.union(treeNodeChild.boundingBox);
478
+ // adjust the specific BB
479
+ if (treeNodeChild.boundingBoxViewport[this._renderingEngine.id] &&
480
+ !treeNodeChild.boundingBoxViewport[this._renderingEngine.id].isEmpty()) {
481
+ // only do this if the node is
482
+ // 1. visible
483
+ // 2. no included in the "excludeViewports"
484
+ // 3. if there are "restrictViewports", it needs to be in them
485
+ if (isVisible)
486
+ treeNode.boundingBoxViewport[this._renderingEngine.id].union(treeNodeChild.boundingBoxViewport[this._renderingEngine.id]);
487
+ }
430
488
  }
431
489
  }
432
490
  exports.SceneTreeManager = SceneTreeManager;
433
- // #endregion Classes (1)
434
491
  //# sourceMappingURL=SceneTreeManager.js.map