diff options
Diffstat (limited to 'src/extend/mesh.c')
-rw-r--r-- | src/extend/mesh.c | 120 |
1 files changed, 115 insertions, 5 deletions
diff --git a/src/extend/mesh.c b/src/extend/mesh.c index 90e8bf5..394a7e8 100644 --- a/src/extend/mesh.c +++ b/src/extend/mesh.c @@ -1,11 +1,19 @@ +#include <math.h> +#include <stdio.h> +#include <string.h> + #include "mesh.h" #include "../util/darray.h" #include "../shaders/common/mathlib.h" +#include "../math/math.h" #define GENERATE_TANGNET //#define GENERATE_NORMAL //#define OPTIMIZE_MESH +#define SMOOTH_TANGENT 1 +#define IMPORT_POLYGON 1 + #define LINE_SIZE 1024 #define UNUSED_VAR(x) ((void)(x)) @@ -225,6 +233,7 @@ Mesh* mesh_loadfromobj(const char* path) { FILE *file; file = fopen(path, "rb"); assert(file != NULL); + char line[LINE_SIZE]; while (1) { @@ -232,6 +241,9 @@ Mesh* mesh_loadfromobj(const char* path) { if (fgets(line, LINE_SIZE, file) == NULL) { break; } + else if (strncmp(line, "o ", 2) == 0) { /* submesh name */ + // ignore + } else if (strncmp(line, "v ", 2) == 0) { /* position */ Vec3 position; items = sscanf(line, "v %f %f %f", @@ -242,6 +254,16 @@ Mesh* mesh_loadfromobj(const char* path) { VertexListElement element = { 0 }; darray_push(vertex_list, element); } + else if (strncmp(line, "v ", 3) == 0) { /* position */ + Vec3 position; + items = sscanf(line, "v %f %f %f", + &position.x, &position.y, &position.z); + assert(items == 3); + darray_push(position_list, position); + // init vertex_list + VertexListElement element = { 0 }; + darray_push(vertex_list, element); + } else if (strncmp(line, "vt ", 3) == 0) { /* texcoord */ Vec2 texcoord; items = sscanf(line, "vt %f %f", @@ -257,6 +279,29 @@ Mesh* mesh_loadfromobj(const char* path) { darray_push(normal_list, normal); } else if (strncmp(line, "f ", 2) == 0) { /* face */ +#if IMPORT_POLYGON + FaceVertex face_vert = { 0 }; + FaceVertex *face_verts = NULL; + char* p = line + 1; // skip f + while (p && *p != 0) { + items = sscanf(p, " %d/%d/%d", &face_vert.posIndex, &face_vert.uvIndex, &face_vert.normalIndex); + if (items == 3) { + darray_push(face_verts, face_vert); + ++p;// skip \s + p = strchr(p, ' '); + } + else ++p; + } + assert(face_verts && darray_size(face_verts) > 0); + FaceVertex* v0 = &face_verts[0]; + for (int i = 1; i < darray_size(face_verts) - 1; ++i) { + FaceVertex* v1 = &face_verts[i]; + FaceVertex* v2 = &face_verts[i + 1]; + FaceInfo face = { *v0, *v1, *v2}; + darray_push(face_list, face); + } + darray_free(face_verts); +#else FaceInfo face; items = sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", // only support triangle &face.vertices[0].posIndex, &face.vertices[0].uvIndex, &face.vertices[0].normalIndex, @@ -264,11 +309,13 @@ Mesh* mesh_loadfromobj(const char* path) { &face.vertices[2].posIndex, &face.vertices[2].uvIndex, &face.vertices[2].normalIndex); assert(items == 9); darray_push(face_list, face); +#endif } else { - // skip + // ignore } + memset(&line, 0, LINE_SIZE); } int vert_counts = darray_size(vertex_list); @@ -331,6 +378,18 @@ Mesh* mesh_loadfromobj(const char* path) { darray_push(mesh_info.triangles, triangle); } + fclose(file); + + darray_free(position_list); + darray_free(normal_list); + darray_free(uv_list); + darray_free(face_list); + for (int i = 0; i < darray_size(vertex_list); ++i) { + VertexListElement* v = &vertex_list[i]; + darray_free(v->vertices); + } + darray_free(vertex_list); + #ifdef GENERATE_TANGNET calc_face_tanget(&mesh_info); calc_vertex_tangnet(&mesh_info); @@ -364,6 +423,8 @@ Mesh* build_mesh(MeshInfo* mesh_info) { void calc_face_tanget(MeshInfo* mesh) { MeshVertexInfo* vertices = mesh->vertices; Triangle* faces = mesh->triangles; + +#if !SMOOTH_TANGENT for (int i = 0; i < darray_size(faces); ++i) { Triangle* face = &faces[i]; int v0 = face->vertices[0]; @@ -375,13 +436,62 @@ void calc_face_tanget(MeshInfo* mesh) { // 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); + float d = (duv1.x * duv2.y - duv2.x * duv1.y); + if (d == 0) d = 0.0000001f; + float f = 1.0f / d; 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); } - // 平均化三角形切线 +#else + Vec3* temp_tangents = NULL; + Vec3 tangent = {0}; + 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 d = duv1.x * duv2.y - duv2.x * duv1.y; + if (d == 0) d = 0.0000001f; + float f = 1.0f / d; + tangent.x = f * (duv2.y * dp1.x - duv1.y * dp2.x); + tangent.y = f * (duv2.y * dp1.y - duv1.y * dp2.y); + tangent.z = f * (duv2.y * dp1.z - duv1.y * dp2.z); + tangent = vec3_normalize(tangent); + darray_push(temp_tangents, tangent); + } + + float smooth_angle = 60; + float cos_smooth = cos(smooth_angle * DEG2RAG); + + for (int i = 0; i < darray_size(faces); ++i) { + Triangle* face = &faces[i]; + Vec3 tangent = temp_tangents[i]; + Vec3 avarage_tangent = tangent; + for (int j = 0; j < 3; ++j) + { + MeshVertexInfo* vert = &vertices[face->vertices[j]]; + for (int k = 0; k < darray_size(vert->related_triangles); ++k) + { + Vec3 related_triangle_tangent = temp_tangents[vert->related_triangles[k]]; + if (vec3_dot(tangent, related_triangle_tangent) < cos_smooth) { + avarage_tangent = vec3_plus(avarage_tangent, related_triangle_tangent); + } + } + } + avarage_tangent = vec3_normalize(avarage_tangent); + face->tangent = avarage_tangent; + } + + darray_free(temp_tangents); +#endif } void calc_vertex_tangnet(MeshInfo* mesh) { @@ -395,14 +505,14 @@ void calc_vertex_tangnet(MeshInfo* mesh) { 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_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); + vert->props.tangent = vec4(tangent.x, tangent.y, tangent.z, 1); } } |