HollowBond/Public/ecma/Geometries/Game/FrameGeometryGame.ecma.js

178 lines
9.8 KiB
JavaScript

"use strict";
const FrameGeometryGame = (function(){
const FrameGeometryGame = function(hollow_bond){
const cache = {};
/**
* Construye el túnel del marco con moldura 3D sin solapamiento de suelo con la sala.
*
* @param {number} pass_w - Ancho libre del vano
* @param {number} height - Altura libre del vano
* @param {number} wall_depth - Grosor del tabique entre salas (room_padding * 2)
* @param {boolean} is_horiz - true si corre en X, false si corre en Z
*/
this.get = (pass_w, height, wall_depth, is_horiz) => {
const key = `${pass_w}_${height}_${wall_depth}_${is_horiz}`;
if(cache[key]){
return cache[key];
}
const geometry = new THREE.BufferGeometry();
// Medias dimensiones del vano libre
const hx = is_horiz ? pass_w / 2 : wall_depth / 2;
const hz = is_horiz ? wall_depth / 2 : pass_w / 2;
const hy = height / 2;
// Dimensiones de la moldura/tapajuntas
const casing_w = 0.06; // 6 cm de solape sobre la pared
const casing_t = 0.02; // 2 cm de relieve hacia el interior de la sala
const positions = [];
const normals = [];
const uvs = [];
const indices = [];
let index_offset = 0;
const add_quad = (p1, p2, p3, p4, normal, uv_w, uv_h) => {
positions.push(...p1, ...p2, ...p3, ...p4);
normals.push(...normal, ...normal, ...normal, ...normal);
uvs.push(0, 0, uv_w, 0, uv_w, uv_h, 0, uv_h);
indices.push(
index_offset, index_offset + 2, index_offset + 1,
index_offset, index_offset + 3, index_offset + 2
);
index_offset += 4;
};
if(is_horiz){
const total_z = hz + casing_t;
// 1. UMBRAL / SUELO TRANSITABLE (+Y)
// Se acota estrictamente a [-hz, hz] para que coincida justo con el final de la moqueta
add_quad(
[-hx, -hy, -hz], [ hx, -hy, -hz], [ hx, -hy, hz], [-hx, -hy, hz],
[0, 1, 0], pass_w, wall_depth
);
// 2. TECHO INTERIOR DEL VANO (-Y)
// Aquí sí cubre hasta total_z para sellar la parte baja de la moldura superior
add_quad(
[-hx, hy, total_z], [ hx, hy, total_z], [ hx, hy, -total_z], [-hx, hy, -total_z],
[0, -1, 0], pass_w, total_z * 2
);
// 3. JAMBAS INTERIORES LATERALES
// Izquierda (+X)
add_quad(
[-hx, -hy, -total_z], [-hx, -hy, total_z], [-hx, hy, total_z], [-hx, hy, -total_z],
[1, 0, 0], total_z * 2, height
);
// Derecha (-X)
add_quad(
[ hx, -hy, total_z], [ hx, -hy, -total_z], [ hx, hy, -total_z], [ hx, hy, total_z],
[-1, 0, 0], total_z * 2, height
);
// 4. MOLDURAS EXTERIORES
// Cara Sur (+Z)
const z_s = total_z;
add_quad([-hx - casing_w, -hy, z_s], [-hx, -hy, z_s], [-hx, hy + casing_w, z_s], [-hx - casing_w, hy + casing_w, z_s], [0, 0, 1], casing_w, height + casing_w);
add_quad([ hx, -hy, z_s], [ hx + casing_w, -hy, z_s], [ hx + casing_w, hy + casing_w, z_s], [ hx, hy + casing_w, z_s], [0, 0, 1], casing_w, height + casing_w);
add_quad([-hx, hy, z_s], [ hx, hy, z_s], [ hx, hy + casing_w, z_s], [-hx, hy + casing_w, z_s], [0, 0, 1], pass_w, casing_w);
// Cantos de cierre contra la pared (Sur)
add_quad([-hx - casing_w, -hy, hz], [-hx - casing_w, -hy, z_s], [-hx - casing_w, hy + casing_w, z_s], [-hx - casing_w, hy + casing_w, hz], [-1, 0, 0], casing_t, height + casing_w);
add_quad([ hx + casing_w, -hy, z_s], [ hx + casing_w, -hy, hz], [ hx + casing_w, hy + casing_w, hz], [ hx + casing_w, hy + casing_w, z_s], [1, 0, 0], casing_t, height + casing_w);
add_quad([-hx - casing_w, hy + casing_w, hz], [ hx + casing_w, hy + casing_w, hz], [ hx + casing_w, hy + casing_w, z_s], [-hx - casing_w, hy + casing_w, z_s], [0, 1, 0], pass_w + casing_w * 2, casing_t);
// Cara Norte (-Z)
const z_n = -total_z;
add_quad([-hx, -hy, z_n], [-hx - casing_w, -hy, z_n], [-hx - casing_w, hy + casing_w, z_n], [-hx, hy + casing_w, z_n], [0, 0, -1], casing_w, height + casing_w);
add_quad([ hx + casing_w, -hy, z_n], [ hx, -hy, z_n], [ hx, hy + casing_w, z_n], [ hx + casing_w, hy + casing_w, z_n], [0, 0, -1], casing_w, height + casing_w);
add_quad([ hx, hy, z_n], [-hx, hy, z_n], [-hx, hy + casing_w, z_n], [ hx, hy + casing_w, z_n], [0, 0, -1], pass_w, casing_w);
// Cantos de cierre contra la pared (Norte)
add_quad([-hx - casing_w, -hy, z_n], [-hx - casing_w, -hy, -hz], [-hx - casing_w, hy + casing_w, -hz], [-hx - casing_w, hy + casing_w, z_n], [-1, 0, 0], casing_t, height + casing_w);
add_quad([ hx + casing_w, -hy, -hz], [ hx + casing_w, -hy, z_n], [ hx + casing_w, hy + casing_w, z_n], [ hx + casing_w, hy + casing_w, -hz], [1, 0, 0], casing_t, height + casing_w);
add_quad([-hx - casing_w, hy + casing_w, z_n], [ hx + casing_w, hy + casing_w, z_n], [ hx + casing_w, hy + casing_w, -hz], [-hx - casing_w, hy + casing_w, -hz], [0, 1, 0], pass_w + casing_w * 2, casing_t);
} else {
const total_x = hx + casing_t;
// 1. UMBRAL / SUELO TRANSITABLE (+Y)
// Se acota a [-hx, hx] para alinearse de forma exacta a la moqueta
add_quad(
[-hx, -hy, -hz], [ hx, -hy, -hz], [ hx, -hy, hz], [-hx, -hy, hz],
[0, 1, 0], wall_depth, pass_w
);
// 2. TECHO INTERIOR (-Y)
add_quad(
[-total_x, hy, hz], [ total_x, hy, hz], [ total_x, hy, -hz], [-total_x, hy, -hz],
[0, -1, 0], total_x * 2, pass_w
);
// 3. JAMBAS INTERIORES LATERALES
// Izquierda (+Z)
add_quad(
[-total_x, -hy, -hz], [ total_x, -hy, -hz], [ total_x, hy, -hz], [-total_x, hy, -hz],
[0, 0, 1], total_x * 2, height
);
// Derecha (-Z)
add_quad(
[ total_x, -hy, hz], [-total_x, -hy, hz], [-total_x, hy, hz], [ total_x, hy, hz],
[0, 0, -1], total_x * 2, height
);
// 4. MOLDURAS EXTERIORES
// Cara Este (+X)
const x_e = total_x;
add_quad([x_e, -hy, hz], [x_e, -hy, hz + casing_w], [x_e, hy + casing_w, hz + casing_w], [x_e, hy + casing_w, hz], [1, 0, 0], casing_w, height + casing_w);
add_quad([x_e, -hy, -hz - casing_w], [x_e, -hy, -hz], [x_e, hy + casing_w, -hz], [x_e, hy + casing_w, -hz - casing_w], [1, 0, 0], casing_w, height + casing_w);
add_quad([x_e, hy, -hz], [x_e, hy, hz], [x_e, hy + casing_w, hz], [x_e, hy + casing_w, -hz], [1, 0, 0], pass_w, casing_w);
// Cantos Este
add_quad([hx, -hy, -hz - casing_w], [x_e, -hy, -hz - casing_w], [x_e, hy + casing_w, -hz - casing_w], [hx, hy + casing_w, -hz - casing_w], [0, 0, -1], casing_t, height + casing_w);
add_quad([x_e, -hy, hz + casing_w], [hx, -hy, hz + casing_w], [hx, hy + casing_w, hz + casing_w], [x_e, hy + casing_w, hz + casing_w], [0, 0, 1], casing_t, height + casing_w);
add_quad([hx, hy + casing_w, -hz - casing_w], [x_e, hy + casing_w, -hz - casing_w], [x_e, hy + casing_w, hz + casing_w], [hx, hy + casing_w, hz + casing_w], [0, 1, 0], casing_t, pass_w + casing_w * 2);
// Cara Oeste (-X)
const x_w = -total_x;
add_quad([x_w, -hy, hz + casing_w], [x_w, -hy, hz], [x_w, hy + casing_w, hz], [x_w, hy + casing_w, hz + casing_w], [-1, 0, 0], casing_w, height + casing_w);
add_quad([x_w, -hy, -hz], [x_w, -hy, -hz - casing_w], [x_w, hy + casing_w, -hz - casing_w], [x_w, hy + casing_w, -hz], [-1, 0, 0], casing_w, height + casing_w);
add_quad([x_w, hy, hz], [x_w, hy, -hz], [x_w, hy + casing_w, -hz], [x_w, hy + casing_w, hz], [-1, 0, 0], pass_w, casing_w);
// Cantos Oeste
add_quad([x_w, -hy, -hz - casing_w], [-hx, -hy, -hz - casing_w], [-hx, hy + casing_w, -hz - casing_w], [x_w, hy + casing_w, -hz - casing_w], [0, 0, -1], casing_t, height + casing_w);
add_quad([-hx, -hy, hz + casing_w], [x_w, -hy, hz + casing_w], [x_w, hy + casing_w, hz + casing_w], [-hx, hy + casing_w, hz + casing_w], [0, 0, 1], casing_t, height + casing_w);
add_quad([x_w, hy + casing_w, -hz - casing_w], [-hx, hy + casing_w, -hz - casing_w], [-hx, hy + casing_w, hz + casing_w], [x_w, hy + casing_w, hz + casing_w], [0, 1, 0], casing_t, pass_w + casing_w * 2);
}
geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
geometry.setAttribute("normal", new THREE.Float32BufferAttribute(normals, 3));
geometry.setAttribute("uv", new THREE.Float32BufferAttribute(uvs, 2));
geometry.setIndex(indices);
cache[key] = geometry;
return geometry;
};
this.reset = () => {
for(const key in cache){
if(cache[key]){
cache[key].dispose();
delete cache[key];
}
}
};
};
return FrameGeometryGame;
})();