@inweb/viewer-three 27.5.0 → 27.6.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.
- package/dist/extensions/components/LightHelperComponent.js +1 -1
- package/dist/extensions/components/LightHelperComponent.js.map +1 -1
- package/dist/extensions/components/LightHelperComponent.min.js +1 -1
- package/dist/extensions/components/LightHelperComponent.module.js +1 -1
- package/dist/extensions/components/LightHelperComponent.module.js.map +1 -1
- package/dist/extensions/components/StatsPanelComponent.js +0 -1
- package/dist/extensions/components/StatsPanelComponent.js.map +1 -1
- package/dist/extensions/components/StatsPanelComponent.min.js +1 -1
- package/dist/extensions/components/StatsPanelComponent.module.js +0 -1
- package/dist/extensions/components/StatsPanelComponent.module.js.map +1 -1
- package/dist/extensions/loaders/GLTFCloudLoader.js +7 -2
- package/dist/extensions/loaders/GLTFCloudLoader.js.map +1 -1
- package/dist/extensions/loaders/GLTFCloudLoader.min.js +1 -1
- package/dist/extensions/loaders/GLTFCloudLoader.module.js +7 -2
- package/dist/extensions/loaders/GLTFCloudLoader.module.js.map +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.js +2 -1
- package/dist/extensions/loaders/GLTFFileLoader.js.map +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.min.js +1 -1
- package/dist/extensions/loaders/GLTFFileLoader.module.js +2 -1
- package/dist/extensions/loaders/GLTFFileLoader.module.js.map +1 -1
- package/dist/extensions/loaders/IFCXLoader.js +10 -5
- package/dist/extensions/loaders/IFCXLoader.js.map +1 -1
- package/dist/extensions/loaders/IFCXLoader.min.js +1 -1
- package/dist/extensions/loaders/IFCXLoader.module.js +10 -5
- package/dist/extensions/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/viewer-three.js +161 -157
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +68 -53
- package/dist/viewer-three.module.js.map +1 -1
- package/extensions/components/LightHelperComponent.ts +1 -1
- package/extensions/components/StatsPanelComponent.ts +0 -1
- package/extensions/loaders/GLTFCloudLoader.ts +8 -2
- package/extensions/loaders/GLTFFileLoader.ts +3 -2
- package/extensions/loaders/IFCX/IFCXFileLoader.ts +11 -5
- package/lib/Viewer/Viewer.d.ts +1 -1
- package/lib/Viewer/measurement/Snapper.d.ts +1 -1
- package/package.json +5 -5
- package/src/Viewer/Viewer.ts +14 -16
- package/src/Viewer/commands/GetSelected2.ts +1 -1
- package/src/Viewer/commands/SetSelected.ts +1 -1
- package/src/Viewer/components/BackgroundComponent.ts +1 -1
- package/src/Viewer/components/CameraComponent.ts +1 -1
- package/src/Viewer/components/CanvasRemoveComponent.ts +0 -1
- package/src/Viewer/components/HighlighterUtils.ts +2 -2
- package/src/Viewer/components/SelectionComponent.ts +4 -2
- package/src/Viewer/helpers/SectionsHelper.js +4 -8
- package/src/Viewer/helpers/WCSHelper.ts +7 -5
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicModelImpl.ts +19 -14
- package/src/Viewer/loaders/GLTFBinaryParser.ts +2 -2
- package/src/Viewer/loaders/GLTFFileDynamicLoader.ts +2 -2
- package/src/Viewer/measurement/Snapper.ts +2 -2
- package/src/Viewer/models/ModelImpl.ts +38 -25
|
@@ -57,7 +57,7 @@ class LightHelperComponent implements IComponent {
|
|
|
57
57
|
const helperSize = extentsSize / 20;
|
|
58
58
|
|
|
59
59
|
this.viewer.scene.traverse((object: any) => {
|
|
60
|
-
let helper: DirectionalLightHelper | HemisphereLightHelper | PointLightHelper;
|
|
60
|
+
let helper: DirectionalLightHelper | HemisphereLightHelper | PointLightHelper | null = null;
|
|
61
61
|
|
|
62
62
|
if (object.isDirectionalLight) helper = new DirectionalLightHelper(object, helperSize, "#aa0000");
|
|
63
63
|
else if (object.isHemisphereLight) helper = new HemisphereLightHelper(object, helperSize, "#ff9800");
|
|
@@ -26,10 +26,16 @@ import { GLTFLoadingManager, Loader, loaders, ModelImpl, Viewer } from "@inweb/v
|
|
|
26
26
|
|
|
27
27
|
class GLTFCloudLoader extends Loader {
|
|
28
28
|
public viewer: Viewer;
|
|
29
|
+
private manager: GLTFLoadingManager | null;
|
|
29
30
|
|
|
30
31
|
constructor(viewer: Viewer) {
|
|
31
32
|
super();
|
|
32
33
|
this.viewer = viewer;
|
|
34
|
+
this.manager = null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
override dispose() {
|
|
38
|
+
if (this.manager) this.manager.dispose();
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
override isSupport(file: any): boolean {
|
|
@@ -43,9 +49,9 @@ class GLTFCloudLoader extends Loader {
|
|
|
43
49
|
|
|
44
50
|
override async load(model: any): Promise<this> {
|
|
45
51
|
const url = `${model.httpClient.serverUrl}${model.path}/${model.database}`;
|
|
46
|
-
|
|
52
|
+
this.manager = new GLTFLoadingManager(url);
|
|
47
53
|
|
|
48
|
-
const loader = new GLTFLoader(manager);
|
|
54
|
+
const loader = new GLTFLoader(this.manager);
|
|
49
55
|
loader.setRequestHeader(model.httpClient.headers);
|
|
50
56
|
|
|
51
57
|
const progress = (event: ProgressEvent) => {
|
|
@@ -26,18 +26,19 @@ import { GLTFLoadingManager, GLTFLoadParams, Loader, loaders, ModelImpl, Viewer
|
|
|
26
26
|
|
|
27
27
|
export class GLTFFileLoader extends Loader {
|
|
28
28
|
public viewer: Viewer;
|
|
29
|
-
private manager: GLTFLoadingManager;
|
|
29
|
+
private manager: GLTFLoadingManager | null;
|
|
30
30
|
|
|
31
31
|
constructor(viewer: Viewer) {
|
|
32
32
|
super();
|
|
33
33
|
this.viewer = viewer;
|
|
34
|
+
this.manager = null;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
override dispose() {
|
|
37
38
|
if (this.manager) this.manager.dispose();
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
override isSupport(file: any, format
|
|
41
|
+
override isSupport(file: any, format = ""): boolean {
|
|
41
42
|
return (
|
|
42
43
|
(typeof file === "string" || file instanceof globalThis.File || file instanceof ArrayBuffer) &&
|
|
43
44
|
/(gltf|glb)$/i.test(format)
|
|
@@ -26,13 +26,19 @@ import { IFCXLoader } from "./IFCXLoader";
|
|
|
26
26
|
|
|
27
27
|
export class IFCXFileLoader extends Loader {
|
|
28
28
|
public viewer: Viewer;
|
|
29
|
+
private manager: GLTFLoadingManager | null;
|
|
29
30
|
|
|
30
31
|
constructor(viewer: Viewer) {
|
|
31
32
|
super();
|
|
32
33
|
this.viewer = viewer;
|
|
34
|
+
this.manager = null;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
override
|
|
37
|
+
override dispose() {
|
|
38
|
+
if (this.manager) this.manager.dispose();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override isSupport(file: any, format = ""): boolean {
|
|
36
42
|
return (
|
|
37
43
|
(typeof file === "string" || file instanceof globalThis.File || file instanceof ArrayBuffer) &&
|
|
38
44
|
/(ifcx)$/i.test(format)
|
|
@@ -40,10 +46,10 @@ export class IFCXFileLoader extends Loader {
|
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
override async load(file: any, format?: string, params: GLTFLoadParams = {}): Promise<this> {
|
|
43
|
-
|
|
49
|
+
this.manager = new GLTFLoadingManager(file, params);
|
|
44
50
|
|
|
45
|
-
const loader = new IFCXLoader(manager);
|
|
46
|
-
loader.setPath(manager.path);
|
|
51
|
+
const loader = new IFCXLoader(this.manager);
|
|
52
|
+
loader.setPath(this.manager.path);
|
|
47
53
|
loader.setCrossOrigin(params.crossOrigin || loader.crossOrigin);
|
|
48
54
|
loader.setWithCredentials(params.withCredentials || loader.withCredentials);
|
|
49
55
|
|
|
@@ -53,7 +59,7 @@ export class IFCXFileLoader extends Loader {
|
|
|
53
59
|
this.viewer.emitEvent({ type: "geometryprogress", data: progress, file });
|
|
54
60
|
};
|
|
55
61
|
|
|
56
|
-
const scene = await loader.loadAsync(manager.fileURL, progress);
|
|
62
|
+
const scene = await loader.loadAsync(this.manager.fileURL, progress);
|
|
57
63
|
if (!this.viewer.scene) return this;
|
|
58
64
|
|
|
59
65
|
let handle = 1;
|
package/lib/Viewer/Viewer.d.ts
CHANGED
|
@@ -161,7 +161,7 @@ export declare class Viewer extends EventEmitter2<ViewerEventMap & CanvasEventMa
|
|
|
161
161
|
activeDragger(): IDragger | null;
|
|
162
162
|
setActiveDragger(name?: string): IDragger | null;
|
|
163
163
|
resetActiveDragger(): void;
|
|
164
|
-
getComponent(name: string): IComponent;
|
|
164
|
+
getComponent(name: string): IComponent | null;
|
|
165
165
|
drawViewpoint(viewpoint: IViewpoint): void;
|
|
166
166
|
createViewpoint(): IViewpoint;
|
|
167
167
|
getSnapshot(type?: string, quality?: number): string;
|
|
@@ -12,5 +12,5 @@ export declare class Snapper {
|
|
|
12
12
|
getMousePosition(event: MouseEvent, target: Vector2): Vector2;
|
|
13
13
|
getPointerIntersects(mouse: Vector2, objects: Object3D[], recursive?: boolean, clip?: boolean): Array<Intersection<Object3D>>;
|
|
14
14
|
getDetectRadius(point: Vector3): number;
|
|
15
|
-
getSnapPoint(mouse: Vector2, objects: Object3D[]): Vector3;
|
|
15
|
+
getSnapPoint(mouse: Vector2, objects: Object3D[]): Vector3 | undefined;
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inweb/viewer-three",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.6.0",
|
|
4
4
|
"description": "JavaScript library for rendering CAD and BIM files in a browser using Three.js",
|
|
5
5
|
"homepage": "https://cloud.opendesign.com/docs/index.html",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"docs": "typedoc"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@inweb/client": "~27.
|
|
39
|
-
"@inweb/eventemitter2": "~27.
|
|
40
|
-
"@inweb/markup": "~27.
|
|
41
|
-
"@inweb/viewer-core": "~27.
|
|
38
|
+
"@inweb/client": "~27.6.0",
|
|
39
|
+
"@inweb/eventemitter2": "~27.6.0",
|
|
40
|
+
"@inweb/markup": "~27.6.0",
|
|
41
|
+
"@inweb/viewer-core": "~27.6.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@streamparser/json": "^0.0.22",
|
package/src/Viewer/Viewer.ts
CHANGED
|
@@ -226,7 +226,8 @@ export class Viewer
|
|
|
226
226
|
this._markup.initialize(this.canvas, this.canvasEvents, this, this);
|
|
227
227
|
|
|
228
228
|
for (const name of components.getComponents().keys()) {
|
|
229
|
-
|
|
229
|
+
const component = components.createComponent(name, this);
|
|
230
|
+
if (component) this._components.push(component);
|
|
230
231
|
}
|
|
231
232
|
|
|
232
233
|
this.syncOptions();
|
|
@@ -258,10 +259,7 @@ export class Viewer
|
|
|
258
259
|
this._components.forEach((component: IComponent) => component.dispose());
|
|
259
260
|
this._components.length = 0;
|
|
260
261
|
|
|
261
|
-
|
|
262
|
-
this._markup.dispose();
|
|
263
|
-
this._markup = undefined;
|
|
264
|
-
}
|
|
262
|
+
this._markup.dispose();
|
|
265
263
|
|
|
266
264
|
if (this.canvas) {
|
|
267
265
|
this.canvasEvents.forEach((x) => this.canvas.removeEventListener(x, this.canvaseventlistener));
|
|
@@ -461,7 +459,7 @@ export class Viewer
|
|
|
461
459
|
if (!format && typeof file === "string") format = file.split(".").pop();
|
|
462
460
|
if (!format && file instanceof globalThis.File) format = file.name.split(".").pop();
|
|
463
461
|
|
|
464
|
-
const loader: ILoader = loaders.createLoader(this, model, format);
|
|
462
|
+
const loader: ILoader | null = loaders.createLoader(this, model, format);
|
|
465
463
|
if (!loader) throw new Error(`Format not supported (${format})`);
|
|
466
464
|
this.loaders.push(loader);
|
|
467
465
|
|
|
@@ -615,8 +613,8 @@ export class Viewer
|
|
|
615
613
|
|
|
616
614
|
setActiveDragger(name = ""): IDragger | null {
|
|
617
615
|
if (!this._activeDragger || this._activeDragger.name !== name) {
|
|
618
|
-
const oldDragger = this._activeDragger;
|
|
619
|
-
let newDragger = null;
|
|
616
|
+
const oldDragger: IDragger | null = this._activeDragger;
|
|
617
|
+
let newDragger: IDragger | null = null;
|
|
620
618
|
|
|
621
619
|
if (this._activeDragger) {
|
|
622
620
|
this._activeDragger.dispose();
|
|
@@ -647,8 +645,8 @@ export class Viewer
|
|
|
647
645
|
}
|
|
648
646
|
}
|
|
649
647
|
|
|
650
|
-
getComponent(name: string): IComponent {
|
|
651
|
-
return this._components.find((component) => component.name === name);
|
|
648
|
+
getComponent(name: string): IComponent | null {
|
|
649
|
+
return this._components.find((component) => component.name === name) || null;
|
|
652
650
|
}
|
|
653
651
|
|
|
654
652
|
drawViewpoint(viewpoint: IViewpoint): void {
|
|
@@ -656,7 +654,7 @@ export class Viewer
|
|
|
656
654
|
|
|
657
655
|
const getVector3FromPoint3d = ({ x, y, z }): Vector3 => new Vector3(x, y, z);
|
|
658
656
|
|
|
659
|
-
const setOrthogonalCamera = (orthogonal_camera
|
|
657
|
+
const setOrthogonalCamera = (orthogonal_camera?: IOrthogonalCamera) => {
|
|
660
658
|
if (orthogonal_camera) {
|
|
661
659
|
const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
|
|
662
660
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
@@ -686,7 +684,7 @@ export class Viewer
|
|
|
686
684
|
}
|
|
687
685
|
};
|
|
688
686
|
|
|
689
|
-
const setPerspectiveCamera = (perspective_camera
|
|
687
|
+
const setPerspectiveCamera = (perspective_camera?: IPerspectiveCamera) => {
|
|
690
688
|
if (perspective_camera) {
|
|
691
689
|
const extentsSize = this.extents.getSize(new Vector3()).length() || 1;
|
|
692
690
|
const rendererSize = this.renderer.getSize(new Vector2());
|
|
@@ -713,7 +711,7 @@ export class Viewer
|
|
|
713
711
|
}
|
|
714
712
|
};
|
|
715
713
|
|
|
716
|
-
const setClippingPlanes = (clipping_planes
|
|
714
|
+
const setClippingPlanes = (clipping_planes?: IClippingPlane[]) => {
|
|
717
715
|
if (clipping_planes) {
|
|
718
716
|
clipping_planes.forEach((clipping_plane) => {
|
|
719
717
|
const plane = new Plane();
|
|
@@ -764,7 +762,7 @@ export class Viewer
|
|
|
764
762
|
|
|
765
763
|
const getPoint3dFromVector3 = ({ x, y, z }): IPoint => ({ x, y, z });
|
|
766
764
|
|
|
767
|
-
const getOrthogonalCamera = (): IOrthogonalCamera => {
|
|
765
|
+
const getOrthogonalCamera = (): IOrthogonalCamera | undefined => {
|
|
768
766
|
if (this.camera["isOrthographicCamera"])
|
|
769
767
|
return {
|
|
770
768
|
view_point: getPoint3dFromVector3(this.camera.position),
|
|
@@ -777,7 +775,7 @@ export class Viewer
|
|
|
777
775
|
else return undefined;
|
|
778
776
|
};
|
|
779
777
|
|
|
780
|
-
const getPerspectiveCamera = (): IPerspectiveCamera => {
|
|
778
|
+
const getPerspectiveCamera = (): IPerspectiveCamera | undefined => {
|
|
781
779
|
if (this.camera["isPerspectiveCamera"])
|
|
782
780
|
return {
|
|
783
781
|
view_point: getPoint3dFromVector3(this.camera.position),
|
|
@@ -789,7 +787,7 @@ export class Viewer
|
|
|
789
787
|
};
|
|
790
788
|
|
|
791
789
|
const getClippingPlanes = (): IClippingPlane[] => {
|
|
792
|
-
const clipping_planes = [];
|
|
790
|
+
const clipping_planes: IClippingPlane[] = [];
|
|
793
791
|
this.clippingPlanes.forEach((plane: Plane) => {
|
|
794
792
|
const clipping_plane = {
|
|
795
793
|
location: getPoint3dFromVector3(plane.coplanarPoint(new Vector3())),
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import type { Viewer } from "../Viewer";
|
|
25
25
|
|
|
26
26
|
export function getSelected2(viewer: Viewer): string[] {
|
|
27
|
-
const handles2 = [];
|
|
27
|
+
const handles2: string[][] = [];
|
|
28
28
|
|
|
29
29
|
viewer.models.forEach((model) => {
|
|
30
30
|
handles2.push(model.getHandlesByObjects(viewer.selected));
|
|
@@ -42,7 +42,7 @@ export class BackgroundComponent implements IComponent {
|
|
|
42
42
|
|
|
43
43
|
dispose() {
|
|
44
44
|
this.viewer.removeEventListener("optionschange", this.syncOptions);
|
|
45
|
-
this.viewer.scene.background =
|
|
45
|
+
this.viewer.scene.background = null;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
syncOptions = () => {
|
|
@@ -80,7 +80,7 @@ export class CameraComponent implements IComponent {
|
|
|
80
80
|
|
|
81
81
|
const target = this.viewer.target.clone();
|
|
82
82
|
|
|
83
|
-
let camera: PerspectiveCamera | OrthographicCamera;
|
|
83
|
+
let camera: PerspectiveCamera | OrthographicCamera | null = null;
|
|
84
84
|
|
|
85
85
|
if (currentCamera.isOrthographicCamera) {
|
|
86
86
|
const fov = currentCamera.userData.fov || 45;
|
|
@@ -40,7 +40,7 @@ export class HighlighterUtils {
|
|
|
40
40
|
|
|
41
41
|
static fromIndexedLine(positions: Float32Array, indices: number[]) {
|
|
42
42
|
const lineGeometry = new LineSegmentsGeometry();
|
|
43
|
-
const segments = [];
|
|
43
|
+
const segments: number[] = [];
|
|
44
44
|
|
|
45
45
|
for (let i = 0; i < indices.length; i += 2) {
|
|
46
46
|
const idx1 = indices[i] * 3;
|
|
@@ -68,7 +68,7 @@ export class HighlighterUtils {
|
|
|
68
68
|
|
|
69
69
|
static fromNonIndexedLine(positions: Float32Array, isLineSegments: boolean) {
|
|
70
70
|
const lineGeometry = new LineSegmentsGeometry();
|
|
71
|
-
const segments = [];
|
|
71
|
+
const segments: number[] = [];
|
|
72
72
|
|
|
73
73
|
if (isLineSegments) {
|
|
74
74
|
for (let i = 0; i < positions.length; i += 6) {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
// acknowledge and accept the above terms.
|
|
22
22
|
///////////////////////////////////////////////////////////////////////////////
|
|
23
23
|
|
|
24
|
-
import { Object3D, Vector2, Vector3 } from "three";
|
|
24
|
+
import { Intersection, Object3D, Vector2, Vector3 } from "three";
|
|
25
25
|
|
|
26
26
|
import type { IComponent } from "@inweb/viewer-core";
|
|
27
27
|
import type { Viewer } from "../Viewer";
|
|
@@ -68,7 +68,9 @@ export class SelectionComponent implements IComponent {
|
|
|
68
68
|
const snapper = new Snapper(this.viewer.camera, this.viewer.clippingPlanes, this.viewer.canvas);
|
|
69
69
|
snapper.threshold = extentsSize / 10000;
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
type Intersection2 = Intersection<Object3D> & { model: IModelImpl };
|
|
72
|
+
|
|
73
|
+
let intersections: Intersection2[] = [];
|
|
72
74
|
this.viewer.models.forEach((model) => {
|
|
73
75
|
const objects = model.getVisibleObjects();
|
|
74
76
|
const intersects = snapper.getPointerIntersects(upPosition, objects);
|
|
@@ -41,10 +41,6 @@ import { LineSegmentsGeometry } from "three/examples/jsm/lines/LineSegmentsGeome
|
|
|
41
41
|
import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
|
|
42
42
|
import { LineSegments2 } from "three/examples/jsm/lines/LineSegments2.js";
|
|
43
43
|
|
|
44
|
-
// ============================================================================
|
|
45
|
-
// MATH UTILITY CLASS
|
|
46
|
-
// ============================================================================
|
|
47
|
-
|
|
48
44
|
/**
|
|
49
45
|
* Spatial Hash Grid class. Used for merging vertices that are practically at the same coordinate (within
|
|
50
46
|
* the given tolerance). This is critical for eliminating gaps caused by floating-point precision
|
|
@@ -115,10 +111,10 @@ class PointHashGrid {
|
|
|
115
111
|
}
|
|
116
112
|
}
|
|
117
113
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Sections Helper Class Manages all meshes related to clipping planes: Fill (Caps), Outlines, and Debug
|
|
116
|
+
* Points
|
|
117
|
+
*/
|
|
122
118
|
class SectionsHelper extends Object3D {
|
|
123
119
|
constructor() {
|
|
124
120
|
super();
|
|
@@ -113,11 +113,13 @@ export class WCSHelper extends Object3D {
|
|
|
113
113
|
canvas.height = 64;
|
|
114
114
|
|
|
115
115
|
const context = canvas.getContext("2d");
|
|
116
|
-
context
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
116
|
+
if (context) {
|
|
117
|
+
context.clearRect(0, 0, 64, 64);
|
|
118
|
+
context.font = "24px Arial";
|
|
119
|
+
context.textAlign = "center";
|
|
120
|
+
context.fillStyle = color.getStyle();
|
|
121
|
+
context.fillText(text, 32, 41);
|
|
122
|
+
}
|
|
121
123
|
|
|
122
124
|
const texture = new CanvasTexture(canvas);
|
|
123
125
|
texture.colorSpace = SRGBColorSpace;
|
|
@@ -62,7 +62,7 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
override getObjects(): Object3D[] {
|
|
65
|
-
const objects = [];
|
|
65
|
+
const objects: Object3D[] = [];
|
|
66
66
|
this.gltfLoader.originalObjects.forEach((object: Object3D) => {
|
|
67
67
|
objects.push(object);
|
|
68
68
|
});
|
|
@@ -78,7 +78,7 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
78
78
|
|
|
79
79
|
const handlesSet = new Set(handles);
|
|
80
80
|
|
|
81
|
-
const objects = [];
|
|
81
|
+
const objects: Object3D[] = [];
|
|
82
82
|
handlesSet.forEach((handle) => {
|
|
83
83
|
objects.push(this.gltfLoader.getObjectsByHandle(handle));
|
|
84
84
|
});
|
|
@@ -153,6 +153,13 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
153
153
|
return target;
|
|
154
154
|
};
|
|
155
155
|
|
|
156
|
+
const calcObjectOffset = (object: Object3D, target: Vector3): Vector3 => {
|
|
157
|
+
const parent = object.parent;
|
|
158
|
+
if (!parent || parent.userData.originalCenter === undefined) return target;
|
|
159
|
+
|
|
160
|
+
return target.subVectors(object.userData.originalCenter, parent.userData.originalCenter);
|
|
161
|
+
};
|
|
162
|
+
|
|
156
163
|
const calcObjectDepth = (object: Object3D): number => {
|
|
157
164
|
if (object.userData.depth !== undefined) return object.userData.depth;
|
|
158
165
|
|
|
@@ -162,17 +169,19 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
162
169
|
object.userData.depth = depth;
|
|
163
170
|
object.userData.originalPosition = object.position.clone();
|
|
164
171
|
object.userData.originalCenter = calcObjectCenter(object, new Vector3());
|
|
172
|
+
object.userData.originalOffset = calcObjectOffset(object, new Vector3());
|
|
165
173
|
|
|
166
174
|
return depth;
|
|
167
175
|
};
|
|
168
176
|
|
|
169
177
|
const explodeScale = scale / 100;
|
|
170
178
|
const explodeRoot = this.scene.children[0];
|
|
179
|
+
const explodeObjects = this.getObjects();
|
|
171
180
|
|
|
172
|
-
if (
|
|
181
|
+
if (explodeRoot.userData.explodeDepth === undefined) {
|
|
173
182
|
let maxDepth = 0;
|
|
174
183
|
|
|
175
|
-
|
|
184
|
+
explodeObjects.forEach((object: Object3D) => {
|
|
176
185
|
const depth = calcObjectDepth(object);
|
|
177
186
|
if (depth > maxDepth) maxDepth = depth;
|
|
178
187
|
});
|
|
@@ -187,11 +196,11 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
187
196
|
|
|
188
197
|
const offsetCache = new Map();
|
|
189
198
|
|
|
190
|
-
const
|
|
199
|
+
const calcExplodeOffset = (object: Object3D, target: Vector3): Vector3 => {
|
|
191
200
|
if (offsetCache.has(object)) return target.copy(offsetCache.get(object));
|
|
192
201
|
|
|
193
202
|
const parent = object.parent;
|
|
194
|
-
if (parent && object !== explodeRoot)
|
|
203
|
+
if (parent && object !== explodeRoot) calcExplodeOffset(parent, target);
|
|
195
204
|
|
|
196
205
|
const depth = object.userData.depth;
|
|
197
206
|
|
|
@@ -199,11 +208,7 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
199
208
|
let objectScale = explodeScale * coeff;
|
|
200
209
|
if (depth === explodeDepth) objectScale *= currentSegmentFraction;
|
|
201
210
|
|
|
202
|
-
|
|
203
|
-
const objectCenter = object.userData.originalCenter;
|
|
204
|
-
const localOffset = objectCenter.clone().sub(parentCenter).multiplyScalar(objectScale);
|
|
205
|
-
|
|
206
|
-
target.add(localOffset);
|
|
211
|
+
target.addScaledVector(object.userData.originalOffset, objectScale);
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
offsetCache.set(object, target.clone());
|
|
@@ -213,9 +218,9 @@ export class DynamicModelImpl extends ModelImpl {
|
|
|
213
218
|
|
|
214
219
|
const transformMap = new Map();
|
|
215
220
|
|
|
216
|
-
|
|
217
|
-
const
|
|
218
|
-
transformMap.set(object, new Matrix4().makeTranslation(
|
|
221
|
+
explodeObjects.forEach((object: Object3D) => {
|
|
222
|
+
const offset = calcExplodeOffset(object, new Vector3());
|
|
223
|
+
transformMap.set(object, new Matrix4().makeTranslation(offset));
|
|
219
224
|
});
|
|
220
225
|
|
|
221
226
|
this.gltfLoader.applyObjectTransforms(transformMap);
|
|
@@ -86,10 +86,10 @@ export class GLTFBinaryParser {
|
|
|
86
86
|
offset += chunkLength;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
if (
|
|
89
|
+
if (this.content === undefined) {
|
|
90
90
|
throw new Error("GLTFBinaryParser: JSON content not found.");
|
|
91
91
|
}
|
|
92
|
-
if (
|
|
92
|
+
if (this.body === undefined) {
|
|
93
93
|
throw new Error("GLTFBinaryParser: Binary buffer chunk not found or type not supported.");
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -49,14 +49,14 @@ export class GLTFFileDynamicLoader extends Loader {
|
|
|
49
49
|
if (this.manager) this.manager.dispose();
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
override isSupport(file: any, format
|
|
52
|
+
override isSupport(file: any, format = ""): boolean {
|
|
53
53
|
return (
|
|
54
54
|
(typeof file === "string" || file instanceof globalThis.File || file instanceof ArrayBuffer) &&
|
|
55
55
|
/(gltf|glb)$/i.test(format)
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
override async load(file: any, format?: string, params
|
|
59
|
+
override async load(file: any, format?: string, params: GLTFLoadParams = {}): Promise<this> {
|
|
60
60
|
this.manager = new GLTFLoadingManager(file, params);
|
|
61
61
|
|
|
62
62
|
const scene = new Group();
|
|
@@ -151,7 +151,7 @@ export class Snapper {
|
|
|
151
151
|
return 0.1;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
getSnapPoint(mouse: Vector2, objects: Object3D[]): Vector3 {
|
|
154
|
+
getSnapPoint(mouse: Vector2, objects: Object3D[]): Vector3 | undefined {
|
|
155
155
|
const intersections = this.getPointerIntersects(mouse, objects);
|
|
156
156
|
if (intersections.length === 0) return undefined;
|
|
157
157
|
|
|
@@ -166,7 +166,7 @@ export class Snapper {
|
|
|
166
166
|
const intersectionPoint = intersections[0].point;
|
|
167
167
|
const localPoint = object.worldToLocal(intersectionPoint.clone());
|
|
168
168
|
|
|
169
|
-
let snapPoint: Vector3;
|
|
169
|
+
let snapPoint: Vector3 | undefined = undefined;
|
|
170
170
|
let snapDistance = this.getDetectRadius(intersectionPoint);
|
|
171
171
|
|
|
172
172
|
const geometry = object.geometry;
|