Calculate smoothed vertex normals based on crease angle

master
outfrost 2020-06-12 05:08:12 +02:00
parent 91db944c53
commit edb5eba367
4 changed files with 50 additions and 8 deletions

View 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);

View 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 };

View 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);

View 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);