import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
/**
* Camera class for managing the perspective camera and its controls.
* Uses Three.js for 3D rendering and interaction.
*
* @class
*/
class Camera {
/**
* Creates an instance of Camera.
* Initializes the camera and controls.
*
* @param {Simulator} simulator - The simulator instance containing scene, canvas, and sizes.
* @constructor
*/
constructor(simulator) {
this.simulator = simulator;
this.scene = this.simulator.scene;
this.canvas = this.simulator.canvas;
this.sizes = this.simulator.sizes;
this.isFreeCamera = false;
this.setInstance();
this.setControls();
}
/**
* Initializes the perspective camera instance.
* Sets up the camera position and adds it to the scene.
*
* @private
*/
setInstance() {
this.instance = new THREE.PerspectiveCamera(75, this.sizes.width / this.sizes.height, 0.1, 10000);
this.instance.position.set(-30, 20, -30);
this.scene.add(this.instance);
}
/**
* Initializes the OrbitControls for camera interaction.
* Configures the controls and attaches them to the camera.
*
* @private
*/
setControls() {
this.controls = new OrbitControls(this.instance, this.canvas);
this.controls.enablePan = false;
this.controls.enableDamping = true;
this.controls.maxDistance = 150;
this.controls.listenToKeyEvents(window);
}
/**
* Resize the camera aspect ratio when the simulator size changes.
*
* @public
*/
resize() {
this.instance.aspect = this.sizes.width / this.sizes.height;
this.instance.updateProjectionMatrix();
}
switchCamera() {
if (this.isFreeCamera) {
// Convert to orbit
this.controls.enabled = true;
document.exitPointerLock();
this.controls = new OrbitControls(this.instance, this.canvas);
this.controls.enablePan = false;
this.controls.enableDamping = true;
this.controls.maxDistance = 150;
this.controls.listenToKeyEvents(window);
} else {
// Convert to free
this.controls.target = this.instance.position
this.controls.enabled = false;
this.simulator.renderer.instance.domElement.requestPointerLock();
}
this.isFreeCamera = !this.isFreeCamera;
}
/**
* Update the camera controls.
*
* @public
*/
update() {
this.controls.update();
}
/**
* Update the target for the camera controls.
*
* @param {THREE.Vector3} target - The new target position for the camera.
* @public
*/
updateTarget(target) {
if (!this.isFreeCamera) {
this.controls.target = target;
}
}
/**
* Disposes of the camera controls and cleans up resources.
*
* This method disposes the OrbitControls instance, ensuring all associated
* resources are properly released to avoid memory leaks.
*
* @public
*/
dispose() {
this.controls.dispose();
}
/**
* Returns the instance of the perspective camera.
*
* This method provides access to the internal THREE.PerspectiveCamera instance,
* allowing external classes or functions to interact with the camera directly.
*
* @returns {THREE.PerspectiveCamera} The perspective camera instance.
* @public
*/
getInstance() {
return this.instance;
}
}
export default Camera;