Add merge shared vertices option for obj export

This commit is contained in:
luboslenco
2025-01-20 17:23:03 +01:00
parent 0586e5e4f0
commit ebded1126e
3 changed files with 113 additions and 4 deletions
+10 -2
View File
@@ -32,6 +32,7 @@ let box_export_color_spaces: string[] = [
let _box_export_bake_material: bool; let _box_export_bake_material: bool;
let _box_export_t: export_preset_texture_t; let _box_export_t: export_preset_texture_t;
let _box_export_apply_displacement: bool; let _box_export_apply_displacement: bool;
let _box_export_merge_vertices: bool;
function box_export_show_textures() { function box_export_show_textures() {
ui_box_show_custom(function (ui: ui_t) { ui_box_show_custom(function (ui: ui_t) {
@@ -356,7 +357,7 @@ function box_export_show_mesh() {
ui_box_show_custom(function (ui: ui_t) { ui_box_show_custom(function (ui: ui_t) {
let htab: ui_handle_t = ui_handle(__ID__); let htab: ui_handle_t = ui_handle(__ID__);
box_export_tab_export_mesh(ui, htab); box_export_tab_export_mesh(ui, htab);
}); }, 400, 240);
} }
function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) { function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) {
@@ -381,6 +382,12 @@ function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) {
let apply_displacement: bool = ui_check(ui_handle(__ID__), tr("Apply Displacement")); let apply_displacement: bool = ui_check(ui_handle(__ID__), tr("Apply Displacement"));
let hmerge: ui_handle_t = ui_handle(__ID__);
if (hmerge.init) {
hmerge.selected = true;
}
let merge_vertices: bool = ui_check(hmerge, tr("Merge Shared Vertices"));
let tris: i32 = 0; let tris: i32 = 0;
let pos: i32 = box_export_mesh_handle.position; let pos: i32 = box_export_mesh_handle.position;
let paint_objects: mesh_object_t[]; let paint_objects: mesh_object_t[];
@@ -407,6 +414,7 @@ function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) {
if (ui_button(tr("Export"))) { if (ui_button(tr("Export"))) {
ui_box_hide(); ui_box_hide();
_box_export_apply_displacement = apply_displacement; _box_export_apply_displacement = apply_displacement;
_box_export_merge_vertices = merge_vertices;
ui_files_show(context_raw.export_mesh_format == mesh_format_t.OBJ ? "obj" : "arm", true, false, function (path: string) { ui_files_show(context_raw.export_mesh_format == mesh_format_t.OBJ ? "obj" : "arm", true, false, function (path: string) {
///if (arm_android || arm_ios) ///if (arm_android || arm_ios)
let f: string = sys_title(); let f: string = sys_title();
@@ -429,7 +437,7 @@ function box_export_tab_export_mesh(ui: ui_t, htab: ui_handle_t) {
paint_objects = [po]; paint_objects = [po];
} }
export_mesh_run(path + path_sep + f, paint_objects, _box_export_apply_displacement); export_mesh_run(path + path_sep + f, paint_objects, _box_export_apply_displacement, _box_export_merge_vertices);
}); });
} }
} }
+4 -2
View File
@@ -1,10 +1,12 @@
function export_mesh_run(path: string, paint_objects: mesh_object_t[] = null, apply_disp: bool = false) { function export_mesh_run(path: string, paint_objects: mesh_object_t[] = null, apply_disp: bool = false, merge_vertices: bool = true) {
if (paint_objects == null) { if (paint_objects == null) {
paint_objects = project_paint_objects; paint_objects = project_paint_objects;
} }
if (context_raw.export_mesh_format == mesh_format_t.OBJ) { if (context_raw.export_mesh_format == mesh_format_t.OBJ) {
export_obj_run(path, paint_objects, apply_disp); merge_vertices ?
export_obj_run(path, paint_objects, apply_disp) :
export_obj_run_fast(path, paint_objects);
} }
else { else {
export_arm_run_mesh(path, paint_objects); export_arm_run_mesh(path, paint_objects);
+99
View File
@@ -177,3 +177,102 @@ function export_obj_run(path: string, paint_objects: mesh_object_t[], apply_disp
} }
iron_file_save_bytes(path, o, 0); iron_file_save_bytes(path, o, 0);
} }
function export_obj_run_fast(path: string, paint_objects: mesh_object_t[]) {
// Skips merging shared vertices
let o: u8[] = [];
export_obj_write_string(o, "# armorpaint.org\n");
let poff: i32 = 0;
let noff: i32 = 0;
let toff: i32 = 0;
for (let i: i32 = 0; i < paint_objects.length; ++i) {
let p: mesh_object_t = paint_objects[i];
let mesh: mesh_data_t = p.data;
let inv: f32 = 1 / 32767;
let sc: f32 = p.data.scale_pos * inv;
let posa: i16_array_t = mesh.vertex_arrays[0].values;
let nora: i16_array_t = mesh.vertex_arrays[1].values;
let texa: i16_array_t = mesh.vertex_arrays[2].values;
let pi: i32 = posa.length / 4;
let ni: i32 = pi;
let ti: i32 = pi;
export_obj_write_string(o, "o " + p.base.name + "\n");
for (let i: i32 = 0; i < pi; ++i) {
export_obj_write_string(o, "v ");
let f: f32 = posa[i * 4] * sc;
export_obj_write_string(o, f + "");
export_obj_write_string(o, " ");
f = posa[i * 4 + 2] * sc;
export_obj_write_string(o, f + "");
export_obj_write_string(o, " ");
f = -posa[i * 4 + 1] * sc;
export_obj_write_string(o, f + "");
export_obj_write_string(o, "\n");
}
for (let i: i32 = 0; i < ni; ++i) {
export_obj_write_string(o, "vn ");
let f: f32 = nora[i * 2] * inv;
export_obj_write_string(o, f + "");
export_obj_write_string(o, " ");
f = posa[i * 4 + 3] * inv;
export_obj_write_string(o, f + "");
export_obj_write_string(o, " ");
f = -nora[i * 2 + 1] * inv;
export_obj_write_string(o, f + "");
export_obj_write_string(o, "\n");
}
for (let i: i32 = 0; i < ti; ++i) {
export_obj_write_string(o, "vt ");
let f: f32 = texa[i * 2] * inv;
export_obj_write_string(o, f + "");
export_obj_write_string(o, " ");
f = 1.0 - texa[i * 2 + 1] * inv;
export_obj_write_string(o, f + "");
export_obj_write_string(o, "\n");
}
let inda: u32_array_t = mesh.index_arrays[0].values;
for (let i: i32 = 0; i < math_floor(inda.length / 3); ++i) {
let pi1: i32 = inda[i * 3 ] + 1 + poff;
let pi2: i32 = inda[i * 3 + 1] + 1 + poff;
let pi3: i32 = inda[i * 3 + 2] + 1 + poff;
let ni1: i32 = inda[i * 3 ] + 1 + noff;
let ni2: i32 = inda[i * 3 + 1] + 1 + noff;
let ni3: i32 = inda[i * 3 + 2] + 1 + noff;
let ti1: i32 = inda[i * 3 ] + 1 + toff;
let ti2: i32 = inda[i * 3 + 1] + 1 + toff;
let ti3: i32 = inda[i * 3 + 2] + 1 + toff;
export_obj_write_string(o, "f ");
export_obj_write_string(o, pi1 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ti1 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ni1 + "");
export_obj_write_string(o, " ");
export_obj_write_string(o, pi2 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ti2 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ni2 + "");
export_obj_write_string(o, " ");
export_obj_write_string(o, pi3 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ti3 + "");
export_obj_write_string(o, "/");
export_obj_write_string(o, ni3 + "");
export_obj_write_string(o, "\n");
}
poff += pi;
noff += ni;
toff += ti;
}
if (!ends_with(path, ".obj")) {
path += ".obj";
}
iron_file_save_bytes(path, o, 0);
}