You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
3.9 KiB
JavaScript

/* Copyright (C) 2024 Sebastián Santisi <ssantisi@fi.uba.ar>, CSC-CONICET */
import * as THREE from 'three';
class Screen {
static isMobile = 'ontouchstart' in document.documentElement;
constructor(camera, renderer, center) {
this.camera = camera;
this.renderer = renderer;
this.center = center;
this.cbmove = null;
this.raycaster = new THREE.Raycaster();
this.pointerScreen = new THREE.Vector2();
this.pointerWorld = new THREE.Vector3();
this.radius = 26;
this.phi = -0.5;
this.theta = 0.45;
this.z = 15;
this.aspect = 1.94;
this.clicked = false;
this.camera.setFocalLength(60);
if(Screen.isMobile) {
window.addEventListener('touchstart', (event) => { this.onClick(event); });
window.addEventListener('touchend', (event) => { this.onMouseUp(event); });
window.addEventListener('touchmove', (event) => { this.onPointerMove(event); });
}
else {
window.addEventListener('mouseup', (event) => { this.onMouseUp(event); });
window.addEventListener('mousedown', (event) => { this.onClick(event); });
window.addEventListener('pointermove', (event) => { this.onPointerMove(event); });
}
window.addEventListener('resize', () => { this.onResize(); });
}
setMoveCallBack(cbmove) {
this.cbmove = cbmove;
}
updatePointers(event) {
if(Screen.isMobile) {
var touch = event.touches[0] || event.changedTouches[0];
var x = touch.pageX;
var y = touch.pageY;
}
else {
var x = event.clientX
var y = event.clientY;
}
this.pointerScreen.x = (x / window.innerWidth) * 2 - 1;
this.pointerScreen.y = -(y / window.innerHeight) * 2 + 1;
this.raycaster.setFromCamera(this.pointerScreen, this.camera);
var point = new THREE.Vector3(this.pointerScreen.x, this.pointerScreen.y, 0.5);
point.unproject(this.camera);
point.sub(this.camera.position).normalize();
var distance = -this.camera.position.z / point.z;
this.pointerWorld.copy(this.camera.position).add(point.multiplyScalar(distance));
}
onClick(event) {
this.clicked = true;
this.updatePointers(event);
}
onMouseUp(event) {
this.clicked = false;
this.updatePointers(event);
ws.move(this.pointerWorld, true);
if(this.cbmove)
this.cbmove(this.pointerWorld, true);
}
onPointerMove(event) {
this.updatePointers(event);
if(this.clicked) {
if(this.cbmove)
this.cbmove(this.pointerWorld, false);
}
}
onResize() {
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.fov = 15;
this.camera.updateProjectionMatrix();
var r;
if(this.camera.aspect > this.aspect)
r = this.radius;
else {
r = this.radius * this.aspect / this.camera.aspect;
}
this.renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById("container").style.height = window.innerHeight;
document.getElementById("container").style.width = window.innerWidth;
document.getElementById("rotate").style.display = this.camera.aspect > 1 ? "none" : "block";
var theta = Math.PI / 2 - this.theta;
var phi = this.phi - Math.PI / 2;
var x = r * Math.sin(theta) * Math.cos(phi) + this.center.x;
var y = r * Math.sin(theta) * Math.sin(phi) + this.center.y;
var z = r * Math.cos(theta) + this.center.z;
this.camera.position.set(x, y, z);
this.camera.up = new THREE.Vector3(0,0,1);
this.camera.lookAt(this.center);
this.raycaster.setFromCamera(this.pointerScreen, this.camera);
}
}
export { Screen };