@inweb/viewer-three 27.2.2 → 27.3.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.
@@ -133,7 +133,7 @@ export class DynamicModelImpl extends ModelImpl {
133
133
  }
134
134
 
135
135
  override explode(scale = 0, coeff = 4): this {
136
- const centers = new Map();
136
+ const centersCache = new Map();
137
137
 
138
138
  const calcObjectCenter = (object: Object3D, target: Vector3): Vector3 => {
139
139
  const extents = new Box3().setFromObject(object);
@@ -141,74 +141,85 @@ export class DynamicModelImpl extends ModelImpl {
141
141
  const handle = object.userData.handle;
142
142
  if (!handle) return extents.getCenter(target);
143
143
 
144
- const center = centers.get(handle);
144
+ const center = centersCache.get(handle);
145
145
  if (center) return target.copy(center);
146
146
 
147
147
  const objects = this.getObjectsByHandles(handle);
148
148
  objects.forEach((x: Object3D) => extents.expandByObject(x));
149
149
  extents.getCenter(target);
150
150
 
151
- centers.set(handle, target.clone());
151
+ centersCache.set(handle, target.clone());
152
152
 
153
153
  return target;
154
154
  };
155
155
 
156
- function calcExplodeDepth(object: Object3D, depth: number): number {
157
- let result = depth;
158
- object.children
159
- .filter((x: Object3D) => !x.userData.isOptimized)
160
- .forEach((x: Object3D) => {
161
- const objectDepth = calcExplodeDepth(x, depth + 1);
162
- if (result < objectDepth) result = objectDepth;
163
- });
156
+ const calcObjectDepth = (object: Object3D): number => {
157
+ if (object.userData.depth !== undefined) return object.userData.depth;
164
158
 
159
+ const parent = object.parent;
160
+ const depth = parent && object !== explodeRoot ? calcObjectDepth(parent) + 1 : 0;
161
+
162
+ object.userData.depth = depth;
165
163
  object.userData.originalPosition = object.position.clone();
166
164
  object.userData.originalCenter = calcObjectCenter(object, new Vector3());
167
165
 
168
- return result;
169
- }
166
+ return depth;
167
+ };
170
168
 
171
169
  const explodeScale = scale / 100;
172
170
  const explodeRoot = this.scene.children[0];
173
171
 
174
- if (!explodeRoot.userData.explodeDepth) explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
175
- const maxDepth = explodeRoot.userData.explodeDepth;
172
+ if (!explodeRoot.userData.explodeDepth) {
173
+ let maxDepth = 0;
174
+
175
+ this.gltfLoader.originalObjects.forEach((object: Object3D) => {
176
+ const depth = calcObjectDepth(object);
177
+ if (depth > maxDepth) maxDepth = depth;
178
+ });
176
179
 
180
+ explodeRoot.userData.explodeDepth = maxDepth;
181
+ }
182
+
183
+ const maxDepth = explodeRoot.userData.explodeDepth;
177
184
  const scaledExplodeDepth = explodeScale * maxDepth + 1;
178
185
  const explodeDepth = 0 | scaledExplodeDepth;
179
186
  const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
180
187
 
181
- const transformMap = new Map();
188
+ const offsetCache = new Map();
189
+
190
+ const calcObjectOffset = (object: Object3D, target: Vector3): Vector3 => {
191
+ if (offsetCache.has(object)) return target.copy(offsetCache.get(object));
182
192
 
183
- function explodeObject(object, depth: number) {
184
- if (object.isCamera) return;
185
- if (object.userData.isHighlightWireframe) return;
193
+ const parent = object.parent;
194
+ if (parent && object !== explodeRoot) calcObjectOffset(parent, target);
186
195
 
187
- object.position.copy(object.userData.originalPosition);
196
+ const depth = object.userData.depth;
188
197
 
189
- if (depth > 0 && depth <= explodeDepth && !object.userData.isExplodeLocked) {
198
+ if (depth > 0 && depth <= explodeDepth) {
190
199
  let objectScale = explodeScale * coeff;
191
200
  if (depth === explodeDepth) objectScale *= currentSegmentFraction;
192
201
 
193
- const parentCenter = object.parent.userData.originalCenter;
202
+ const parentCenter = parent.userData.originalCenter;
194
203
  const objectCenter = object.userData.originalCenter;
195
- const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
204
+ const localOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
196
205
 
197
- object.position.add(objectOffset);
198
-
199
- const matrix = new Matrix4().makeTranslation(objectOffset.x, objectOffset.y, objectOffset.z);
200
- transformMap.set(object, matrix);
206
+ target.add(localOffset);
201
207
  }
202
208
 
203
- object.children
204
- .filter((x: Object3D) => !x.userData.isOptimized)
205
- .forEach((x: Object3D) => explodeObject(x, depth + 1));
206
- }
209
+ offsetCache.set(object, target.clone());
207
210
 
208
- explodeObject(explodeRoot, 0);
209
- this.scene.updateMatrixWorld();
211
+ return target;
212
+ };
213
+
214
+ const transformMap = new Map();
215
+
216
+ this.gltfLoader.originalObjects.forEach((object: Object3D) => {
217
+ const globalOffset = calcObjectOffset(object, new Vector3());
218
+ transformMap.set(object, new Matrix4().makeTranslation(globalOffset));
219
+ });
210
220
 
211
221
  this.gltfLoader.applyObjectTransforms(transformMap);
222
+ this.scene.updateMatrixWorld();
212
223
 
213
224
  return this;
214
225
  }
@@ -84,7 +84,12 @@ export class Snapper {
84
84
  return target.set(event.clientX, event.clientY);
85
85
  }
86
86
 
87
- getPointerIntersects(mouse: Vector2, objects: Object3D[]): Array<Intersection<Object3D>> {
87
+ getPointerIntersects(
88
+ mouse: Vector2,
89
+ objects: Object3D[],
90
+ recursive = false,
91
+ clip = true
92
+ ): Array<Intersection<Object3D>> {
88
93
  const rect = this.canvas.getBoundingClientRect();
89
94
  const x = ((mouse.x - rect.left) / rect.width) * 2 - 1;
90
95
  const y = (-(mouse.y - rect.top) / rect.height) * 2 + 1;
@@ -101,11 +106,14 @@ export class Snapper {
101
106
  Sprite: {},
102
107
  };
103
108
 
104
- let intersects = this.raycaster.intersectObjects(objects, false);
109
+ let intersects = this.raycaster.intersectObjects(objects, recursive);
105
110
 
106
- (this.renderer.clippingPlanes || []).forEach((plane: Plane) => {
107
- intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
108
- });
111
+ if (clip) {
112
+ const clippingPlanes = this.renderer.clippingPlanes || [];
113
+ clippingPlanes.forEach((plane: Plane) => {
114
+ intersects = intersects.filter((intersect) => plane.distanceToPoint(intersect.point) >= 0);
115
+ });
116
+ }
109
117
 
110
118
  return intersects;
111
119
  }
@@ -383,35 +383,36 @@ export class ModelImpl implements IModelImpl {
383
383
  }
384
384
 
385
385
  explode(scale = 0, coeff = 4): this {
386
- const centers = new Map();
386
+ const centersCache = new Map();
387
387
 
388
- const getObjectCenter = (object: Object3D, target: Vector3): Vector3 => {
388
+ const calcObjectCenter = (object: Object3D, target: Vector3): Vector3 => {
389
389
  const extents = new Box3().setFromObject(object);
390
390
 
391
391
  const handle = object.userData.handle;
392
392
  if (!handle) return extents.getCenter(target);
393
393
 
394
- const center = centers.get(handle);
394
+ const center = centersCache.get(handle);
395
395
  if (center) return target.copy(center);
396
396
 
397
397
  const objects = this.getObjectsByHandles(handle);
398
398
  objects.forEach((x: Object3D) => extents.expandByObject(x));
399
399
  extents.getCenter(target);
400
400
 
401
- centers.set(handle, target.clone());
401
+ centersCache.set(handle, target.clone());
402
402
 
403
403
  return target;
404
404
  };
405
405
 
406
406
  function calcExplodeDepth(object: Object3D, depth: number): number {
407
407
  let result = depth;
408
+
408
409
  object.children.forEach((x: Object3D) => {
409
410
  const objectDepth = calcExplodeDepth(x, depth + 1);
410
411
  if (result < objectDepth) result = objectDepth;
411
412
  });
412
413
 
413
414
  object.userData.originalPosition = object.position.clone();
414
- object.userData.originalCenter = getObjectCenter(object, new Vector3());
415
+ object.userData.originalCenter = calcObjectCenter(object, new Vector3());
415
416
 
416
417
  return result;
417
418
  }
@@ -419,14 +420,16 @@ export class ModelImpl implements IModelImpl {
419
420
  const explodeScale = scale / 100;
420
421
  const explodeRoot = this.scene;
421
422
 
422
- if (!explodeRoot.userData.explodeDepth) explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
423
- const maxDepth = explodeRoot.userData.explodeDepth;
423
+ if (!explodeRoot.userData.explodeDepth) {
424
+ explodeRoot.userData.explodeDepth = calcExplodeDepth(explodeRoot, 1);
425
+ }
424
426
 
427
+ const maxDepth = explodeRoot.userData.explodeDepth;
425
428
  const scaledExplodeDepth = explodeScale * maxDepth + 1;
426
429
  const explodeDepth = 0 | scaledExplodeDepth;
427
430
  const currentSegmentFraction = scaledExplodeDepth - explodeDepth;
428
431
 
429
- function explodeObject(object, depth: number) {
432
+ function explodeObject(object: any, depth: number) {
430
433
  if (object.isCamera) return;
431
434
  if (object.userData.isHighlightWireframe) return;
432
435
 
@@ -438,9 +441,9 @@ export class ModelImpl implements IModelImpl {
438
441
 
439
442
  const parentCenter = object.parent.userData.originalCenter;
440
443
  const objectCenter = object.userData.originalCenter;
441
- const objectOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
444
+ const localOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
442
445
 
443
- object.position.add(objectOffset);
446
+ object.position.add(localOffset);
444
447
  }
445
448
 
446
449
  object.children.forEach((x: Object3D) => explodeObject(x, depth + 1));