92 lines
4.0 KiB
JavaScript
92 lines
4.0 KiB
JavaScript
"use strict";
|
|
|
|
const RailingGeometryGame = (function(){
|
|
|
|
const RailingGeometryGame = function(hollow_bond){
|
|
|
|
const cache = {};
|
|
|
|
// Genera un prisma cuadrangular (box) dentro de los buffers de la geometría
|
|
const append_box = (buffers, min_x, max_x, min_y, max_y, min_z, max_z) => {
|
|
const { positions, normals, uvs, indices } = buffers;
|
|
let offset = positions.length / 3;
|
|
|
|
const add_quad = (p1, p2, p3, p4, n) => {
|
|
positions.push(...p1, ...p2, ...p3, ...p4);
|
|
normals.push(...n, ...n, ...n, ...n);
|
|
uvs.push(0, 0, 1, 0, 1, 1, 0, 1);
|
|
indices.push(offset, offset + 2, offset + 1, offset, offset + 3, offset + 2);
|
|
offset += 4;
|
|
};
|
|
|
|
// Top (+Y) y Bottom (-Y)
|
|
add_quad([min_x, max_y, max_z], [max_x, max_y, max_z], [max_x, max_y, min_z], [min_x, max_y, min_z], [0, 1, 0]);
|
|
add_quad([min_x, min_y, min_z], [max_x, min_y, min_z], [max_x, min_y, max_z], [min_x, min_y, max_z], [0, -1, 0]);
|
|
|
|
// North (-Z) y South (+Z)
|
|
add_quad([max_x, min_y, min_z], [min_x, min_y, min_z], [min_x, max_y, min_z], [max_x, max_y, min_z], [0, 0, -1]);
|
|
add_quad([min_x, min_y, max_z], [max_x, min_y, max_z], [max_x, max_y, max_z], [min_x, max_y, max_z], [0, 0, 1]);
|
|
|
|
// West (-X) y East (+X)
|
|
add_quad([min_x, min_y, min_z], [min_x, min_y, max_z], [min_x, max_y, max_z], [min_x, max_y, min_z], [-1, 0, 0]);
|
|
add_quad([max_x, min_y, max_z], [max_x, min_y, min_z], [max_x, max_y, min_z], [max_x, max_y, max_z], [1, 0, 0]);
|
|
};
|
|
|
|
this.get_for_segment = segment => {
|
|
const is_x = (segment.side === "north" || segment.side === "south");
|
|
const length = is_x ? Math.abs(segment.xt - segment.xf) : Math.abs(segment.zt - segment.zf);
|
|
const height = segment.height || 1.0;
|
|
const th = segment.thickness || 0.08;
|
|
const h_th = th * 0.5;
|
|
|
|
const key = `rail_${is_x ? "x" : "z"}_${length.toFixed(2)}`;
|
|
if(cache[key]){
|
|
return cache[key];
|
|
}
|
|
|
|
const buffers = { positions: [], normals: [], uvs: [], indices: [] };
|
|
const half_len = length * 0.5;
|
|
|
|
// 1. Pasamanos superior (1.0m) y Travesaño medio (0.5m)
|
|
if(is_x){
|
|
append_box(buffers, -half_len, half_len, height - 0.05, height, -h_th, h_th);
|
|
append_box(buffers, -half_len, half_len, height * 0.5 - 0.02, height * 0.5 + 0.02, -h_th * 0.7, h_th * 0.7);
|
|
} else {
|
|
append_box(buffers, -h_th, h_th, height - 0.05, height, -half_len, half_len);
|
|
append_box(buffers, -h_th * 0.7, h_th * 0.7, height * 0.5 - 0.02, height * 0.5 + 0.02, -half_len, half_len);
|
|
}
|
|
|
|
// 2. Postes verticales (en los extremos y espaciados cada ~1.0m)
|
|
const post_count = Math.max(2, Math.round(length / 1.0) + 1);
|
|
for(let i = 0; i < post_count; i++){
|
|
const t = i / (post_count - 1);
|
|
const pos = (t - 0.5) * length;
|
|
|
|
if(is_x){
|
|
append_box(buffers, pos - h_th, pos + h_th, 0, height, -h_th, h_th);
|
|
} else {
|
|
append_box(buffers, -h_th, h_th, 0, height, pos - h_th, pos + h_th);
|
|
}
|
|
}
|
|
|
|
const geometry = new THREE.BufferGeometry();
|
|
geometry.setAttribute("position", new THREE.Float32BufferAttribute(buffers.positions, 3));
|
|
geometry.setAttribute("normal", new THREE.Float32BufferAttribute(buffers.normals, 3));
|
|
geometry.setAttribute("uv", new THREE.Float32BufferAttribute(buffers.uvs, 2));
|
|
geometry.setIndex(buffers.indices);
|
|
|
|
cache[key] = geometry;
|
|
return geometry;
|
|
};
|
|
|
|
this.reset = () => {
|
|
for(const k in cache){
|
|
cache[k].dispose();
|
|
delete cache[k];
|
|
}
|
|
};
|
|
|
|
};
|
|
|
|
return RailingGeometryGame;
|
|
})(); |