UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

109 lines (85 loc) 2.72 kB
import { EPSILON } from "../../../math/EPSILON.js"; import { epsilonEquals } from "../../../math/epsilonEquals.js"; import v3_morton_encode from "../morton/v3_morton_encode.js"; /** * * @param {TopoVertex} a * @param {TopoVertex} b * @param {number} tolerance */ function isPositionEquivalent(a, b, tolerance) { return epsilonEquals(b.x, a.x, tolerance) && epsilonEquals(b.y, a.y, tolerance) && epsilonEquals(b.z, a.z, tolerance) ; } /** * * @param {Map<TopoVertex,TopoVertex[]>} result * @param {TopoVertex} a * @param {TopoVertex} b */ function recordDuplicate(result, a, b) { let vertices = result.get(a); if (vertices === undefined) { vertices = []; result.set(a, vertices); } vertices.push(b); } /** * * @param {TopoMesh} mesh * @param {AABB3} aabb * @param {number} tolerance * @returns {Map<TopoVertex, TopoVertex[]>} */ export function computeTopoMeshVertexDuplicates(mesh, aabb, tolerance = EPSILON) { const vertices = mesh.vertices; const n = vertices.length; // build spatial index for faster duplicate search const spatial_hash = []; /** * * @type {Map<TopoVertex, TopoVertex[]>} */ const result = new Map(); let i, j; const x0 = aabb.x0; const y0 = aabb.y0; const z0 = aabb.z0; // 10 bit quantization const e_x = 1023 / aabb.getExtentsX(); const e_y = 1023 / aabb.getExtentsY(); const e_z = 1023 / aabb.getExtentsZ(); // for (i = 0; i < n; i++) { const vertex_a = vertices[i]; const morton_code = v3_morton_encode( Math.round((vertex_a.x - x0) * e_x), Math.round((vertex_a.y - y0) * e_y), Math.round((vertex_a.z - z0) * e_z) ); let spatial_bucket = spatial_hash[morton_code]; if (spatial_bucket === undefined) { spatial_bucket = []; spatial_hash[morton_code] = spatial_bucket; } else { // look at others in the bucket const bucket_size = spatial_bucket.length; for (j = 0; j < bucket_size; j++) { /** * @type {TopoVertex} */ const vertex_b = spatial_bucket[j]; if (isPositionEquivalent(vertex_a, vertex_b, tolerance)) { // same coordinates recordDuplicate(result, vertex_a, vertex_b); recordDuplicate(result, vertex_b, vertex_a); } } } spatial_bucket.push(vertex_a); } return result; }