119 lines
3.6 KiB
C++
119 lines
3.6 KiB
C++
#include "color.h"
|
|
#include "engine.h"
|
|
#include "geometry.h"
|
|
#include "util.h"
|
|
#include <cstdio>
|
|
|
|
|
|
// MACROS
|
|
#define DrawPixel(buffer, width, color, x, y)\
|
|
{\
|
|
buffer[width * y + x] = color;\
|
|
}
|
|
|
|
|
|
// STRUCTURES
|
|
struct BoundingBox
|
|
{
|
|
BoundingBox(Point &v0, Point &v1, Point &v2)
|
|
{
|
|
yMin = MIN(v0.y, MIN(v1.y, v2.y));
|
|
yMax = MAX(v0.y, MAX(v1.y, v2.y));
|
|
|
|
xMin = MIN(v0.x, MIN(v1.x, v2.x));
|
|
xMax = MAX(v0.x, MAX(v1.x, v2.x));
|
|
}
|
|
|
|
float yMin, yMax;
|
|
float xMin, xMax;
|
|
};
|
|
|
|
|
|
// PUBLIC FUNCTIONS
|
|
void RenderMesh(Engine_Buffer &buffer, MeshRenderData &mesh)
|
|
{
|
|
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 yMax = (int)ceilf(box.yMax) - 1;
|
|
int xMin = (int)ceilf(box.xMin);
|
|
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 x = xMin; x <= xMax; ++x)
|
|
{
|
|
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];
|
|
barycenter[1] = (dot0202 * dot0P01 - dot0102 * dot0P02) * denomInv;
|
|
barycenter[2] = (dot0101 * dot0P02 - dot0102 * dot0P01) * denomInv;
|
|
barycenter[0] = 1.0f - barycenter[1] - barycenter[2];
|
|
|
|
// Point is inside the triangle
|
|
if ( (barycenter[0] >= 0.0f)
|
|
&& (barycenter[1] >= 0.0f)
|
|
&& (barycenter[2] >= 0.0f))
|
|
{
|
|
ColorF32 totalColor;
|
|
|
|
if (mesh.smooth)
|
|
{
|
|
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);
|
|
|
|
if (zInv > buffer.zbuffer[pixel])
|
|
{
|
|
DrawPixel(buffer.buffer, buffer.width, color.u32, x, y);
|
|
|
|
buffer.zbuffer[pixel] = zInv;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|