summaryrefslogtreecommitdiff
path: root/src/extend/mesh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/extend/mesh.c')
-rw-r--r--src/extend/mesh.c209
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) {
+//}