experiment with less memory intensive mesh indexing

This commit is contained in:
Stewart Allen 2022-04-13 20:40:45 -04:00
commit f4e928a703
3 changed files with 112 additions and 7 deletions

View file

@ -420,12 +420,12 @@ const tool = {
}); });
}, },
mapFaces(models) { mapFaces(models, opt = {}) {
models = fallback(models); models = fallback(models);
api.log.emit('mapping faces').pin(); api.log.emit('mapping faces').pin();
let promises = []; let promises = [];
for (let m of models) { for (let m of models) {
let p = worker.model_mapFaces({ id: m.id }).then(data => { let p = worker.model_mapFaces({ id: m.id, opt }).then(data => {
// console.log({map_info: data}); // console.log({map_info: data});
}); });
promises.push(p); promises.push(p);

View file

@ -104,9 +104,9 @@ mesh.tool = class MeshTool {
this.vertices = this.checkVertices(vertices, 3); this.vertices = this.checkVertices(vertices, 3);
const normals = this.normals = []; const normals = this.normals = [];
const sides = this.sides = []; const sides = this.sides = [];
const _va = new THREE.Vector3(); const _va = new Vector3();
const _vb = new THREE.Vector3(); const _vb = new Vector3();
const _vc = new THREE.Vector3(); const _vc = new Vector3();
for (let i=0, l=vertices.length; i<l; ) { for (let i=0, l=vertices.length; i<l; ) {
_va.set(vertices[i++], vertices[i++], vertices[i++]); _va.set(vertices[i++], vertices[i++], vertices[i++]);
_vb.set(vertices[i++], vertices[i++], vertices[i++]); _vb.set(vertices[i++], vertices[i++], vertices[i++]);
@ -143,6 +143,98 @@ mesh.tool = class MeshTool {
return this; return this;
} }
// combines generatedFaces() and generateFaceMap()
// face record: vi1, vi2, vi3, nx, ny, nz
// vi = vertex index
// n = normal
// af = adjacent face index
index(vertices) {
const prec = this.precision;
const vcount = vertices.length / 3;
const fcount = vcount / 3;
const vround = vertices.map(v => (v * prec) | 0);
// new compressed vertex array
const verts = [];
// new compressed normals array
const norms = [];
// side records [ fcount, f1, f2 ]
const sides = new Uint32Array(fcount * 3);
// side extended records when face count exceeds 2 (bad mesh)
const sideExt = {};
// face record array [ v0, v1, v2, ni, s0, s1, s2 ]
const faces = new Uint32Array(fcount * 7);
// vertex key to vertex index
const vimap = {};
// normal key to normal index
const nimap = {};
// side key to side index
const simap = {};
// tmp face vertex indices
const vinds = [ 0, 0, 0 ];
// tmp vector array
const vects = [ new Vector3(), new Vector3(), new Vector3() ];
// i=vround index, fi=faces record index
// vi=vinds index % 3, x,y,z = tmp vars
// fn=next face index, vn=next vertex index, sn=next side index
for (let i=0, l=vround.length, fn=0, vn=0, sn=0, fi=0, vi=0, x, y, z; i<l; ) {
// create unique vertex map
vects[vi].set(x = vround[i++], y = vround[i++], z = vround[i++]);
let key = [ x, y, z ].join(',');
// vertex index
let vid = vimap[key];
if (vid === undefined) {
vid = vimap[key] = vn++;
verts.push(x / prec, y / prec, z / prec);
}
vinds[vi++] = vid;
// completed record for a face
if (vi === 3) {
// create indexed unique normal map
const vn = THREE.computeFaceNormal(...vects);
const vnk = [ vn.x, vn.y, vn.z ].map(v => (v * prec) | 0).join(',');
let vni = nimap[vnk];
if (vni === undefined) {
vni = nimap[vnk] = norms.length / 3;
norms.push(vn.x, vn.y, vn.z);
}
const [ v0, v1, v2 ] = vinds;
// create consistent side order for index key
const s0 = (v0 < v1 ? [ v0, v1 ] : [ v1, v0 ]).join(',');
const s1 = (v1 < v2 ? [ v1, v2 ] : [ v2, v1 ]).join(',');
const s2 = (v2 < v0 ? [ v2, v0 ] : [ v0, v2 ]).join(',');
const vv = [ v0, v1, v1, v2, v2, v0 ];
// store face indexes into sdrec array for each side
const smap = [ s0, s1, s2 ].map(key => {
let sid = simap[key];
if (sid === undefined) {
sid = simap[key] = sn++;
}
let sdoff = sid * 3;
let sdcnt = ++sides[sdoff];
if (sdcnt > 2) {
(sideExt[sid] = sideExt[sid] || [ sides[sdoff + 1], sides[sdoff + 2] ]).push(fn);
} else {
sides[sdoff + sdcnt] = fn;
}
return sid;
});
faces[fi++] = v0;
faces[fi++] = v1;
faces[fi++] = v2;
faces[fi++] = vni;
faces[fi++] = smap[0];
faces[fi++] = smap[1];
faces[fi++] = smap[2];
vi = 0;
fn++;
}
}
this.indexed = {
faces, verts, norms, sides, sideExt
};
// console.log({ fcount, faces, sides, sideExt, norms, vround, verts });
}
getAdjacentFaces(face) { getAdjacentFaces(face) {
if (!this.sides) { if (!this.sides) {
throw "missing sides"; throw "missing sides";

View file

@ -95,6 +95,19 @@ function mapFaces(id) {
return tool; return tool;
} }
function indexFaces(id) {
let rec = cache[id];
let { geo, tool } = rec;
if (!tool) {
tool = rec.tool = new mesh.tool();
}
if (!tool.normals) {
log(`${id} | indexing mesh`);
tool.index(geo.attributes.position.array);
}
return tool;
}
let model = { let model = {
load(data) { load(data) {
let { vertices, name, id } = data; let { vertices, name, id } = data;
@ -280,8 +293,8 @@ let model = {
}, },
mapFaces(data) { mapFaces(data) {
let { id } = data; let { id, opt } = data;
let tool = mapFaces(id); let tool = opt.index ? indexFaces(id) : mapFaces(id);
return { mapped: true }; return { mapped: true };
}, },