diff options
Diffstat (limited to 'src/extend/mesh.c')
-rw-r--r-- | src/extend/mesh.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/extend/mesh.c b/src/extend/mesh.c index e69de29..4993222 100644 --- a/src/extend/mesh.c +++ b/src/extend/mesh.c @@ -0,0 +1,209 @@ +#include "mesh.h" + +#define LINE_SIZE 1024 + + +#define darray_push(darray, value) \ + do { \ + (darray) = darray_hold((darray), 1, sizeof(*(darray))); \ + (darray)[darray_size(darray) - 1] = (value); \ + } while (0) + +#define DARRAY_RAW_DATA(darray) ((int*)(darray) - 2) +#define DARRAY_CAPACITY(darray) (DARRAY_RAW_DATA(darray)[0]) +#define DARRAY_OCCUPIED(darray) (DARRAY_RAW_DATA(darray)[1]) + +int darray_size(void *darray) { + return darray != NULL ? DARRAY_OCCUPIED(darray) : 0; +} + +void darray_free(void *darray) { + if (darray != NULL) { + free(DARRAY_RAW_DATA(darray)); + } +} + +#define UNUSED_VAR(x) ((void)(x)) + + +void *darray_hold(void *darray, int count, int itemsize) { + assert(count > 0 && itemsize > 0); + if (darray == NULL) { + int raw_size = sizeof(int) * 2 + itemsize * count; + int *base = (int*)malloc(raw_size); + base[0] = count; /* capacity */ + base[1] = count; /* occupied */ + return base + 2; + } + else if (DARRAY_OCCUPIED(darray) + count <= DARRAY_CAPACITY(darray)) { + DARRAY_OCCUPIED(darray) += count; + return darray; + } + else { + int needed_size = DARRAY_OCCUPIED(darray) + count; + int double_curr = DARRAY_CAPACITY(darray) * 2; + int capacity = needed_size > double_curr ? needed_size : double_curr; + int occupied = needed_size; + int raw_size = sizeof(int) * 2 + itemsize * capacity; + int *base = (int*)realloc(DARRAY_RAW_DATA(darray), raw_size); + base[0] = capacity; + base[1] = occupied; + return base + 2; + } +} + +Vec3 vec3_min(Vec3 a, Vec3 b) { + float x = min(a.x, b.x); + float y = min(a.y, b.y); + float z = min(a.z, b.z); + Vec3 r = { x, y, z }; + return r; +} + +Vec3 vec3_max(Vec3 a, Vec3 b) { + float x = max(a.x, b.x); + float y = max(a.y, b.y); + float z = max(a.z, b.z); + Vec3 r = { x, y, z }; + return r; +} + +static Mesh *build_mesh( + Vec3 *positions, Vec2 *texcoords, Vec3 *normals, + Vec4 *tangents, Vec4 *joints, Vec4 *weights, + int *position_indices, int *texcoord_indices, int *normal_indices) { + Vec3 bbox_min = { +1e6, +1e6, +1e6 }; + Vec3 bbox_max = { -1e6, -1e6, -1e6 }; + int num_indices = darray_size(position_indices); + int num_faces = num_indices / 3; + Mesh *mesh; + int i; + + assert(num_faces > 0 && num_faces * 3 == num_indices); + assert(darray_size(position_indices) == num_indices); + assert(darray_size(texcoord_indices) == num_indices); + assert(darray_size(normal_indices) == num_indices); + + mesh = (Mesh*)malloc(sizeof(Mesh)); + mesh->triangles = ssrM_newvector(int, 3 * num_faces); + int nvert = DARRAY_OCCUPIED(positions); + Vert* vertices = ssrM_newvector(Vert, nvert); + + for (i = 0; i < num_indices; i++) { + int position_index = position_indices[i]; + int texcoord_index = texcoord_indices[i]; + int normal_index = normal_indices[i]; + assert(position_index >= 0 && position_index < darray_size(positions)); + assert(texcoord_index >= 0 && texcoord_index < darray_size(texcoords)); + assert(normal_index >= 0 && normal_index < darray_size(normals)); + + vertices[position_index].index = position_index; + vertices[position_index].position = positions[position_index]; + vertices[position_index].texcoord = texcoords[texcoord_index]; + vertices[position_index].normal = normals[normal_index]; + + if (tangents) { + int tangent_index = position_index; + ssr_assert(tangent_index >= 0 && tangent_index < darray_size(tangents)); + vertices[position_index].tangent = tangents[tangent_index]; + } + + mesh->triangles[i] = position_index; + + //bbox_min = vec3_min(bbox_min, vertices[i].position); + //bbox_max = vec3_max(bbox_max, vertices[i].position); + } + + mesh->tris_count = num_faces; + mesh->verts_count = nvert; + mesh->vertices = vertices; + //mesh->center = vec3_div(vec3_add(bbox_min, bbox_max), 2); + + return mesh; +} + +Mesh* mesh_loadfromobj(const char *filename) { + Vec3 *positions = NULL; + Vec2 *texcoords = NULL; + Vec3 *normals = NULL; + Vec4 *tangents = NULL; + Vec4 *joints = NULL; + Vec4 *weights = NULL; + int *position_indices = NULL; + int *texcoord_indices = NULL; + int *normal_indices = NULL; + char line[LINE_SIZE]; + Mesh *mesh; + FILE *file; + + file = fopen(filename, "rb"); + assert(file != NULL); + while (1) { + int items; + if (fgets(line, LINE_SIZE, file) == NULL) { + break; + } + else if (strncmp(line, "v ", 2) == 0) { /* position */ + Vec3 position; + items = sscanf(line, "v %f %f %f", + &position.x, &position.y, &position.z); + assert(items == 3); + darray_push(positions, position); + } + else if (strncmp(line, "vt ", 3) == 0) { /* texcoord */ + Vec2 texcoord; + items = sscanf(line, "vt %f %f", + &texcoord.x, &texcoord.y); + assert(items == 2); + darray_push(texcoords, texcoord); + } + else if (strncmp(line, "vn ", 3) == 0) { /* normal */ + Vec3 normal; + items = sscanf(line, "vn %f %f %f", + &normal.x, &normal.y, &normal.z); + assert(items == 3); + darray_push(normals, normal); + } + else if (strncmp(line, "f ", 2) == 0) { /* face */ + int i; + int pos_indices[3], uv_indices[3], n_indices[3]; + items = sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", + &pos_indices[0], &uv_indices[0], &n_indices[0], + &pos_indices[1], &uv_indices[1], &n_indices[1], + &pos_indices[2], &uv_indices[2], &n_indices[2]); + assert(items == 9); + for (i = 0; i < 3; i++) { + darray_push(position_indices, pos_indices[i] - 1); + darray_push(texcoord_indices, uv_indices[i] - 1); + darray_push(normal_indices, n_indices[i] - 1); + } + } else if (strncmp(line, "# ext.tangent ", 14) == 0) { /* tangent */ + Vec4 tangent; + items = sscanf(line, "# ext.tangent %f %f %f %f", + &tangent.x, &tangent.y, &tangent.z, &tangent.w); + assert(items == 4); + darray_push(tangents, tangent); + } + } + fclose(file); + + mesh = build_mesh(positions, texcoords, normals, tangents, joints, weights, + position_indices, texcoord_indices, normal_indices); + darray_free(positions); + darray_free(texcoords); + darray_free(normals); + darray_free(tangents); + darray_free(joints); + darray_free(weights); + darray_free(position_indices); + darray_free(texcoord_indices); + darray_free(normal_indices); + + printf("%s: %d verts, %d tris\n", filename, mesh->verts_count, mesh->tris_count); + + return mesh; +} +// +// +//Mesh* mesh_loadfromobj(const char* path) { +//} |