paint: unwrap cleanup

This commit is contained in:
luboslenco
2026-05-03 00:12:20 +02:00
parent 732eaebdb4
commit 2d9ed708f0
4 changed files with 52 additions and 140 deletions
+1 -1
View File
@@ -364,7 +364,7 @@ void project_import_mesh(bool replace_existing, void (*done
void project_append_mesh(); void project_append_mesh();
void project_import_mesh_box(char *path, bool replace_existing, bool clear_layers, void (*done)(void)); void project_import_mesh_box(char *path, bool replace_existing, bool clear_layers, void (*done)(void));
void project_reimport_mesh(); 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_asset(char *filters, bool hdr_as_envmap);
void project_import_swatches(bool replace_existing); void project_import_swatches(bool replace_existing);
void project_reimport_textures(); void project_reimport_textures();
+43 -71
View File
@@ -2,7 +2,7 @@
#include "global.h" #include "global.h"
bool import_mesh_clear_layers = true; 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) { void import_mesh_run(char *path, bool _clear_layers, bool replace_existing) {
if (!path_is_mesh(path)) { 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; import_mesh_clear_layers = _clear_layers;
g_context->layer_filter = 0; g_context->layer_filter = 0;
gc_unroot(import_mesh_meshes_to_unwrap);
import_mesh_meshes_to_unwrap = NULL;
char *p = to_lower_case(path); char *p = to_lower_case(path);
if (ends_with(p, ".obj")) { if (ends_with(p, ".obj")) {
import_obj_run(path, replace_existing); 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); 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) { if (g_context->merged_object != NULL) {
mesh_data_delete(g_context->merged_object->data); mesh_data_delete(g_context->merged_object->data);
mesh_object_remove(g_context->merged_object); mesh_object_remove(g_context->merged_object);
@@ -82,7 +79,6 @@ void import_mesh_finish_import() {
} }
if (project_paint_objects->length > 1) { if (project_paint_objects->length > 1) {
// Sort by name // Sort by name
array_sort(project_paint_objects, &import_mesh_finish_import_sort); array_sort(project_paint_objects, &import_mesh_finish_import_sort);
@@ -113,17 +109,49 @@ void import_mesh_finish_import() {
render_path_raytrace_ready = false; render_path_raytrace_ready = false;
g_context->paint_body = NULL; g_context->paint_body = NULL;
tab_meshes_reset_preview_map(); tab_meshes_reset_preview_map();
}
void _import_mesh_make_mesh_finish_import(void *_) { if (import_mesh_needs_unwrap) {
import_mesh_finish_import(); import_mesh_needs_unwrap = false;
project_unwrap_mesh_box();
}
} }
void _import_mesh_make_mesh_clear_layers(void *_) { void _import_mesh_make_mesh_clear_layers(void *_) {
layers_init(); 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 *raw = import_mesh_raw_mesh(mesh);
mesh_data_t *md = mesh_data_create(raw); 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 // 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) { void import_mesh_add_mesh(raw_mesh_t *mesh) {
for (i32 i = 0; i < project_paint_objects->length; ++i) { if (mesh->texa == NULL) {
mesh_object_t *p = project_paint_objects->buffer[i]; i32 verts = mesh->posa->length / 4;
if (string_equals(p->base->name, s)) { mesh->texa = i16_array_create(verts * 2);
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_add_mesh(raw_mesh_t *mesh) {
mesh_data_t *raw = import_mesh_raw_mesh(mesh); mesh_data_t *raw = import_mesh_raw_mesh(mesh);
if (g_context->tool == TOOL_TYPE_CURSOR) { 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; 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 *import_mesh_raw_mesh(raw_mesh_t *mesh) {
mesh_data_t *raw = GC_ALLOC_INIT(mesh_data_t, {.name = mesh->name, mesh_data_t *raw = GC_ALLOC_INIT(mesh_data_t, {.name = mesh->name,
.vertex_arrays = any_array_create_from_raw( .vertex_arrays = any_array_create_from_raw(
+8 -52
View File
@@ -8,14 +8,10 @@ char *_project_import_mesh_box_path;
bool _project_import_mesh_box_replace_existing; bool _project_import_mesh_box_replace_existing;
bool _project_import_mesh_box_clear_layers; bool _project_import_mesh_box_clear_layers;
void (*_project_import_mesh_box_done)(void); 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_asset_hdr_as_envmap;
bool _project_import_swatches_replace_existing; bool _project_import_swatches_replace_existing;
asset_t *_project_reimport_texture_asset; asset_t *_project_reimport_texture_asset;
scene_t *_project_scene_mesh_gc; scene_t *_project_scene_mesh_gc;
i32 _project_unwrap_by = 0;
void project_open_on_file_picked(char *path) { void project_open_on_file_picked(char *path) {
if (!ends_with(path, ".arm")) { 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 *)) { void project_unwrap_mesh(raw_mesh_t *mesh, void (*done)(raw_mesh_t *)) {
string_array_t *unwrap_plugins = project_get_unwrap_plugins(); char *f = "uv_unwrap";
void (*cb)(void *mesh) = any_map_get(util_mesh_unwrappers, f);
if (_project_unwrap_by == unwrap_plugins->length - 1) { cb(mesh);
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);
}
done(mesh); done(mesh);
} }
void project_unwrap_mesh_box_draw() { void project_unwrap_mesh_box_draw() {
raw_mesh_t *mesh = _project_unwrap_mesh_box_mesh; ui_end_element();
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_row2(); ui_row2();
if (ui_icon_button(tr("Cancel"), ICON_CLOSE, UI_ALIGN_CENTER)) { if (ui_icon_button(tr("Cancel"), ICON_CLOSE, UI_ALIGN_CENTER)) {
ui_box_hide(); ui_box_hide();
@@ -574,23 +540,13 @@ void project_unwrap_mesh_box_draw() {
console_toast(tr("Unwrapping mesh")); console_toast(tr("Unwrapping mesh"));
#endif #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) { void project_unwrap_mesh_box() {
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;
}
ui_box_show_custom(&project_unwrap_mesh_box_draw, 400, 200, NULL, true, tr("Unwrap Mesh")); ui_box_show_custom(&project_unwrap_mesh_box_draw, 400, 200, NULL, true, tr("Unwrap Mesh"));
} }
-16
View File
@@ -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); 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 util_mesh_decimate_sort(i32 *pa, i32 *pb) {
i32 a = *(pa); i32 a = *(pa);
i32 b = *(pb); i32 b = *(pb);