diff --git a/src/main.js b/src/main.js index 3f88ac9..b40ed5a 100644 --- a/src/main.js +++ b/src/main.js @@ -885,6 +885,60 @@ function getDoorGridPosition(room, door) { } } +// Calcula la posición completa de la puerta en el mundo 3D +// Devuelve: { worldPos: {x, z}, meshPos: {x, y, z}, rotation: number, wallOffset: number } +function getDoorWorldPosition(room, door, centerX, centerZ, halfSizeX, halfSizeZ) { + const doorGridPos = getDoorGridPosition(room, door); + const doorWorldPos = gridToWorld(doorGridPos.x, doorGridPos.y); + + const doorHeight = 2.0; + let meshPos = { x: 0, y: doorHeight / 2, z: 0 }; + let rotation = 0; + let wallOffset = 0; + + switch (door.side) { + case 'N': + // Pared Norte: puerta alineada en X, Z en el borde norte + meshPos.x = doorWorldPos.x; + meshPos.z = centerZ - halfSizeZ; + rotation = 0; + // Offset relativo al centro de la pared (para el hueco) + wallOffset = doorWorldPos.x - centerX; + break; + case 'S': + // Pared Sur: puerta alineada en X, Z en el borde sur + meshPos.x = doorWorldPos.x; + meshPos.z = centerZ + halfSizeZ; + rotation = 0; + // Para pared Sur, el offset es directo (sin inversión) + wallOffset = doorWorldPos.x - centerX; + break; + case 'E': + // Pared Este: puerta alineada en Z, X en el borde este + meshPos.x = centerX + halfSizeX; + meshPos.z = doorWorldPos.z; + rotation = Math.PI / 2; + // Offset relativo al centro de la pared + wallOffset = doorWorldPos.z - centerZ; + break; + case 'W': + // Pared Oeste: puerta alineada en Z, X en el borde oeste + meshPos.x = centerX - halfSizeX; + meshPos.z = doorWorldPos.z; + rotation = Math.PI / 2; + // Para pared Oeste, el offset es directo (sin inversión) + wallOffset = doorWorldPos.z - centerZ; + break; + } + + return { + worldPos: doorWorldPos, + meshPos: meshPos, + rotation: rotation, + wallOffset: wallOffset + }; +} + // --- CARGA Y RENDERIZADO --- const textureLoader = new THREE.TextureLoader(); @@ -1047,27 +1101,9 @@ async function renderRoom(room) { const doorWidth = 1.5; const doorHeight = 2.0; - // Calcular posición relativa de la puerta en la pared - // config.width es el ancho total. El rango local es [-W/2, W/2] - - // Obtener coordenadas de la puerta - const doorGridPos = getDoorGridPosition(room, door); - const doorWorldPos = gridToWorld(doorGridPos.x, doorGridPos.y); - - // Necesitamos proyectar la posición de la puerta sobre el eje de la pared para saber su offset - // Pared N/S: Offset es diferencia en X. - // Pared E/W: Offset es diferencia en Z (pero ojo con la dirección del plano). - - let doorOffset = 0; // Offset del centro de la puerta respecto al centro de la pared - if (config.side === 'N') { - doorOffset = doorWorldPos.x - centerX; - } else if (config.side === 'S') { - doorOffset = -(doorWorldPos.x - centerX); // S wall is rotated 180, local X is opposite world X - } else if (config.side === 'E') { - doorOffset = doorWorldPos.z - centerZ; - } else if (config.side === 'W') { - doorOffset = -(doorWorldPos.z - centerZ); // W wall is rotated 90, local X is opposite world Z - } + // Usar función unificada para obtener la posición de la puerta + const doorInfo = getDoorWorldPosition(room, door, centerX, centerZ, halfSizeX, halfSizeZ); + const doorOffset = doorInfo.wallOffset; const w = config.width; @@ -1088,10 +1124,6 @@ async function renderRoom(room) { createWallSegment(rightWidth, wallHeight, rightCenter, wallHeight / 2, opacity, "RightSeg"); // Dintel (Arriba de la puerta) - // Ancho: doorWidth - // Altura: wallHeight - doorHeight (2.5 - 2.0 = 0.5) - // Centro X: doorOffset - // Centro Y: doorHeight + (dintelHeight / 2) -> 2.0 + 0.25 = 2.25 const lintelHeight = wallHeight - doorHeight; if (lintelHeight > 0) { createWallSegment(doorWidth, lintelHeight, doorOffset, doorHeight + (lintelHeight / 2), opacity, "Lintel"); @@ -1123,31 +1155,11 @@ async function renderRoom(room) { const doorMesh = new THREE.Mesh(doorGeometry, doorMaterial); doorMesh.userData.id = door.id; doorMesh.visible = !door.isOpen; // Ocultar si ya está abierta - const doorGridPos = getDoorGridPosition(room, door); - const doorWorldPos = gridToWorld(doorGridPos.x, doorGridPos.y); - switch (door.side) { - case 'N': - // Pared Norte: Alinear X con worldPos, Z con borde norte - doorMesh.position.set(doorWorldPos.x, doorHeight / 2, centerZ - halfSizeZ); - doorMesh.rotation.y = 0; - break; - case 'S': - // Pared Sur - doorMesh.position.set(doorWorldPos.x, doorHeight / 2, centerZ + halfSizeZ); - doorMesh.rotation.y = 0; // O Math.PI, visualmente igual para puerta plana 1.5x2 - break; - case 'E': - // Pared Este: Alinear Z con worldPos, X con borde este - doorMesh.position.set(centerX + halfSizeX, doorHeight / 2, doorWorldPos.z); - doorMesh.rotation.y = Math.PI / 2; - break; - case 'W': - // Pared Oeste - doorMesh.position.set(centerX - halfSizeX, doorHeight / 2, doorWorldPos.z); - doorMesh.rotation.y = Math.PI / 2; - break; - } + // Usar función unificada para posicionar la puerta + const doorInfo = getDoorWorldPosition(room, door, centerX, centerZ, halfSizeX, halfSizeZ); + doorMesh.position.set(doorInfo.meshPos.x, doorInfo.meshPos.y, doorInfo.meshPos.z); + doorMesh.rotation.y = doorInfo.rotation; scene.add(doorMesh); roomMeshes.doors.push(doorMesh);