diff options
Diffstat (limited to 'src/extend/mesh.c')
-rw-r--r-- | src/extend/mesh.c | 193 |
1 files changed, 111 insertions, 82 deletions
diff --git a/src/extend/mesh.c b/src/extend/mesh.c index 1f393db..e7685e6 100644 --- a/src/extend/mesh.c +++ b/src/extend/mesh.c @@ -1,61 +1,15 @@ #include "mesh.h" +#include "../util/darray.h" +#include "../shaders/common/mathlib.h" #define GENERATE_TANGNET //#define GENERATE_NORMAL //#define OPTIMIZE_MESH - #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 internal_vec3_min(Vec3 a, Vec3 b) { float x = min(a.x, b.x); float y = min(a.y, b.y); @@ -72,6 +26,13 @@ Vec3 internal_vec3_max(Vec3 a, Vec3 b) { return r; } +/************************************************************************/ +/* obj loader */ +/************************************************************************/ + +#define SIMPLE_OBJ_LOADER 0 + +#if SIMPLE_OBJ_LOADER static Mesh *build_mesh( Vec3 *positions, Vec2 *texcoords, Vec3 *normals, Vec4 *tangents, Vec4 *joints, Vec4 *weights, @@ -126,13 +87,6 @@ static Mesh *build_mesh( return mesh; } -/************************************************************************/ -/* obj loader */ -/************************************************************************/ - -#define SIMPLE_OBJ_LOADER 0 - -#if SIMPLE_OBJ_LOADER Mesh* mesh_loadfromobj(const char *filename) { Vec3 *positions = NULL; Vec2 *texcoords = NULL; @@ -215,8 +169,7 @@ Mesh* mesh_loadfromobj(const char *filename) { return mesh; } -#else - +#else // SIMPLE_OBJ_LOADER typedef struct { int normal_index; int uv_index; @@ -235,6 +188,24 @@ typedef struct { FaceVertex vertices[3]; } FaceInfo; +typedef struct { + int vertices[3]; + Vec3 tangent; // tangent of face +} Triangle; + +typedef struct { + Vert props; // position, normal, texcoord etc + int* related_triangles; +} MeshVertexInfo; + +typedef struct { + MeshVertexInfo* vertices; // vertices list + Triangle* triangles; // triangles list +} MeshInfo; + +void calc_face_tanget(MeshInfo* mesh); +void calc_vertex_tangnet(MeshInfo* mesh); + Mesh* mesh_loadfromobj(const char* path) { Vec3* position_list = NULL; Vec3* normal_list = NULL; @@ -297,11 +268,13 @@ Mesh* mesh_loadfromobj(const char* path) { int vert_count = 0; - Mesh temp_mesh = {0}; + //Mesh temp_mesh = {0}; + MeshInfo mesh_info = {0}; for (int i = 0; i < darray_size(face_list); ++i) { FaceInfo* face = &face_list[i]; + Triangle triangle = {0}; for (int j = 0; j < 3; ++j) { FaceVertex face_vert = face->vertices[j]; @@ -311,52 +284,108 @@ Mesh* mesh_loadfromobj(const char* path) { VertexListElement* vertex = &vertex_list[pos_index]; if (vertex->vertices) { - for (int j = 0; j < darray_size(vertex->vertices); ++j) + for (int k = 0; k < darray_size(vertex->vertices); ++k) { - VertexInfo* vert = &vertex->vertices[j]; + VertexInfo* vert = &vertex->vertices[k]; if (vert->normal_index == normal_index && vert->uv_index == uv_index) { - darray_push(temp_mesh.triangles, vert->index); + triangle.vertices[j] = vert->index; + MeshVertexInfo* mesh_vertex_info = &mesh_info.vertices[vert->index]; + darray_push(mesh_vertex_info->related_triangles, i); goto next; } } } - // create seam - VertexInfo new_vert; new_vert.normal_index = normal_index; new_vert.uv_index = uv_index; new_vert.index = vert_count; - darray_push(vertex->vertices, new_vert); - Vert vert; - vert.position = position_list[pos_index]; - vert.normal = normal_list[normal_index]; - vert.texcoord = uv_list[uv_index]; - vert.index = vert_count; - darray_push(temp_mesh.vertices, vert); - - darray_push(temp_mesh.triangles, vert_count); - - ++temp_mesh.vert_count; + MeshVertexInfo vert = {0}; + vert.props.position = position_list[pos_index]; + vert.props.normal = normal_list[normal_index]; + vert.props.texcoord = uv_list[uv_index]; + vert.props.index = vert_count; + darray_push(vert.related_triangles, i); + darray_push(mesh_info.vertices, vert); + triangle.vertices[j] = vert_count; + ++vert_count; - next: continue; + next: + continue; } - - ++temp_mesh.tris_count; + + darray_push(mesh_info.triangles, triangle); } + calc_face_tanget(&mesh_info); + calc_vertex_tangnet(&mesh_info); + Mesh* mesh = malloc(sizeof(Mesh)); - mesh->triangles = temp_mesh.triangles; - mesh->vertices = temp_mesh.vertices; - mesh->tris_count = temp_mesh.tris_count; - mesh->vert_count = temp_mesh.vert_count; + int num_of_face = darray_size(mesh_info.triangles) ; + mesh->triangles = malloc(num_of_face * 3 * sizeof(uint)); + for (int i = 0; i < darray_size(mesh_info.triangles); ++i) { + mesh->triangles[3 * i] = mesh_info.triangles[i].vertices[0]; + mesh->triangles[3 * i + 1] = mesh_info.triangles[i].vertices[1]; + mesh->triangles[3 * i + 2] = mesh_info.triangles[i].vertices[2]; + } + mesh->tris_count = num_of_face; + mesh->vertices = malloc(sizeof(Vert) * darray_size(mesh_info.vertices)); + for (int i = 0; i < darray_size(mesh_info.vertices); ++i) { + mesh->vertices[i] = mesh_info.vertices[i].props; + } + mesh->vert_count = darray_size(mesh_info.vertices); return mesh; } -#endif
\ No newline at end of file +void calc_face_tanget(MeshInfo* mesh) { + MeshVertexInfo* vertices = mesh->vertices; + Triangle* faces = mesh->triangles; + for (int i = 0; i < darray_size(faces); ++i) { + Triangle* face = &faces[i]; + int v0 = face->vertices[0]; + int v1 = face->vertices[1]; + int v2 = face->vertices[2]; + // delta uv + Vec2 duv1 = vec2_minus(vertices[v1].props.texcoord, vertices[v0].props.texcoord); + Vec2 duv2 = vec2_minus(vertices[v2].props.texcoord, vertices[v0].props.texcoord); + // edge + Vec3 dp1 = vec3_minus(vertices[v1].props.position, vertices[v0].props.position); + Vec3 dp2 = vec3_minus(vertices[v2].props.position, vertices[v0].props.position); + float f = 1.0f / (duv1.x * duv2.y - duv2.x * duv1.y); + face->tangent.x = f * (duv2.y * dp1.x - duv1.y * dp2.x); + face->tangent.y = f * (duv2.y * dp1.y - duv1.y * dp2.y); + face->tangent.z = f * (duv2.y * dp1.z - duv1.y * dp2.z); + face->tangent = vec3_normalize(face->tangent); + } + // 平均化三角形切线 +} + +void calc_vertex_tangnet(MeshInfo* mesh) { + MeshVertexInfo* vertices = mesh->vertices; + Triangle* faces = mesh->triangles; + for (int i = 0; i < darray_size(vertices); ++i) { + MeshVertexInfo* vert = &vertices[i]; + Vec3 tangent = vec3(0,0,0); + Vec3 bitangent = vec3(0,0,0); + int face_count = darray_size(vert->related_triangles); + for (int j = 0; j < face_count; ++j) { + int face_index = vert->related_triangles[j]; + Triangle* face = &faces[face_index]; + tangent = vec3_plus(tangent, face->tangent); + } + tangent = vec3_normalize(tangent); + vert->props.tangent = vec4(tangent.x, tangent.y, tangent.z, 1); + // orthogonalize + bitangent = vec3_normalize(vec3_cross(vert->props.normal, tangent)); + internal_vec3_orthogonalize( + &tangent, &bitangent, &vert->props.normal, &tangent, &bitangent, &vert->props.normal); + } +} + +#endif // SIMPLE_OBJ_LOADER
\ No newline at end of file |