improve slice/preview visuals with custom normals

This commit is contained in:
Stewart Allen 2022-10-14 12:42:51 -04:00
commit ce856146e9
7 changed files with 143 additions and 41 deletions

View file

@ -195,13 +195,15 @@ kiri.Layers.prototype.encode = function(state) {
polys: encode(layer.polys, state),
lines: encodePointArray(layer.lines, state),
faces: codec.allocFloat32Array(layer.faces),
norms: layer.norms ? codec.allocFloat32Array(layer.norms) : undefined,
cface: layer.cface || codec.undef,
color: layer.color,
paths: layer.paths.map(lp => {
const pe = {
z: lp.z,
index: lp.index,
faces: codec.allocFloat32Array(lp.faces)
faces: codec.allocFloat32Array(lp.faces),
norms: lp.norms ? codec.allocFloat32Array(lp.norms) : undefined
};
if (zeroOut && state.zeros && pe.faces.length) {
state.zeros.push(pe.faces.buffer);
@ -226,22 +228,25 @@ kiri.Layers.prototype.encode = function(state) {
registerDecoder('layers', function(v, state) {
let render = new kiri.Layers();
for (let i=0; i<v.layers.length; i++) {
const data = v.data[i];
const d = render.layers[v.layers[i]] = {
polys: decode(v.data[i].polys, state),
cpoly: v.data[i].cpoly,
lines: decodePointArray(v.data[i].lines),
faces: codec.allocFloat32Array(v.data[i].faces),
cface: v.data[i].cface,
color: v.data[i].color,
paths: v.data[i].paths.map(lp => {
polys: decode(data.polys, state),
cpoly: data.cpoly,
lines: decodePointArray(data.lines),
faces: codec.allocFloat32Array(data.faces),
norms: data.norms ? codec.allocFloat32Array(data.norms) : undefined,
cface: data.cface,
color: data.color,
paths: data.paths.map(lp => {
return {
z: lp.z,
index: lp.index,
faces: codec.allocFloat32Array(lp.faces)
faces: codec.allocFloat32Array(lp.faces),
norms: lp.norms ? codec.allocFloat32Array(lp.norms) : undefined
};
}),
cpath: v.data[i].cpath,
off: v.data[i].off
cpath: data.cpath,
off: data.off
};
// fixup null -> Infinity in material counts (JSON stringify sucks)
if (d.cface) {

View file

@ -55,6 +55,7 @@ class Layers {
lines: [],
polys: [], // colors are an attribute on polygons
faces: [],
norms: undefined, // vertex normals
cface: undefined, // face color indices
paths: [],
cpath: undefined, // path colors indices
@ -148,18 +149,25 @@ class Layers {
if (!polys.length) {
return;
}
const z = polys[0].getZ(), faces = this.current.faces;
const cur = this.current;
const z = polys[0].getZ(), faces = cur.faces;
const off_opt = { z, flat: true };
polys.forEach(poly => {
const faceidx = faces.length / 3;
if (newPath) {
const path = poly.toPath2D(offset * 0.95);
const { left, right, normals } = path;
for (let p of path.faces) {
faces.push(p.x, p.y, p.z);
}
if (opts.outline) {
this.addPolys(newPolygon().addPoints(path.left).setOpen());
this.addPolys(newPolygon().addPoints(path.right).setOpen());
this.addPolys(newPolygon().addPoints(left).setOpenValue(poly.open));
this.addPolys(newPolygon().addPoints(right).setOpenValue(poly.open));
}
if (cur.norms) {
cur.norms.appendAll(normals);
} else {
cur.norms = normals;
}
} else {
let exp = off_opt.outs = [];
@ -186,7 +194,6 @@ class Layers {
});
});
}
const cur = this.current;
const color = opts.color ?
(typeof(opts.color) === 'number' ? { line: opts.color, face: opts.color } : opts.color) :
cur.color;
@ -220,7 +227,7 @@ class Layers {
continue;
}
const z = opts.z || poly.getZ();
const faces = poly.toPath3D(offset, height, 0);
const { faces, normals } = poly.toPath3D(offset, height, 0);
const cur = this.current;
const one = cur.paths[0];
if (one) {
@ -244,8 +251,11 @@ class Layers {
cur.cpath.push(Object.assign({ start: indln, count: Infinity }, opts.color));
}
}
if (normals) {
one.norms.appendAll(normals);
}
} else {
cur.paths.push({ index: [], faces, z });
cur.paths.push({ index: [], faces, z, norms: normals });
if (opts.color) {
cur.cpath = [ Object.assign({ start: 0, count: Infinity }, opts.color) ];
}

View file

@ -101,7 +101,7 @@ class Stack {
}
}
const { polys, lines, faces, cface, paths, cpath, color, off } = layer;
const { polys, lines, faces, cface, paths, cpath, color, off, norms } = layer;
const meshes = [];
const defstate = !off;
const mats = [];
@ -168,15 +168,20 @@ class Stack {
} else {
geo.setAttribute('position', new THREE.BufferAttribute(faces, 3));
}
geo.computeVertexNormals();
if (norms) {
geo.setAttribute('normal', new THREE.BufferAttribute(norms, 3));
// geo.normalizeNormals();
} else {
geo.computeVertexNormals();
}
if (cface) {
cface.forEach((c, i) => geo.addGroup(c.start, c.count, i));
} else {
geo.addGroup(0, Infinity, 0);
}
const mesh = new THREE.Mesh(geo, mat);
mesh.castShadow = true;
mesh.receiveShadow = true;
// mesh.castShadow = true;
// mesh.receiveShadow = true;
meshes.push(mesh);
group.add(mesh);
mats.appendAll(mat);
@ -191,11 +196,18 @@ class Stack {
mat.forEach(m => m.visible = defstate);
// const mat = newMat(data);
paths.forEach((path, i) => {
const { index, faces, z, colors } = path;
const { index, faces, norms, z, colors } = path;
const geo = new THREE.BufferGeometry();
geo.setAttribute('position', new THREE.BufferAttribute(faces, 3));
if (index.length) geo.setIndex(index);
geo.computeVertexNormals();
if (index.length) {
geo.setIndex(index);
}
if (norms) {
geo.setAttribute('normal', new THREE.BufferAttribute(norms, 3));
// geo.normalizeNormals();
} else {
geo.computeVertexNormals();
}
if (cpath) {
cpath.forEach((c, i) => geo.addGroup(c.start, c.count, i));
} else {
@ -203,8 +215,8 @@ class Stack {
}
const mesh = new THREE.Mesh(geo, mat);
mesh.position.z = z;
mesh.castShadow = true;
mesh.receiveShadow = true;
// mesh.castShadow = true;
// mesh.receiveShadow = true;
meshes.push(mesh);
group.add(mesh);
});

View file

@ -307,8 +307,8 @@ class Widget {
mesh.renderOrder = 1;
geometry.computeVertexNormals();
geometry.addGroup(0, Infinity, 0);
mesh.castShadow = true;
mesh.receiveShadow = true;
// mesh.castShadow = true;
// mesh.receiveShadow = true;
mesh.widget = this;
this.mesh = mesh;
// invalidates points cache (like any scale/rotation)