Fix: Vistas isométricas con quaternions fijos para evitar degradación

- Precálculo de quaternions para cada vista (N, S, E, W)
- Eliminado uso de lookAt() en cambios de vista
- Uso de Vector3 nativos de Three.js
- Sistema completamente determinista sin acumulación de errores
This commit is contained in:
2025-12-21 00:25:30 +01:00
parent 38960df5d9
commit 92fdfed49c

View File

@@ -157,27 +157,54 @@ document.querySelector('#app').appendChild(renderer.domElement);
// Cámara isométrica (zoom más cercano)
const aspect = window.innerWidth / window.innerHeight;
const d = 8; // Reducido de 10 a 8 para zoom aún más cercano
const d = 8;
const camera = new THREE.OrthographicCamera(-d * aspect, d * aspect, d, -d, 1, 1000);
// Vistas isométricas predefinidas
// Vistas isométricas COMPLETAMENTE predefinidas (sin acumulación de errores)
// Cada vista tiene posición, target Y quaternion fijo
const CAMERA_VIEWS = {
N: { position: { x: 20, y: 20, z: 20 }, target: { x: 0, y: 0, z: 0 } }, // Norte (default)
S: { position: { x: -20, y: 20, z: -20 }, target: { x: 0, y: 0, z: 0 } }, // Sur
E: { position: { x: -20, y: 20, z: 20 }, target: { x: 0, y: 0, z: 0 } }, // Este
W: { position: { x: 20, y: 20, z: -20 }, target: { x: 0, y: 0, z: 0 } } // Oeste
N: {
position: new THREE.Vector3(20, 20, 20),
target: new THREE.Vector3(0, 0, 0),
up: new THREE.Vector3(0, 1, 0)
},
S: {
position: new THREE.Vector3(-20, 20, -20),
target: new THREE.Vector3(0, 0, 0),
up: new THREE.Vector3(0, 1, 0)
},
E: {
position: new THREE.Vector3(-20, 20, 20),
target: new THREE.Vector3(0, 0, 0),
up: new THREE.Vector3(0, 1, 0)
},
W: {
position: new THREE.Vector3(20, 20, -20),
target: new THREE.Vector3(0, 0, 0),
up: new THREE.Vector3(0, 1, 0)
}
};
// Precalcular quaternions para cada vista (FIJOS, nunca cambian)
Object.keys(CAMERA_VIEWS).forEach(key => {
const view = CAMERA_VIEWS[key];
const tempCamera = new THREE.PerspectiveCamera();
tempCamera.position.copy(view.position);
tempCamera.up.copy(view.up);
tempCamera.lookAt(view.target);
view.quaternion = tempCamera.quaternion.clone();
});
// OrbitControls solo para zoom y paneo (sin rotación)
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableRotate = false; // Deshabilitar rotación
controls.enableRotate = false;
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = true;
controls.mouseButtons = {
LEFT: null, // Click izquierdo libre para selección
MIDDLE: THREE.MOUSE.PAN, // Paneo con botón central
RIGHT: THREE.MOUSE.PAN // Paneo también con botón derecho
LEFT: null,
MIDDLE: THREE.MOUSE.PAN,
RIGHT: THREE.MOUSE.PAN
};
controls.zoomToCursor = true;
controls.minZoom = 0.5;
@@ -185,10 +212,15 @@ controls.maxZoom = 3;
function setCameraView(direction) {
const view = CAMERA_VIEWS[direction];
camera.position.set(view.position.x, view.position.y, view.position.z);
camera.lookAt(view.target.x, view.target.y, view.target.z);
controls.target.set(view.target.x, view.target.y, view.target.z);
// Aplicar posición, quaternion y up FIJOS (sin lookAt que acumula errores)
camera.position.copy(view.position);
camera.quaternion.copy(view.quaternion);
camera.up.copy(view.up);
controls.target.copy(view.target);
controls.update();
SESSION.currentView = direction;
updateCompassUI();
}