]> git.lizzy.rs Git - shadowclad.git/commitdiff
Calculate smoothed vertex normals based on crease angle shading-bug-25
authoroutfrost <kotlet.bahn@gmail.com>
Fri, 12 Jun 2020 03:08:12 +0000 (05:08 +0200)
committeroutfrost <kotlet.bahn@gmail.com>
Fri, 12 Jun 2020 03:08:12 +0000 (05:08 +0200)
src/engine/asset.c
src/engine/geometry.c
src/engine/geometry.h
src/engine/render.c

index 83b3180f88d2860dd5d2f4ec72d339053aea3746..b7d5346cce8f70333c4ebff088a98362ccd83d64 100644 (file)
@@ -1,5 +1,6 @@
 #include "asset.h"
 
+#include <math.h>
 #include <stdlib.h>
 #include <assimp/cimport.h>
 //#include <assimp/metadata.h>
@@ -12,6 +13,8 @@
 
 #define IMPORT_DEBUG_ 1
 
+static const float smoothingThresholdAngle = TAU / 14.0f;
+
 static const struct aiScene* importScene(const char* path);
 static Vector3D triangleNormal(Vector3D v1, Vector3D v2, Vector3D v3);
 static Vector3D convertAiVector3D(struct aiVector3D vect);
@@ -168,6 +171,42 @@ const Solid* importSolid(const char* path) {
                        
                        mesh.faces[faceIndex] = face;
                }
+
+               float smoothingThreshold = cosf(smoothingThresholdAngle);
+               Face* smoothedFaces = malloc(mesh.numFaces * sizeof(Face));
+               for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) {
+                       Face face = mesh.faces[faceIndex];
+
+                       if (face.normals) {
+                               face.normals = memcpy(malloc(face.numIndices * sizeof(Vector3D)),
+                                                     face.normals,
+                                                     face.numIndices * sizeof(Vector3D));
+
+                               for (size_t indexIndex = 0; indexIndex < face.numIndices; ++indexIndex) {
+                                       Vector3D smoothedNormal = face.normals[indexIndex];
+
+                                       for (size_t i = 0; i < mesh.numFaces; ++i) {
+                                               if (i == faceIndex || !mesh.faces[i].normals) {
+                                                       continue;
+                                               }
+
+                                               for (size_t k = 0; k < mesh.faces[i].numIndices; ++k) {
+                                                       if (mesh.faces[i].indices[k] == face.indices[indexIndex]
+                                                           && dotProduct(face.normals[indexIndex],
+                                                                         mesh.faces[i].normals[k]) >= smoothingThreshold) {
+                                                               smoothedNormal = addVectors(smoothedNormal, mesh.faces[i].normals[k]);
+                                                       }
+                                               }
+                                       }
+
+                                       face.normals[indexIndex] = normalized(smoothedNormal);
+                               }
+                       }
+                       smoothedFaces[faceIndex] = face;
+               }
+               // TODO Actually clean up the stuff inside
+               free(mesh.faces);
+               mesh.faces = smoothedFaces;
                
                solid->meshes[meshIndex] = mesh;
        }
@@ -237,7 +276,9 @@ const Solid* importSolid(const char* path) {
 }
 
 static const struct aiScene* importScene(const char* path) {
-       const struct aiScene* scene = aiImportFile(path, aiProcess_PreTransformVertices);
+       const struct aiScene* scene = aiImportFile(path, aiProcess_JoinIdenticalVertices
+                                                        | aiProcess_PreTransformVertices
+                                                        | aiProcess_ValidateDataStructure);
        if (scene != NULL && scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) {
                logError("Incomplete scene imported from %s", path);
                aiReleaseImport(scene);
index 311a645864adf0fa08fed6017a187574ae658372..da7749713941978f667a81379ee9c9fffd385ed3 100644 (file)
@@ -3,10 +3,6 @@
 #include <math.h>
 #include <stddef.h>
 
-const float TAU = 6.28318530718f;
-
-
-
 Transform identity() {
        return (Transform) { .a1 = 1.0f, .a2 = 0.0f, .a3 = 0.0f, .a4 = 0.0f,
                             .b1 = 0.0f, .b2 = 1.0f, .b3 = 0.0f, .b4 = 0.0f,
@@ -72,6 +68,10 @@ Vector3D crossProduct(Vector3D v1, Vector3D v2) {
                            .z = (v1.x * v2.y) - (v1.y * v2.x) };
 }
 
+float dotProduct(Vector3D v1, Vector3D v2) {
+       return (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z);
+}
+
 Vector3D applyTransform(Transform transform, Vector3D vec) {
        GLfloat* a = (GLfloat*) &transform;
        GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f };
index bac0ebb93de2c52ab457fff085e524eadc30a233..ee18ea9cabac20d57cc42092fbbd46bdba6f6433 100644 (file)
@@ -19,7 +19,7 @@ struct Transform {
        GLfloat d1, d2, d3, d4;
 };
 
-extern const float TAU;
+static const float TAU = 6.28318530718f;
 
 Transform identity();
 Transform multiply(Transform t1, Transform t2);
@@ -28,6 +28,7 @@ void rotate(Transform* transform, Vector3D axis, float angle);
 Vector3D addVectors(Vector3D v1, Vector3D v2);
 Vector3D subtractVectors(Vector3D v1, Vector3D v2);
 Vector3D crossProduct(Vector3D v1, Vector3D v2);
+float dotProduct(Vector3D v1, Vector3D v2);
 Vector3D applyTransform(Transform transform, Vector3D vec);
 Vector3D translationOf(Transform transform);
 Vector3D normalized(Vector3D vec);
index 6ba5103b306be17a628b6eb67c57b58e8835f421..089c475809a974981eb805414df5f7f6509b3da4 100644 (file)
@@ -153,14 +153,14 @@ static void drawSolid(const Solid* solid) {
                        const Face face = mesh.faces[faceIndex];
                        
 #if RENDER_DEBUG_
-                       if (mesh.normals) {
+                       if (face.normals) {
                                glDisable(GL_LIGHTING);
                                glDisable(GL_TEXTURE_2D);
                                glBegin(GL_LINES);
                                for (size_t i = 0; i < face.numIndices; ++i) {
                                        size_t vertIndex = face.indices[i];
                                        Vector3D vertex = mesh.vertices[vertIndex];
-                                       Vector3D normal = mesh.normals[vertIndex];
+                                       Vector3D normal = face.normals[i];
                                        glColor3f(ab(normal.x), ab(normal.y), ab(normal.z));
                                        glVertex3f(vertex.x, vertex.y, vertex.z);
                                        glVertex3f(vertex.x + normal.x, vertex.y + normal.y, vertex.z + normal.z);