add obj export
This commit is contained in:
parent
5bb0cd327f
commit
7ea66a9e7b
6 changed files with 91 additions and 38 deletions
|
|
@ -127,33 +127,33 @@ function space_init(data) {
|
|||
}
|
||||
let { shiftKey, metaKey, ctrlKey, code } = evt;
|
||||
switch (code) {
|
||||
case 'KeyD':
|
||||
if (shiftKey) {
|
||||
for (let m of selection.models()) {
|
||||
m.debug();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'KeyC':
|
||||
selection.centerXY().focus();
|
||||
break;
|
||||
return selection.centerXY().focus();
|
||||
case 'KeyX':
|
||||
return api.file.export();
|
||||
case 'KeyV':
|
||||
selection.focus();
|
||||
break;
|
||||
return selection.focus();
|
||||
case 'KeyW':
|
||||
api.wireframe();
|
||||
break;
|
||||
return api.wireframe();
|
||||
case 'KeyG':
|
||||
api.grid();
|
||||
break;
|
||||
return api.grid();
|
||||
case 'KeyB':
|
||||
selection.boundsBox({toggle:true});
|
||||
break;
|
||||
return selection.boundsBox({toggle:true});
|
||||
case 'KeyH':
|
||||
space.view.home();
|
||||
break;
|
||||
return space.view.home();
|
||||
case 'KeyR':
|
||||
api.tool.repair();
|
||||
break;
|
||||
return api.tool.repair();
|
||||
case 'KeyT':
|
||||
space.view.top();
|
||||
break;
|
||||
return space.view.top();
|
||||
case 'KeyZ':
|
||||
space.view.reset();
|
||||
break;
|
||||
return space.view.reset();
|
||||
}
|
||||
},
|
||||
'keydown', evt => {
|
||||
|
|
@ -172,13 +172,6 @@ function space_init(data) {
|
|||
estop(evt);
|
||||
}
|
||||
break;
|
||||
case 'KeyD':
|
||||
if (shiftKey) {
|
||||
for (let m of selection.models()) {
|
||||
m.debug();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Escape':
|
||||
selection.clear();
|
||||
estop(evt);
|
||||
|
|
|
|||
|
|
@ -218,7 +218,16 @@ let file = {
|
|||
},
|
||||
|
||||
export() {
|
||||
console.log('...export todo');
|
||||
let recs = selection.models().map(m => { return {
|
||||
id: m.id, matrix: m.matrix, file: m.file
|
||||
} });
|
||||
api.log.emit(`exporting ${recs.length} model(s)`);
|
||||
moto.client.fn.file_export({
|
||||
recs, format: "obj"
|
||||
}).then(data => {
|
||||
console.log({work_export: data});
|
||||
util.download(data, "export.obj");
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -244,7 +253,7 @@ let tool = {
|
|||
}
|
||||
};
|
||||
|
||||
// api is augmented in mesh.build
|
||||
// api is augmented in mesh.build (log, modal, download)
|
||||
let api = mesh.api = {
|
||||
clear() {
|
||||
for (let group of group.list()) {
|
||||
|
|
@ -300,8 +309,8 @@ let api = mesh.api = {
|
|||
let deferFn = [];
|
||||
let boundsCache = {};
|
||||
|
||||
// util functions augmented in build (download)
|
||||
let util = mesh.util = {
|
||||
|
||||
uuid(segs = 1) {
|
||||
let uid = [];
|
||||
while (segs-- > 0) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,13 @@ broker.listeners({
|
|||
|
||||
let spin_timer;
|
||||
|
||||
// add download / blob export to util
|
||||
let download = mesh.util.download = (data, filename = "mesh-data") => {
|
||||
let url = window.URL.createObjectURL(new Blob([data], {type: "octet/stream"}));
|
||||
$('download').innerHTML = `<a id="_data_export_" href="${url}" download="${filename}">x</a>`;
|
||||
$('_data_export_').click();
|
||||
};
|
||||
|
||||
// add modal dialog functions to api
|
||||
let modal = mesh.api.modal = {
|
||||
show(title, contents) {
|
||||
|
|
@ -155,7 +162,8 @@ function ui_build() {
|
|||
h.div({ id: 'actions' }),
|
||||
h.div({ id: 'grouplist'}),
|
||||
h.div({ id: 'selectlist'}),
|
||||
h.div({ id: 'logger', onmouseover() { log.show() } })
|
||||
h.div({ id: 'logger', onmouseover() { log.show() } }),
|
||||
h.div({ id: 'download', class: "hide" })
|
||||
]);
|
||||
|
||||
let { actions, grouplist, selectlist, logger } = bound;
|
||||
|
|
@ -174,7 +182,7 @@ function ui_build() {
|
|||
onchange(evt) { broker.send.load_files(evt.target.files) }
|
||||
})
|
||||
]),
|
||||
h.button({ _: 'export', onclick: api.file.export, disabled: true }),
|
||||
h.button({ _: 'export', onclick: api.file.export }),
|
||||
h.div({ class: "vsep" }),
|
||||
h.button({ _: 'analyze', disabled: true }),
|
||||
h.button({ _: 'repair', onclick: api.tool.repair }),
|
||||
|
|
@ -215,7 +223,9 @@ function ui_build() {
|
|||
.map(g => h.div([
|
||||
h.button({ _: `group`, title: g.id,
|
||||
class: [ "group", selHas(g) ? 'selected' : undefined ],
|
||||
onclick() { api.selection.toggle(g) }
|
||||
onclick(e) {
|
||||
e.shiftKey ? api.selection.toggle(g) : api.selection.set([g])
|
||||
}
|
||||
}),
|
||||
h.div({ class: "vsep" }),
|
||||
h.div({ class: "models"},
|
||||
|
|
|
|||
|
|
@ -76,9 +76,13 @@ mesh.model = class MeshModel extends mesh.object {
|
|||
return this.mesh;
|
||||
}
|
||||
|
||||
get matrix() {
|
||||
return this.mesh.matrixWorld.elements;
|
||||
}
|
||||
|
||||
debug() {
|
||||
worker.model_debug({
|
||||
matrix: this.mesh.matrixWorld.elements,
|
||||
matrix: this.matrix,
|
||||
id: this.id
|
||||
}).then(data => {
|
||||
// for debugging matrix ops
|
||||
|
|
|
|||
|
|
@ -31,6 +31,13 @@ function cacheUpdate(id, data) {
|
|||
Object.assign(cache[id], data);
|
||||
}
|
||||
|
||||
function translate_encode(id, matrix) {
|
||||
let rec = cache[id];
|
||||
let geo = rec.geo.clone();
|
||||
geo.applyMatrix4(core_matrix.clone().multiply( new THREE.Matrix4().fromArray(matrix) ));
|
||||
return geo.attributes.position.array;
|
||||
}
|
||||
|
||||
let model = {
|
||||
load(data) {
|
||||
let { vertices, indices, name, id } = data;
|
||||
|
|
@ -41,7 +48,9 @@ let model = {
|
|||
},
|
||||
|
||||
debug(data) {
|
||||
let { matrix, id } = data;
|
||||
let { id, matrix } = data;
|
||||
return translate_encode(id, matrix);
|
||||
throw "should not here";
|
||||
let rec = cache[id];
|
||||
let geo = rec.geo.clone();
|
||||
let m4 = core_matrix.clone().multiply( new THREE.Matrix4().fromArray(matrix) );
|
||||
|
|
@ -108,14 +117,41 @@ let object = {
|
|||
}
|
||||
};
|
||||
|
||||
worker.bind("debug", (data, send) => {
|
||||
let file = {
|
||||
export(data, send) {
|
||||
let { format, recs } = data;
|
||||
switch (format) {
|
||||
case "obj":
|
||||
let p = 1;
|
||||
let obj = [];
|
||||
for (let rec of recs) {
|
||||
let { id, matrix, file } = rec;
|
||||
let verts = translate_encode(id, matrix);
|
||||
obj.push(`g ${file}`);
|
||||
for (let i=0; i<verts.length; p += 3) {
|
||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
||||
obj.push(`v ${verts[i++]} ${verts[i++]} ${verts[i++]}`);
|
||||
obj.push(`f ${p} ${p+1} ${p+2}`);
|
||||
}
|
||||
}
|
||||
return obj.join('\n');
|
||||
default:
|
||||
throw `invalid format "${format}"`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function debug() {
|
||||
console.log({work_cache: cache});
|
||||
});
|
||||
}
|
||||
|
||||
worker.bindObject({
|
||||
debug,
|
||||
model,
|
||||
group,
|
||||
object
|
||||
object,
|
||||
file
|
||||
});
|
||||
|
||||
worker.ready();
|
||||
|
|
|
|||
|
|
@ -86,12 +86,13 @@ const dispatch = moto.worker = {
|
|||
if (run) {
|
||||
try {
|
||||
let data = run(msg.data, send);
|
||||
if (data || async === false) {
|
||||
if (!done && (data || async === false)) {
|
||||
send.done(data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.trace(error.stack);
|
||||
dispatch.send({ data: {error: error.toString()}, done: true });
|
||||
send.error(error.toString());
|
||||
// dispatch.send({ data: {error: error.toString()}, done: true });
|
||||
}
|
||||
} else {
|
||||
console.log({worker_unhandled: e});
|
||||
|
|
|
|||
Loading…
Reference in a new issue