From 91db944c53065453405fb8d9335b5cb06ee40bc9 Mon Sep 17 00:00:00 2001 From: outfrost Date: Fri, 12 Jun 2020 02:52:07 +0200 Subject: [PATCH] Calculate face normals from vertices --- src/engine/asset.c | 28 +++++++++++++++++++++++++++- src/engine/asset.h | 1 + src/engine/geometry.c | 14 ++++++++++++++ src/engine/geometry.h | 3 +++ src/engine/render.c | 14 ++++++-------- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/engine/asset.c b/src/engine/asset.c index b5744aa..83b3180 100644 --- a/src/engine/asset.c +++ b/src/engine/asset.c @@ -13,6 +13,7 @@ #define IMPORT_DEBUG_ 1 static const struct aiScene* importScene(const char* path); +static Vector3D triangleNormal(Vector3D v1, Vector3D v2, Vector3D v3); static Vector3D convertAiVector3D(struct aiVector3D vect); static const char* replaceFileExtension(const struct aiString path, const char* ext); @@ -138,12 +139,33 @@ const Solid* importSolid(const char* path) { const unsigned int numIndices = aiFace.mNumIndices; Face face = { .numIndices = numIndices, - .indices = malloc(numIndices * sizeof(size_t)) }; + .indices = malloc(numIndices * sizeof(size_t)), + .normals = malloc(numIndices * sizeof(Vector3D)) }; for (unsigned int i = 0; i < numIndices; ++i) { face.indices[i] = aiFace.mIndices[i]; } + if (numIndices == 3) { + Vector3D normal = triangleNormal(mesh.vertices[face.indices[0]], + mesh.vertices[face.indices[1]], + mesh.vertices[face.indices[2]]); + for (size_t i = 0; i < numIndices; ++i) { + face.normals[i] = normal; + } + } + else { + if (mesh.normals) { + for (size_t i = 0; i < numIndices; ++i) { + face.normals[i] = mesh.normals[face.indices[i]]; + } + } + else { + free(face.normals); + face.normals = NULL; + } + } + mesh.faces[faceIndex] = face; } @@ -224,6 +246,10 @@ static const struct aiScene* importScene(const char* path) { return scene; } +static Vector3D triangleNormal(Vector3D v1, Vector3D v2, Vector3D v3) { + return normalized(crossProduct(subtractVectors(v2, v1), subtractVectors(v3, v1))); +} + static Vector3D convertAiVector3D(struct aiVector3D vect) { return (Vector3D) { .x = vect.x, .y = vect.y, diff --git a/src/engine/asset.h b/src/engine/asset.h index 9354c47..21ecadb 100644 --- a/src/engine/asset.h +++ b/src/engine/asset.h @@ -31,6 +31,7 @@ struct Mesh { struct Face { size_t numIndices; size_t* indices; + Vector3D* normals; }; struct Material { diff --git a/src/engine/geometry.c b/src/engine/geometry.c index 2cfb0aa..311a645 100644 --- a/src/engine/geometry.c +++ b/src/engine/geometry.c @@ -58,6 +58,20 @@ void rotate(Transform* transform, Vector3D axis, float angle) { *transform); } +Vector3D addVectors(Vector3D v1, Vector3D v2){ + return (Vector3D) { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; +} + +Vector3D subtractVectors(Vector3D v1, Vector3D v2) { + return (Vector3D) { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; +} + +Vector3D crossProduct(Vector3D v1, Vector3D v2) { + return (Vector3D) { .x = (v1.y * v2.z) - (v1.z * v2.y), + .y = (v1.z * v2.x) - (v1.x * v2.z), + .z = (v1.x * v2.y) - (v1.y * v2.x) }; +} + Vector3D applyTransform(Transform transform, Vector3D vec) { GLfloat* a = (GLfloat*) &transform; GLfloat b[4] = { vec.x, vec.y, vec.z, 1.0f }; diff --git a/src/engine/geometry.h b/src/engine/geometry.h index ff45938..bac0ebb 100644 --- a/src/engine/geometry.h +++ b/src/engine/geometry.h @@ -25,6 +25,9 @@ Transform identity(); Transform multiply(Transform t1, Transform t2); void translate(Transform* transform, Vector3D vec); 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); Vector3D applyTransform(Transform transform, Vector3D vec); Vector3D translationOf(Transform transform); Vector3D normalized(Vector3D vec); diff --git a/src/engine/render.c b/src/engine/render.c index c75dc71..6ba5103 100644 --- a/src/engine/render.c +++ b/src/engine/render.c @@ -39,7 +39,7 @@ void initRender() { glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05f); glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.005f); - glShadeModel(GL_FLAT); + //glShadeModel(GL_FLAT); } void renderFrame() { @@ -148,14 +148,12 @@ static void drawSolid(const Solid* solid) { const Mesh mesh = solid->meshes[meshIndex]; glBindTexture(GL_TEXTURE_2D, solid->materials[mesh.materialIndex].textureId); - bool hasNormals = mesh.normals != NULL; - bool hasTextureCoords = mesh.textureCoords != NULL; for (size_t faceIndex = 0; faceIndex < mesh.numFaces; ++faceIndex) { const Face face = mesh.faces[faceIndex]; #if RENDER_DEBUG_ - if (hasNormals) { + if (mesh.normals) { glDisable(GL_LIGHTING); glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); @@ -185,15 +183,15 @@ static void drawSolid(const Solid* solid) { for (size_t i = 0; i < face.numIndices; ++i) { size_t vertIndex = face.indices[i]; - size_t normalIndex = face.indices[2]; - if (hasNormals) { - if (hasTextureCoords) { + if (face.normals) { + if (mesh.textureCoords) { Vector3D coords = mesh.textureCoords[vertIndex]; glTexCoord2f(coords.x, coords.y); } - Vector3D normal = mesh.normals[normalIndex]; + Vector3D normal = face.normals[i]; glNormal3f(normal.x, normal.y, normal.z); } + Vector3D vertex = mesh.vertices[vertIndex]; glVertex3f(vertex.x, vertex.y, vertex.z); } -- 2.44.0