| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650 |
- #include "iron_obj.h"
- #include <math.h>
- #include <stdlib.h>
- #include <string.h>
- #include "iron_array.h"
- #include "iron_vec4.h"
- #include "iron_string.h"
- #include "iron_gc.h"
- static raw_mesh_t *part = NULL;
- static f32_array_t pos_temp;
- static f32_array_t uv_temp;
- static f32_array_t nor_temp;
- static uint32_t va[512];
- static uint32_t ua[512];
- static uint32_t na[512];
- static int vi = 0;
- static int ui = 0;
- static int ni = 0;
- static uint8_t buf[128];
- static char str[256];
- static int vind_off = 0;
- static int tind_off = 0;
- static int nind_off = 0;
- static uint8_t *bytes = NULL;
- static size_t bytes_length = 0;
- static f32_array_t *pos_first;
- static f32_array_t *uv_first;
- static f32_array_t *nor_first;
- static int read_int() {
- int bi = 0;
- while (true) { // Read into buffer
- char c = bytes[part->pos];
- if (c == '/' || c == '\n' || c == '\r' || c == ' ') {
- break;
- }
- part->pos++;
- buf[bi++] = c;
- }
- int res = 0; // Parse buffer into int
- int dec = 1;
- int off = buf[0] == '-' ? 1 : 0;
- int len = bi - 1;
- for (int i = 0; i < bi - off; ++i) {
- res += (buf[len - i] - 48) * dec;
- dec *= 10;
- }
- if (off > 0) {
- res *= -1;
- }
- return res;
- }
- static void read_face_fast() {
- while (true) {
- va[vi++] = read_int() - 1;
- part->pos++; // '/'
- ua[ui++] = read_int() - 1;
- part->pos++; // '/'
- na[ni++] = read_int() - 1;
- if (bytes[part->pos] == '\n' || bytes[part->pos] == '\r') {
- break;
- }
- part->pos++; // ' '
- // Some exporters put space at the end of "f" line
- if (vi >= 3 && (bytes[part->pos] == '\n' || bytes[part->pos] == '\r')) {
- break;
- }
- }
- }
- static void read_face() {
- while (true) {
- va[vi++] = read_int() - 1;
- if (uv_temp.length > 0 || nor_temp.length > 0) {
- part->pos++; // "/"
- if (uv_temp.length > 0) {
- ua[ui++] = read_int() - 1;
- }
- if (nor_temp.length > 0) {
- // Some exporters put fake uv index even when uv data is not present... (f 1/1/1 instead of f 1//1)
- bool has_bogus_uv = uv_temp.length == 0 && bytes[part->pos] != '/';
- if (has_bogus_uv) {
- read_int();
- }
- part->pos++; // "/"
- na[ni++] = read_int() - 1;
- }
- }
- // Some exporters put "//" even when normal and uv data are not present (f 1//)
- else if (uv_temp.length == 0 && nor_temp.length == 0 && bytes[part->pos] == '/') {
- part->pos += 2;
- }
- if (bytes[part->pos] == '\n' || bytes[part->pos] == '\r') {
- break;
- }
- part->pos++; // " "
- // Some exporters put space at the end of "f" line
- if (vi >= 3 && (bytes[part->pos] == '\n' || bytes[part->pos] == '\r')) {
- break;
- }
- }
- }
- static float read_float() {
- int bi = 0;
- while (true) { // Read into buffer
- char c = bytes[part->pos];
- if (c == ' ' || c == '\n' || c == '\r') {
- break;
- }
- if (c == 'E' || c == 'e') {
- part->pos++;
- int first = buf[0] == '-' ? -(buf[1] - 48) : buf[0] - 48;
- int exp = read_int();
- int dec = 1;
- int loop = exp > 0 ? exp : -exp;
- for (int i = 0; i < loop; ++i) {
- dec *= 10;
- }
- return exp > 0 ? (float)first * dec : (float)first / dec;
- }
- part->pos++;
- buf[bi++] = c;
- }
- float res = 0.0; // Parse buffer into float
- int64_t dot = 1;
- int64_t dec = 1;
- int off = buf[0] == '-' ? 1 : 0;
- int len = bi - 1;
- for (int i = 0; i < bi - off; ++i) {
- char c = buf[len - i];
- if (c == '.') {
- dot = dec;
- continue;
- }
- res += (c - 48) * dec;
- dec *= 10;
- }
- if (off > 0) {
- res /= -dot;
- }
- else {
- res /= dot;
- }
- return res;
- }
- static char *read_string() {
- size_t begin = part->pos;
- while (true) {
- char c = bytes[part->pos];
- if (c == '\n' || c == '\r' || c == ' ') {
- break;
- }
- part->pos++;
- }
- for (int i = 0; i < part->pos - begin; ++i) {
- str[i] = bytes[begin + i];
- }
- str[part->pos - begin] = '\0';
- return str;
- }
- static void next_line() {
- while (true) {
- char c = bytes[part->pos++];
- if (c == '\n' || part->pos >= bytes_length) {
- break; // \n, \r\n
- }
- }
- }
- static int get_tile(int i1, int i2, int i3, i32_array_t *uv_indices, int tiles_u) {
- float u1 = uv_temp.buffer[uv_indices->buffer[i1] * 2 ];
- float v1 = uv_temp.buffer[uv_indices->buffer[i1] * 2 + 1];
- float u2 = uv_temp.buffer[uv_indices->buffer[i2] * 2 ];
- float v2 = uv_temp.buffer[uv_indices->buffer[i2] * 2 + 1];
- float u3 = uv_temp.buffer[uv_indices->buffer[i3] * 2 ];
- float v3 = uv_temp.buffer[uv_indices->buffer[i3] * 2 + 1];
- int tile_u = (int)((u1 + u2 + u3) / 3);
- int tile_v = (int)((v1 + v2 + v3) / 3);
- return tile_u + tile_v * tiles_u;
- }
- static bool pnpoly(float v0x, float v0y, float v1x, float v1y, float v2x, float v2y, float px, float py) {
- // https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
- bool c = false;
- if (((v0y > py) != (v2y > py)) && (px < (v2x - v0x) * (py - v0y) / (v2y - v0y) + v0x)) {
- c = !c;
- }
- if (((v1y > py) != (v0y > py)) && (px < (v0x - v1x) * (py - v1y) / (v0y - v1y) + v1x)) {
- c = !c;
- }
- if (((v2y > py) != (v1y > py)) && (px < (v1x - v2x) * (py - v2y) / (v1y - v2y) + v2x)) {
- c = !c;
- }
- return c;
- }
- iron_vector4_t calc_normal(iron_vector4_t a, iron_vector4_t b, iron_vector4_t c) {
- iron_vector4_t cb = vec4_sub(c, b);
- iron_vector4_t ab = vec4_sub(a, b);
- cb = vec4_cross(cb, ab);
- cb = vec4_norm(cb);
- return cb;
- }
- // 'o' for object split, 'g' for groups, 'u'semtl for materials
- raw_mesh_t *obj_parse(buffer_t *file_bytes, char split_code, uint64_t start_pos, bool udim) {
- bytes = file_bytes->buffer;
- bytes_length = file_bytes->length;
- part = gc_alloc(sizeof(raw_mesh_t));
- part->scale_pos = 1.0;
- part->scale_tex = 1.0;
- part->pos = start_pos;
- part->udims_u = 1;
- part->udims_v = 1;
- part->name = string_copy(str);
- i32_array_t pos_indices = {0};
- i32_array_t uv_indices = {0};
- i32_array_t nor_indices = {0};
- bool reading_faces = false;
- bool reading_object = false;
- bool full_attrib = false;
- if (start_pos == 0) {
- vind_off = tind_off = nind_off = 0;
- }
- if (split_code == 'u' && start_pos > 0) {
- pos_temp = *pos_first;
- nor_temp = *nor_first;
- uv_temp = *uv_first;
- }
- else {
- memset(&pos_temp, 0, sizeof(pos_temp));
- memset(&uv_temp, 0, sizeof(uv_temp));
- memset(&nor_temp, 0, sizeof(nor_temp));
- }
- while (true) {
- if (part->pos >= bytes_length) {
- break;
- }
- char c0 = bytes[part->pos++];
- if (reading_object && reading_faces && (c0 == 'v' || c0 == split_code)) {
- part->pos--;
- part->has_next = true;
- break;
- }
- if (c0 == 'v') {
- char c1 = bytes[part->pos++];
- if (c1 == ' ') {
- if (bytes[part->pos] == ' ') part->pos++; // Some exporters put additional space directly after "v"
- f32_array_push(&pos_temp, read_float());
- part->pos++; // Space
- f32_array_push(&pos_temp, read_float());
- part->pos++; // Space
- f32_array_push(&pos_temp, read_float());
- }
- else if (c1 == 't') {
- part->pos++; // Space
- f32_array_push(&uv_temp, read_float());
- part->pos++; // Space
- f32_array_push(&uv_temp, read_float());
- if (nor_temp.length > 0) {
- full_attrib = true;
- }
- }
- else if (c1 == 'n') {
- part->pos++; // Space
- f32_array_push(&nor_temp, read_float());
- part->pos++; // Space
- f32_array_push(&nor_temp, read_float());
- part->pos++; // Space
- f32_array_push(&nor_temp, read_float());
- if (uv_temp.length > 0) {
- full_attrib = true;
- }
- }
- }
- else if (c0 == 'f') {
- part->pos++; // Space
- if (bytes[part->pos] == ' ') {
- part->pos++; // Some exporters put additional space directly after "f"
- }
- reading_faces = true;
- vi = ui = ni = 0;
- full_attrib ? read_face_fast() : read_face();
- if (vi <= 4) { // Convex, fan triangulation
- i32_array_push(&pos_indices, va[0]);
- i32_array_push(&pos_indices, va[1]);
- i32_array_push(&pos_indices, va[2]);
- for (int i = 3; i < vi; ++i) {
- i32_array_push(&pos_indices, va[0]);
- i32_array_push(&pos_indices, va[i - 1]);
- i32_array_push(&pos_indices, va[i]);
- }
- if (uv_temp.length > 0) {
- i32_array_push(&uv_indices, ua[0]);
- i32_array_push(&uv_indices, ua[1]);
- i32_array_push(&uv_indices, ua[2]);
- for (int i = 3; i < ui; ++i) {
- i32_array_push(&uv_indices, ua[0]);
- i32_array_push(&uv_indices, ua[i - 1]);
- i32_array_push(&uv_indices, ua[i]);
- }
- }
- if (nor_temp.length > 0) {
- i32_array_push(&nor_indices, na[0]);
- i32_array_push(&nor_indices, na[1]);
- i32_array_push(&nor_indices, na[2]);
- for (int i = 3; i < ni; ++i) {
- i32_array_push(&nor_indices, na[0]);
- i32_array_push(&nor_indices, na[i - 1]);
- i32_array_push(&nor_indices, na[i]);
- }
- }
- }
- else { // Convex or concave, ear clipping
- int _vind_off = split_code == 'u' ? 0 : vind_off;
- int _nind_off = split_code == 'u' ? 0 : nind_off;
- float nx = 0.0;
- float ny = 0.0;
- float nz = 0.0;
- if (nor_temp.length > 0) {
- nx = nor_temp.buffer[(na[0] - _nind_off) * 3 ];
- ny = nor_temp.buffer[(na[0] - _nind_off) * 3 + 1];
- nz = nor_temp.buffer[(na[0] - _nind_off) * 3 + 2];
- }
- else {
- iron_vector4_t n = calc_normal(
- vec4_create(pos_temp.buffer[(va[0] - _vind_off) * 3], pos_temp.buffer[(va[0] - _vind_off) * 3 + 1], pos_temp.buffer[(va[0] - _vind_off) * 3 + 2], 1.0f),
- vec4_create(pos_temp.buffer[(va[1] - _vind_off) * 3], pos_temp.buffer[(va[1] - _vind_off) * 3 + 1], pos_temp.buffer[(va[1] - _vind_off) * 3 + 2], 1.0f),
- vec4_create(pos_temp.buffer[(va[2] - _vind_off) * 3], pos_temp.buffer[(va[2] - _vind_off) * 3 + 1], pos_temp.buffer[(va[2] - _vind_off) * 3 + 2], 1.0f)
- );
- nx = n.x;
- ny = n.y;
- nz = n.z;
- }
- float nxabs = (float)fabs(nx);
- float nyabs = (float)fabs(ny);
- float nzabs = (float)fabs(nz);
- bool flip = nx + ny + nz > 0;
- int axis = nxabs > nyabs && nxabs > nzabs ? 0 : nyabs > nxabs && nyabs > nzabs ? 1 : 2;
- int axis0 = axis == 0 ? (flip ? 2 : 1) : axis == 1 ? (flip ? 0 : 2) : (flip ? 1 : 0);
- int axis1 = axis == 0 ? (flip ? 1 : 2) : axis == 1 ? (flip ? 2 : 0) : (flip ? 0 : 1);
- int loops = 0;
- int i = -1;
- while (vi > 3 && loops++ < vi) {
- i = (i + 1) % vi;
- int i1 = (i + 1) % vi;
- int i2 = (i + 2) % vi;
- int vi0 = (va[i ] - _vind_off) * 3;
- int vi1 = (va[i1] - _vind_off) * 3;
- int vi2 = (va[i2] - _vind_off) * 3;
- float v0x = pos_temp.buffer[vi0 + axis0];
- float v0y = pos_temp.buffer[vi0 + axis1];
- float v1x = pos_temp.buffer[vi1 + axis0];
- float v1y = pos_temp.buffer[vi1 + axis1];
- float v2x = pos_temp.buffer[vi2 + axis0];
- float v2y = pos_temp.buffer[vi2 + axis1];
- float e0x = v0x - v1x; // Not an interior vertex
- float e0y = v0y - v1y;
- float e1x = v2x - v1x;
- float e1y = v2y - v1y;
- float cross = e0x * e1y - e0y * e1x;
- if (cross <= 0) {
- continue;
- }
- bool overlap = false; // Other vertex found inside this triangle
- for (int j = 0; j < vi - 3; ++j) {
- int j0 = (va[(i + 3 + j) % vi] - _vind_off) * 3;
- float px = pos_temp.buffer[j0 + axis0];
- float py = pos_temp.buffer[j0 + axis1];
- if (pnpoly(v0x, v0y, v1x, v1y, v2x, v2y, px, py)) {
- overlap = true;
- break;
- }
- }
- if (overlap) {
- continue;
- }
- i32_array_push(&pos_indices, va[i ]); // Found ear
- i32_array_push(&pos_indices, va[i1]);
- i32_array_push(&pos_indices, va[i2]);
- if (uv_temp.length > 0) {
- i32_array_push(&uv_indices, ua[i ]);
- i32_array_push(&uv_indices, ua[i1]);
- i32_array_push(&uv_indices, ua[i2]);
- }
- if (nor_temp.length > 0) {
- i32_array_push(&nor_indices, na[i ]);
- i32_array_push(&nor_indices, na[i1]);
- i32_array_push(&nor_indices, na[i2]);
- }
- for (int j = ((i + 1) % vi); j < vi - 1; ++j) { // Consume vertex
- va[j] = va[j + 1];
- ua[j] = ua[j + 1];
- na[j] = na[j + 1];
- }
- vi--;
- i--;
- loops = 0;
- }
- i32_array_push(&pos_indices, va[0]); // Last one
- i32_array_push(&pos_indices, va[1]);
- i32_array_push(&pos_indices, va[2]);
- if (uv_temp.length > 0) {
- i32_array_push(&uv_indices, ua[0]);
- i32_array_push(&uv_indices, ua[1]);
- i32_array_push(&uv_indices, ua[2]);
- }
- if (nor_temp.length > 0) {
- i32_array_push(&nor_indices, na[0]);
- i32_array_push(&nor_indices, na[1]);
- i32_array_push(&nor_indices, na[2]);
- }
- }
- }
- else if (c0 == split_code) {
- if (split_code == 'u') {
- part->pos += 5; // "u"semtl
- }
- part->pos++; // Space
- if (!udim) {
- reading_object = true;
- }
- part->name = string_copy(read_string());
- }
- next_line();
- }
- if (start_pos > 0) {
- if (split_code != 'u') {
- for (int i = 0; i < pos_indices.length; ++i) {
- pos_indices.buffer[i] -= vind_off;
- }
- for (int i = 0; i < uv_indices.length; ++i) {
- uv_indices.buffer[i] -= tind_off;
- }
- for (int i = 0; i < nor_indices.length; ++i) {
- nor_indices.buffer[i] -= nind_off;
- }
- }
- }
- else {
- if (split_code == 'u') {
- pos_first = &pos_temp;
- nor_first = &nor_temp;
- uv_first = &uv_temp;
- }
- }
- vind_off += (int)(pos_temp.length / 3); // Assumes separate vertex data per object
- tind_off += (int)(uv_temp.length / 2);
- nind_off += (int)(nor_temp.length / 3);
- // Pack positions to (-1, 1) range
- part->scale_pos = 0.0;
- for (int i = 0; i < pos_temp.length; ++i) {
- float f = (float)fabs(pos_temp.buffer[i]);
- if (part->scale_pos < f) {
- part->scale_pos = f;
- }
- }
- float inv = 32767 * (1 / part->scale_pos);
- part->posa = calloc(sizeof(i16_array_t), 1);
- part->posa->length = part->posa->capacity = pos_indices.length * 4;
- part->posa->buffer = malloc(part->posa->capacity * sizeof(int16_t));
- part->inda = calloc(sizeof(u32_array_t), 1);
- part->inda->length = part->inda->capacity = pos_indices.length;
- part->inda->buffer = malloc(part->inda->capacity * sizeof(uint32_t));
- part->vertex_count = pos_indices.length;
- part->index_count = pos_indices.length;
- int inda_length = pos_indices.length;
- for (int i = 0; i < pos_indices.length; ++i) {
- part->posa->buffer[i * 4 ] = (int)( pos_temp.buffer[pos_indices.buffer[i] * 3 ] * inv);
- part->posa->buffer[i * 4 + 1] = (int)(-pos_temp.buffer[pos_indices.buffer[i] * 3 + 2] * inv);
- part->posa->buffer[i * 4 + 2] = (int)( pos_temp.buffer[pos_indices.buffer[i] * 3 + 1] * inv);
- part->inda->buffer[i] = i;
- }
- if (nor_indices.length > 0) {
- part->nora = calloc(sizeof(i16_array_t), 1);
- part->nora->length = part->nora->capacity = nor_indices.length * 2;
- part->nora->buffer = malloc(part->nora->capacity * sizeof(int16_t));
- for (int i = 0; i < pos_indices.length; ++i) {
- part->nora->buffer[i * 2 ] = (int)( nor_temp.buffer[nor_indices.buffer[i] * 3 ] * 32767);
- part->nora->buffer[i * 2 + 1] = (int)(-nor_temp.buffer[nor_indices.buffer[i] * 3 + 2] * 32767);
- part->posa->buffer[i * 4 + 3] = (int)( nor_temp.buffer[nor_indices.buffer[i] * 3 + 1] * 32767);
- }
- }
- else {
- // Calc normals
- part->nora = calloc(sizeof(i16_array_t), 1);
- part->nora->length = part->nora->capacity = inda_length * 2;
- part->nora->buffer = malloc(part->nora->capacity * sizeof(int16_t));
- for (int i = 0; i < (int)(inda_length / 3); ++i) {
- int i1 = part->inda->buffer[i * 3 ];
- int i2 = part->inda->buffer[i * 3 + 1];
- int i3 = part->inda->buffer[i * 3 + 2];
- iron_vector4_t n = calc_normal(
- vec4_create(part->posa->buffer[i1 * 4], part->posa->buffer[i1 * 4 + 1], part->posa->buffer[i1 * 4 + 2], 1.0),
- vec4_create(part->posa->buffer[i2 * 4], part->posa->buffer[i2 * 4 + 1], part->posa->buffer[i2 * 4 + 2], 1.0),
- vec4_create(part->posa->buffer[i3 * 4], part->posa->buffer[i3 * 4 + 1], part->posa->buffer[i3 * 4 + 2], 1.0)
- );
- part->nora->buffer[i1 * 2 ] = (int)(n.x * 32767);
- part->nora->buffer[i1 * 2 + 1] = (int)(n.y * 32767);
- part->posa->buffer[i1 * 4 + 3] = (int)(n.z * 32767);
- part->nora->buffer[i2 * 2 ] = (int)(n.x * 32767);
- part->nora->buffer[i2 * 2 + 1] = (int)(n.y * 32767);
- part->posa->buffer[i2 * 4 + 3] = (int)(n.z * 32767);
- part->nora->buffer[i3 * 2 ] = (int)(n.x * 32767);
- part->nora->buffer[i3 * 2 + 1] = (int)(n.y * 32767);
- part->posa->buffer[i3 * 4 + 3] = (int)(n.z * 32767);
- }
- }
- if (uv_indices.length > 0) {
- if (udim) {
- // Find number of tiles
- int tiles_u = 1;
- int tiles_v = 1;
- for (int i = 0; i < (int)(uv_temp.length / 2); ++i) {
- while (uv_temp.buffer[i * 2 ] > tiles_u) tiles_u++;
- while (uv_temp.buffer[i * 2 + 1] > tiles_v) tiles_v++;
- }
- // Amount of indices pre tile
- uint32_t *num = (uint32_t *)malloc(tiles_u * tiles_v * sizeof(uint32_t));
- memset(num, 0, tiles_u * tiles_v * sizeof(uint32_t));
- for (int i = 0; i < (int)(inda_length / 3); ++i) {
- int tile = get_tile(part->inda->buffer[i * 3], part->inda->buffer[i * 3 + 1], part->inda->buffer[i * 3 + 2], &uv_indices, tiles_u);
- num[tile] += 3;
- }
- // Split indices per tile
- part->udims = any_array_create(tiles_u * tiles_v);
- part->udims_u = tiles_u;
- part->udims_v = tiles_v;
- for (int i = 0; i < tiles_u * tiles_v; ++i) {
- part->udims->buffer[i] = u32_array_create(num[i]);
- num[i] = 0;
- }
- for (int i = 0; i < (int)(inda_length / 3); ++i) {
- int i1 = part->inda->buffer[i * 3 ];
- int i2 = part->inda->buffer[i * 3 + 1];
- int i3 = part->inda->buffer[i * 3 + 2];
- int tile = get_tile(i1, i2, i3, &uv_indices, tiles_u);
- u32_array_t *a = part->udims->buffer[tile];
- a->buffer[num[tile]++] = i1;
- a->buffer[num[tile]++] = i2;
- a->buffer[num[tile]++] = i3;
- }
- // Normalize uvs to 0-1 range
- int16_t *uvtiles = (int16_t *)malloc(uv_temp.length * sizeof(int16_t));
- for (int i = 0; i < (int)(inda_length / 3); ++i) { // TODO: merge loops
- int i1 = part->inda->buffer[i * 3 ];
- int i2 = part->inda->buffer[i * 3 + 1];
- int i3 = part->inda->buffer[i * 3 + 2];
- int tile = get_tile(i1, i2, i3, &uv_indices, tiles_u);
- int tile_u = tile % tiles_u;
- int tile_v = (int)(tile / tiles_u);
- uvtiles[uv_indices.buffer[i1] * 2 ] = tile_u;
- uvtiles[uv_indices.buffer[i1] * 2 + 1] = tile_v;
- uvtiles[uv_indices.buffer[i2] * 2 ] = tile_u;
- uvtiles[uv_indices.buffer[i2] * 2 + 1] = tile_v;
- uvtiles[uv_indices.buffer[i3] * 2 ] = tile_u;
- uvtiles[uv_indices.buffer[i3] * 2 + 1] = tile_v;
- }
- for (int i = 0; i < uv_temp.length; ++i) {
- uv_temp.buffer[i] -= uvtiles[i];
- }
- free(uvtiles);
- free(num);
- }
- part->texa = calloc(sizeof(i16_array_t), 1);
- part->texa->length = part->texa->capacity = uv_indices.length * 2;
- part->texa->buffer = malloc(part->texa->capacity * sizeof(int16_t));
- for (int i = 0; i < uv_indices.length; ++i) {
- float uvx = uv_temp.buffer[uv_indices.buffer[i] * 2];
- if (uvx > 1.0) {
- uvx = uvx - (int)(uvx);
- }
- float uvy = uv_temp.buffer[uv_indices.buffer[i] * 2 + 1];
- if (uvy > 1.0) {
- uvy = uvy - (int)(uvy);
- }
- part->texa->buffer[i * 2 ] = (int)( uvx * 32767);
- part->texa->buffer[i * 2 + 1] = (int)((1.0 - uvy) * 32767);
- }
- }
- bytes = NULL;
- if (!part->has_next) {
- pos_first = nor_first = uv_first = NULL;
- array_free(&pos_temp);
- array_free(&uv_temp);
- array_free(&nor_temp);
- }
- array_free(&pos_indices);
- array_free(&uv_indices);
- array_free(&nor_indices);
- return part;
- }
- void obj_destroy(raw_mesh_t *part) {
- // if (part->udims != NULL) {
- // for (int i = 0; i < part->udims_u * part->udims_v; ++i) {
- // free(part->udims[i]);
- // }
- // free(part->udims);
- // }
- free(part->posa);
- free(part->nora);
- free(part->texa);
- free(part->inda);
- gc_free(part);
- }
|