sculpt: export fixes
This commit is contained in:
@@ -10,7 +10,10 @@ void export_mesh_run(char *path, mesh_object_t_array_t *paint_objects, bool appl
|
||||
paint_objects = g_project->_->paint_objects;
|
||||
}
|
||||
if (g_context->export_mesh_format == MESH_FORMAT_OBJ) {
|
||||
if (merge_vertices) {
|
||||
if (g_config->workflow == WORKFLOW_SCULPT) {
|
||||
export_obj_run_sculpt(path, paint_objects);
|
||||
}
|
||||
else if (merge_vertices) {
|
||||
export_obj_run(path, paint_objects, apply_disp);
|
||||
}
|
||||
else {
|
||||
|
||||
+125
-23
@@ -275,15 +275,63 @@ void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
iron_file_save_bytes(path, o, 0);
|
||||
}
|
||||
|
||||
void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
slot_layer_t *l = NULL;
|
||||
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
|
||||
if (g_project->_->layers->buffer[i]->texpaint_sculpt != NULL) {
|
||||
l = g_project->_->layers->buffer[i];
|
||||
break;
|
||||
static bool export_obj_sculpt_layer_mask(slot_layer_t *l, f32_array_t *pmask, i32 len, i16_array_t *texa, u32_array_t *inda, f32 inv) {
|
||||
slot_layer_t_array_t *masks = slot_layer_get_masks(l, true);
|
||||
if (masks == NULL) {
|
||||
return false;
|
||||
}
|
||||
#ifdef IRON_BGRA
|
||||
i32 r_off = 2;
|
||||
#else
|
||||
i32 r_off = 0;
|
||||
#endif
|
||||
bool any = false;
|
||||
for (i32 mi = 0; mi < masks->length; ++mi) {
|
||||
slot_layer_t *m = masks->buffer[mi];
|
||||
if (!slot_layer_is_visible(m) || m->texpaint == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!any) {
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
pmask->buffer[i] = 1.0;
|
||||
}
|
||||
any = true;
|
||||
}
|
||||
buffer_t *mp = gpu_get_texture_pixels(m->texpaint);
|
||||
i32 mw = m->texpaint->width;
|
||||
i32 mh = m->texpaint->height;
|
||||
f32 opac = slot_layer_get_opacity(m);
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
i32 vid = inda->buffer[i];
|
||||
f32 u = texa->buffer[vid * 2] * inv;
|
||||
f32 v = texa->buffer[vid * 2 + 1] * inv;
|
||||
i32 x = math_floor(u * mw);
|
||||
i32 y = math_floor(v * mh);
|
||||
x = x < 0 ? 0 : (x >= mw ? mw - 1 : x);
|
||||
y = y < 0 ? 0 : (y >= mh ? mh - 1 : y);
|
||||
f32 r = buffer_get_u8(mp, (y * mw + x) * 4 + r_off) / 255.0;
|
||||
pmask->buffer[i] *= (1.0 - opac) + r * opac;
|
||||
}
|
||||
}
|
||||
if (l == NULL) {
|
||||
if (any) {
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
f32 c = pmask->buffer[i];
|
||||
pmask->buffer[i] = c < 0.0 ? 0.0 : (c > 1.0 ? 1.0 : c);
|
||||
}
|
||||
}
|
||||
return any;
|
||||
}
|
||||
|
||||
void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
slot_layer_t_array_t *sculpt_layers = any_array_create_from_raw((void *[]){}, 0);
|
||||
for (i32 i = 0; i < g_project->_->layers->length; ++i) {
|
||||
slot_layer_t *l = g_project->_->layers->buffer[i];
|
||||
if (l->texpaint_sculpt != NULL && slot_layer_is_visible(l)) {
|
||||
any_array_push(sculpt_layers, l);
|
||||
}
|
||||
}
|
||||
i32 count = sculpt_layers->length;
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -294,18 +342,71 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
mesh_data_t *mesh = p->data;
|
||||
f32 sc = mesh->scale_pos;
|
||||
i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values;
|
||||
i32 len = math_floor(mesh->index_array->length);
|
||||
u32_array_t *inda = mesh->index_array;
|
||||
i32 len = math_floor(inda->length);
|
||||
i32 tris = math_floor(len / 3.0);
|
||||
f32 inv = 1.0 / 32767.0;
|
||||
|
||||
buffer_t *pixels = gpu_get_texture_pixels(l->texpaint_sculpt);
|
||||
// The base render target holds the rest-pose positions
|
||||
buffer_t *base_pixels = NULL;
|
||||
render_target_t *base_rt = any_map_get(render_path_render_targets, "texpaint_sculpt_base");
|
||||
if (base_rt != NULL && base_rt->_image != NULL) {
|
||||
base_pixels = gpu_get_texture_pixels(base_rt->_image);
|
||||
}
|
||||
|
||||
// Accumulate the combined position of every vertex across all layers and masks
|
||||
f32_array_t *cpos = f32_array_create(len * 3);
|
||||
f32_array_t *pmask = f32_array_create(len);
|
||||
|
||||
buffer_t *l0 = gpu_get_texture_pixels(sculpt_layers->buffer[0]->texpaint_sculpt);
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
cpos->buffer[i * 3] = buffer_get_f32(l0, i * 16);
|
||||
cpos->buffer[i * 3 + 1] = buffer_get_f32(l0, i * 16 + 4);
|
||||
cpos->buffer[i * 3 + 2] = buffer_get_f32(l0, i * 16 + 8);
|
||||
}
|
||||
// Blend the base layer back toward the rest pose where its mask is dark
|
||||
if (export_obj_sculpt_layer_mask(sculpt_layers->buffer[0], pmask, len, texa, inda, inv) && base_pixels != NULL) {
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
f32 bx = buffer_get_f32(base_pixels, i * 16);
|
||||
f32 by = buffer_get_f32(base_pixels, i * 16 + 4);
|
||||
f32 bz = buffer_get_f32(base_pixels, i * 16 + 8);
|
||||
f32 w = pmask->buffer[i];
|
||||
cpos->buffer[i * 3] = bx + (cpos->buffer[i * 3] - bx) * w;
|
||||
cpos->buffer[i * 3 + 1] = by + (cpos->buffer[i * 3 + 1] - by) * w;
|
||||
cpos->buffer[i * 3 + 2] = bz + (cpos->buffer[i * 3 + 2] - bz) * w;
|
||||
}
|
||||
}
|
||||
// Add each additional layers displacement relative to the rest pose
|
||||
for (i32 k = 1; k < count; ++k) {
|
||||
buffer_t *lk = gpu_get_texture_pixels(sculpt_layers->buffer[k]->texpaint_sculpt);
|
||||
bool masked = export_obj_sculpt_layer_mask(sculpt_layers->buffer[k], pmask, len, texa, inda, inv);
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
f32 dx = buffer_get_f32(lk, i * 16);
|
||||
f32 dy = buffer_get_f32(lk, i * 16 + 4);
|
||||
f32 dz = buffer_get_f32(lk, i * 16 + 8);
|
||||
if (base_pixels != NULL) {
|
||||
dx -= buffer_get_f32(base_pixels, i * 16);
|
||||
dy -= buffer_get_f32(base_pixels, i * 16 + 4);
|
||||
dz -= buffer_get_f32(base_pixels, i * 16 + 8);
|
||||
}
|
||||
if (masked) {
|
||||
f32 w = pmask->buffer[i];
|
||||
dx *= w;
|
||||
dy *= w;
|
||||
dz *= w;
|
||||
}
|
||||
cpos->buffer[i * 3] += dx;
|
||||
cpos->buffer[i * 3 + 1] += dy;
|
||||
cpos->buffer[i * 3 + 2] += dz;
|
||||
}
|
||||
}
|
||||
|
||||
export_obj_write_string(o, string("o %s\n", p->base->name));
|
||||
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
f32 x = buffer_get_f32(pixels, i * 16) * sc;
|
||||
f32 y = buffer_get_f32(pixels, i * 16 + 4) * sc;
|
||||
f32 z = buffer_get_f32(pixels, i * 16 + 8) * sc;
|
||||
f32 x = cpos->buffer[i * 3] * sc;
|
||||
f32 y = cpos->buffer[i * 3 + 1] * sc;
|
||||
f32 z = cpos->buffer[i * 3 + 2] * sc;
|
||||
export_obj_write_string(o, "v ");
|
||||
export_obj_write_string(o, f32_to_string(x));
|
||||
export_obj_write_string(o, " ");
|
||||
@@ -317,15 +418,15 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
|
||||
for (i32 t = 0; t < tris; ++t) {
|
||||
i32 i0 = t * 3, i1 = t * 3 + 1, i2 = t * 3 + 2;
|
||||
f32 x0 = buffer_get_f32(pixels, i0 * 16) * sc;
|
||||
f32 y0 = buffer_get_f32(pixels, i0 * 16 + 4) * sc;
|
||||
f32 z0 = buffer_get_f32(pixels, i0 * 16 + 8) * sc;
|
||||
f32 x1 = buffer_get_f32(pixels, i1 * 16) * sc;
|
||||
f32 y1 = buffer_get_f32(pixels, i1 * 16 + 4) * sc;
|
||||
f32 z1 = buffer_get_f32(pixels, i1 * 16 + 8) * sc;
|
||||
f32 x2 = buffer_get_f32(pixels, i2 * 16) * sc;
|
||||
f32 y2 = buffer_get_f32(pixels, i2 * 16 + 4) * sc;
|
||||
f32 z2 = buffer_get_f32(pixels, i2 * 16 + 8) * sc;
|
||||
f32 x0 = cpos->buffer[i0 * 3] * sc;
|
||||
f32 y0 = cpos->buffer[i0 * 3 + 1] * sc;
|
||||
f32 z0 = cpos->buffer[i0 * 3 + 2] * sc;
|
||||
f32 x1 = cpos->buffer[i1 * 3] * sc;
|
||||
f32 y1 = cpos->buffer[i1 * 3 + 1] * sc;
|
||||
f32 z1 = cpos->buffer[i1 * 3 + 2] * sc;
|
||||
f32 x2 = cpos->buffer[i2 * 3] * sc;
|
||||
f32 y2 = cpos->buffer[i2 * 3 + 1] * sc;
|
||||
f32 z2 = cpos->buffer[i2 * 3 + 2] * sc;
|
||||
f32 e1x = x1 - x0, e1y = y1 - y0, e1z = z1 - z0;
|
||||
f32 e2x = x2 - x0, e2y = y2 - y0, e2z = z2 - z0;
|
||||
f32 nx = e1y * e2z - e1z * e2y;
|
||||
@@ -347,8 +448,9 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
f32 u = texa->buffer[i * 2] * inv;
|
||||
f32 v = 1.0 - texa->buffer[i * 2 + 1] * inv;
|
||||
i32 vid = inda->buffer[i];
|
||||
f32 u = texa->buffer[vid * 2] * inv;
|
||||
f32 v = 1.0 - texa->buffer[vid * 2 + 1] * inv;
|
||||
export_obj_write_string(o, "vt ");
|
||||
export_obj_write_string(o, f32_to_string(u));
|
||||
export_obj_write_string(o, " ");
|
||||
|
||||
Reference in New Issue
Block a user