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.c120
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);
}
}