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.
This commit is contained in:
parent
8b9e6b54c8
commit
370fb7bce0
|
@ -28,11 +28,16 @@ struct Vertex
|
||||||
ColorF32 color;
|
ColorF32 color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MeshRenderData
|
struct Mesh_LocalData
|
||||||
{
|
{
|
||||||
std::vector<Vertex> vertsTransformed;
|
std::vector<Vertex> verts;
|
||||||
std::vector<Face> culledFaces;
|
std::vector<Face> faces;
|
||||||
bool smooth;
|
};
|
||||||
|
|
||||||
|
struct Mesh_TransformedData
|
||||||
|
{
|
||||||
|
std::vector<Vertex> verts;
|
||||||
|
std::vector<Face> faces;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
|
@ -50,61 +55,25 @@ struct Mesh
|
||||||
scale = 1.0f;
|
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;
|
Point position;
|
||||||
float rotation[3];
|
float rotation[3];
|
||||||
float scale;
|
float scale;
|
||||||
|
|
||||||
std::vector<Vertex> verts;
|
|
||||||
std::vector<Face> faces;
|
|
||||||
Material material;
|
Material material;
|
||||||
|
bool smooth;
|
||||||
|
|
||||||
MeshRenderData renderData;
|
Mesh_LocalData local;
|
||||||
|
Mesh_TransformedData transformed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// PUBLIC FUNCTIONS
|
||||||
|
void CullBackfaces(
|
||||||
|
Mesh_LocalData &local, Mesh_TransformedData &transformed,
|
||||||
|
Point &camPosition);
|
||||||
|
|
||||||
void RenderMesh(
|
void RenderMesh(
|
||||||
Engine_Buffer &buffer, MeshRenderData &mesh);
|
Engine_Buffer &buffer, Mesh_TransformedData &mesh, bool smooth);
|
||||||
|
|
||||||
|
|
||||||
#define GEOMETRY_H
|
#define GEOMETRY_H
|
||||||
|
|
|
@ -65,35 +65,35 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
|
|
||||||
Matrix tScale = Transform_Scale(mesh.scale);
|
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.transformed.verts[v].point = mesh.local.verts[v].point * tScale * tRotate * tTranslate;
|
||||||
mesh.renderData.vertsTransformed[v].normal = mesh.verts[v].normal * tScale * tRotate * tTranslate;
|
mesh.transformed.verts[v].normal = mesh.local.verts[v].normal * tScale * tRotate * tTranslate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cull backfaces before computing colors
|
// Cull backfaces before computing colors
|
||||||
mesh.CullBackfaces(camera.position);
|
CullBackfaces(mesh.local, mesh.transformed, camera.position);
|
||||||
|
|
||||||
|
|
||||||
// Color the vertices for Gouraud shading
|
// 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)
|
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);
|
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
|
||||||
|
|
||||||
for (int c = 0; c < lights.diffuseCount; ++c)
|
for (int c = 0; c < lights.diffuseCount; ++c)
|
||||||
{
|
{
|
||||||
totalColor += lights.diffuse[c].ComputeColor(
|
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
|
// Color the face for flat shading
|
||||||
else
|
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);
|
ColorF32 totalColor = lights.ambient.ComputeColor(mesh.material.kAmbient);
|
||||||
|
|
||||||
for (int c = 0; c < lights.diffuseCount; ++c)
|
for (int c = 0; c < lights.diffuseCount; ++c)
|
||||||
{
|
{
|
||||||
totalColor += lights.diffuse[c].ComputeColor(
|
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
|
// Perspective to screen
|
||||||
Matrix tScreen = Transform_Screen(camera.xScale, camera.yScale);
|
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.transformed.verts[v].point *= tView * tPersp * tScreen;
|
||||||
mesh.renderData.vertsTransformed[v].point /= mesh.renderData.vertsTransformed[v].point.w;
|
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)
|
void Engine_Shutdown(void)
|
||||||
|
@ -208,10 +208,10 @@ static void CheckInputs(uint32_t input)
|
||||||
|
|
||||||
if (CHECK_BIT(input, SHADING_TOGGLE))
|
if (CHECK_BIT(input, SHADING_TOGGLE))
|
||||||
{
|
{
|
||||||
mesh.renderData.smooth = true;
|
mesh.smooth = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mesh.renderData.smooth = false;
|
mesh.smooth = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,17 +30,53 @@ struct BoundingBox
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// 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)
|
transformed.faces.clear();
|
||||||
{
|
|
||||||
unsigned int vIndex0 = mesh.culledFaces[f].vertIndex[0];
|
|
||||||
unsigned int vIndex1 = mesh.culledFaces[f].vertIndex[1];
|
|
||||||
unsigned int vIndex2 = mesh.culledFaces[f].vertIndex[2];
|
|
||||||
|
|
||||||
Vertex v0 = mesh.vertsTransformed[vIndex0];
|
for (size_t f = 0; f < local.faces.size(); ++f)
|
||||||
Vertex v1 = mesh.vertsTransformed[vIndex1];
|
{
|
||||||
Vertex v2 = mesh.vertsTransformed[vIndex2];
|
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
|
// Bounding box used to for iterating over possible pixels of this triangle
|
||||||
BoundingBox box(v0.point, v1.point, v2.point);
|
BoundingBox box(v0.point, v1.point, v2.point);
|
||||||
|
@ -80,7 +116,7 @@ void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh)
|
||||||
{
|
{
|
||||||
ColorF32 totalColor;
|
ColorF32 totalColor;
|
||||||
|
|
||||||
if (mesh.smooth)
|
if (smooth)
|
||||||
{
|
{
|
||||||
totalColor =
|
totalColor =
|
||||||
(barycenter[0] * v0.color)
|
(barycenter[0] * v0.color)
|
||||||
|
@ -89,7 +125,7 @@ void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
totalColor = mesh.culledFaces[f].color;
|
totalColor = mesh.faces[f].color;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorU32 color = ColorF32::ConvertToU32(totalColor);
|
ColorU32 color = ColorF32::ConvertToU32(totalColor);
|
||||||
|
|
|
@ -41,7 +41,7 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
&v.point.y,
|
&v.point.y,
|
||||||
&v.point.z);
|
&v.point.z);
|
||||||
|
|
||||||
mesh.verts.push_back(v);
|
mesh.local.verts.push_back(v);
|
||||||
}
|
}
|
||||||
else if (token[0] == 'f')
|
else if (token[0] == 'f')
|
||||||
{
|
{
|
||||||
|
@ -58,7 +58,7 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
f.vertIndex[1] -= 1;
|
f.vertIndex[1] -= 1;
|
||||||
f.vertIndex[2] -= 1;
|
f.vertIndex[2] -= 1;
|
||||||
|
|
||||||
mesh.faces.push_back(f);
|
mesh.local.faces.push_back(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
token = GetLine(buffer, sizeof(buffer), fp);
|
token = GetLine(buffer, sizeof(buffer), fp);
|
||||||
|
@ -67,10 +67,10 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
ComputeNormals(mesh);
|
ComputeNormals(mesh);
|
||||||
|
|
||||||
printf("OBJ: %s\n", filename);
|
printf("OBJ: %s\n", filename);
|
||||||
printf("Verts: %lu\n", mesh.verts.size());
|
printf("Verts: %lu\n", mesh.local.verts.size());
|
||||||
printf("Faces: %lu\n", mesh.faces.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);
|
fclose(fp);
|
||||||
|
|
||||||
|
@ -100,36 +100,36 @@ static char *GetLine(char *buffer, int maxLength, FILE *fp)
|
||||||
|
|
||||||
static void ComputeNormals(Mesh &mesh)
|
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 v0 = mesh.local.faces[f].vertIndex[0];
|
||||||
unsigned int v1 = mesh.faces[f].vertIndex[1];
|
unsigned int v1 = mesh.local.faces[f].vertIndex[1];
|
||||||
unsigned int v2 = mesh.faces[f].vertIndex[2];
|
unsigned int v2 = mesh.local.faces[f].vertIndex[2];
|
||||||
|
|
||||||
Vector v01 = mesh.verts[v1].point - mesh.verts[v0].point;
|
Vector v01 = mesh.local.verts[v1].point - mesh.local.verts[v0].point;
|
||||||
Vector v02 = mesh.verts[v2].point - mesh.verts[v0].point;
|
Vector v02 = mesh.local.verts[v2].point - mesh.local.verts[v0].point;
|
||||||
|
|
||||||
Vector normal = Vector::Cross(v01, v02);
|
Vector normal = Vector::Cross(v01, v02);
|
||||||
|
|
||||||
// Add each vertex's normal to the sum for future averaging
|
// Add each vertex's normal to the sum for future averaging
|
||||||
mesh.verts[v0].normal += normal;
|
mesh.local.verts[v0].normal += normal;
|
||||||
mesh.verts[v1].normal += normal;
|
mesh.local.verts[v1].normal += normal;
|
||||||
mesh.verts[v2].normal += normal;
|
mesh.local.verts[v2].normal += normal;
|
||||||
|
|
||||||
++vertexNormalCount[v0];
|
++vertexNormalCount[v0];
|
||||||
++vertexNormalCount[v1];
|
++vertexNormalCount[v1];
|
||||||
++vertexNormalCount[v2];
|
++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)
|
if (vertexNormalCount[v] > 0)
|
||||||
{
|
{
|
||||||
// Compute the average normal for this vertex
|
// Compute the average normal for this vertex
|
||||||
mesh.verts[v].normal /= vertexNormalCount[v];
|
mesh.local.verts[v].normal /= vertexNormalCount[v];
|
||||||
mesh.verts[v].normal.Normalize();
|
mesh.local.verts[v].normal.Normalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue