summaryrefslogtreecommitdiff
path: root/Draw/draw.h
diff options
context:
space:
mode:
authorVasco <[email protected]>2026-08-24 03:53:16 +0100
committerVasco <[email protected]>2026-08-24 03:53:16 +0100
commitad5248a3e1bafc1b7dec4c8af82d56ed324ef314 (patch)
treeb575c3b85d6ad314fa9768855bed9aed8642917e /Draw/draw.h
parent5dc2716abd43166cd65133625f408ad36a6623b3 (diff)
Slimed out podium. Updated math. Rend kinda works but still bugged.
Diffstat (limited to 'Draw/draw.h')
-rw-r--r--Draw/draw.h307
1 files changed, 184 insertions, 123 deletions
diff --git a/Draw/draw.h b/Draw/draw.h
index fded875..73b2b3e 100644
--- a/Draw/draw.h
+++ b/Draw/draw.h
@@ -5,178 +5,239 @@
#ifndef DRAW_H
#define DRAW_H
+/* CHANGE LOG
+ * 0.0.0 - @vasco - prototyping
+ */
+
+#include <math.h>
#include <stdint.h>
-#include <string.h>
#include <stdlib.h>
-#include <math.h>
+#include <string.h>
+
+#define DRAW__MIN(a, b) ((a) < (b) ? (a) : (b))
+#define DRAW__MAX(a, b) ((a) > (b) ? (a) : (b))
typedef struct Draw {
- uint32_t *px;
- int w, h;
- int cx, cy, cw, ch;
+ uint32_t *px;
+ int w, h;
+ int cx, cy, cw, ch;
} Draw;
-#define DRAW__MIN(a, b) ((a) < (b) ? (a) : (b))
-#define DRAW__MAX(a, b) ((a) > (b) ? (a) : (b))
+static void draw_begin(Draw *d, uint32_t *px, int w, int h);
+static void draw_clip(Draw *d, int x, int y, int w, int h);
+static void draw_clip_reset(Draw *d);
+static void draw_pixel(Draw *d, int x, int y, uint32_t color);
+static uint32_t draw__lerp(uint32_t c0, uint32_t c1, float t);
+static float draw__cross(float ax, float ay, float bx, float by, float cx, float cy);
+static void draw_blit(Draw *d, int x, int y, const uint32_t *src, int sw, int sh);
+static void draw_rect(Draw *d, int x, int y, int w, int h, uint32_t color);
+static void draw_rect_gradient(Draw *d, int x, int y, int w, int h, uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3);
+static void draw_tri(Draw *d, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t c0, uint32_t c1, uint32_t c2);
+static void draw_line(Draw *d, int x0, int y0, int x1, int y1, int width, uint32_t c0, uint32_t c1);
-static inline void
+void
draw_begin(Draw *d, uint32_t *px, int w, int h)
{
- d->px = px;
- d->w = w;
- d->h = h;
- d->cx = 0;
- d->cy = 0;
- d->cw = w;
- d->ch = h;
+ d->px = px;
+ d->w = w;
+ d->h = h;
+ d->cx = 0;
+ d->cy = 0;
+ d->cw = w;
+ d->ch = h;
}
-static inline void
+void
draw_clip(Draw *d, int x, int y, int w, int h)
{
- d->cx = x;
- d->cy = y;
- d->cw = w;
- d->ch = h;
+ d->cx = x;
+ d->cy = y;
+ d->cw = w;
+ d->ch = h;
}
-static inline void
+void
draw_clip_reset(Draw *d)
{
- d->cx = 0;
- d->cy = 0;
- d->cw = d->w;
- d->ch = d->h;
+ d->cx = 0;
+ d->cy = 0;
+ d->cw = d->w;
+ d->ch = d->h;
}
-static inline void
+void
draw_pixel(Draw *d, int x, int y, uint32_t color)
{
- if (x < d->cx || x >= d->cx + d->cw || y < d->cy || y >= d->cy + d->ch) return;
- if (x < 0 || x >= d->w || y < 0 || y >= d->h) return;
- d->px[y * d->w + x] = color;
+ if (x < d->cx || x >= d->cx + d->cw || y < d->cy || y >= d->cy + d->ch)
+ return;
+ if (x < 0 || x >= d->w || y < 0 || y >= d->h)
+ return;
+ d->px[y * d->w + x] = color;
}
-static inline uint32_t
+uint32_t
draw__lerp(uint32_t c0, uint32_t c1, float t)
{
- if (t <= 0.0f) return c0;
- if (t >= 1.0f) return c1;
- uint32_t a0 = (c0 >> 24) & 0xFF, a1 = (c1 >> 24) & 0xFF;
- uint32_t r0 = (c0 >> 16) & 0xFF, r1 = (c1 >> 16) & 0xFF;
- uint32_t g0 = (c0 >> 8) & 0xFF, g1 = (c1 >> 8) & 0xFF;
- uint32_t b0 = c0 & 0xFF, b1 = c1 & 0xFF;
- uint32_t a = (uint32_t)(a0 + t * ((float)a1 - (float)a0));
- uint32_t r = (uint32_t)(r0 + t * ((float)r1 - (float)r0));
- uint32_t g = (uint32_t)(g0 + t * ((float)g1 - (float)g0));
- uint32_t b = (uint32_t)(b0 + t * ((float)b1 - (float)b0));
- return (a << 24) | (r << 16) | (g << 8) | b;
+ uint32_t a0, a1, r0, r1, g0, g1, b0, b1;
+ uint32_t a, r, g, b;
+ if (t <= 0.0f)
+ return c0;
+ if (t >= 1.0f)
+ return c1;
+ a0 = (c0 >> 24) & 0xFF;
+ a1 = (c1 >> 24) & 0xFF;
+ r0 = (c0 >> 16) & 0xFF;
+ r1 = (c1 >> 16) & 0xFF;
+ g0 = (c0 >> 8) & 0xFF;
+ g1 = (c1 >> 8) & 0xFF;
+ b0 = c0 & 0xFF;
+ b1 = c1 & 0xFF;
+ a = (uint32_t)(a0 + t * ((float)a1 - (float)a0));
+ r = (uint32_t)(r0 + t * ((float)r1 - (float)r0));
+ g = (uint32_t)(g0 + t * ((float)g1 - (float)g0));
+ b = (uint32_t)(b0 + t * ((float)b1 - (float)b0));
+ return (a << 24) | (r << 16) | (g << 8) | b;
}
-static inline float
+float
draw__cross(float ax, float ay, float bx, float by, float cx, float cy)
{
- return (cx - ax) * (by - ay) - (cy - ay) * (bx - ax);
+ return (cx - ax) * (by - ay) - (cy - ay) * (bx - ax);
}
-static inline void
+void
draw_blit(Draw *d, int x, int y, const uint32_t *src, int sw, int sh)
{
- for (int row = 0; row < sh; ++row) {
- int ty = y + row;
- if (ty < d->cy || ty >= d->cy + d->ch || ty < 0 || ty >= d->h) continue;
- int x0 = DRAW__MAX(x, d->cx);
- int x1 = DRAW__MIN(x + sw, d->cx + d->cw);
- if (x0 >= x1) continue;
- memcpy(&d->px[ty * d->w + x0], &src[row * sw + (x0 - x)], (size_t)(x1 - x0) * sizeof(uint32_t));
- }
+ int row, ty, x0, x1;
+ for (row = 0; row < sh; ++row) {
+ ty = y + row;
+ if (ty < d->cy || ty >= d->cy + d->ch || ty < 0 || ty >= d->h)
+ continue;
+ x0 = DRAW__MAX(x, d->cx);
+ x1 = DRAW__MIN(x + sw, d->cx + d->cw);
+ if (x0 >= x1)
+ continue;
+ memcpy(&d->px[ty * d->w + x0], &src[row * sw + (x0 - x)], (size_t)(x1 - x0) * sizeof(uint32_t));
+ }
}
-static inline void
+void
draw_rect(Draw *d, int x, int y, int w, int h, uint32_t color)
{
- int x0 = DRAW__MAX(x, d->cx);
- int y0 = DRAW__MAX(y, d->cy);
- int x1 = DRAW__MIN(x + w, d->cx + d->cw);
- int y1 = DRAW__MIN(y + h, d->cy + d->ch);
- for (int py = y0; py < y1; ++py) {
- if (py < 0 || py >= d->h) continue;
- for (int px = x0; px < x1; ++px) {
- if (px < 0 || px >= d->w) continue;
- d->px[py * d->w + px] = color;
- }
- }
+ int x0, y0, x1, y1;
+ int py, px;
+ x0 = DRAW__MAX(x, d->cx);
+ y0 = DRAW__MAX(y, d->cy);
+ x1 = DRAW__MIN(x + w, d->cx + d->cw);
+ y1 = DRAW__MIN(y + h, d->cy + d->ch);
+ for (py = y0; py < y1; ++py) {
+ if (py < 0 || py >= d->h)
+ continue;
+ for (px = x0; px < x1; ++px) {
+ if (px < 0 || px >= d->w)
+ continue;
+ d->px[py * d->w + px] = color;
+ }
+ }
}
-static inline void
+void
draw_rect_gradient(Draw *d, int x, int y, int w, int h, uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3)
{
- for (int ry = 0; ry < h; ++ry) {
- float ty = (h > 1) ? (float)ry / (float)(h - 1) : 0.0f;
- uint32_t left = draw__lerp(c0, c3, ty);
- uint32_t right = draw__lerp(c1, c2, ty);
- for (int rx = 0; rx < w; ++rx) {
- float tx = (w > 1) ? (float)rx / (float)(w - 1) : 0.0f;
- draw_pixel(d, x + rx, y + ry, draw__lerp(left, right, tx));
- }
- }
+ int ry, rx;
+ float ty, tx;
+ uint32_t left, right;
+ for (ry = 0; ry < h; ++ry) {
+ ty = (h > 1) ? (float)ry / (float)(h - 1) : 0.0f;
+ left = draw__lerp(c0, c3, ty);
+ right = draw__lerp(c1, c2, ty);
+ for (rx = 0; rx < w; ++rx) {
+ tx = (w > 1) ? (float)rx / (float)(w - 1) : 0.0f;
+ draw_pixel(d, x + rx, y + ry, draw__lerp(left, right, tx));
+ }
+ }
}
-static inline void
+void
draw_tri(Draw *d, int x0, int y0, int x1, int y1, int x2, int y2, uint32_t c0, uint32_t c1, uint32_t c2)
{
- int min_x = DRAW__MIN(x0, DRAW__MIN(x1, x2));
- int max_x = DRAW__MAX(x0, DRAW__MAX(x1, x2));
- int min_y = DRAW__MIN(y0, DRAW__MIN(y1, y2));
- int max_y = DRAW__MAX(y0, DRAW__MAX(y1, y2));
- float area = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2);
- if (area == 0.0f) return;
- int solid = (c0 == c1 && c1 == c2);
- for (int y = min_y; y <= max_y; ++y) {
- for (int x = min_x; x <= max_x; ++x) {
- float w0 = draw__cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y);
- float w1 = draw__cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y);
- float w2 = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x, (float)y);
- if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0)) {
- uint32_t c = c0;
- if (!solid) {
- w0 /= area;
- w1 /= area;
- w2 /= area;
- c = draw__lerp(c0, c1, w1 / (w0 + w1 + 1e-6f));
- c = draw__lerp(c, c2, w2);
- }
- draw_pixel(d, x, y, c);
- }
- }
- }
+ int min_x, max_x, min_y, max_y;
+ int solid;
+ int x, y;
+ float area;
+ float w0, w1, w2;
+ uint32_t c;
+ min_x = DRAW__MIN(x0, DRAW__MIN(x1, x2));
+ max_x = DRAW__MAX(x0, DRAW__MAX(x1, x2));
+ min_y = DRAW__MIN(y0, DRAW__MIN(y1, y2));
+ max_y = DRAW__MAX(y0, DRAW__MAX(y1, y2));
+ area = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x2, (float)y2);
+ if (area == 0.0f)
+ return;
+ solid = (c0 == c1 && c1 == c2);
+ for (y = min_y; y <= max_y; ++y) {
+ for (x = min_x; x <= max_x; ++x) {
+ w0 = draw__cross((float)x1, (float)y1, (float)x2, (float)y2, (float)x, (float)y);
+ w1 = draw__cross((float)x2, (float)y2, (float)x0, (float)y0, (float)x, (float)y);
+ w2 = draw__cross((float)x0, (float)y0, (float)x1, (float)y1, (float)x, (float)y);
+ if ((w0 >= 0 && w1 >= 0 && w2 >= 0) || (w0 <= 0 && w1 <= 0 && w2 <= 0)) {
+ c = c0;
+ if (!solid) {
+ w0 /= area;
+ w1 /= area;
+ w2 /= area;
+ c = draw__lerp(c0, c1, w1 / (w0 + w1 + 1e-6f));
+ c = draw__lerp(c, c2, w2);
+ }
+ draw_pixel(d, x, y, c);
+ }
+ }
+ }
}
-static inline void
+void
draw_line(Draw *d, int x0, int y0, int x1, int y1, int width, uint32_t c0, uint32_t c1)
{
- float total = 0.0f;
- int grad = (c0 != c1);
- if (grad) total = sqrtf((float)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)));
- int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
- int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
- int err = dx + dy;
- int ox0 = x0, oy0 = y0;
- int hw = width / 2;
- for (;;) {
- uint32_t c = c0;
- if (grad) {
- float cd = sqrtf((float)((x0 - ox0) * (x0 - ox0) + (y0 - oy0) * (y0 - oy0)));
- c = draw__lerp(c0, c1, total > 0.0f ? cd / total : 0.0f);
- }
- for (int ox = -hw; ox <= hw; ++ox)
- for (int oy = -hw; oy <= hw; ++oy)
- draw_pixel(d, x0 + ox, y0 + oy, c);
- if (x0 == x1 && y0 == y1) break;
- int e2 = 2 * err;
- if (e2 >= dy) { err += dy; x0 += sx; }
- if (e2 <= dx) { err += dx; y0 += sy; }
- }
+ float total;
+ int grad;
+ int dx, sx, dy, sy, err;
+ int ox0, oy0, hw;
+ int ox, oy, e2;
+ uint32_t c;
+ total = 0.0f;
+ grad = (c0 != c1);
+ if (grad)
+ total = sqrtf((float)((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)));
+ dx = abs(x1 - x0);
+ sx = x0 < x1 ? 1 : -1;
+ dy = -abs(y1 - y0);
+ sy = y0 < y1 ? 1 : -1;
+ err = dx + dy;
+ ox0 = x0;
+ oy0 = y0;
+ hw = width / 2;
+ for (;;) {
+ c = c0;
+ if (grad) {
+ float cd;
+ cd = sqrtf((float)((x0 - ox0) * (x0 - ox0) + (y0 - oy0) * (y0 - oy0)));
+ c = draw__lerp(c0, c1, total > 0.0f ? cd / total : 0.0f);
+ }
+ for (ox = -hw; ox <= hw; ++ox)
+ for (oy = -hw; oy <= hw; ++oy)
+ draw_pixel(d, x0 + ox, y0 + oy, c);
+ if (x0 == x1 && y0 == y1)
+ break;
+ e2 = 2 * err;
+ if (e2 >= dy) {
+ err += dy;
+ x0 += sx;
+ }
+ if (e2 <= dx) {
+ err += dx;
+ y0 += sy;
+ }
+ }
}
#endif /* DRAW_H */