Add triangle filling with a solid color
This commit is contained in:
parent
33cb124d77
commit
f642b0ec02
4
Makefile
4
Makefile
|
@ -36,10 +36,10 @@ WARNINGS_OFF=-Wno-missing-braces -Wno-gnu-anonymous-struct -Wno-old-style-cast\
|
||||||
CFLAGS=$(D) $(O) -std=c++11 $(WARNINGS_ON) $(WARNINGS_OFF) -I$(INCLUDE_DIR)
|
CFLAGS=$(D) $(O) -std=c++11 $(WARNINGS_ON) $(WARNINGS_OFF) -I$(INCLUDE_DIR)
|
||||||
LIBS=-lSDL2
|
LIBS=-lSDL2
|
||||||
|
|
||||||
_HEADERS = engine.h geometry.h loader.h platform.h point.h transform.h util.h
|
_HEADERS = color.h engine.h geometry.h loader.h platform.h point.h transform.h util.h
|
||||||
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
|
HEADERS = $(patsubst %,$(INCLUDE_DIR)/%,$(_HEADERS))
|
||||||
|
|
||||||
_OBJS = engine.o loader.o main.o platform.o transform.o
|
_OBJS = engine.o geometry.o loader.o main.o platform.o transform.o
|
||||||
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS))
|
OBJS = $(patsubst %,$(BUILD_DIR)/%,$(_OBJS))
|
||||||
|
|
||||||
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.cpp $(HEADERS)
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef COLOR_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
|
struct ColorU32
|
||||||
|
{
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t b;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t a;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t u32;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define COLOR_H
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#ifndef GEOMETRY_H
|
#ifndef GEOMETRY_H
|
||||||
|
|
||||||
#include "point.h"
|
#include "point.h"
|
||||||
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
// STRUCTURES
|
||||||
struct Face
|
struct Face
|
||||||
{
|
{
|
||||||
unsigned int vertIndex[3];
|
unsigned int vertIndex[3];
|
||||||
|
@ -33,6 +35,14 @@ struct Mesh
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
void FillTriangle(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2);
|
||||||
|
|
||||||
|
|
||||||
#define GEOMETRY_H
|
#define GEOMETRY_H
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "color.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
#include "geometry.h"
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "matrix.h"
|
#include "matrix.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
|
@ -73,6 +75,14 @@ void Engine_Render(Engine_Buffer &buffer, uint32_t input)
|
||||||
unsigned int v0 = mesh.faces[f].vertIndex[0];
|
unsigned int v0 = mesh.faces[f].vertIndex[0];
|
||||||
unsigned int v1 = mesh.faces[f].vertIndex[1];
|
unsigned int v1 = mesh.faces[f].vertIndex[1];
|
||||||
unsigned int v2 = mesh.faces[f].vertIndex[2];
|
unsigned int v2 = mesh.faces[f].vertIndex[2];
|
||||||
|
|
||||||
|
ColorU32 white = {0xff,0xff,0xff,0xff};
|
||||||
|
|
||||||
|
FillTriangle(
|
||||||
|
buffer.pixels, buffer.width, white.u32,
|
||||||
|
mesh.vertsTransformed[v0].x, mesh.vertsTransformed[v0].y,
|
||||||
|
mesh.vertsTransformed[v1].x, mesh.vertsTransformed[v1].y,
|
||||||
|
mesh.vertsTransformed[v2].x, mesh.vertsTransformed[v2].y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include "color.h"
|
||||||
|
#include "geometry.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
|
||||||
|
// MACROS
|
||||||
|
#define DrawPixel(buffer, width, color, x, y)\
|
||||||
|
{\
|
||||||
|
buffer[width * y + x] = color;\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PRIVATE PROTOTYPES
|
||||||
|
static void FillTriangleFlatBottom(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2);
|
||||||
|
|
||||||
|
static void FillTriangleFlatTop(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2);
|
||||||
|
|
||||||
|
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
void FillTriangle(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2)
|
||||||
|
{
|
||||||
|
// Horizontal or vertical
|
||||||
|
if ((FLOAT_EQUAL(x0,x1) && FLOAT_EQUAL(x1, x2))
|
||||||
|
|| (FLOAT_EQUAL(y0, y1) && FLOAT_EQUAL(y1, y2)))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort in ascending Y order
|
||||||
|
float temp;
|
||||||
|
if (y0 > y1)
|
||||||
|
{
|
||||||
|
SWAP(x0, x1, temp);
|
||||||
|
SWAP(y0, y1, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y0 > y2)
|
||||||
|
{
|
||||||
|
SWAP(x0, x2, temp);
|
||||||
|
SWAP(y0, y2, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 > y2)
|
||||||
|
{
|
||||||
|
SWAP(x1, x2, temp);
|
||||||
|
SWAP(y1, y2, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Flat top triangle
|
||||||
|
if (FLOAT_EQUAL(y0, y1))
|
||||||
|
{
|
||||||
|
FillTriangleFlatTop(buffer, width, color, x0, y0, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flat bottom triangle
|
||||||
|
else if (FLOAT_EQUAL(y1, y2))
|
||||||
|
{
|
||||||
|
FillTriangleFlatBottom(buffer, width, color, x0, y0, x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other - decompose into two triangles
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Calculate x coordinate at point of decomposition using intercept theorem
|
||||||
|
// New y is the same as y1
|
||||||
|
float x3 = x0 + (((y1 - y0) / (y2 - y0)) * (x2 - x0));
|
||||||
|
float y3 = y1;
|
||||||
|
|
||||||
|
FillTriangleFlatBottom(buffer, width, color, x0, y0, x1, y1, x3, y3);
|
||||||
|
FillTriangleFlatTop(buffer, width, color, x1, y1, x3, y3, x2, y2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// PRIVATE FUNCTIONS
|
||||||
|
static void FillTriangleFlatBottom(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2)
|
||||||
|
{
|
||||||
|
if (x2 < x1)
|
||||||
|
{
|
||||||
|
float temp;
|
||||||
|
SWAP(x1, x2, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Top-left fill convention
|
||||||
|
float dxdy_left = (x1 - x0) / (y1 - y0);
|
||||||
|
float dxdy_right = (x2 - x0) / (y2 - y0);
|
||||||
|
int yStart = (int)ceilf(y0);
|
||||||
|
int yEnd = (int)ceilf(y2) - 1;
|
||||||
|
float xStart = x0 + dxdy_left * (yStart - y0);
|
||||||
|
float xEnd = x0 + dxdy_right * (yStart - y0);
|
||||||
|
|
||||||
|
|
||||||
|
// Fill
|
||||||
|
for (int y = yStart; y <= yEnd; ++y)
|
||||||
|
{
|
||||||
|
int xStartInt = (int)xStart;
|
||||||
|
int xEndInt = (int)xEnd;
|
||||||
|
|
||||||
|
for (int x = xStartInt; x <= xEndInt; ++x)
|
||||||
|
{
|
||||||
|
DrawPixel(buffer, width, color, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
xStart += dxdy_left;
|
||||||
|
xEnd += dxdy_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FillTriangleFlatTop(
|
||||||
|
uint32_t *buffer, int width, uint32_t color,
|
||||||
|
float x0, float y0,
|
||||||
|
float x1, float y1,
|
||||||
|
float x2, float y2)
|
||||||
|
{
|
||||||
|
if (x1 < x0)
|
||||||
|
{
|
||||||
|
float temp;
|
||||||
|
SWAP(x1, x0, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Top-left fill convention
|
||||||
|
float dxdy_left = (x2 - x0) / (y2 - y0);
|
||||||
|
float dxdy_right = (x2 - x1) / (y2 - y1);
|
||||||
|
int yStart = (int)ceilf(y0);
|
||||||
|
int yEnd = (int)ceilf(y2) - 1;
|
||||||
|
float xStart = x0 + dxdy_left * (yStart - y0);
|
||||||
|
float xEnd = x1 + dxdy_right * (yStart - y0);
|
||||||
|
|
||||||
|
|
||||||
|
// Fill
|
||||||
|
for (int y = yStart; y <= yEnd; ++y)
|
||||||
|
{
|
||||||
|
int xStartInt = (int)xStart;
|
||||||
|
int xEndInt = (int)xEnd;
|
||||||
|
|
||||||
|
for (int x = xStartInt; x <= xEndInt; ++x)
|
||||||
|
{
|
||||||
|
DrawPixel(buffer, width, color, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
xStart += dxdy_left;
|
||||||
|
xEnd += dxdy_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue