/** Copyright Stewart Allen -- All Rights Reserved */ "use strict"; (function() { const BASE = self.base = self.base || {}; if (BASE.Mesh) { return; } BASE.Mesh = class Mesh { constructor(params = {}) { this.precision = params.precision || 6; if (params.vertices) { this.setData(params.vertices, params.faces); } } /** * set vertices and faces of the mesh. if only vertices are provided * then the data is assumed to be un-indexed and will be indexed into * faces. if faces are provided, they are assumed to be index references * into the vertex data. * * the end result is face data mapped to an indexed set of unique vertices. * * @param {number[]} vertices * @param {number[]} faces */ setData(vertices, faces) { if (!vertices) { throw "missing vertices"; } if (vertices.length % 3 !== 0) { throw "invalid vertices"; } // when face/index data is missing, vertices need to be normalized if (!faces) { faces = []; let nuvt = []; // new vertex list let hash = {}; // find vertex matches let prec = this.precision; for (let i=0, l=vertices.length; i Math.abs(v))); // console.log({d, max}); return this.unit = d.map(v => v / max); } } function diffUnitVector(uv1, uv2) { let diff = 0; for (let i=0; i<3; i++) { diff += Math.abs(uv1[i] - uv2[i]); } return diff; } function getLine(v1, v2) { let s1 = vertices[v1] + vertices[v1+1]*1000 + vertices[v1+2]*100000; let s2 = vertices[v2] + vertices[v2+1]*1000 + vertices[v2+2]*100000; let key = s1 <= s2 ? [v1,v2].join('-') : [v2,v1].join('-'); let line = hash[key]; if (!line) { // point order will be swapped for reconstructed faces // to preserve chirality (assuming face normals are correct) line = hash[key] = new Line(v1, v2); lines.push(line); let lm1 = vmap[v1] = vmap[v1] || []; let lm2 = vmap[v2] = vmap[v2] || []; lm1.push(line); lm2.push(line); } return line; } for (let i=0, l=this.faces.length; i l.faces.length === 1); console.log({edges}); let loops = []; // connect edge lines into closed loops for (let i=0, l=edges.length; i l !== line && !l.used && l.faces.length === 1); if (adjacent.length === 0) { break; } if (adjacent.length > 2) { console.log('error adjacent', adjacent); break; } if (adjacent.length === 1) { if (line.v2 !== adjacent[0].v1) { console.log('chirality mismatch'); } line = adjacent[0]; } else { // follow edges according to chirality line = adjacent[0].v1 === line.v2 ? adjacent[0] : adjacent[1] } loop.push(line); line.used = true; } // drop co-linear points because they can't be connected into valid faces // fixup remaining line by dropping common point and using dropped line's point for (let j=0, jl=loop.length; j !l.del); console.log({loop}); loops.push(loop); } console.log({loops}); return this; } }; })();