@inweb/viewer-three 26.9.0 → 26.9.2
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/plugins/components/AxesHelperComponent.js +8 -6
- package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
- package/dist/plugins/components/AxesHelperComponent.min.js +1 -1
- package/dist/plugins/components/AxesHelperComponent.module.js +7 -5
- package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
- package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
- package/dist/plugins/loaders/PotreeLoader.js +160 -0
- package/dist/plugins/loaders/PotreeLoader.js.map +1 -0
- package/dist/plugins/loaders/PotreeLoader.min.js +1 -0
- package/dist/plugins/loaders/PotreeLoader.module.js +68 -0
- package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -0
- package/dist/viewer-three.js +153 -110
- package/dist/viewer-three.js.map +1 -1
- package/dist/viewer-three.min.js +3 -3
- package/dist/viewer-three.module.js +152 -96
- package/dist/viewer-three.module.js.map +1 -1
- package/lib/Viewer/Viewer.d.ts +3 -2
- package/lib/Viewer/commands/SetDefaultViewPosition.d.ts +2 -2
- package/package.json +6 -5
- package/plugins/components/AxesHelperComponent.ts +10 -6
- package/plugins/loaders/{IFCXCloudLoader.ts → IFCX/IFCXCloudLoader.ts} +1 -1
- package/plugins/loaders/{IFCXFileLoader.ts → IFCX/IFCXFileLoader.ts} +1 -1
- package/plugins/loaders/Potree/PotreeFileLoader.ts +106 -0
- package/plugins/loaders/Potree/PotreeModelImpl.ts +36 -0
- package/plugins/loaders/Potree/index.ts +28 -0
- package/src/Viewer/Viewer.ts +39 -15
- package/src/Viewer/commands/SetDefaultViewPosition.ts +20 -16
- package/src/Viewer/commands/ZoomTo.ts +13 -13
- package/src/Viewer/components/ExtentsComponent.ts +1 -1
- package/src/Viewer/components/LightComponent.ts +8 -6
- package/src/Viewer/components/ResizeCanvasComponent.ts +1 -18
- package/src/Viewer/draggers/OrbitDragger.ts +9 -0
- package/src/Viewer/draggers/WalkDragger.ts +1 -0
- package/src/Viewer/helpers/WCSHelper.ts +3 -3
- package/src/Viewer/loaders/DynamicGltfLoader/DynamicGltfLoader.js +37 -12
- package/src/Viewer/loaders/DynamicGltfLoader/GltfStructure.js +32 -32
- package/src/Viewer/loaders/GLTFCloudDynamicLoader.ts +2 -2
- /package/plugins/loaders/{IFCXLoader.ts → IFCX/index.ts} +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ModelImpl, Loader, loaders } from "@inweb/viewer-three";
|
|
2
|
+
|
|
3
|
+
import { Potree, PointColorType, PointSizeType, PointShape } from "potree-core";
|
|
4
|
+
|
|
5
|
+
class PotreeModelImpl extends ModelImpl {
|
|
6
|
+
getExtents(target) {
|
|
7
|
+
return target.union(this.pco.pcoGeometry.boundingBox);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class PotreeFileLoader extends Loader {
|
|
12
|
+
constructor(viewer) {
|
|
13
|
+
super();
|
|
14
|
+
this.updatePointClouds = () => {
|
|
15
|
+
const result = this.potree.updatePointClouds(this.pointClouds, this.viewer.camera, this.viewer.renderer);
|
|
16
|
+
if (result.exceededMaxLoadsToGPU || result.nodeLoadPromises.length > 0) this.viewer.update();
|
|
17
|
+
};
|
|
18
|
+
this.viewer = viewer;
|
|
19
|
+
this.potree = new Potree;
|
|
20
|
+
this.pointClouds = [];
|
|
21
|
+
this.viewer.addEventListener("render", this.updatePointClouds);
|
|
22
|
+
this.viewer.addEventListener("changecamera", this.updatePointClouds);
|
|
23
|
+
}
|
|
24
|
+
dispose() {
|
|
25
|
+
this.pointClouds.forEach((pco => pco.dispose()));
|
|
26
|
+
this.viewer.removeEventListener("render", this.updatePointClouds);
|
|
27
|
+
this.viewer.removeEventListener("changecamera", this.updatePointClouds);
|
|
28
|
+
}
|
|
29
|
+
isSupport(file, format) {
|
|
30
|
+
return typeof file === "string" && /(cloud.js|metadata.json)$/i.test(file);
|
|
31
|
+
}
|
|
32
|
+
async load(file, format, params = {}) {
|
|
33
|
+
const path = (params.path || "") + file;
|
|
34
|
+
const index = path.lastIndexOf("/");
|
|
35
|
+
const baseUrl = path.slice(0, index + 1);
|
|
36
|
+
const url = path.slice(index + 1);
|
|
37
|
+
const pco = await this.potree.loadPointCloud(url, baseUrl);
|
|
38
|
+
pco.material.size = 1;
|
|
39
|
+
pco.material.shape = 2;
|
|
40
|
+
pco.material.inputColorEncoding = 1;
|
|
41
|
+
pco.material.outputColorEncoding = 1;
|
|
42
|
+
pco.material.pointColorType = PointColorType.RGB;
|
|
43
|
+
pco.material.pointSizeType = PointSizeType.ADAPTIVE;
|
|
44
|
+
pco.material.shape = PointShape.CIRCLE;
|
|
45
|
+
if (params.position) pco.position.copy(params.position);
|
|
46
|
+
if (params.rotation) pco.rotation.copy(params.rotation);
|
|
47
|
+
if (params.scale) pco.scale.copy(params.scale);
|
|
48
|
+
this.pointClouds.push(pco);
|
|
49
|
+
const modelImpl = new PotreeModelImpl(pco);
|
|
50
|
+
modelImpl.loader = this;
|
|
51
|
+
modelImpl.viewer = this.viewer;
|
|
52
|
+
modelImpl.pco = pco;
|
|
53
|
+
this.viewer.scene.add(pco);
|
|
54
|
+
this.viewer.models.push(modelImpl);
|
|
55
|
+
this.viewer.syncOptions();
|
|
56
|
+
this.viewer.syncOverlay();
|
|
57
|
+
this.viewer.update();
|
|
58
|
+
this.viewer.emitEvent({
|
|
59
|
+
type: "databasechunk",
|
|
60
|
+
data: pco,
|
|
61
|
+
file: file
|
|
62
|
+
});
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
loaders.registerLoader("potree-file", (viewer => new PotreeFileLoader(viewer)));
|
|
68
|
+
//# sourceMappingURL=PotreeLoader.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PotreeLoader.module.js","sources":["../../../plugins/loaders/Potree/PotreeModelImpl.ts","../../../plugins/loaders/Potree/PotreeFileLoader.ts","../../../plugins/loaders/Potree/index.ts"],"sourcesContent":["///////////////////////////////////////////////////////////////////////////////\n// Copyright (C) 2002-2025, Open Design Alliance (the \"Alliance\").\n// All rights reserved.\n//\n// This software and its documentation and related materials are owned by\n// the Alliance. The software may only be incorporated into application\n// programs owned by members of the Alliance, subject to a signed\n// Membership Agreement and Supplemental Software License Agreement with the\n// Alliance. The structure and organization of this software are the valuable\n// trade secrets of the Alliance and its suppliers. The software is also\n// protected by copyright law and international treaty provisions. Application\n// programs incorporating this software must include the following statement\n// with their copyright notices:\n//\n// This application incorporates Open Design Alliance software pursuant to a\n// license agreement with Open Design Alliance.\n// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.\n// All rights reserved.\n//\n// By use of this software, its documentation or related materials, you\n// acknowledge and accept the above terms.\n///////////////////////////////////////////////////////////////////////////////\n\nimport { Box3 } from \"three\";\nimport { PointCloudOctree } from \"potree-core\";\nimport { ModelImpl } from \"@inweb/viewer-three\";\n\n// Potree model implementation.\n\nexport class PotreeModelImpl extends ModelImpl {\n public pco: PointCloudOctree;\n\n override getExtents(target: Box3): Box3 {\n return target.union(this.pco.pcoGeometry.boundingBox);\n }\n}\n","///////////////////////////////////////////////////////////////////////////////\n// Copyright (C) 2002-2025, Open Design Alliance (the \"Alliance\").\n// All rights reserved.\n//\n// This software and its documentation and related materials are owned by\n// the Alliance. The software may only be incorporated into application\n// programs owned by members of the Alliance, subject to a signed\n// Membership Agreement and Supplemental Software License Agreement with the\n// Alliance. The structure and organization of this software are the valuable\n// trade secrets of the Alliance and its suppliers. The software is also\n// protected by copyright law and international treaty provisions. Application\n// programs incorporating this software must include the following statement\n// with their copyright notices:\n//\n// This application incorporates Open Design Alliance software pursuant to a\n// license agreement with Open Design Alliance.\n// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.\n// All rights reserved.\n//\n// By use of this software, its documentation or related materials, you\n// acknowledge and accept the above terms.\n///////////////////////////////////////////////////////////////////////////////\n\nimport { Euler, Vector3 } from \"three\";\nimport { PointColorType, PointCloudOctree, PointSizeType, PointShape, Potree } from \"potree-core\";\nimport { Loader, Viewer } from \"@inweb/viewer-three\";\n\nimport { PotreeModelImpl } from \"./PotreeModelImpl\";\n\nexport type PotreeLoadParams = {\n path?: string;\n position?: Vector3;\n rotation?: Euler;\n scale?: Vector3;\n};\n\nexport class PotreeFileLoader extends Loader {\n public viewer: Viewer;\n public potree: Potree;\n public pointClouds: PointCloudOctree[];\n\n constructor(viewer: Viewer) {\n super();\n this.viewer = viewer;\n\n this.potree = new Potree();\n this.pointClouds = [];\n\n this.viewer.addEventListener(\"render\", this.updatePointClouds);\n this.viewer.addEventListener(\"changecamera\", this.updatePointClouds);\n }\n\n override dispose() {\n this.pointClouds.forEach((pco) => pco.dispose());\n\n this.viewer.removeEventListener(\"render\", this.updatePointClouds);\n this.viewer.removeEventListener(\"changecamera\", this.updatePointClouds);\n }\n\n override isSupport(file: any, format?: string): boolean {\n return typeof file === \"string\" && /(cloud.js|metadata.json)$/i.test(file);\n }\n\n override async load(file: any, format?: string, params: PotreeLoadParams = {}): Promise<this> {\n const path = (params.path || \"\") + file;\n const index = path.lastIndexOf(\"/\");\n const baseUrl = path.slice(0, index + 1);\n const url = path.slice(index + 1);\n\n const pco = await this.potree.loadPointCloud(url, baseUrl);\n pco.material.size = 1.0;\n pco.material.shape = 2;\n pco.material.inputColorEncoding = 1;\n pco.material.outputColorEncoding = 1;\n pco.material.pointColorType = PointColorType.RGB; // RGB | DEPTH | HEIGHT | POINT_INDEX | LOD | CLASSIFICATION\n pco.material.pointSizeType = PointSizeType.ADAPTIVE; // ADAPTIVE | FIXED\n pco.material.shape = PointShape.CIRCLE; // CIRCLE | SQUARE\n\n if (params.position) pco.position.copy(params.position);\n if (params.rotation) pco.rotation.copy(params.rotation);\n if (params.scale) pco.scale.copy(params.scale);\n\n this.pointClouds.push(pco);\n\n const modelImpl = new PotreeModelImpl(pco);\n modelImpl.loader = this;\n modelImpl.viewer = this.viewer;\n modelImpl.pco = pco;\n\n this.viewer.scene.add(pco);\n this.viewer.models.push(modelImpl);\n\n this.viewer.syncOptions();\n this.viewer.syncOverlay();\n this.viewer.update();\n\n this.viewer.emitEvent({ type: \"databasechunk\", data: pco, file });\n\n return this;\n }\n\n updatePointClouds = () => {\n const result = this.potree.updatePointClouds(this.pointClouds, this.viewer.camera, this.viewer.renderer);\n if (result.exceededMaxLoadsToGPU || result.nodeLoadPromises.length > 0) this.viewer.update();\n };\n}\n","///////////////////////////////////////////////////////////////////////////////\n// Copyright (C) 2002-2025, Open Design Alliance (the \"Alliance\").\n// All rights reserved.\n//\n// This software and its documentation and related materials are owned by\n// the Alliance. The software may only be incorporated into application\n// programs owned by members of the Alliance, subject to a signed\n// Membership Agreement and Supplemental Software License Agreement with the\n// Alliance. The structure and organization of this software are the valuable\n// trade secrets of the Alliance and its suppliers. The software is also\n// protected by copyright law and international treaty provisions. Application\n// programs incorporating this software must include the following statement\n// with their copyright notices:\n//\n// This application incorporates Open Design Alliance software pursuant to a\n// license agreement with Open Design Alliance.\n// Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.\n// All rights reserved.\n//\n// By use of this software, its documentation or related materials, you\n// acknowledge and accept the above terms.\n///////////////////////////////////////////////////////////////////////////////\n\nimport { loaders } from \"@inweb/viewer-three\";\n\nimport { PotreeFileLoader } from \"./PotreeFileLoader\";\n\nloaders.registerLoader(\"potree-file\", (viewer: any) => new PotreeFileLoader(viewer));\n"],"names":["PotreeModelImpl","ModelImpl","getExtents","target","union","this","pco","pcoGeometry","boundingBox","PotreeFileLoader","Loader","constructor","viewer","super","updatePointClouds","result","potree","pointClouds","camera","renderer","exceededMaxLoadsToGPU","nodeLoadPromises","length","update","Potree","addEventListener","dispose","forEach","removeEventListener","isSupport","file","format","test","load","params","path","index","lastIndexOf","baseUrl","slice","url","loadPointCloud","material","size","shape","inputColorEncoding","outputColorEncoding","pointColorType","PointColorType","RGB","pointSizeType","PointSizeType","ADAPTIVE","PointShape","CIRCLE","position","copy","rotation","scale","push","modelImpl","loader","scene","add","models","syncOptions","syncOverlay","emitEvent","type","data","loaders","registerLoader"],"mappings":";;;;AA6BM,MAAOA,wBAAwBC;IAG1B,UAAAC,CAAWC;QAClB,OAAOA,OAAOC,MAAMC,KAAKC,IAAIC,YAAYC;;;;ACGvC,MAAOC,yBAAyBC;IAKpC,WAAAC,CAAYC;QACVC;QA2DFR,KAAiBS,oBAAG;YAClB,MAAMC,SAASV,KAAKW,OAAOF,kBAAkBT,KAAKY,aAAaZ,KAAKO,OAAOM,QAAQb,KAAKO,OAAOO;YAC/F,IAAIJ,OAAOK,yBAAyBL,OAAOM,iBAAiBC,SAAS,GAAGjB,KAAKO,OAAOW;AAAQ;QA5D5FlB,KAAKO,SAASA;QAEdP,KAAKW,SAAS,IAAIQ;QAClBnB,KAAKY,cAAc;QAEnBZ,KAAKO,OAAOa,iBAAiB,UAAUpB,KAAKS;QAC5CT,KAAKO,OAAOa,iBAAiB,gBAAgBpB,KAAKS;;IAG3C,OAAAY;QACPrB,KAAKY,YAAYU,SAASrB,OAAQA,IAAIoB;QAEtCrB,KAAKO,OAAOgB,oBAAoB,UAAUvB,KAAKS;QAC/CT,KAAKO,OAAOgB,oBAAoB,gBAAgBvB,KAAKS;;IAG9C,SAAAe,CAAUC,MAAWC;QAC5B,cAAcD,SAAS,YAAY,6BAA6BE,KAAKF;;IAG9D,UAAMG,CAAKH,MAAWC,QAAiBG,SAA2B,CAAA;QACzE,MAAMC,QAAQD,OAAOC,QAAQ,MAAML;QACnC,MAAMM,QAAQD,KAAKE,YAAY;QAC/B,MAAMC,UAAUH,KAAKI,MAAM,GAAGH,QAAQ;QACtC,MAAMI,MAAML,KAAKI,MAAMH,QAAQ;QAE/B,MAAM9B,YAAYD,KAAKW,OAAOyB,eAAeD,KAAKF;QAClDhC,IAAIoC,SAASC,OAAO;QACpBrC,IAAIoC,SAASE,QAAQ;QACrBtC,IAAIoC,SAASG,qBAAqB;QAClCvC,IAAIoC,SAASI,sBAAsB;QACnCxC,IAAIoC,SAASK,iBAAiBC,eAAeC;QAC7C3C,IAAIoC,SAASQ,gBAAgBC,cAAcC;QAC3C9C,IAAIoC,SAASE,QAAQS,WAAWC;QAEhC,IAAIpB,OAAOqB,UAAUjD,IAAIiD,SAASC,KAAKtB,OAAOqB;QAC9C,IAAIrB,OAAOuB,UAAUnD,IAAImD,SAASD,KAAKtB,OAAOuB;QAC9C,IAAIvB,OAAOwB,OAAOpD,IAAIoD,MAAMF,KAAKtB,OAAOwB;QAExCrD,KAAKY,YAAY0C,KAAKrD;QAEtB,MAAMsD,YAAY,IAAI5D,gBAAgBM;QACtCsD,UAAUC,SAASxD;QACnBuD,UAAUhD,SAASP,KAAKO;QACxBgD,UAAUtD,MAAMA;QAEhBD,KAAKO,OAAOkD,MAAMC,IAAIzD;QACtBD,KAAKO,OAAOoD,OAAOL,KAAKC;QAExBvD,KAAKO,OAAOqD;QACZ5D,KAAKO,OAAOsD;QACZ7D,KAAKO,OAAOW;QAEZlB,KAAKO,OAAOuD,UAAU;YAAEC,MAAM;YAAiBC,MAAM/D;YAAKwB;;QAE1D,OAAOzB;;;;ACvEXiE,QAAQC,eAAe,gBAAgB3D,UAAgB,IAAIH,iBAAiBG"}
|
package/dist/viewer-three.js
CHANGED
|
@@ -80902,6 +80902,12 @@ void main() {
|
|
|
80902
80902
|
this.viewer.target.copy(this.orbit.target);
|
|
80903
80903
|
this.viewer.update();
|
|
80904
80904
|
switch (this.orbit.state) {
|
|
80905
|
+
case STATE.ROTATE:
|
|
80906
|
+
case STATE.TOUCH_ROTATE:
|
|
80907
|
+
this.viewer.emitEvent({
|
|
80908
|
+
type: "orbit",
|
|
80909
|
+
});
|
|
80910
|
+
break;
|
|
80905
80911
|
case STATE.PAN:
|
|
80906
80912
|
case STATE.TOUCH_PAN:
|
|
80907
80913
|
this.viewer.emitEvent({
|
|
@@ -80921,6 +80927,7 @@ void main() {
|
|
|
80921
80927
|
});
|
|
80922
80928
|
break;
|
|
80923
80929
|
}
|
|
80930
|
+
this.viewer.emitEvent({ type: "changecamera" });
|
|
80924
80931
|
this.changed = true;
|
|
80925
80932
|
};
|
|
80926
80933
|
this.stopContextMenu = (event) => {
|
|
@@ -81724,6 +81731,7 @@ void main() {
|
|
|
81724
81731
|
};
|
|
81725
81732
|
this.controlsChange = () => {
|
|
81726
81733
|
this.viewer.update();
|
|
81734
|
+
this.viewer.emitEvent({ type: "changecamera" });
|
|
81727
81735
|
};
|
|
81728
81736
|
this.walkspeedChange = (event) => {
|
|
81729
81737
|
this.viewer.emitEvent(event);
|
|
@@ -82047,32 +82055,32 @@ void main() {
|
|
|
82047
82055
|
function zoomTo(viewer, box) {
|
|
82048
82056
|
if (box.isEmpty())
|
|
82049
82057
|
return;
|
|
82050
|
-
const
|
|
82051
|
-
const
|
|
82058
|
+
const boxCenter = box.getCenter(new Vector3());
|
|
82059
|
+
const boxSize = box.getBoundingSphere(new Sphere()).radius;
|
|
82052
82060
|
const rendererSize = viewer.renderer.getSize(new Vector2());
|
|
82053
82061
|
const aspect = rendererSize.x / rendererSize.y;
|
|
82054
82062
|
const camera = viewer.camera;
|
|
82055
82063
|
if (camera.isPerspectiveCamera) {
|
|
82056
|
-
const offset = new Vector3(0, 0, 1)
|
|
82057
|
-
|
|
82058
|
-
|
|
82059
|
-
camera.position.copy(
|
|
82064
|
+
const offset = new Vector3(0, 0, 1)
|
|
82065
|
+
.applyQuaternion(camera.quaternion)
|
|
82066
|
+
.multiplyScalar(boxSize / Math.tan(MathUtils.DEG2RAD * camera.fov * 0.5));
|
|
82067
|
+
camera.position.copy(offset).add(boxCenter);
|
|
82060
82068
|
camera.updateMatrixWorld();
|
|
82061
82069
|
}
|
|
82062
82070
|
if (camera.isOrthographicCamera) {
|
|
82063
|
-
camera.top =
|
|
82064
|
-
camera.bottom = -
|
|
82071
|
+
camera.top = boxSize;
|
|
82072
|
+
camera.bottom = -boxSize;
|
|
82065
82073
|
camera.left = camera.bottom * aspect;
|
|
82066
82074
|
camera.right = camera.top * aspect;
|
|
82067
82075
|
camera.zoom = 1;
|
|
82068
82076
|
camera.updateProjectionMatrix();
|
|
82069
|
-
const offset = new Vector3(0, 0, 1)
|
|
82070
|
-
|
|
82071
|
-
|
|
82072
|
-
camera.position.copy(
|
|
82077
|
+
const offset = new Vector3(0, 0, 1)
|
|
82078
|
+
.applyQuaternion(camera.quaternion)
|
|
82079
|
+
.multiplyScalar(viewer.extents.getBoundingSphere(new Sphere()).radius * 3);
|
|
82080
|
+
camera.position.copy(offset).add(boxCenter);
|
|
82073
82081
|
camera.updateMatrixWorld();
|
|
82074
82082
|
}
|
|
82075
|
-
viewer.target.copy(
|
|
82083
|
+
viewer.target.copy(boxCenter);
|
|
82076
82084
|
viewer.update();
|
|
82077
82085
|
viewer.emitEvent({ type: "zoom" });
|
|
82078
82086
|
}
|
|
@@ -82100,27 +82108,30 @@ void main() {
|
|
|
82100
82108
|
// acknowledge and accept the above terms.
|
|
82101
82109
|
///////////////////////////////////////////////////////////////////////////////
|
|
82102
82110
|
const defaultViewPositions = {
|
|
82103
|
-
front: new Vector3(0, 0, 1),
|
|
82104
|
-
back: new Vector3(0, 0,
|
|
82105
|
-
left: new Vector3(
|
|
82106
|
-
right: new Vector3(1, 0, 0),
|
|
82111
|
+
front: new Vector3(0, 0, -1),
|
|
82112
|
+
back: new Vector3(0, 0, 1),
|
|
82113
|
+
left: new Vector3(1, 0, 0),
|
|
82114
|
+
right: new Vector3(-1, 0, 0),
|
|
82107
82115
|
bottom: new Vector3(0, -1, 0),
|
|
82108
82116
|
top: new Vector3(0, 1, 0),
|
|
82109
|
-
|
|
82110
|
-
sw: new Vector3(
|
|
82111
|
-
|
|
82112
|
-
|
|
82117
|
+
se: new Vector3(-1, 1, -1).normalize(),
|
|
82118
|
+
sw: new Vector3(1, 1, -1).normalize(),
|
|
82119
|
+
ne: new Vector3(-1, 1, 1).normalize(),
|
|
82120
|
+
nw: new Vector3(1, 1, 1).normalize(),
|
|
82113
82121
|
};
|
|
82114
82122
|
function setDefaultViewPosition(viewer, position) {
|
|
82115
|
-
const
|
|
82116
|
-
const
|
|
82117
|
-
const
|
|
82118
|
-
const
|
|
82123
|
+
const extentsCenter = viewer.extents.getCenter(new Vector3());
|
|
82124
|
+
const extentsSize = viewer.extents.getBoundingSphere(new Sphere()).radius * 2;
|
|
82125
|
+
const upY = new Vector3(0, 1, 0);
|
|
82126
|
+
const offsetY = defaultViewPositions[position] || defaultViewPositions["sw"];
|
|
82127
|
+
const up = new Vector3().copy(viewer.camera.up);
|
|
82128
|
+
const quaternion = new Quaternion().setFromUnitVectors(upY, up);
|
|
82129
|
+
const offset = new Vector3().copy(offsetY).applyQuaternion(quaternion);
|
|
82119
82130
|
const camera = viewer.camera;
|
|
82120
|
-
camera.position.copy(
|
|
82121
|
-
camera.lookAt(
|
|
82131
|
+
camera.position.copy(offset).multiplyScalar(extentsSize).add(extentsCenter);
|
|
82132
|
+
camera.lookAt(extentsCenter);
|
|
82122
82133
|
camera.updateMatrixWorld();
|
|
82123
|
-
viewer.target.copy(
|
|
82134
|
+
viewer.target.copy(extentsCenter);
|
|
82124
82135
|
viewer.update();
|
|
82125
82136
|
viewer.emit({ type: "viewposition", data: position });
|
|
82126
82137
|
zoomTo(viewer, viewer.extents);
|
|
@@ -82802,7 +82813,7 @@ void main() {
|
|
|
82802
82813
|
const extents = new Box3();
|
|
82803
82814
|
this.viewer.models.forEach((model) => model.getExtents(extents));
|
|
82804
82815
|
this.viewer.extents.copy(extents);
|
|
82805
|
-
extents.getCenter(this.viewer.target);
|
|
82816
|
+
this.viewer.extents.getCenter(this.viewer.target);
|
|
82806
82817
|
};
|
|
82807
82818
|
this.viewer = viewer;
|
|
82808
82819
|
this.viewer.addEventListener("databasechunk", this.syncExtents);
|
|
@@ -82857,12 +82868,13 @@ void main() {
|
|
|
82857
82868
|
return;
|
|
82858
82869
|
const extentsCenter = this.viewer.extents.getCenter(new Vector3());
|
|
82859
82870
|
const extentsSize = this.viewer.extents.getBoundingSphere(new Sphere()).radius;
|
|
82860
|
-
const
|
|
82861
|
-
|
|
82862
|
-
|
|
82863
|
-
|
|
82871
|
+
const upY = new Vector3(0, 1, 0);
|
|
82872
|
+
const frontY = new Vector3(0, 0, -1);
|
|
82873
|
+
const up = new Vector3().copy(this.viewer.camera.up);
|
|
82874
|
+
const quaternion = new Quaternion().setFromUnitVectors(upY, up);
|
|
82875
|
+
const front = new Vector3().copy(frontY).applyQuaternion(quaternion).negate();
|
|
82864
82876
|
this.directionalLight.position
|
|
82865
|
-
.copy(
|
|
82877
|
+
.copy(up)
|
|
82866
82878
|
.applyAxisAngle(front, (-Math.PI * 30) / 180)
|
|
82867
82879
|
.multiplyScalar(extentsSize * 2)
|
|
82868
82880
|
.add(extentsCenter);
|
|
@@ -82968,21 +82980,7 @@ void main() {
|
|
|
82968
82980
|
const { width, height } = entries[0].contentRect;
|
|
82969
82981
|
if (!width || !height)
|
|
82970
82982
|
return; // <- invisible viewer, or viewer with parent removed
|
|
82971
|
-
|
|
82972
|
-
const aspect = width / height;
|
|
82973
|
-
if (camera.isPerspectiveCamera) {
|
|
82974
|
-
camera.aspect = aspect;
|
|
82975
|
-
camera.updateProjectionMatrix();
|
|
82976
|
-
}
|
|
82977
|
-
if (camera.isOrthographicCamera) {
|
|
82978
|
-
camera.left = camera.bottom * aspect;
|
|
82979
|
-
camera.right = camera.top * aspect;
|
|
82980
|
-
camera.updateProjectionMatrix();
|
|
82981
|
-
}
|
|
82982
|
-
this.viewer.renderer.setSize(width, height, true);
|
|
82983
|
-
this.viewer.composer.setSize(width, height);
|
|
82984
|
-
this.viewer.update(true);
|
|
82985
|
-
this.viewer.emitEvent({ type: "resize", width, height });
|
|
82983
|
+
this.viewer.setSize(width, height);
|
|
82986
82984
|
};
|
|
82987
82985
|
this.viewer = viewer;
|
|
82988
82986
|
this.resizeObserver = new ResizeObserver(this.resizeViewer);
|
|
@@ -84462,9 +84460,9 @@ void main() {
|
|
|
84462
84460
|
this.size = 160;
|
|
84463
84461
|
this.orthoCamera = new OrthographicCamera(-2, 2, 2, -2, 0, 4);
|
|
84464
84462
|
this.orthoCamera.position.set(0, 0, 2);
|
|
84465
|
-
const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
84466
|
-
const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
84467
|
-
const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#
|
|
84463
|
+
const matRed = new MeshBasicMaterial({ toneMapped: false, color: "#dd0000" });
|
|
84464
|
+
const matGreen = new MeshBasicMaterial({ toneMapped: false, color: "#00dd00" });
|
|
84465
|
+
const matBlue = new MeshBasicMaterial({ toneMapped: false, color: "#0000dd" });
|
|
84468
84466
|
const spriteRed = this.getSpriteMaterial(matRed.color, "X");
|
|
84469
84467
|
const spriteGreen = this.getSpriteMaterial(matGreen.color, "Y");
|
|
84470
84468
|
const spriteBlue = this.getSpriteMaterial(matBlue.color, "Z");
|
|
@@ -90265,11 +90263,12 @@ void main() {
|
|
|
90265
90263
|
const MAX_CHUNK = 30 * 1024 * 1024; // 100 MB
|
|
90266
90264
|
|
|
90267
90265
|
class GltfStructure {
|
|
90268
|
-
constructor(id) {
|
|
90266
|
+
constructor(id, loadController) {
|
|
90269
90267
|
this.id = `${id}`;
|
|
90270
90268
|
this.json = null;
|
|
90271
90269
|
this.baseUrl = "";
|
|
90272
|
-
this.loadController =
|
|
90270
|
+
this.loadController = loadController;
|
|
90271
|
+
this.loader = null;
|
|
90273
90272
|
this.batchDelay = 10;
|
|
90274
90273
|
this.maxBatchSize = 5 * 1024 * 1024;
|
|
90275
90274
|
this.maxRangesPerRequest = 512;
|
|
@@ -90281,10 +90280,10 @@ void main() {
|
|
|
90281
90280
|
this.materialCache = new Map();
|
|
90282
90281
|
}
|
|
90283
90282
|
|
|
90284
|
-
async initialize(
|
|
90285
|
-
this.json = await loadController.loadJson();
|
|
90286
|
-
this.baseUrl = await loadController.baseUrl();
|
|
90287
|
-
this.
|
|
90283
|
+
async initialize(loader) {
|
|
90284
|
+
this.json = await this.loadController.loadJson();
|
|
90285
|
+
this.baseUrl = await this.loadController.baseUrl();
|
|
90286
|
+
this.loader = loader;
|
|
90288
90287
|
}
|
|
90289
90288
|
|
|
90290
90289
|
clear() {
|
|
@@ -90297,10 +90296,12 @@ void main() {
|
|
|
90297
90296
|
this.batchTimeout = null;
|
|
90298
90297
|
}
|
|
90299
90298
|
|
|
90300
|
-
// Clear materials and textures
|
|
90301
90299
|
this.disposeMaterials();
|
|
90302
90300
|
this.textureCache.clear();
|
|
90303
90301
|
this.materials.clear();
|
|
90302
|
+
|
|
90303
|
+
this.activeChunkLoads = 0;
|
|
90304
|
+
this.chunkQueue = [];
|
|
90304
90305
|
}
|
|
90305
90306
|
|
|
90306
90307
|
getJson() {
|
|
@@ -90379,35 +90380,32 @@ void main() {
|
|
|
90379
90380
|
finalRanges.push({ start, end, requests });
|
|
90380
90381
|
}
|
|
90381
90382
|
}
|
|
90382
|
-
/*
|
|
90383
|
-
for (const range of finalRanges) {
|
|
90384
|
-
const length = range.end - range.start;
|
|
90385
|
-
const buffer = await this.loadController.loadBinaryData([
|
|
90386
|
-
{ offset: range.start, length: length }
|
|
90387
|
-
]);
|
|
90388
|
-
for (const req of range.requests) {
|
|
90389
|
-
const relOffset = req.offset - range.start;
|
|
90390
|
-
try {
|
|
90391
|
-
req._resolve({ buffer, relOffset, length: req.length });
|
|
90392
|
-
} catch (e) {
|
|
90393
|
-
req._reject(e);
|
|
90394
|
-
}
|
|
90395
|
-
}
|
|
90396
|
-
}
|
|
90397
|
-
*/
|
|
90398
90383
|
|
|
90399
|
-
const promises = finalRanges.map(async (range) => {
|
|
90400
|
-
|
|
90401
|
-
|
|
90402
|
-
|
|
90403
|
-
const
|
|
90404
|
-
|
|
90405
|
-
|
|
90406
|
-
|
|
90407
|
-
req.
|
|
90384
|
+
const promises = finalRanges.map(async (range, index) => {
|
|
90385
|
+
await this.loader.waitForChunkSlot();
|
|
90386
|
+
|
|
90387
|
+
try {
|
|
90388
|
+
const length = range.end - range.start;
|
|
90389
|
+
const buffer = await this.loadController.loadBinaryData([{ offset: range.start, length }]);
|
|
90390
|
+
|
|
90391
|
+
for (const req of range.requests) {
|
|
90392
|
+
const relOffset = req.offset - range.start;
|
|
90393
|
+
try {
|
|
90394
|
+
req._resolve({ buffer, relOffset, length: req.length });
|
|
90395
|
+
} catch (e) {
|
|
90396
|
+
req._reject(e);
|
|
90397
|
+
}
|
|
90408
90398
|
}
|
|
90399
|
+
} catch (error) {
|
|
90400
|
+
for (const req of range.requests) {
|
|
90401
|
+
req._reject(error);
|
|
90402
|
+
}
|
|
90403
|
+
console.warn(`Failed to load chunk ${index + 1}/${finalRanges.length} (${range.start}-${range.end}):`, error);
|
|
90404
|
+
} finally {
|
|
90405
|
+
this.loader.releaseChunkSlot();
|
|
90409
90406
|
}
|
|
90410
90407
|
});
|
|
90408
|
+
|
|
90411
90409
|
await Promise.all(promises);
|
|
90412
90410
|
|
|
90413
90411
|
this.pendingRequests = [];
|
|
@@ -90825,6 +90823,10 @@ void main() {
|
|
|
90825
90823
|
this.hiddenHandles = new Set();
|
|
90826
90824
|
this.newOptimizedObjects = new Set();
|
|
90827
90825
|
this.oldOptimizeObjects = new Set();
|
|
90826
|
+
|
|
90827
|
+
this.maxConcurrentChunks = 8;
|
|
90828
|
+
this.activeChunkLoads = 0;
|
|
90829
|
+
this.chunkQueue = [];
|
|
90828
90830
|
}
|
|
90829
90831
|
|
|
90830
90832
|
setVisibleEdges(visible) {
|
|
@@ -91234,6 +91236,7 @@ void main() {
|
|
|
91234
91236
|
const structureArray = Array.isArray(structures) ? structures : [structures];
|
|
91235
91237
|
|
|
91236
91238
|
for (const structure of structureArray) {
|
|
91239
|
+
await structure.initialize(this);
|
|
91237
91240
|
this.structures.push(structure);
|
|
91238
91241
|
}
|
|
91239
91242
|
|
|
@@ -91625,13 +91628,6 @@ void main() {
|
|
|
91625
91628
|
this.nodesToLoad = [];
|
|
91626
91629
|
}
|
|
91627
91630
|
|
|
91628
|
-
async addStructure(loadController) {
|
|
91629
|
-
const structure = new GltfStructure();
|
|
91630
|
-
await structure.initialize(loadController);
|
|
91631
|
-
this.structures.push(structure);
|
|
91632
|
-
return structure;
|
|
91633
|
-
}
|
|
91634
|
-
|
|
91635
91631
|
removeOptimization() {
|
|
91636
91632
|
this.originalObjects.forEach((obj) => (obj.visible = true));
|
|
91637
91633
|
|
|
@@ -91663,7 +91659,8 @@ void main() {
|
|
|
91663
91659
|
}
|
|
91664
91660
|
|
|
91665
91661
|
clear() {
|
|
91666
|
-
|
|
91662
|
+
this.chunkQueue = [];
|
|
91663
|
+
|
|
91667
91664
|
this.structures.forEach((structure) => {
|
|
91668
91665
|
if (structure) {
|
|
91669
91666
|
structure.clear();
|
|
@@ -91704,7 +91701,6 @@ void main() {
|
|
|
91704
91701
|
});
|
|
91705
91702
|
this.loadedMeshes.clear();
|
|
91706
91703
|
|
|
91707
|
-
// Clear all structure roots and their children
|
|
91708
91704
|
this.structureRoots.forEach((rootGroup) => {
|
|
91709
91705
|
if (rootGroup) {
|
|
91710
91706
|
rootGroup.traverse((child) => {
|
|
@@ -91724,7 +91720,6 @@ void main() {
|
|
|
91724
91720
|
});
|
|
91725
91721
|
this.structureRoots.clear();
|
|
91726
91722
|
|
|
91727
|
-
// Clear all optimized objects
|
|
91728
91723
|
this.mergedMesh.forEach((mesh) => {
|
|
91729
91724
|
if (mesh.geometry) mesh.geometry.dispose();
|
|
91730
91725
|
if (mesh.material) {
|
|
@@ -92477,7 +92472,6 @@ void main() {
|
|
|
92477
92472
|
});
|
|
92478
92473
|
}
|
|
92479
92474
|
|
|
92480
|
-
// Возвращает bounding box для конкретной структуры
|
|
92481
92475
|
getStructureGeometryExtent(structureId) {
|
|
92482
92476
|
const extent = new Box3();
|
|
92483
92477
|
for (const [nodeId, node] of this.nodes.entries()) {
|
|
@@ -92495,6 +92489,35 @@ void main() {
|
|
|
92495
92489
|
}
|
|
92496
92490
|
return extent;
|
|
92497
92491
|
}
|
|
92492
|
+
|
|
92493
|
+
setMaxConcurrentChunks(maxChunks) {
|
|
92494
|
+
if (maxChunks < 1) {
|
|
92495
|
+
console.warn("Max concurrent chunks must be at least 1");
|
|
92496
|
+
return;
|
|
92497
|
+
}
|
|
92498
|
+
this.maxConcurrentChunks = maxChunks;
|
|
92499
|
+
}
|
|
92500
|
+
|
|
92501
|
+
waitForChunkSlot() {
|
|
92502
|
+
if (this.activeChunkLoads < this.maxConcurrentChunks) {
|
|
92503
|
+
this.activeChunkLoads++;
|
|
92504
|
+
return Promise.resolve();
|
|
92505
|
+
}
|
|
92506
|
+
|
|
92507
|
+
return new Promise((resolve) => {
|
|
92508
|
+
this.chunkQueue.push(resolve);
|
|
92509
|
+
});
|
|
92510
|
+
}
|
|
92511
|
+
|
|
92512
|
+
releaseChunkSlot() {
|
|
92513
|
+
this.activeChunkLoads--;
|
|
92514
|
+
|
|
92515
|
+
if (this.chunkQueue.length > 0) {
|
|
92516
|
+
const nextResolve = this.chunkQueue.shift();
|
|
92517
|
+
this.activeChunkLoads++;
|
|
92518
|
+
nextResolve();
|
|
92519
|
+
}
|
|
92520
|
+
}
|
|
92498
92521
|
}
|
|
92499
92522
|
|
|
92500
92523
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -92540,6 +92563,7 @@ void main() {
|
|
|
92540
92563
|
this.gltfLoader = new DynamicGltfLoader(this.viewer.camera, scene, this.viewer.renderer);
|
|
92541
92564
|
this.gltfLoader.memoryLimit = this.viewer.options.memoryLimit;
|
|
92542
92565
|
this.gltfLoader.setVisibleEdges(this.viewer.options.edgeModel);
|
|
92566
|
+
// this.gltfLoader.setMaxConcurrentChunks(this.viewer.options.maxConcurrentChunks);
|
|
92543
92567
|
this.gltfLoader.addEventListener("databasechunk", (data) => {
|
|
92544
92568
|
const modelImpl = new DynamicModelImpl(scene);
|
|
92545
92569
|
modelImpl.loader = this;
|
|
@@ -92583,8 +92607,7 @@ void main() {
|
|
|
92583
92607
|
},
|
|
92584
92608
|
baseUrl: () => Promise.resolve(`${model.httpClient.serverUrl}${model.path}/`),
|
|
92585
92609
|
};
|
|
92586
|
-
const structure = new GltfStructure(model.id);
|
|
92587
|
-
await structure.initialize(loadController);
|
|
92610
|
+
const structure = new GltfStructure(model.id, loadController);
|
|
92588
92611
|
await this.gltfLoader.loadStructure(structure);
|
|
92589
92612
|
await this.gltfLoader.loadNodes();
|
|
92590
92613
|
return this;
|
|
@@ -109764,7 +109787,7 @@ void main() {
|
|
|
109764
109787
|
this.target = new Vector3();
|
|
109765
109788
|
this._activeDragger = null;
|
|
109766
109789
|
this._components = [];
|
|
109767
|
-
this.
|
|
109790
|
+
this._renderTime = 0;
|
|
109768
109791
|
this.render = this.render.bind(this);
|
|
109769
109792
|
this.update = this.update.bind(this);
|
|
109770
109793
|
this._markup = new KonvaMarkup();
|
|
@@ -109790,13 +109813,13 @@ void main() {
|
|
|
109790
109813
|
this.addEventListener("optionschange", (event) => this.syncOptions(event.data));
|
|
109791
109814
|
this.scene = new Scene();
|
|
109792
109815
|
this.helpers = new Helpers();
|
|
109793
|
-
this.target = new Vector3();
|
|
109816
|
+
this.target = new Vector3(0, 0, 0);
|
|
109794
109817
|
const pixelRatio = window.devicePixelRatio;
|
|
109795
109818
|
const rect = canvas.parentElement.getBoundingClientRect();
|
|
109796
109819
|
const width = rect.width || 1;
|
|
109797
109820
|
const height = rect.height || 1;
|
|
109798
109821
|
const aspect = width / height;
|
|
109799
|
-
this.camera = new PerspectiveCamera(45, aspect, 0.
|
|
109822
|
+
this.camera = new PerspectiveCamera(45, aspect, 0.001, 1000);
|
|
109800
109823
|
this.camera.up.set(0, 1, 0);
|
|
109801
109824
|
this.camera.position.set(0, 0, 1);
|
|
109802
109825
|
this.camera.lookAt(this.target);
|
|
@@ -109828,6 +109851,7 @@ void main() {
|
|
|
109828
109851
|
this.composer.addPass(this.fxaaPass);
|
|
109829
109852
|
this.composer.addPass(this.ssaaRenderPass);
|
|
109830
109853
|
this.composer.addPass(this.outputPass);
|
|
109854
|
+
this.composer.setSize(width, height);
|
|
109831
109855
|
this.canvas = canvas;
|
|
109832
109856
|
this.canvasEvents.forEach((x) => canvas.addEventListener(x, this.canvaseventlistener));
|
|
109833
109857
|
this._markup.initialize(this.canvas, this.canvasEvents, this, this);
|
|
@@ -109836,8 +109860,8 @@ void main() {
|
|
|
109836
109860
|
}
|
|
109837
109861
|
this.syncOptions();
|
|
109838
109862
|
this.syncOverlay();
|
|
109839
|
-
this.
|
|
109840
|
-
this.render(this.
|
|
109863
|
+
this._renderTime = performance.now();
|
|
109864
|
+
this.render(this._renderTime);
|
|
109841
109865
|
if (typeof onProgress === "function")
|
|
109842
109866
|
onProgress(new ProgressEvent("progress", { lengthComputable: true, loaded: 1, total: 1 }));
|
|
109843
109867
|
this.emitEvent({ type: "initializeprogress", data: 1, loaded: 1, total: 1 });
|
|
@@ -109889,8 +109913,27 @@ void main() {
|
|
|
109889
109913
|
isInitialized() {
|
|
109890
109914
|
return !!this.renderer;
|
|
109891
109915
|
}
|
|
109916
|
+
setSize(width, height, updateStyle = true) {
|
|
109917
|
+
if (!this.renderer)
|
|
109918
|
+
return;
|
|
109919
|
+
const camera = this.camera;
|
|
109920
|
+
const aspect = width / height;
|
|
109921
|
+
if (camera.isPerspectiveCamera) {
|
|
109922
|
+
camera.aspect = aspect;
|
|
109923
|
+
camera.updateProjectionMatrix();
|
|
109924
|
+
}
|
|
109925
|
+
if (camera.isOrthographicCamera) {
|
|
109926
|
+
camera.left = camera.bottom * aspect;
|
|
109927
|
+
camera.right = camera.top * aspect;
|
|
109928
|
+
camera.updateProjectionMatrix();
|
|
109929
|
+
}
|
|
109930
|
+
this.renderer.setSize(width, height, updateStyle);
|
|
109931
|
+
this.composer.setSize(width, height);
|
|
109932
|
+
this.update(true);
|
|
109933
|
+
this.emitEvent({ type: "resize", width, height });
|
|
109934
|
+
}
|
|
109892
109935
|
update(force = false) {
|
|
109893
|
-
this.
|
|
109936
|
+
this._renderNeeded = true;
|
|
109894
109937
|
if (force)
|
|
109895
109938
|
this.render();
|
|
109896
109939
|
this.emitEvent({ type: "update", data: force });
|
|
@@ -109899,13 +109942,13 @@ void main() {
|
|
|
109899
109942
|
var _a, _b;
|
|
109900
109943
|
if (!this.renderer)
|
|
109901
109944
|
return;
|
|
109902
|
-
if (!
|
|
109945
|
+
if (!this._renderNeeded && !force)
|
|
109903
109946
|
return;
|
|
109904
109947
|
if (!time)
|
|
109905
109948
|
time = performance.now();
|
|
109906
|
-
const deltaTime = (time - this.
|
|
109907
|
-
this.
|
|
109908
|
-
this.
|
|
109949
|
+
const deltaTime = (time - this._renderTime) / 1000;
|
|
109950
|
+
this._renderTime = time;
|
|
109951
|
+
this._renderNeeded = false;
|
|
109909
109952
|
if (this.options.antialiasing === true || this.options.antialiasing === "msaa") {
|
|
109910
109953
|
this.renderer.render(this.scene, this.camera);
|
|
109911
109954
|
this.renderer.render(this.helpers, this.camera);
|
|
@@ -110202,7 +110245,7 @@ void main() {
|
|
|
110202
110245
|
camera.left = camera.bottom * aspect;
|
|
110203
110246
|
camera.right = camera.top * aspect;
|
|
110204
110247
|
camera.near = 0;
|
|
110205
|
-
camera.far = extentsSize *
|
|
110248
|
+
camera.far = extentsSize * 1000;
|
|
110206
110249
|
camera.zoom = orthogonal_camera.view_to_world_scale;
|
|
110207
110250
|
camera.updateProjectionMatrix();
|
|
110208
110251
|
camera.up.copy(getVector3FromPoint3d(orthogonal_camera.up_vector));
|
|
@@ -110223,8 +110266,8 @@ void main() {
|
|
|
110223
110266
|
const camera = new PerspectiveCamera();
|
|
110224
110267
|
camera.fov = perspective_camera.field_of_view;
|
|
110225
110268
|
camera.aspect = aspect;
|
|
110226
|
-
camera.near = extentsSize /
|
|
110227
|
-
camera.far = extentsSize *
|
|
110269
|
+
camera.near = extentsSize / 1000;
|
|
110270
|
+
camera.far = extentsSize * 1000;
|
|
110228
110271
|
camera.updateProjectionMatrix();
|
|
110229
110272
|
camera.up.copy(getVector3FromPoint3d(perspective_camera.up_vector));
|
|
110230
110273
|
camera.position.copy(getVector3FromPoint3d(perspective_camera.view_point));
|