mirror of
https://github.com/armory3d/armorpaint.git
synced 2026-10-02 02:54:34 +08:00
paint: make obj export faster
This commit is contained in:
+192
-232
@@ -1,14 +1,123 @@
|
||||
|
||||
#include "../global.h"
|
||||
|
||||
static void export_obj_write_string(u8_array_t *out, char *str) {
|
||||
for (i32 i = 0; i < string_length(str); ++i) {
|
||||
u8_array_push(out, char_code_at(str, i));
|
||||
static void export_obj_reserve(u8_array_t *out, u32 size) {
|
||||
if (out->length + size > out->capacity) {
|
||||
u32 cap = out->capacity < 1024 ? 1024 : out->capacity * 2;
|
||||
while (cap < out->length + size) {
|
||||
cap *= 2;
|
||||
}
|
||||
out->buffer = realloc(out->buffer, cap);
|
||||
out->capacity = cap;
|
||||
}
|
||||
}
|
||||
|
||||
static void export_obj_write_string(u8_array_t *out, char *str) {
|
||||
u32 len = strlen(str);
|
||||
export_obj_reserve(out, len);
|
||||
memcpy(out->buffer + out->length, str, len);
|
||||
out->length += len;
|
||||
}
|
||||
|
||||
static void export_obj_write_char(u8_array_t *out, char c) {
|
||||
export_obj_reserve(out, 1);
|
||||
out->buffer[out->length++] = c;
|
||||
}
|
||||
|
||||
static void export_obj_write_i32(u8_array_t *out, i32 i) {
|
||||
char s[16];
|
||||
i32 l = 0;
|
||||
u32 u = i < 0 ? -(u32)i : (u32)i;
|
||||
do {
|
||||
s[l++] = '0' + u % 10;
|
||||
u /= 10;
|
||||
} while (u > 0);
|
||||
export_obj_reserve(out, l + 1);
|
||||
if (i < 0) {
|
||||
out->buffer[out->length++] = '-';
|
||||
}
|
||||
while (l > 0) {
|
||||
out->buffer[out->length++] = s[--l];
|
||||
}
|
||||
}
|
||||
|
||||
static void export_obj_write_f32(u8_array_t *out, f32 f) {
|
||||
char s[64];
|
||||
i32 l = snprintf(s, sizeof(s), "%f", f);
|
||||
if (l <= 0 || l >= (i32)sizeof(s)) {
|
||||
return;
|
||||
}
|
||||
while (l > 1 && s[l - 1] == '0') {
|
||||
l--;
|
||||
}
|
||||
if (s[l - 1] == '.') {
|
||||
l--;
|
||||
}
|
||||
export_obj_reserve(out, l);
|
||||
memcpy(out->buffer + out->length, s, l);
|
||||
out->length += l;
|
||||
}
|
||||
|
||||
static void export_obj_write_vec(u8_array_t *out, char *prefix, f32 x, f32 y, f32 z, bool has_z) {
|
||||
export_obj_write_string(out, prefix);
|
||||
export_obj_write_f32(out, x);
|
||||
export_obj_write_char(out, ' ');
|
||||
export_obj_write_f32(out, y);
|
||||
if (has_z) {
|
||||
export_obj_write_char(out, ' ');
|
||||
export_obj_write_f32(out, z);
|
||||
}
|
||||
export_obj_write_char(out, '\n');
|
||||
}
|
||||
|
||||
static void export_obj_write_face(u8_array_t *out, i32 *p, i32 *t, i32 *n) {
|
||||
export_obj_write_char(out, 'f');
|
||||
for (i32 k = 0; k < 3; ++k) {
|
||||
export_obj_write_char(out, ' ');
|
||||
export_obj_write_i32(out, p[k]);
|
||||
export_obj_write_char(out, '/');
|
||||
export_obj_write_i32(out, t[k]);
|
||||
export_obj_write_char(out, '/');
|
||||
export_obj_write_i32(out, n[k]);
|
||||
}
|
||||
export_obj_write_char(out, '\n');
|
||||
}
|
||||
|
||||
static u64 export_obj_key(i16 a, i16 b, i16 c) {
|
||||
return (u64)(u16)a | ((u64)(u16)b << 16) | ((u64)(u16)c << 32);
|
||||
}
|
||||
|
||||
static i32 export_obj_dedupe(u64 *keys, i32 len, i32 *map, i32 *first) {
|
||||
u32 cap = 16;
|
||||
while (cap < (u32)len * 2) {
|
||||
cap *= 2;
|
||||
}
|
||||
i32 *table = calloc(cap, sizeof(i32)); // Unique index + 1, 0 is empty
|
||||
i32 count = 0;
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
u64 k = keys[i];
|
||||
u32 s = (u32)((k * 0x9E3779B97F4A7C15ull) >> 32) & (cap - 1);
|
||||
while (true) {
|
||||
i32 e = table[s];
|
||||
if (e == 0) {
|
||||
table[s] = count + 1;
|
||||
first[count] = i;
|
||||
map[i] = count++;
|
||||
break;
|
||||
}
|
||||
if (keys[first[e - 1]] == k) {
|
||||
map[i] = e - 1;
|
||||
break;
|
||||
}
|
||||
s = (s + 1) & (cap - 1);
|
||||
}
|
||||
}
|
||||
free(table);
|
||||
return count;
|
||||
}
|
||||
|
||||
void export_obj_run(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
u8_array_t *o = u8_array_create_from_raw((u8[]){}, 0);
|
||||
u8_array_t *o = u8_array_create(0);
|
||||
export_obj_write_string(o, "# armorpaint.org\n");
|
||||
|
||||
i32 poff = 0;
|
||||
@@ -23,145 +132,66 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
i16_array_t *nora = mesh->vertex_arrays->buffer[1]->values;
|
||||
i16_array_t *texa = mesh->vertex_arrays->buffer[2]->values;
|
||||
i32 len = math_floor(posa->length / 4.0);
|
||||
i32 size = len > 0 ? len : 1;
|
||||
|
||||
// Merge shared vertices and remap indices
|
||||
i16_array_t *posa2 = i16_array_create(len * 3);
|
||||
i16_array_t *nora2 = i16_array_create(len * 3);
|
||||
i16_array_t *texa2 = i16_array_create(len * 2);
|
||||
i32_array_t *posmap = i32_array_create(len);
|
||||
i32_array_t *normap = i32_array_create(len);
|
||||
i32_array_t *texmap = i32_array_create(len);
|
||||
u64 *keys = malloc(size * sizeof(u64));
|
||||
i32 *posmap = malloc(size * sizeof(i32));
|
||||
i32 *normap = malloc(size * sizeof(i32));
|
||||
i32 *texmap = malloc(size * sizeof(i32));
|
||||
i32 *posfst = malloc(size * sizeof(i32));
|
||||
i32 *norfst = malloc(size * sizeof(i32));
|
||||
i32 *texfst = malloc(size * sizeof(i32));
|
||||
for (i32 j = 0; j < len; ++j)
|
||||
keys[j] = export_obj_key(posa->buffer[j * 4], posa->buffer[j * 4 + 1], posa->buffer[j * 4 + 2]);
|
||||
i32 pi = export_obj_dedupe(keys, len, posmap, posfst);
|
||||
for (i32 j = 0; j < len; ++j)
|
||||
keys[j] = export_obj_key(nora->buffer[j * 2], nora->buffer[j * 2 + 1], posa->buffer[j * 4 + 3]);
|
||||
i32 ni = export_obj_dedupe(keys, len, normap, norfst);
|
||||
for (i32 j = 0; j < len; ++j)
|
||||
keys[j] = export_obj_key(texa->buffer[j * 2], texa->buffer[j * 2 + 1], 0);
|
||||
i32 ti = export_obj_dedupe(keys, len, texmap, texfst);
|
||||
|
||||
i32 pi = 0;
|
||||
i32 ni = 0;
|
||||
i32 ti = 0;
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
bool found = false;
|
||||
for (i32 j = 0; j < pi; ++j) {
|
||||
if (posa2->buffer[j * 3] == posa->buffer[i * 4] && posa2->buffer[j * 3 + 1] == posa->buffer[i * 4 + 1] &&
|
||||
posa2->buffer[j * 3 + 2] == posa->buffer[i * 4 + 2]) {
|
||||
posmap->buffer[i] = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
posmap->buffer[i] = pi;
|
||||
posa2->buffer[pi * 3] = posa->buffer[i * 4];
|
||||
posa2->buffer[pi * 3 + 1] = posa->buffer[i * 4 + 1];
|
||||
posa2->buffer[pi * 3 + 2] = posa->buffer[i * 4 + 2];
|
||||
pi++;
|
||||
}
|
||||
|
||||
found = false;
|
||||
for (i32 j = 0; j < ni; ++j) {
|
||||
if (nora2->buffer[j * 3] == nora->buffer[i * 2] && nora2->buffer[j * 3 + 1] == nora->buffer[i * 2 + 1] &&
|
||||
nora2->buffer[j * 3 + 2] == posa->buffer[i * 4 + 3]) {
|
||||
normap->buffer[i] = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
normap->buffer[i] = ni;
|
||||
nora2->buffer[ni * 3] = nora->buffer[i * 2];
|
||||
nora2->buffer[ni * 3 + 1] = nora->buffer[i * 2 + 1];
|
||||
nora2->buffer[ni * 3 + 2] = posa->buffer[i * 4 + 3];
|
||||
ni++;
|
||||
}
|
||||
|
||||
found = false;
|
||||
for (i32 j = 0; j < ti; ++j) {
|
||||
if (texa2->buffer[j * 2] == texa->buffer[i * 2] && texa2->buffer[j * 2 + 1] == texa->buffer[i * 2 + 1]) {
|
||||
texmap->buffer[i] = j;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
texmap->buffer[i] = ti;
|
||||
texa2->buffer[ti * 2] = texa->buffer[i * 2];
|
||||
texa2->buffer[ti * 2 + 1] = texa->buffer[i * 2 + 1];
|
||||
ti++;
|
||||
}
|
||||
export_obj_write_string(o, "o ");
|
||||
export_obj_write_string(o, p->base->name);
|
||||
export_obj_write_char(o, '\n');
|
||||
for (i32 j = 0; j < pi; ++j) {
|
||||
i32 v = posfst[j];
|
||||
export_obj_write_vec(o, "v ", posa->buffer[v * 4] * sc, posa->buffer[v * 4 + 2] * sc, -posa->buffer[v * 4 + 1] * sc, true);
|
||||
}
|
||||
|
||||
export_obj_write_string(o, string_tmp("o %s\n", p->base->name));
|
||||
for (i32 i = 0; i < pi; ++i) {
|
||||
export_obj_write_string(o, "v ");
|
||||
f32 f = posa2->buffer[i * 3] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = posa2->buffer[i * 3 + 2] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = -posa2->buffer[i * 3 + 1] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < ni; ++j) {
|
||||
i32 v = norfst[j];
|
||||
export_obj_write_vec(o, "vn ", nora->buffer[v * 2] * inv, posa->buffer[v * 4 + 3] * inv, -nora->buffer[v * 2 + 1] * inv, true);
|
||||
}
|
||||
for (i32 i = 0; i < ni; ++i) {
|
||||
export_obj_write_string(o, "vn ");
|
||||
f32 f = nora2->buffer[i * 3] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = nora2->buffer[i * 3 + 2] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = -nora2->buffer[i * 3 + 1] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
}
|
||||
for (i32 i = 0; i < ti; ++i) {
|
||||
export_obj_write_string(o, "vt ");
|
||||
f32 f = texa2->buffer[i * 2] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = 1.0 - texa2->buffer[i * 2 + 1] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < ti; ++j) {
|
||||
i32 v = texfst[j];
|
||||
export_obj_write_vec(o, "vt ", texa->buffer[v * 2] * inv, 1.0 - texa->buffer[v * 2 + 1] * inv, 0.0, false);
|
||||
}
|
||||
|
||||
u32_array_t *inda = mesh->index_array;
|
||||
for (i32 i = 0; i < math_floor(inda->length / 3.0); ++i) {
|
||||
i32 pi1 = posmap->buffer[inda->buffer[i * 3]] + 1 + poff;
|
||||
i32 pi2 = posmap->buffer[inda->buffer[i * 3 + 1]] + 1 + poff;
|
||||
i32 pi3 = posmap->buffer[inda->buffer[i * 3 + 2]] + 1 + poff;
|
||||
i32 ni1 = normap->buffer[inda->buffer[i * 3]] + 1 + noff;
|
||||
i32 ni2 = normap->buffer[inda->buffer[i * 3 + 1]] + 1 + noff;
|
||||
i32 ni3 = normap->buffer[inda->buffer[i * 3 + 2]] + 1 + noff;
|
||||
i32 ti1 = texmap->buffer[inda->buffer[i * 3]] + 1 + toff;
|
||||
i32 ti2 = texmap->buffer[inda->buffer[i * 3 + 1]] + 1 + toff;
|
||||
i32 ti3 = texmap->buffer[inda->buffer[i * 3 + 2]] + 1 + toff;
|
||||
export_obj_write_string(o, "f ");
|
||||
export_obj_write_string(o, i32_to_string(pi1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni1));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(pi2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni2));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(pi3));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti3));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni3));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < math_floor(inda->length / 3.0); ++j) {
|
||||
i32 pf[3];
|
||||
i32 tf[3];
|
||||
i32 nf[3];
|
||||
for (i32 k = 0; k < 3; ++k) {
|
||||
i32 v = inda->buffer[j * 3 + k];
|
||||
pf[k] = posmap[v] + 1 + poff;
|
||||
tf[k] = texmap[v] + 1 + toff;
|
||||
nf[k] = normap[v] + 1 + noff;
|
||||
}
|
||||
export_obj_write_face(o, pf, tf, nf);
|
||||
}
|
||||
poff += pi;
|
||||
noff += ni;
|
||||
toff += ti;
|
||||
|
||||
array_delete(posa2);
|
||||
array_delete(nora2);
|
||||
array_delete(texa2);
|
||||
array_delete(posmap);
|
||||
array_delete(normap);
|
||||
array_delete(texmap);
|
||||
free(keys);
|
||||
free(posmap);
|
||||
free(normap);
|
||||
free(texmap);
|
||||
free(posfst);
|
||||
free(norfst);
|
||||
free(texfst);
|
||||
}
|
||||
|
||||
if (!ends_with(path, ".obj")) {
|
||||
@@ -174,7 +204,7 @@ void export_obj_run(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
// Skips merging shared vertices
|
||||
|
||||
u8_array_t *o = u8_array_create_from_raw((u8[]){}, 0);
|
||||
u8_array_t *o = u8_array_create(0);
|
||||
export_obj_write_string(o, "# armorpaint.org\n");
|
||||
|
||||
i32 poff = 0;
|
||||
@@ -193,71 +223,31 @@ void export_obj_run_fast(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
i32 ni = pi;
|
||||
i32 ti = pi;
|
||||
|
||||
export_obj_write_string(o, string_tmp("o %s\n", p->base->name));
|
||||
for (i32 i = 0; i < pi; ++i) {
|
||||
export_obj_write_string(o, "v ");
|
||||
f32 f = posa->buffer[i * 4] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = posa->buffer[i * 4 + 2] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = -posa->buffer[i * 4 + 1] * sc;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
export_obj_write_string(o, "o ");
|
||||
export_obj_write_string(o, p->base->name);
|
||||
export_obj_write_char(o, '\n');
|
||||
for (i32 j = 0; j < pi; ++j) {
|
||||
export_obj_write_vec(o, "v ", posa->buffer[j * 4] * sc, posa->buffer[j * 4 + 2] * sc, -posa->buffer[j * 4 + 1] * sc, true);
|
||||
}
|
||||
for (i32 i = 0; i < ni; ++i) {
|
||||
export_obj_write_string(o, "vn ");
|
||||
f32 f = nora->buffer[i * 2] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = posa->buffer[i * 4 + 3] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = -nora->buffer[i * 2 + 1] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < ni; ++j) {
|
||||
export_obj_write_vec(o, "vn ", nora->buffer[j * 2] * inv, posa->buffer[j * 4 + 3] * inv, -nora->buffer[j * 2 + 1] * inv, true);
|
||||
}
|
||||
for (i32 i = 0; i < ti; ++i) {
|
||||
export_obj_write_string(o, "vt ");
|
||||
f32 f = texa->buffer[i * 2] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, " ");
|
||||
f = 1.0 - texa->buffer[i * 2 + 1] * inv;
|
||||
export_obj_write_string(o, f32_to_string(f));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < ti; ++j) {
|
||||
export_obj_write_vec(o, "vt ", texa->buffer[j * 2] * inv, 1.0 - texa->buffer[j * 2 + 1] * inv, 0.0, false);
|
||||
}
|
||||
|
||||
u32_array_t *inda = mesh->index_array;
|
||||
for (i32 i = 0; i < math_floor(inda->length / 3.0); ++i) {
|
||||
i32 pi1 = inda->buffer[i * 3] + 1 + poff;
|
||||
i32 pi2 = inda->buffer[i * 3 + 1] + 1 + poff;
|
||||
i32 pi3 = inda->buffer[i * 3 + 2] + 1 + poff;
|
||||
i32 ni1 = inda->buffer[i * 3] + 1 + noff;
|
||||
i32 ni2 = inda->buffer[i * 3 + 1] + 1 + noff;
|
||||
i32 ni3 = inda->buffer[i * 3 + 2] + 1 + noff;
|
||||
i32 ti1 = inda->buffer[i * 3] + 1 + toff;
|
||||
i32 ti2 = inda->buffer[i * 3 + 1] + 1 + toff;
|
||||
i32 ti3 = inda->buffer[i * 3 + 2] + 1 + toff;
|
||||
export_obj_write_string(o, "f ");
|
||||
export_obj_write_string(o, i32_to_string(pi1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni1));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(pi2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni2));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(pi3));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ti3));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(ni3));
|
||||
export_obj_write_string(o, "\n");
|
||||
for (i32 j = 0; j < math_floor(inda->length / 3.0); ++j) {
|
||||
i32 pf[3];
|
||||
i32 tf[3];
|
||||
i32 nf[3];
|
||||
for (i32 k = 0; k < 3; ++k) {
|
||||
i32 v = inda->buffer[j * 3 + k];
|
||||
pf[k] = v + 1 + poff;
|
||||
tf[k] = v + 1 + toff;
|
||||
nf[k] = v + 1 + noff;
|
||||
}
|
||||
export_obj_write_face(o, pf, tf, nf);
|
||||
}
|
||||
poff += pi;
|
||||
noff += ni;
|
||||
@@ -332,7 +322,7 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
return;
|
||||
}
|
||||
|
||||
u8_array_t *o = u8_array_create_from_raw((u8[]){}, 0);
|
||||
u8_array_t *o = u8_array_create(0);
|
||||
export_obj_write_string(o, "# armorpaint.org\n");
|
||||
|
||||
mesh_object_t *p = paint_objects->buffer[0];
|
||||
@@ -398,19 +388,15 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
}
|
||||
}
|
||||
|
||||
export_obj_write_string(o, string_tmp("o %s\n", p->base->name));
|
||||
export_obj_write_string(o, "o ");
|
||||
export_obj_write_string(o, p->base->name);
|
||||
export_obj_write_char(o, '\n');
|
||||
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
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, " ");
|
||||
export_obj_write_string(o, f32_to_string(z));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, f32_to_string(-y));
|
||||
export_obj_write_string(o, "\n");
|
||||
export_obj_write_vec(o, "v ", x, z, -y, true);
|
||||
}
|
||||
|
||||
for (i32 t = 0; t < tris; ++t) {
|
||||
@@ -435,47 +421,21 @@ void export_obj_run_sculpt(char *path, mesh_object_t_array_t *paint_objects) {
|
||||
ny /= nl;
|
||||
nz /= nl;
|
||||
}
|
||||
export_obj_write_string(o, "vn ");
|
||||
export_obj_write_string(o, f32_to_string(nx));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, f32_to_string(nz));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, f32_to_string(-ny));
|
||||
export_obj_write_string(o, "\n");
|
||||
export_obj_write_vec(o, "vn ", nx, nz, -ny, true);
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < len; ++i) {
|
||||
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, " ");
|
||||
export_obj_write_string(o, f32_to_string(v));
|
||||
export_obj_write_string(o, "\n");
|
||||
export_obj_write_vec(o, "vt ", u, v, 0.0, false);
|
||||
}
|
||||
|
||||
for (i32 t = 0; t < tris; ++t) {
|
||||
i32 b = t * 3 + 1;
|
||||
export_obj_write_string(o, "f ");
|
||||
export_obj_write_string(o, i32_to_string(b));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(b));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(t + 1));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(b + 1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(b + 1));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(t + 1));
|
||||
export_obj_write_string(o, " ");
|
||||
export_obj_write_string(o, i32_to_string(b + 2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(b + 2));
|
||||
export_obj_write_string(o, "/");
|
||||
export_obj_write_string(o, i32_to_string(t + 1));
|
||||
export_obj_write_string(o, "\n");
|
||||
i32 b = t * 3 + 1;
|
||||
i32 pf[3] = {b, b + 1, b + 2};
|
||||
i32 nf[3] = {t + 1, t + 1, t + 1};
|
||||
export_obj_write_face(o, pf, pf, nf);
|
||||
}
|
||||
|
||||
if (!ends_with(path, ".obj")) {
|
||||
|
||||
Reference in New Issue
Block a user