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.c193
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