From 370fb7bce01d396a4b928b0e52b86c25d7c58939 Mon Sep 17 00:00:00 2001 From: Austin Morlan Date: Mon, 10 Sep 2018 20:11:52 -0700 Subject: [PATCH] Move backface culling out of Mesh struct In the future the function will be able to take a list of meshes for a data-oriented approach. --- include/geometry.h | 65 ++++++++++++---------------------------------- src/engine.cpp | 36 ++++++++++++------------- src/geometry.cpp | 58 +++++++++++++++++++++++++++++++++-------- src/loader.cpp | 36 ++++++++++++------------- 4 files changed, 100 insertions(+), 95 deletions(-) diff --git a/include/geometry.h b/include/geometry.h index 77253bd..d6d0a37 100644 --- a/include/geometry.h +++ b/include/geometry.h @@ -28,11 +28,16 @@ struct Vertex ColorF32 color; }; -struct MeshRenderData +struct Mesh_LocalData { - std::vector vertsTransformed; - std::vector culledFaces; - bool smooth; + std::vector verts; + std::vector faces; +}; + +struct Mesh_TransformedData +{ + std::vector verts; + std::vector faces; }; struct Mesh @@ -50,61 +55,25 @@ struct Mesh scale = 1.0f; } - inline void CullBackfaces(Point camPosition) - { - renderData.culledFaces.clear(); - - for (size_t f = 0; f < faces.size(); ++f) - { - unsigned int v0 = faces[f].vertIndex[0]; - unsigned int v1 = faces[f].vertIndex[1]; - unsigned int v2 = faces[f].vertIndex[2]; - - Vector v01 = - renderData.vertsTransformed[v1].point - - renderData.vertsTransformed[v0].point; - - Vector v02 = - renderData.vertsTransformed[v2].point - - renderData.vertsTransformed[v0].point; - - Vector normal = Vector::Cross(v01, v02); - - // Store normal for flat shading - faces[f].normal = normal; - faces[f].normal.Normalize(); - - // Invert for Blender-compatibility - normal = -normal; - - // Eye vector to viewport - Vector view = camPosition - renderData.vertsTransformed[v0].point; - - float dot = Vector::Dot(normal, view); - - if (dot < EPSILON_E3) - { - renderData.culledFaces.push_back(faces[f]); - } - } - } - - Point position; float rotation[3]; float scale; - std::vector verts; - std::vector faces; Material material; + bool smooth; - MeshRenderData renderData; + Mesh_LocalData local; + Mesh_TransformedData transformed; }; // PUBLIC FUNCTIONS +void CullBackfaces( + Mesh_LocalData &local, Mesh_TransformedData &transformed, + Point &camPosition); + void RenderMesh( - Engine_Buffer &buffer, MeshRenderData &mesh); + Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth); #define GEOMETRY_H diff --git a/src/engine.cpp b/src/engine.cpp index 2a7ff32..79f609a 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -65,35 +65,35 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) Matrix tScale = Transform_Scale(mesh.scale); - for (size_t v = 0; v < mesh.verts.size(); ++v) + for (size_t v = 0; v < mesh.local.verts.size(); ++v) { - mesh.renderData.vertsTransformed[v].point = mesh.verts[v].point * tScale * tRotate * tTranslate; - mesh.renderData.vertsTransformed[v].normal = mesh.verts[v].normal * tScale * tRotate * tTranslate; + mesh.transformed.verts[v].point = mesh.local.verts[v].point * tScale * tRotate * tTranslate; + mesh.transformed.verts[v].normal = mesh.local.verts[v].normal * tScale * tRotate * tTranslate; } // Cull backfaces before computing colors - mesh.CullBackfaces(camera.position); + CullBackfaces(mesh.local, mesh.transformed, camera.position); // Color the vertices for Gouraud shading - if (mesh.renderData.smooth) + if (mesh.smooth) { - for (size_t f = 0; f < mesh.renderData.culledFaces.size(); ++f) + for (size_t f = 0; f < mesh.transformed.faces.size(); ++f) { for (int i = 0; i < 3; ++i) { - unsigned int v = mesh.renderData.culledFaces[f].vertIndex[i]; + unsigned int v = mesh.transformed.faces[f].vertIndex[i]; ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient); for (int c = 0; c < lights.diffuseCount; ++c) { totalColor += lights.diffuse[c].ComputeColor( - mesh.material.kDiffuse, mesh.renderData.vertsTransformed[v].normal); + mesh.material.kDiffuse, mesh.transformed.verts[v].normal); } - mesh.renderData.vertsTransformed[v].color = totalColor; + mesh.transformed.verts[v].color = totalColor; } } } @@ -101,17 +101,17 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) // Color the face for flat shading else { - for (size_t f = 0; f < mesh.renderData.culledFaces.size(); ++f) + for (size_t f = 0; f < mesh.transformed.faces.size(); ++f) { ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient); for (int c = 0; c < lights.diffuseCount; ++c) { totalColor += lights.diffuse[c].ComputeColor( - mesh.material.kDiffuse, mesh.renderData.culledFaces[f].normal); + mesh.material.kDiffuse, mesh.transformed.faces[f].normal); } - mesh.renderData.culledFaces[f].color = totalColor; + mesh.transformed.faces[f].color = totalColor; } } @@ -126,13 +126,13 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input) // Perspective to screen Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale); - for (size_t v = 0; v < mesh.verts.size(); ++v) + for (size_t v = 0; v < mesh.transformed.verts.size(); ++v) { - mesh.renderData.vertsTransformed[v].point *= tView * tPersp * tScreen; - mesh.renderData.vertsTransformed[v].point /= mesh.renderData.vertsTransformed[v].point.w; + mesh.transformed.verts[v].point *= tView * tPersp * tScreen; + mesh.transformed.verts[v].point /= mesh.transformed.verts[v].point.w; } - RenderMesh(buffer, mesh.renderData); + RenderMesh(buffer, mesh.transformed, mesh.smooth); } void Engine_Shutdown(void) @@ -208,10 +208,10 @@ static void CheckInputs(uint32_t input) if (CHECK_BIT(input, SHADING_TOGGLE)) { - mesh.renderData.smooth = true; + mesh.smooth = true; } else { - mesh.renderData.smooth = false; + mesh.smooth = false; } } diff --git a/src/geometry.cpp b/src/geometry.cpp index a24324d..520f06f 100644 --- a/src/geometry.cpp +++ b/src/geometry.cpp @@ -30,17 +30,53 @@ struct BoundingBox // PUBLIC FUNCTIONS -void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh) +void CullBackfaces( + Mesh_LocalData &local, Mesh_TransformedData &transformed, + Point &camPosition) { - for(size_t f = 0; f < mesh.culledFaces.size(); ++f) - { - unsigned int vIndex0 = mesh.culledFaces[f].vertIndex[0]; - unsigned int vIndex1 = mesh.culledFaces[f].vertIndex[1]; - unsigned int vIndex2 = mesh.culledFaces[f].vertIndex[2]; + transformed.faces.clear(); - Vertex v0 = mesh.vertsTransformed[vIndex0]; - Vertex v1 = mesh.vertsTransformed[vIndex1]; - Vertex v2 = mesh.vertsTransformed[vIndex2]; + for (size_t f = 0; f < local.faces.size(); ++f) + { + unsigned int v0 = local.faces[f].vertIndex[0]; + unsigned int v1 = local.faces[f].vertIndex[1]; + unsigned int v2 = local.faces[f].vertIndex[2]; + + Vector v01 = transformed.verts[v1].point - transformed.verts[v0].point; + Vector v02 = transformed.verts[v2].point - transformed.verts[v0].point; + Vector normal = Vector::Cross(v01, v02); + + // Store normal for flat shading + local.faces[f].normal = normal; + local.faces[f].normal.Normalize(); + + // Invert for Blender-compatibility + normal = -normal; + + // Eye vector to viewport + Vector view = camPosition - transformed.verts[v0].point; + + float dot = Vector::Dot(normal, view); + + if (dot < EPSILON_E3) + { + transformed.faces.push_back(local.faces[f]); + } + } + +} + +void RenderMesh(Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth) +{ + for(size_t f = 0; f < mesh.faces.size(); ++f) + { + unsigned int vIndex0 = mesh.faces[f].vertIndex[0]; + unsigned int vIndex1 = mesh.faces[f].vertIndex[1]; + unsigned int vIndex2 = mesh.faces[f].vertIndex[2]; + + Vertex v0 = mesh.verts[vIndex0]; + Vertex v1 = mesh.verts[vIndex1]; + Vertex v2 = mesh.verts[vIndex2]; // Bounding box used to for iterating over possible pixels of this triangle BoundingBox box(v0.point, v1.point, v2.point); @@ -80,7 +116,7 @@ void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh) { ColorF32 totalColor; - if (mesh.smooth) + if (smooth) { totalColor = (barycenter[0] * v0.color) @@ -89,7 +125,7 @@ void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh) } else { - totalColor = mesh.culledFaces[f].color; + totalColor = mesh.faces[f].color; } ColorU32 color = ColorF32::ConvertToU32(totalColor); diff --git a/src/loader.cpp b/src/loader.cpp index 4e249a9..3bb1a16 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -41,7 +41,7 @@ int LoadMesh(char *filename, Mesh &mesh) &v.point.y, &v.point.z); - mesh.verts.push_back(v); + mesh.local.verts.push_back(v); } else if (token[0] == 'f') { @@ -58,7 +58,7 @@ int LoadMesh(char *filename, Mesh &mesh) f.vertIndex[1] -= 1; f.vertIndex[2] -= 1; - mesh.faces.push_back(f); + mesh.local.faces.push_back(f); } token = GetLine(buffer, sizeof(buffer), fp); @@ -67,10 +67,10 @@ int LoadMesh(char *filename, Mesh &mesh) ComputeNormals(mesh); printf("OBJ: %s\n", filename); - printf("Verts: %lu\n", mesh.verts.size()); - printf("Faces: %lu\n", mesh.faces.size()); + printf("Verts: %lu\n", mesh.local.verts.size()); + printf("Faces: %lu\n", mesh.local.faces.size()); - mesh.renderData.vertsTransformed.resize(mesh.verts.size()); + mesh.transformed.verts.resize(mesh.local.verts.size()); fclose(fp); @@ -100,36 +100,36 @@ static char *GetLine(char *buffer, int maxLength, FILE *fp) static void ComputeNormals(Mesh &mesh) { - int *vertexNormalCount = (int*)calloc((size_t)(mesh.verts.size()), sizeof(int)); + int *vertexNormalCount = (int*)calloc((size_t)(mesh.local.verts.size()), sizeof(int)); - for (size_t f = 0; f < mesh.faces.size(); ++f) + for (size_t f = 0; f < mesh.local.faces.size(); ++f) { - unsigned int v0 = mesh.faces[f].vertIndex[0]; - unsigned int v1 = mesh.faces[f].vertIndex[1]; - unsigned int v2 = mesh.faces[f].vertIndex[2]; + unsigned int v0 = mesh.local.faces[f].vertIndex[0]; + unsigned int v1 = mesh.local.faces[f].vertIndex[1]; + unsigned int v2 = mesh.local.faces[f].vertIndex[2]; - Vector v01 = mesh.verts[v1].point - mesh.verts[v0].point; - Vector v02 = mesh.verts[v2].point - mesh.verts[v0].point; + Vector v01 = mesh.local.verts[v1].point - mesh.local.verts[v0].point; + Vector v02 = mesh.local.verts[v2].point - mesh.local.verts[v0].point; Vector normal = Vector::Cross(v01, v02); // Add each vertex's normal to the sum for future averaging - mesh.verts[v0].normal += normal; - mesh.verts[v1].normal += normal; - mesh.verts[v2].normal += normal; + mesh.local.verts[v0].normal += normal; + mesh.local.verts[v1].normal += normal; + mesh.local.verts[v2].normal += normal; ++vertexNormalCount[v0]; ++vertexNormalCount[v1]; ++vertexNormalCount[v2]; } - for (size_t v = 0; v < mesh.verts.size(); ++v) + for (size_t v = 0; v < mesh.local.verts.size(); ++v) { if (vertexNormalCount[v] > 0) { // Compute the average normal for this vertex - mesh.verts[v].normal /= vertexNormalCount[v]; - mesh.verts[v].normal.Normalize(); + mesh.local.verts[v].normal /= vertexNormalCount[v]; + mesh.local.verts[v].normal.Normalize(); } } }