Add Gouraud shading
This commit is contained in:
parent
bf5fabfdb2
commit
8b9e6b54c8
|
@ -70,6 +70,16 @@ inline ColorF32 operator*(ColorF32 c, float f)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// f * c
|
||||||
|
inline ColorF32 operator*(float f, ColorF32 c)
|
||||||
|
{
|
||||||
|
ColorF32 result;
|
||||||
|
|
||||||
|
result = c * f;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
#define COLOR_H
|
#define COLOR_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,8 @@ enum Engine_Input
|
||||||
ROTATE_Z_POS,
|
ROTATE_Z_POS,
|
||||||
ROTATE_Z_NEG,
|
ROTATE_Z_NEG,
|
||||||
SCALE_UP,
|
SCALE_UP,
|
||||||
SCALE_DOWN
|
SCALE_DOWN,
|
||||||
|
SHADING_TOGGLE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,22 @@ struct Material
|
||||||
struct Face
|
struct Face
|
||||||
{
|
{
|
||||||
unsigned int vertIndex[3];
|
unsigned int vertIndex[3];
|
||||||
ColorU32 color;
|
Vector normal;
|
||||||
|
ColorF32 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
Point point;
|
||||||
|
Vector normal;
|
||||||
|
ColorF32 color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MeshRenderData
|
||||||
|
{
|
||||||
|
std::vector<Vertex> vertsTransformed;
|
||||||
|
std::vector<Face> culledFaces;
|
||||||
|
bool smooth;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Mesh
|
struct Mesh
|
||||||
|
@ -37,7 +52,7 @@ struct Mesh
|
||||||
|
|
||||||
inline void CullBackfaces(Point camPosition)
|
inline void CullBackfaces(Point camPosition)
|
||||||
{
|
{
|
||||||
culledFaces.clear();
|
renderData.culledFaces.clear();
|
||||||
|
|
||||||
for (size_t f = 0; f < faces.size(); ++f)
|
for (size_t f = 0; f < faces.size(); ++f)
|
||||||
{
|
{
|
||||||
|
@ -45,41 +60,51 @@ struct Mesh
|
||||||
unsigned int v1 = faces[f].vertIndex[1];
|
unsigned int v1 = faces[f].vertIndex[1];
|
||||||
unsigned int v2 = faces[f].vertIndex[2];
|
unsigned int v2 = faces[f].vertIndex[2];
|
||||||
|
|
||||||
Vector v01 = vertsTransformed[v1] - vertsTransformed[v0];
|
Vector v01 =
|
||||||
Vector v02 = vertsTransformed[v2] - vertsTransformed[v0];
|
renderData.vertsTransformed[v1].point
|
||||||
|
- renderData.vertsTransformed[v0].point;
|
||||||
|
|
||||||
|
Vector v02 =
|
||||||
|
renderData.vertsTransformed[v2].point -
|
||||||
|
renderData.vertsTransformed[v0].point;
|
||||||
|
|
||||||
Vector normal = Vector::Cross(v01, v02);
|
Vector normal = Vector::Cross(v01, v02);
|
||||||
|
|
||||||
|
// Store normal for flat shading
|
||||||
|
faces[f].normal = normal;
|
||||||
|
faces[f].normal.Normalize();
|
||||||
|
|
||||||
// Invert for Blender-compatibility
|
// Invert for Blender-compatibility
|
||||||
normal = -normal;
|
normal = -normal;
|
||||||
|
|
||||||
// Eye vector to viewport
|
// Eye vector to viewport
|
||||||
Vector view = camPosition - vertsTransformed[v0];
|
Vector view = camPosition - renderData.vertsTransformed[v0].point;
|
||||||
|
|
||||||
float dot = Vector::Dot(normal, view);
|
float dot = Vector::Dot(normal, view);
|
||||||
|
|
||||||
if (dot < EPSILON_E3)
|
if (dot < EPSILON_E3)
|
||||||
{
|
{
|
||||||
culledFaces.push_back(faces[f]);
|
renderData.culledFaces.push_back(faces[f]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Point position;
|
Point position;
|
||||||
float rotation[3];
|
float rotation[3];
|
||||||
float scale;
|
float scale;
|
||||||
std::vector<Point> verts;
|
|
||||||
std::vector<Point> vertsTransformed;
|
std::vector<Vertex> verts;
|
||||||
std::vector<Face> faces;
|
std::vector<Face> faces;
|
||||||
std::vector<Face> culledFaces;
|
|
||||||
Material material;
|
Material material;
|
||||||
|
|
||||||
|
MeshRenderData renderData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// PUBLIC FUNCTIONS
|
||||||
void FillTriangle(
|
void RenderMesh(
|
||||||
Engine_Buffer &buffer, ColorU32 &color,
|
Engine_Buffer &buffer, MeshRenderData &mesh);
|
||||||
Point &p0, Point &p1, Point &p2);
|
|
||||||
|
|
||||||
|
|
||||||
#define GEOMETRY_H
|
#define GEOMETRY_H
|
||||||
|
|
|
@ -74,6 +74,7 @@ inline Point operator*(Point v, Matrix m)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v *=m
|
||||||
inline Point &operator*=(Point &v, Matrix m)
|
inline Point &operator*=(Point &v, Matrix m)
|
||||||
{
|
{
|
||||||
v = v * m;
|
v = v * m;
|
||||||
|
@ -81,6 +82,26 @@ inline Point &operator*=(Point &v, Matrix m)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v * m
|
||||||
|
inline Vector operator*(Vector v, Matrix m)
|
||||||
|
{
|
||||||
|
Vector result;
|
||||||
|
|
||||||
|
for (int col = 0; col < 4; ++col)
|
||||||
|
{
|
||||||
|
float sum = 0.0;
|
||||||
|
|
||||||
|
for (int row = 0; row < 4; ++row)
|
||||||
|
{
|
||||||
|
sum += v.e[row] * m.e[row][col];
|
||||||
|
}
|
||||||
|
|
||||||
|
result.e[col] = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MATRIX_H
|
#define MATRIX_H
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -76,6 +76,48 @@ inline Vector operator-(Vector v)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v1 + v2
|
||||||
|
inline Vector operator+(Vector v1, Vector v2)
|
||||||
|
{
|
||||||
|
Vector result;
|
||||||
|
|
||||||
|
result.x = v1.x + v2.x;
|
||||||
|
result.y = v1.y + v2.y;
|
||||||
|
result.z = v1.z + v2.z;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v1 += v2
|
||||||
|
inline Vector &operator+=(Vector &v1, Vector v2)
|
||||||
|
{
|
||||||
|
v1 = v1 + v2;
|
||||||
|
|
||||||
|
return v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v / f
|
||||||
|
inline Vector operator/(Vector v, float f)
|
||||||
|
{
|
||||||
|
Vector result;
|
||||||
|
|
||||||
|
float inverse = 1.0f / f;
|
||||||
|
|
||||||
|
result.x = v.x * inverse;
|
||||||
|
result.y = v.y * inverse;
|
||||||
|
result.z = v.z * inverse;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// v /= f
|
||||||
|
inline Vector &operator/=(Vector &v, float f)
|
||||||
|
{
|
||||||
|
v = v / f;
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define VEC_H
|
#define VEC_H
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -67,7 +67,8 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
|
|
||||||
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
||||||
{
|
{
|
||||||
mesh.vertsTransformed[v] = mesh.verts[v] * tScale * tRotate * tTranslate;
|
mesh.renderData.vertsTransformed[v].point = mesh.verts[v].point * tScale * tRotate * tTranslate;
|
||||||
|
mesh.renderData.vertsTransformed[v].normal = mesh.verts[v].normal * tScale * tRotate * tTranslate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,28 +76,43 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
mesh.CullBackfaces(camera.position);
|
mesh.CullBackfaces(camera.position);
|
||||||
|
|
||||||
|
|
||||||
// Color the faces (flat shading)
|
// Color the vertices for Gouraud shading
|
||||||
for (size_t f = 0; f < mesh.culledFaces.size(); ++f)
|
if (mesh.renderData.smooth)
|
||||||
{
|
{
|
||||||
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
|
for (size_t f = 0; f < mesh.renderData.culledFaces.size(); ++f)
|
||||||
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
|
{
|
||||||
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
Vector v01 = mesh.vertsTransformed[v1] - mesh.vertsTransformed[v0];
|
unsigned int v = mesh.renderData.culledFaces[f].vertIndex[i];
|
||||||
Vector v02 = mesh.vertsTransformed[v2] - mesh.vertsTransformed[v0];
|
|
||||||
|
|
||||||
Vector normal = Vector::Cross(v01, v02);
|
|
||||||
normal.Normalize();
|
|
||||||
|
|
||||||
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, normal);
|
mesh.material.kDiffuse, mesh.renderData.vertsTransformed[v].normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
mesh.faces[f].color = ColorF32::ConvertToU32(totalColor);
|
mesh.renderData.vertsTransformed[v].color = totalColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color the face for flat shading
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (size_t f = 0; f < mesh.renderData.culledFaces.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.renderData.culledFaces[f].color = totalColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,24 +128,11 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
|
|
||||||
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
for (size_t v = 0; v < mesh.verts.size(); ++v)
|
||||||
{
|
{
|
||||||
mesh.vertsTransformed[v] *= tView * tPersp * tScreen;
|
mesh.renderData.vertsTransformed[v].point *= tView * tPersp * tScreen;
|
||||||
mesh.vertsTransformed[v] /= mesh.vertsTransformed[v].w;
|
mesh.renderData.vertsTransformed[v].point /= mesh.renderData.vertsTransformed[v].point.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RenderMesh(buffer, mesh.renderData);
|
||||||
// Fill each face with its respective color
|
|
||||||
for(size_t f = 0; f < mesh.culledFaces.size(); ++f)
|
|
||||||
{
|
|
||||||
unsigned int v0 = mesh.culledFaces[f].vertIndex[0];
|
|
||||||
unsigned int v1 = mesh.culledFaces[f].vertIndex[1];
|
|
||||||
unsigned int v2 = mesh.culledFaces[f].vertIndex[2];
|
|
||||||
|
|
||||||
FillTriangle(
|
|
||||||
buffer, mesh.faces[f].color,
|
|
||||||
mesh.vertsTransformed[v0],
|
|
||||||
mesh.vertsTransformed[v1],
|
|
||||||
mesh.vertsTransformed[v2]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine_Shutdown(void)
|
void Engine_Shutdown(void)
|
||||||
|
@ -202,4 +205,13 @@ static void CheckInputs(uint32_t input)
|
||||||
{
|
{
|
||||||
mesh.scale -= 0.1f;
|
mesh.scale -= 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CHECK_BIT(input, SHADING_TOGGLE))
|
||||||
|
{
|
||||||
|
mesh.renderData.smooth = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mesh.renderData.smooth = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,52 +29,78 @@ struct BoundingBox
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void ComputeBarycenter(float *w, Point &v0, Point &v1, Point &v2, Point &p)
|
|
||||||
{
|
|
||||||
float area = (v2.x - v0.x) * (v1.y - v0.y) - (v2.y - v0.y) * (v1.x - v0.x);
|
|
||||||
|
|
||||||
float result[3];
|
|
||||||
result[0] = (p.x - v1.x) * (v2.y - v1.y) - (p.y - v1.y) * (v2.x - v1.x);
|
|
||||||
result[1] = (p.x - v2.x) * (v0.y - v2.y) - (p.y - v2.y) * (v0.x - v2.x);
|
|
||||||
result[2] = (p.x - v0.x) * (v1.y - v0.y) - (p.y - v0.y) * (v1.x - v0.x);
|
|
||||||
|
|
||||||
result[0] /= area;
|
|
||||||
result[1] /= area;
|
|
||||||
result[2] /= area;
|
|
||||||
|
|
||||||
w[0] = result[0];
|
|
||||||
w[1] = result[1];
|
|
||||||
w[2] = result[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// PUBLIC FUNCTIONS
|
||||||
void FillTriangle(
|
void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh)
|
||||||
Engine_Buffer &buffer, ColorU32 &color,
|
|
||||||
Point &v0, Point &v1, Point &v2)
|
|
||||||
{
|
{
|
||||||
BoundingBox box(v0, v1, v2);
|
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];
|
||||||
|
|
||||||
|
Vertex v0 = mesh.vertsTransformed[vIndex0];
|
||||||
|
Vertex v1 = mesh.vertsTransformed[vIndex1];
|
||||||
|
Vertex v2 = mesh.vertsTransformed[vIndex2];
|
||||||
|
|
||||||
|
// Bounding box used to for iterating over possible pixels of this triangle
|
||||||
|
BoundingBox box(v0.point, v1.point, v2.point);
|
||||||
int yMin = (int)ceilf(box.yMin);
|
int yMin = (int)ceilf(box.yMin);
|
||||||
int yMax = (int)ceilf(box.yMax) - 1;
|
int yMax = (int)ceilf(box.yMax) - 1;
|
||||||
int xMin = (int)ceilf(box.xMin);
|
int xMin = (int)ceilf(box.xMin);
|
||||||
int xMax = (int)ceilf(box.xMax) - 1;
|
int xMax = (int)ceilf(box.xMax) - 1;
|
||||||
|
|
||||||
|
// Constants for this triangle used for barycentric calculations
|
||||||
|
Vector v01 = v1.point - v0.point;
|
||||||
|
Vector v02 = v2.point - v0.point;
|
||||||
|
float dot0101 = Vector::Dot(v01, v01);
|
||||||
|
float dot0102 = Vector::Dot(v01, v02);
|
||||||
|
float dot0202 = Vector::Dot(v02, v02);
|
||||||
|
|
||||||
|
// Iterate bounding box and determine if each point is in the triangle
|
||||||
for (int y = yMin; y <= yMax; ++y)
|
for (int y = yMin; y <= yMax; ++y)
|
||||||
{
|
{
|
||||||
for (int x = xMin; x <= xMax; ++x)
|
for (int x = xMin; x <= xMax; ++x)
|
||||||
{
|
{
|
||||||
Point p(x, y, 1.0f);
|
Point p(x, y, 1.0f);
|
||||||
|
|
||||||
|
Vector v0P = p - v0.point;
|
||||||
|
float dot0P01 = Vector::Dot(v0P, v01);
|
||||||
|
float dot0P02 = Vector::Dot(v0P, v02);
|
||||||
|
float denomInv = 1.0f / ((dot0101 * dot0202) - (dot0102 * dot0102));
|
||||||
|
|
||||||
float barycenter[3];
|
float barycenter[3];
|
||||||
|
barycenter[1] = (dot0202 * dot0P01 - dot0102 * dot0P02) * denomInv;
|
||||||
|
barycenter[2] = (dot0101 * dot0P02 - dot0102 * dot0P01) * denomInv;
|
||||||
|
barycenter[0] = 1.0f - barycenter[1] - barycenter[2];
|
||||||
|
|
||||||
ComputeBarycenter(barycenter, v0, v1, v2, p);
|
// Point is inside the triangle
|
||||||
|
if ( (barycenter[0] >= 0.0f)
|
||||||
if (barycenter[0] >= 0 && barycenter[1] >= 0 && barycenter[2] >= 0)
|
&& (barycenter[1] >= 0.0f)
|
||||||
|
&& (barycenter[2] >= 0.0f))
|
||||||
{
|
{
|
||||||
float zInv =
|
ColorF32 totalColor;
|
||||||
(barycenter[0] * (1.0f/v0.z))
|
|
||||||
+ (barycenter[1] * (1.0f/v1.z))
|
if (mesh.smooth)
|
||||||
+ (barycenter[2] * (1.0f/v2.z));
|
{
|
||||||
|
totalColor =
|
||||||
|
(barycenter[0] * v0.color)
|
||||||
|
+ (barycenter[1] * v1.color)
|
||||||
|
+ (barycenter[2] * v2.color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
totalColor = mesh.culledFaces[f].color;
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorU32 color = ColorF32::ConvertToU32(totalColor);
|
||||||
|
|
||||||
|
|
||||||
|
float z =
|
||||||
|
(barycenter[0] * v0.point.z)
|
||||||
|
+ (barycenter[1] * v1.point.z)
|
||||||
|
+ (barycenter[2] * v2.point.z);
|
||||||
|
|
||||||
|
float zInv = 1.0f / z;
|
||||||
|
|
||||||
int pixel = (y * buffer.width + x);
|
int pixel = (y * buffer.width + x);
|
||||||
|
|
||||||
|
@ -88,4 +114,5 @@ void FillTriangle(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
// STATIC PROTOTYPES
|
// STATIC PROTOTYPES
|
||||||
static char *GetLine(char *buffer, int maxLength, FILE *fp);
|
static char *GetLine(char *buffer, int maxLength, FILE *fp);
|
||||||
|
static void ComputeNormals(Mesh &mesh);
|
||||||
|
|
||||||
|
|
||||||
// PUBLIC FUNCTIONS
|
// PUBLIC FUNCTIONS
|
||||||
|
@ -31,14 +32,14 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
{
|
{
|
||||||
if (token[0] == 'v')
|
if (token[0] == 'v')
|
||||||
{
|
{
|
||||||
Point v;
|
Vertex v;
|
||||||
|
|
||||||
sscanf(
|
sscanf(
|
||||||
token, "%s %f %f %f",
|
token, "%s %f %f %f",
|
||||||
garbage,
|
garbage,
|
||||||
&v.x,
|
&v.point.x,
|
||||||
&v.y,
|
&v.point.y,
|
||||||
&v.z);
|
&v.point.z);
|
||||||
|
|
||||||
mesh.verts.push_back(v);
|
mesh.verts.push_back(v);
|
||||||
}
|
}
|
||||||
|
@ -63,11 +64,13 @@ int LoadMesh(char *filename, Mesh &mesh)
|
||||||
token = GetLine(buffer, sizeof(buffer), fp);
|
token = GetLine(buffer, sizeof(buffer), fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ComputeNormals(mesh);
|
||||||
|
|
||||||
printf("OBJ: %s\n", filename);
|
printf("OBJ: %s\n", filename);
|
||||||
printf("Verts: %lu\n", mesh.verts.size());
|
printf("Verts: %lu\n", mesh.verts.size());
|
||||||
printf("Faces: %lu\n", mesh.faces.size());
|
printf("Faces: %lu\n", mesh.faces.size());
|
||||||
|
|
||||||
mesh.vertsTransformed.resize(mesh.verts.size());
|
mesh.renderData.vertsTransformed.resize(mesh.verts.size());
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
|
@ -93,3 +96,40 @@ static char *GetLine(char *buffer, int maxLength, FILE *fp)
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ComputeNormals(Mesh &mesh)
|
||||||
|
{
|
||||||
|
int *vertexNormalCount = (int*)calloc((size_t)(mesh.verts.size()), sizeof(int));
|
||||||
|
|
||||||
|
for (size_t f = 0; f < mesh.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];
|
||||||
|
|
||||||
|
Vector v01 = mesh.verts[v1].point - mesh.verts[v0].point;
|
||||||
|
Vector v02 = mesh.verts[v2].point - mesh.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;
|
||||||
|
|
||||||
|
++vertexNormalCount[v0];
|
||||||
|
++vertexNormalCount[v1];
|
||||||
|
++vertexNormalCount[v2];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t v = 0; v < mesh.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -169,6 +169,10 @@ static void HandleEvent(
|
||||||
{
|
{
|
||||||
SET_BIT(platform.input, ROTATE_Y_NEG);
|
SET_BIT(platform.input, ROTATE_Y_NEG);
|
||||||
} break;
|
} break;
|
||||||
|
case SDLK_g:
|
||||||
|
{
|
||||||
|
SET_BIT(platform.input, SHADING_TOGGLE);
|
||||||
|
} break;
|
||||||
case SDLK_UP:
|
case SDLK_UP:
|
||||||
{
|
{
|
||||||
SET_BIT(platform.input, SCALE_UP);
|
SET_BIT(platform.input, SCALE_UP);
|
||||||
|
@ -231,6 +235,10 @@ static void HandleEvent(
|
||||||
{
|
{
|
||||||
CLEAR_BIT(platform.input, ROTATE_Y_NEG);
|
CLEAR_BIT(platform.input, ROTATE_Y_NEG);
|
||||||
} break;
|
} break;
|
||||||
|
case SDLK_g:
|
||||||
|
{
|
||||||
|
CLEAR_BIT(platform.input, SHADING_TOGGLE);
|
||||||
|
} break;
|
||||||
case SDLK_UP:
|
case SDLK_UP:
|
||||||
{
|
{
|
||||||
CLEAR_BIT(platform.input, SCALE_UP);
|
CLEAR_BIT(platform.input, SCALE_UP);
|
||||||
|
|
Loading…
Reference in New Issue