From 2d9ed708f0ca40246dc919daab621d62ed8aabb2 Mon Sep 17 00:00:00 2001 From: luboslenco Date: Sun, 3 May 2026 00:12:20 +0200 Subject: [PATCH] paint: unwrap cleanup --- paint/sources/functions.h | 2 +- paint/sources/import_mesh.c | 114 ++++++++++++++---------------------- paint/sources/project.c | 60 +++---------------- paint/sources/util_mesh.c | 16 ----- 4 files changed, 52 insertions(+), 140 deletions(-) diff --git a/paint/sources/functions.h b/paint/sources/functions.h index 628ee849..fdc8c4ef 100644 --- a/paint/sources/functions.h +++ b/paint/sources/functions.h @@ -364,7 +364,7 @@ void project_import_mesh(bool replace_existing, void (*done void project_append_mesh(); void project_import_mesh_box(char *path, bool replace_existing, bool clear_layers, void (*done)(void)); void project_reimport_mesh(); -void project_unwrap_mesh_box(raw_mesh_t *mesh, void (*done)(raw_mesh_t *), bool skip_ui); +void project_unwrap_mesh_box(); void project_import_asset(char *filters, bool hdr_as_envmap); void project_import_swatches(bool replace_existing); void project_reimport_textures(); diff --git a/paint/sources/import_mesh.c b/paint/sources/import_mesh.c index 07fb7d20..0058e19b 100644 --- a/paint/sources/import_mesh.c +++ b/paint/sources/import_mesh.c @@ -2,7 +2,7 @@ #include "global.h" bool import_mesh_clear_layers = true; -any_array_t *import_mesh_meshes_to_unwrap = NULL; +bool import_mesh_needs_unwrap = false; void import_mesh_run(char *path, bool _clear_layers, bool replace_existing) { if (!path_is_mesh(path)) { @@ -15,9 +15,6 @@ void import_mesh_run(char *path, bool _clear_layers, bool replace_existing) { import_mesh_clear_layers = _clear_layers; g_context->layer_filter = 0; - gc_unroot(import_mesh_meshes_to_unwrap); - import_mesh_meshes_to_unwrap = NULL; - char *p = to_lower_case(path); if (ends_with(p, ".obj")) { import_obj_run(path, replace_existing); @@ -66,7 +63,7 @@ i32 import_mesh_finish_import_sort(void **pa, void **pb) { return strcmp(a->base->name, b->base->name); } -void import_mesh_finish_import() { +void import_mesh_finish_import(void *_) { if (g_context->merged_object != NULL) { mesh_data_delete(g_context->merged_object->data); mesh_object_remove(g_context->merged_object); @@ -82,7 +79,6 @@ void import_mesh_finish_import() { } if (project_paint_objects->length > 1) { - // Sort by name array_sort(project_paint_objects, &import_mesh_finish_import_sort); @@ -113,17 +109,49 @@ void import_mesh_finish_import() { render_path_raytrace_ready = false; g_context->paint_body = NULL; tab_meshes_reset_preview_map(); -} -void _import_mesh_make_mesh_finish_import(void *_) { - import_mesh_finish_import(); + if (import_mesh_needs_unwrap) { + import_mesh_needs_unwrap = false; + project_unwrap_mesh_box(); + } } void _import_mesh_make_mesh_clear_layers(void *_) { layers_init(); } -void _import_mesh_make_mesh(raw_mesh_t *mesh) { +bool _import_mesh_is_unique_name(char *s) { + for (i32 i = 0; i < project_paint_objects->length; ++i) { + mesh_object_t *p = project_paint_objects->buffer[i]; + if (string_equals(p->base->name, s)) { + return false; + } + } + return true; +} + +char *_import_mesh_number_ext(i32 i) { + if (i < 10) { + return string(".00%s", i32_to_string(i)); + } + if (i < 100) { + return string(".0%s", i32_to_string(i)); + } + return string(".%s", i32_to_string(i)); +} + +void import_mesh_make_mesh(raw_mesh_t *mesh) { + if (mesh == NULL || mesh->posa == NULL || mesh->nora == NULL || mesh->inda == NULL || mesh->posa->length == 0) { + console_error(strings_failed_to_read_mesh_data()); + return; + } + + import_mesh_needs_unwrap = mesh->texa == NULL; + if (mesh->texa == NULL) { + i32 verts = mesh->posa->length / 4; + mesh->texa = i16_array_create(verts * 2); + } + mesh_data_t *raw = import_mesh_raw_mesh(mesh); mesh_data_t *md = mesh_data_create(raw); @@ -178,30 +206,15 @@ void _import_mesh_make_mesh(raw_mesh_t *mesh) { } // Wait for add_mesh calls to finish - sys_notify_on_next_frame(&_import_mesh_make_mesh_finish_import, NULL); + sys_notify_on_next_frame(&import_mesh_finish_import, NULL); } -bool _import_mesh_is_unique_name(char *s) { - for (i32 i = 0; i < project_paint_objects->length; ++i) { - mesh_object_t *p = project_paint_objects->buffer[i]; - if (string_equals(p->base->name, s)) { - return false; - } +void import_mesh_add_mesh(raw_mesh_t *mesh) { + if (mesh->texa == NULL) { + i32 verts = mesh->posa->length / 4; + mesh->texa = i16_array_create(verts * 2); } - return true; -} -char *_import_mesh_number_ext(i32 i) { - if (i < 10) { - return string(".00%s", i32_to_string(i)); - } - if (i < 100) { - return string(".0%s", i32_to_string(i)); - } - return string(".%s", i32_to_string(i)); -} - -void _import_mesh_add_mesh(raw_mesh_t *mesh) { mesh_data_t *raw = import_mesh_raw_mesh(mesh); if (g_context->tool == TOOL_TYPE_CURSOR) { @@ -236,47 +249,6 @@ void _import_mesh_add_mesh(raw_mesh_t *mesh) { util_uv_dilatemap_cached = false; } -void import_mesh_first_unwrap_done(raw_mesh_t *mesh) { - _import_mesh_make_mesh(mesh); - for (i32 i = 0; i < import_mesh_meshes_to_unwrap->length; ++i) { - raw_mesh_t *mesh = import_mesh_meshes_to_unwrap->buffer[i]; - project_unwrap_mesh_box(mesh, _import_mesh_add_mesh, true); - } -} - -void import_mesh_make_mesh(raw_mesh_t *mesh) { - if (mesh == NULL || mesh->posa == NULL || mesh->nora == NULL || mesh->inda == NULL || mesh->posa->length == 0) { - console_error(strings_failed_to_read_mesh_data()); - return; - } - - if (mesh->texa == NULL) { - if (import_mesh_meshes_to_unwrap == NULL) { - gc_unroot(import_mesh_meshes_to_unwrap); - import_mesh_meshes_to_unwrap = any_array_create_from_raw((void *[]){}, 0); - gc_root(import_mesh_meshes_to_unwrap); - } - project_unwrap_mesh_box(mesh, import_mesh_first_unwrap_done, false); - } - else { - _import_mesh_make_mesh(mesh); - } -} - -void import_mesh_add_mesh(raw_mesh_t *mesh) { - if (mesh->texa == NULL) { - if (import_mesh_meshes_to_unwrap != NULL) { - any_array_push(import_mesh_meshes_to_unwrap, mesh); - } - else { - project_unwrap_mesh_box(mesh, _import_mesh_add_mesh, false); - } - } - else { - _import_mesh_add_mesh(mesh); - } -} - mesh_data_t *import_mesh_raw_mesh(raw_mesh_t *mesh) { mesh_data_t *raw = GC_ALLOC_INIT(mesh_data_t, {.name = mesh->name, .vertex_arrays = any_array_create_from_raw( diff --git a/paint/sources/project.c b/paint/sources/project.c index f5cf4c5e..9f7f77e4 100644 --- a/paint/sources/project.c +++ b/paint/sources/project.c @@ -8,14 +8,10 @@ char *_project_import_mesh_box_path; bool _project_import_mesh_box_replace_existing; bool _project_import_mesh_box_clear_layers; void (*_project_import_mesh_box_done)(void); -raw_mesh_t *_project_unwrap_mesh_box_mesh; -void (*_project_unwrap_mesh_box_done)(raw_mesh_t *); -bool _project_unwrap_mesh_box_skip_ui; bool _project_import_asset_hdr_as_envmap; bool _project_import_swatches_replace_existing; asset_t *_project_reimport_texture_asset; scene_t *_project_scene_mesh_gc; -i32 _project_unwrap_by = 0; void project_open_on_file_picked(char *path) { if (!ends_with(path, ".arm")) { @@ -524,45 +520,15 @@ void project_reimport_mesh() { } } -string_array_t *project_get_unwrap_plugins() { - string_array_t *unwrap_plugins = any_array_create_from_raw((void *[]){}, 0); - if (box_preferences_files_plugin == NULL) { - box_preferences_fetch_plugins(); - } -#ifdef WITH_PLUGINS - for (i32 i = 0; i < box_preferences_files_plugin->length; ++i) { - char *f = box_preferences_files_plugin->buffer[i]; - if (string_index_of(f, "uv_unwrap") >= 0 && ends_with(f, ".c")) { - any_array_push(unwrap_plugins, f); - } - } - any_array_push(unwrap_plugins, "uv_unwrap"); -#endif - any_array_push(unwrap_plugins, "equirect"); - return unwrap_plugins; -} - void project_unwrap_mesh(raw_mesh_t *mesh, void (*done)(raw_mesh_t *)) { - string_array_t *unwrap_plugins = project_get_unwrap_plugins(); - - if (_project_unwrap_by == unwrap_plugins->length - 1) { - util_mesh_equirect_unwrap(mesh); - } - else { - char *f = unwrap_plugins->buffer[_project_unwrap_by]; - void (*cb)(void *mesh) = any_map_get(util_mesh_unwrappers, f); - cb(mesh); - } + char *f = "uv_unwrap"; + void (*cb)(void *mesh) = any_map_get(util_mesh_unwrappers, f); + cb(mesh); done(mesh); } void project_unwrap_mesh_box_draw() { - raw_mesh_t *mesh = _project_unwrap_mesh_box_mesh; - void (*done)(raw_mesh_t *) = _project_unwrap_mesh_box_done; - - string_array_t *unwrap_plugins = project_get_unwrap_plugins(); - _project_unwrap_by = ui_combo(ui_handle(__ID__), unwrap_plugins, tr("Plugin"), true, UI_ALIGN_LEFT, true); - + ui_end_element(); ui_row2(); if (ui_icon_button(tr("Cancel"), ICON_CLOSE, UI_ALIGN_CENTER)) { ui_box_hide(); @@ -574,23 +540,13 @@ void project_unwrap_mesh_box_draw() { console_toast(tr("Unwrapping mesh")); #endif - project_unwrap_mesh(mesh, done); +#ifdef WITH_PLUGINS + plugin_uv_unwrap_button(); +#endif } } -void project_unwrap_mesh_box(raw_mesh_t *mesh, void (*done)(raw_mesh_t *), bool skip_ui) { - gc_unroot(_project_unwrap_mesh_box_mesh); - _project_unwrap_mesh_box_mesh = mesh; - gc_root(_project_unwrap_mesh_box_mesh); - gc_unroot(_project_unwrap_mesh_box_done); - _project_unwrap_mesh_box_done = done; - gc_root(_project_unwrap_mesh_box_done); - - if (skip_ui) { - project_unwrap_mesh(mesh, done); - return; - } - +void project_unwrap_mesh_box() { ui_box_show_custom(&project_unwrap_mesh_box_draw, 400, 200, NULL, true, tr("Unwrap Mesh")); } diff --git a/paint/sources/util_mesh.c b/paint/sources/util_mesh.c index 0d63a92b..351a290c 100644 --- a/paint/sources/util_mesh.c +++ b/paint/sources/util_mesh.c @@ -422,22 +422,6 @@ void util_mesh_apply_displacement(gpu_texture_t *texpaint_pack, f32 strength, f3 mesh_data_build_vertices(g->_->vertex_buffer, o->data->vertex_arrays); } -void util_mesh_equirect_unwrap(raw_mesh_t *mesh) { - i32 verts = math_floor(mesh->posa->length / 4.0); - mesh->texa = i16_array_create(verts * 2); - vec4_t n = (vec4_t){0.0, 0.0, 0.0, 1.0}; - for (i32 i = 0; i < verts; ++i) { - n = (vec4_t){mesh->posa->buffer[i * 4] / 32767.0, mesh->posa->buffer[i * 4 + 1] / 32767.0, mesh->posa->buffer[i * 4 + 2] / 32767.0, 1.0}; - n = vec4_norm(n); - // Sphere projection - // mesh.texa[i * 2 ] = math_atan2(n.x, n.y) / (math_pi() * 2) + 0.5; - // mesh.texa[i * 2 + 1] = n.z * 0.5 + 0.5; - // Equirect - mesh->texa->buffer[i * 2] = math_floor(((math_atan2(-n.z, n.x) + math_pi()) / (float)(math_pi() * 2)) * 32767); - mesh->texa->buffer[i * 2 + 1] = math_floor((math_acos(n.y) / (float)math_pi()) * 32767); - } -} - i32 util_mesh_decimate_sort(i32 *pa, i32 *pb) { i32 a = *(pa); i32 b = *(pb);