Skip to content

Instantly share code, notes, and snippets.

@aolo2
Created May 20, 2019 12:15
Show Gist options
  • Select an option

  • Save aolo2/1e2fffec52f677c5ea420ca982f20e3b to your computer and use it in GitHub Desktop.

Select an option

Save aolo2/1e2fffec52f677c5ea420ca982f20e3b to your computer and use it in GitHub Desktop.
static s32
orient_2d(s32 ax, s32 ay, s32 bx, s32 by, s32 x, s32 y)
{
return(bx - ax) * (y - ay) - (by - ay) * (x - ax);
}
static void
fill_triangle(struct framebuffer *fb,
s32 v0x, s32 v0y, s32 v1x, s32 v1y, s32 v2x, s32 v2y)
{
// NOTE: ensure CCW orientation
s32 sarea = (v0x * v1y - v1x * v0y
+ v1x * v2y - v2x * v1y
+ v2x * v0y - v0x * v2y);
if (sarea < 0) {
SWAP(v2x, v1x);
SWAP(v2y, v1y);
}
// NOTE: compute the AABB
s32 min_x = MIN(v0x, MIN(v1x, v2x));
s32 min_y = MIN(v0y, MIN(v1y, v2y));
s32 max_x = MAX(v0x, MAX(v1x, v2x));
s32 max_y = MAX(v0y, MAX(v1y, v2y));
// NOTE: clip against screen bounds
min_x = MAX(min_x, 0);
min_y = MAX(min_y, 0);
max_x = MIN(max_x, fb->width - 1);
max_y = MIN(max_y, fb->height - 1);
u32 *base;
for (s32 y = min_y; y <= max_y; ++y) {
base = (u32 *) fb->pixels + y * fb->width + min_x;
for (s32 x = min_x; x <= max_x; ++x) {
s32 w0 = orient_2d(v1x, v1y, v2x, v2y, x, y);
s32 w1 = orient_2d(v2x, v2y, v0x, v0y, x, y);
s32 w2 = orient_2d(v0x, v0y, v1x, v1y, x, y);
if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
*base = 0xFFFFFFFF;
}
++base;
}
}
}
static void
bresenham_plot_high(struct framebuffer *fb,
s32 x0, s32 y0, s32 x1, s32 y1)
{
u32 *base = (u32 *) fb->pixels + y0 * fb->width + x0;
s32 dx = x1 - x0;
s32 dy = y1 - y0;
s32 xi = 1;
if (dx < 0) {
xi = -1;
dx = -dx;
}
s32 D = 2 * dx - dy;
s32 x = x0;
for (s32 y = y0; y <= y1; ++y) {
*base = 0xFFFFFFFF;
if (D > 0) {
x += xi;
base += xi;
D -= 2 * dy;
}
D += 2 * dx;
base += fb->width;
}
}
static void
bresenham_plot_low(struct framebuffer *fb,
s32 x0, s32 y0, s32 x1, s32 y1)
{
u32 *base = (u32 *) fb->pixels + y0 * fb->width + x0;
s32 dx = x1 - x0;
s32 dy = y1 - y0;
s32 yi = 1;
if (dy < 0) {
yi = -1;
dy = -dy;
}
s32 D = 2 * dy - dx;
s32 y = y0;
for (s32 x = x0; x <= x1; ++x) {
*base = 0xFFFFFFFF;
if (D > 0) {
y += yi;
base += fb->width * yi;
D -= 2 * dx;
}
D += 2 * dy;
++base;
}
}
static void
bresenham_line(struct framebuffer *fb,
s32 x0, s32 y0, s32 x1, s32 y1)
{
if (abs(y1 - y0) < abs(x1 - x0)) {
if (x0 > x1) {
bresenham_plot_low(fb, x1, y1, x0, y0);
} else {
bresenham_plot_low(fb, x0, y0, x1, y1);
}
} else {
if (y0 > y1) {
bresenham_plot_high(fb, x1, y1, x0, y0);
} else {
bresenham_plot_high(fb, x0, y0, x1, y1);
}
}
}
static void
bresenham_circle_symmetric_draw(struct framebuffer *fb,
s32 cx, s32 cy, s32 x, s32 y)
{
u32 *base = fb->pixels;
base[(cy + y) * fb->width + cx + x] = 0xFFFFFFFF;
base[(cy + y) * fb->width + cx - x] = 0xFFFFFFFF;
base[(cy - y) * fb->width + cx + x] = 0xFFFFFFFF;
base[(cy - y) * fb->width + cx - x] = 0xFFFFFFFF;
base[(cy + x) * fb->width + cx + y] = 0xFFFFFFFF;
base[(cy + x) * fb->width + cx - y] = 0xFFFFFFFF;
base[(cy - x) * fb->width + cx + y] = 0xFFFFFFFF;
base[(cy - x) * fb->width + cx - y] = 0xFFFFFFFF;
}
static void
bresenham_circle(struct framebuffer *fb,
s32 cx, s32 cy, s32 r)
{
s32 x = 0;
s32 y = r;
s32 D = 3 - 2 * r;
bresenham_circle_symmetric_draw(fb, cx, cy, x, y);
while (y >= x) {
++x;
if (D > 0) {
--y;
D += ((x - y) << 2) + 10;
} else {
D += (x << 2) + 6;
}
bresenham_circle_symmetric_draw(fb, cx, cy, x, y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment