fix stl export size (kiri). add stl export (mesh)
This commit is contained in:
parent
b8877f1225
commit
66ca161ccd
4 changed files with 56 additions and 16 deletions
|
|
@ -1740,10 +1740,10 @@
|
||||||
}
|
}
|
||||||
return obj.join('\n');
|
return obj.join('\n');
|
||||||
}
|
}
|
||||||
let stl = new Uint8Array(80 + 4 + facets * 50);
|
let stl = new Uint8Array(80 + 4 + facets/3 * 50);
|
||||||
let dat = new DataView(stl.buffer);
|
let dat = new DataView(stl.buffer);
|
||||||
let pos = 84;
|
let pos = 84;
|
||||||
dat.setInt32(80, facets, true);
|
dat.setInt32(80, facets/3, true);
|
||||||
for (let out of outs) {
|
for (let out of outs) {
|
||||||
let { position } = out.geo.attributes;
|
let { position } = out.geo.attributes;
|
||||||
let pvals = position.array;
|
let pvals = position.array;
|
||||||
|
|
|
||||||
|
|
@ -225,14 +225,14 @@ let file = {
|
||||||
if (recs.length === 0) {
|
if (recs.length === 0) {
|
||||||
return api.log.emit(`no models to export`);
|
return api.log.emit(`no models to export`);
|
||||||
}
|
}
|
||||||
function doit() {
|
function doit(ext = 'obj') {
|
||||||
api.log.emit(`exporting ${recs.length} model(s)`);
|
api.log.emit(`exporting ${recs.length} model(s)`);
|
||||||
let file = api.modal.bound.filename.value || "export.obj";
|
let file = api.modal.bound.filename.value || "export.obj";
|
||||||
if (file.toLowerCase().indexOf(".obj") < 0) {
|
if (file.toLowerCase().indexOf(`.${ext}`) < 0) {
|
||||||
file = file + ".obj";
|
file = `${file}.${ext}`;
|
||||||
}
|
}
|
||||||
worker.file_export({
|
worker.file_export({
|
||||||
recs, format: "obj"
|
recs, format: ext
|
||||||
}).then(data => {
|
}).then(data => {
|
||||||
if (data.length) {
|
if (data.length) {
|
||||||
util.download(data, file);
|
util.download(data, file);
|
||||||
|
|
@ -247,7 +247,8 @@ let file = {
|
||||||
h.input({ id: "filename", value: "mesh_export" })
|
h.input({ id: "filename", value: "mesh_export" })
|
||||||
]),
|
]),
|
||||||
h.div([
|
h.div([
|
||||||
h.button({ _: "download", onclick: doit })
|
h.button({ _: "download OBJ", onclick() { doit('obj') } }),
|
||||||
|
h.button({ _: "download STL", onclick() { doit('stl') } })
|
||||||
])
|
])
|
||||||
]) ]
|
]) ]
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -100,22 +100,56 @@ let object = {
|
||||||
let file = {
|
let file = {
|
||||||
export(data, send) {
|
export(data, send) {
|
||||||
let { format, recs } = data;
|
let { format, recs } = data;
|
||||||
|
let vtot = 0;
|
||||||
|
for (let rec of recs) {
|
||||||
|
let { id, matrix, file } = rec;
|
||||||
|
let vs = rec.varr = Array.from(translate_encode(id, matrix)).map(v => v.round(5));
|
||||||
|
vtot += (vs.length / 3);
|
||||||
|
}
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case "obj":
|
case "obj":
|
||||||
let p = 1;
|
let p = 1;
|
||||||
let obj = [`# Generated By Kiri:Moto (units = millimeters)`];
|
let obj = [`# Generated By Mesh:Tool @ https://grid.space/mesh (units = millimeters)`];
|
||||||
for (let rec of recs) {
|
for (let rec of recs) {
|
||||||
let { id, matrix, file } = rec;
|
let { id, matrix, file, varr } = rec;
|
||||||
let verts = Array.from(translate_encode(id, matrix)).map(v => v.round(5));
|
|
||||||
obj.push(`g ${file}`);
|
obj.push(`g ${file}`);
|
||||||
for (let i=0; i<verts.length; p += 3) {
|
for (let i=0; i<varr.length; p += 3) {
|
||||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
obj.push(`v ${varr[i++]} ${varr[i++]} ${varr[i++]}`);
|
||||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
obj.push(`v ${varr[i++]} ${varr[i++]} ${varr[i++]}`);
|
||||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
obj.push(`v ${varr[i++]} ${varr[i++]} ${varr[i++]}`);
|
||||||
obj.push(`f ${p} ${p+1} ${p+2}`);
|
obj.push(`f ${p} ${p+1} ${p+2}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj.join('\n');
|
return obj.join('\n');
|
||||||
|
case "stl":
|
||||||
|
let stl = new Uint8Array(80 + 4 + vtot/3 * 50);
|
||||||
|
let dat = new DataView(stl.buffer);
|
||||||
|
let pos = 84;
|
||||||
|
// todo put Kiri:Moto info in header
|
||||||
|
dat.setInt32(80, vtot/3, true);
|
||||||
|
for (let rec of recs) {
|
||||||
|
let { id, matrix, file, varr } = rec;
|
||||||
|
for (let i=0, l=varr.length; i<l;) {
|
||||||
|
let p0 = new THREE.Vector3(varr[i++], varr[i++], varr[i++]);
|
||||||
|
let p1 = new THREE.Vector3(varr[i++], varr[i++], varr[i++]);
|
||||||
|
let p2 = new THREE.Vector3(varr[i++], varr[i++], varr[i++]);
|
||||||
|
let norm = THREE.computeFaceNormal(p0, p1, p2);
|
||||||
|
dat.setFloat32(pos + 0, norm.x, true);
|
||||||
|
dat.setFloat32(pos + 4, norm.y, true);
|
||||||
|
dat.setFloat32(pos + 8, norm.z, true);
|
||||||
|
dat.setFloat32(pos + 12, p0.x, true);
|
||||||
|
dat.setFloat32(pos + 16, p0.y, true);
|
||||||
|
dat.setFloat32(pos + 20, p0.z, true);
|
||||||
|
dat.setFloat32(pos + 24, p1.x, true);
|
||||||
|
dat.setFloat32(pos + 28, p1.y, true);
|
||||||
|
dat.setFloat32(pos + 32, p1.z, true);
|
||||||
|
dat.setFloat32(pos + 36, p2.x, true);
|
||||||
|
dat.setFloat32(pos + 40, p2.y, true);
|
||||||
|
dat.setFloat32(pos + 44, p2.z, true);
|
||||||
|
pos += 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stl;
|
||||||
default:
|
default:
|
||||||
throw `invalid format "${format}"`;
|
throw `invalid format "${format}"`;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,15 +171,20 @@ button:hover {
|
||||||
color: #888;
|
color: #888;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.export {
|
||||||
|
flex-direction: column;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
.export, .export div {
|
.export, .export div {
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export input {
|
.export input, .export button {
|
||||||
padding: 3px;
|
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.export button {
|
.export button {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue