1 | "use strict"; |
---|
2 | import * as THREE from 'three'; |
---|
3 | |
---|
4 | const OrbitControls = require('three-orbit-controls')(THREE); |
---|
5 | |
---|
6 | /** |
---|
7 | * Class for creating camera object in THREE.js view. it uses OrbitControls for |
---|
8 | * user moving. It is designed to work with model analysis. |
---|
9 | */ |
---|
10 | class Camera { |
---|
11 | /** |
---|
12 | * Method for Camera initialization. It's adjusting the view according to |
---|
13 | * camera resize, prepares OrbitControls as default controller. |
---|
14 | */ |
---|
15 | init() { |
---|
16 | this.perspectiveCamera = new THREE.PerspectiveCamera( |
---|
17 | this.config.fieldOfView, |
---|
18 | window.innerWidth / window.innerHeight, |
---|
19 | this.config.near, |
---|
20 | this.config.far |
---|
21 | ); |
---|
22 | this.perspectiveCamera.up.set(0,0,1); |
---|
23 | this.cameraControl = new OrbitControls(this.perspectiveCamera, this.rendererDOMElement); |
---|
24 | this.cameraControl.autoRotate = this.autoRotate; |
---|
25 | this.cameraControl.autoRotateSpeed = this.config.autoRotateSpeed; |
---|
26 | this.cameraControl.enableKeys = false; |
---|
27 | } |
---|
28 | |
---|
29 | /** |
---|
30 | * Creates instance of camera, then initalizes it with init() method |
---|
31 | * @param {{fieldOfView: number, near: number, far: number}} config Configuration of Camera view |
---|
32 | * @param {Element} rendererDOMElement Canvas in which element will be drawn. |
---|
33 | * @param {boolean} autoRotate true if camera should rotate, false otherwise |
---|
34 | */ |
---|
35 | constructor(config, rendererDOMElement, autoRotate) { |
---|
36 | this.config = config; |
---|
37 | this.rendererDOMElement = rendererDOMElement; |
---|
38 | this.autoRotate = autoRotate; |
---|
39 | this.perspectiveCamera = null; |
---|
40 | this.cameraControl = null; |
---|
41 | this.init(); |
---|
42 | } |
---|
43 | |
---|
44 | /** |
---|
45 | * Method for updating modelBox coordinates |
---|
46 | * @param {{min: {x: number, y: number, z: number}, max: {x: number, y: number, z: number}}} modelBox Bounding box of Model |
---|
47 | * @param {{min: {x: number, y: number, z: number}, max: {x: number, y: number, z: number}}} box update of bounding box |
---|
48 | */ |
---|
49 | updateModelBox(modelBox, box) { |
---|
50 | modelBox.min.x = Math.min( modelBox.min.x, box.min.x ); |
---|
51 | modelBox.min.y = Math.min( modelBox.min.y, box.min.y ); |
---|
52 | modelBox.min.z = Math.min( modelBox.min.z, box.min.z ); |
---|
53 | |
---|
54 | modelBox.max.x = Math.max( modelBox.max.x, box.max.x ); |
---|
55 | modelBox.max.y = Math.max( modelBox.max.y, box.max.y ); |
---|
56 | modelBox.max.z = Math.max( modelBox.max.z, box.max.z ); |
---|
57 | } |
---|
58 | |
---|
59 | /** |
---|
60 | * Extracts bounding box of given object. |
---|
61 | * @param {Object3D} object object for which bounding box is extracted |
---|
62 | * @returns {Box3} bounding box of object |
---|
63 | */ |
---|
64 | getBoundingBox(object) { |
---|
65 | let box = new THREE.Box3(); |
---|
66 | box.setFromObject(object); |
---|
67 | return box; |
---|
68 | } |
---|
69 | |
---|
70 | /** |
---|
71 | * Calculates Camera position and rotation that should be used in order to see all meshes in scene. |
---|
72 | * @param {Mesh[]} meshes list of meshes to be bound by camera. |
---|
73 | * @returns {{target: {x: number, y: number, z: number}, position: {x: number, y: number, z: number}}} new position of Camera and target, to which Camera should point |
---|
74 | */ |
---|
75 | calculateCameraSetting(meshes) { |
---|
76 | if (meshes.length == 0) { |
---|
77 | return this.config.defaultSettings; |
---|
78 | } |
---|
79 | |
---|
80 | let modelBox = new THREE.Box3(); |
---|
81 | for (let i = 0; i < meshes.length; i++) { |
---|
82 | let mesh = meshes[i]; |
---|
83 | let box = this.getBoundingBox(mesh); |
---|
84 | this.updateModelBox(modelBox, box); |
---|
85 | } |
---|
86 | |
---|
87 | let modelSphere = modelBox.getBoundingSphere(); |
---|
88 | |
---|
89 | this.targetPosition = modelSphere.center.clone(); |
---|
90 | this.cameraPosition = modelSphere.center.clone().addScalar(modelSphere.radius); |
---|
91 | |
---|
92 | return { |
---|
93 | target: { |
---|
94 | x: modelSphere.center.x, |
---|
95 | y: modelSphere.center.y, |
---|
96 | z: modelSphere.center.z |
---|
97 | }, |
---|
98 | position: { |
---|
99 | x: modelSphere.center.x + modelSphere.radius, |
---|
100 | y: modelSphere.center.y + modelSphere.radius, |
---|
101 | z: modelSphere.center.z + modelSphere.radius |
---|
102 | } |
---|
103 | }; |
---|
104 | } |
---|
105 | |
---|
106 | /** |
---|
107 | * Moves Camera to cover all selected meshes in canvas. |
---|
108 | * @param {Mesh[]} meshes list of meshes to be seen |
---|
109 | */ |
---|
110 | zoomAll(meshes) { |
---|
111 | let settings = this.calculateCameraSetting(meshes); |
---|
112 | this.cameraControl.target.set(settings.target.x, settings.target.y, settings.target.z); |
---|
113 | this.perspectiveCamera.position.set(settings.position.x, settings.position.y, settings.position.z); |
---|
114 | this.cameraControl.update(); |
---|
115 | } |
---|
116 | |
---|
117 | /** |
---|
118 | * Getter for THREE.js perspective camera logic. |
---|
119 | * @returns {PerspectiveCamera} reference to Camera perspective camera |
---|
120 | */ |
---|
121 | getPerspectiveCamera() { |
---|
122 | return this.perspectiveCamera; |
---|
123 | } |
---|
124 | |
---|
125 | /** |
---|
126 | * Getter for THREE.js orbit controls logic. |
---|
127 | * @returns {OrbitControls} reference to Camera orbit controls |
---|
128 | */ |
---|
129 | getCameraControl() { |
---|
130 | return this.cameraControl; |
---|
131 | } |
---|
132 | |
---|
133 | /** |
---|
134 | * Sets the camera autorotation property. |
---|
135 | * @param {boolean} autoRotate true if camera should autorotate, false otherwise |
---|
136 | */ |
---|
137 | setAutoRotate(autoRotate) { |
---|
138 | this.autoRotate = autoRotate; |
---|
139 | this.cameraControl.autoRotate = this.autoRotate; |
---|
140 | } |
---|
141 | } |
---|
142 | |
---|
143 | export default Camera; |
---|