feat: add stroke thickness
This commit is contained in:
@@ -4,86 +4,86 @@
|
||||
inline M33 m33_zero(void) { return (M33){{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}; }
|
||||
|
||||
inline M33 m33_identity(void) {
|
||||
return (M33){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
|
||||
return (M33){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
|
||||
}
|
||||
|
||||
inline M33 m33_translate(double tx, double ty) {
|
||||
return (M33){{{1, 0, tx}, {0, 1, ty}, {0, 0, 1}}};
|
||||
return (M33){{{1, 0, tx}, {0, 1, ty}, {0, 0, 1}}};
|
||||
}
|
||||
|
||||
inline M33 m33_scale(double sx, double sy) {
|
||||
return (M33){{{sx, 0, 0}, {0, sy, 0}, {0, 0, 1}}};
|
||||
return (M33){{{sx, 0, 0}, {0, sy, 0}, {0, 0, 1}}};
|
||||
}
|
||||
|
||||
inline M33 m33_rotate(double theta) {
|
||||
return (M33){
|
||||
{{cos(theta), -sin(theta), 0}, {sin(theta), cos(theta), 0}, {0, 0, 1}}};
|
||||
return (M33){
|
||||
{{cos(theta), -sin(theta), 0}, {sin(theta), cos(theta), 0}, {0, 0, 1}}};
|
||||
}
|
||||
|
||||
inline M33 m33_shear(double theta_x, double theta_y) {
|
||||
return (M33){{{1, tan(theta_x), 0}, {tan(theta_y), 1, 0}, {0, 0, 0}}};
|
||||
return (M33){{{1, tan(theta_x), 0}, {tan(theta_y), 1, 0}, {0, 0, 0}}};
|
||||
}
|
||||
|
||||
M33 m33_add(const M33 m1, const M33 m2) {
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m1.m[i][j] + m2.m[i][j];
|
||||
return res;
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m1.m[i][j] + m2.m[i][j];
|
||||
return res;
|
||||
}
|
||||
|
||||
M33 m33_sub(const M33 m1, const M33 m2) {
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m1.m[i][j] - m2.m[i][j];
|
||||
return res;
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m1.m[i][j] - m2.m[i][j];
|
||||
return res;
|
||||
}
|
||||
|
||||
M33 m33_mul(const M33 m1, const M33 m2) {
|
||||
M33 res = {{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}};
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
for (int k = 0; k < 3; ++k)
|
||||
res.m[i][j] += m1.m[i][k] * m2.m[k][j];
|
||||
return res;
|
||||
M33 res = {{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}};
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
for (int k = 0; k < 3; ++k)
|
||||
res.m[i][j] += m1.m[i][k] * m2.m[k][j];
|
||||
return res;
|
||||
}
|
||||
|
||||
M33 m33_transpose(const M33 m) {
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m.m[j][i];
|
||||
return res;
|
||||
M33 res;
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int j = 0; j < 3; ++j)
|
||||
res.m[i][j] = m.m[j][i];
|
||||
return res;
|
||||
}
|
||||
|
||||
// 2D affine transform inversion (not general 3x3 inversion)
|
||||
M33 m33_inverse(const M33 m) {
|
||||
M33 inv;
|
||||
double det;
|
||||
M33 inv;
|
||||
double det;
|
||||
|
||||
det = m.m[0][0] * m.m[1][1] - m.m[0][1] * m.m[1][0];
|
||||
if (det == 0.0) {
|
||||
return m33_identity();
|
||||
}
|
||||
double invDet = 1.0 / det;
|
||||
det = m.m[0][0] * m.m[1][1] - m.m[0][1] * m.m[1][0];
|
||||
if (det == 0.0) {
|
||||
return m33_identity();
|
||||
}
|
||||
double invDet = 1.0 / det;
|
||||
|
||||
inv.m[0][0] = m.m[1][1] * invDet;
|
||||
inv.m[0][1] = -m.m[0][1] * invDet;
|
||||
inv.m[1][0] = -m.m[1][0] * invDet;
|
||||
inv.m[1][1] = m.m[0][0] * invDet;
|
||||
inv.m[0][0] = m.m[1][1] * invDet;
|
||||
inv.m[0][1] = -m.m[0][1] * invDet;
|
||||
inv.m[1][0] = -m.m[1][0] * invDet;
|
||||
inv.m[1][1] = m.m[0][0] * invDet;
|
||||
|
||||
inv.m[0][2] = -(inv.m[0][0] * m.m[0][2] + inv.m[0][1] * m.m[1][2]);
|
||||
inv.m[1][2] = -(inv.m[1][0] * m.m[0][2] + inv.m[1][1] * m.m[1][2]);
|
||||
inv.m[0][2] = -(inv.m[0][0] * m.m[0][2] + inv.m[0][1] * m.m[1][2]);
|
||||
inv.m[1][2] = -(inv.m[1][0] * m.m[0][2] + inv.m[1][1] * m.m[1][2]);
|
||||
|
||||
inv.m[2][0] = 0;
|
||||
inv.m[2][1] = 0;
|
||||
inv.m[2][2] = 1;
|
||||
inv.m[2][0] = 0;
|
||||
inv.m[2][1] = 0;
|
||||
inv.m[2][2] = 1;
|
||||
|
||||
return inv;
|
||||
return inv;
|
||||
}
|
||||
|
||||
V2 m33_transform(const M33 mat, const V2 v) {
|
||||
return (V2){mat.m[0][0] * v.x + mat.m[0][1] * v.y + mat.m[0][2],
|
||||
mat.m[1][0] * v.x + mat.m[1][1] * v.y + mat.m[1][2]};
|
||||
return (V2){mat.m[0][0] * v.x + mat.m[0][1] * v.y + mat.m[0][2],
|
||||
mat.m[1][0] * v.x + mat.m[1][1] * v.y + mat.m[1][2]};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
// Row major 3x3 matricies
|
||||
typedef struct {
|
||||
double m[3][3];
|
||||
double m[3][3];
|
||||
} M33;
|
||||
|
||||
M33 m33_identity(void);
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
#include "primitives.h"
|
||||
|
||||
VektorPolyline *vektor_polyline_new(void) {
|
||||
VektorPolyline *pl = malloc(sizeof(VektorPolyline));
|
||||
pl->count = 0;
|
||||
pl->capacity = 4;
|
||||
pl->points = malloc(sizeof(V2) * pl->capacity);
|
||||
return pl;
|
||||
VektorPolyline *pl = malloc(sizeof(VektorPolyline));
|
||||
pl->count = 0;
|
||||
pl->capacity = 4;
|
||||
pl->points = malloc(sizeof(V2) * pl->capacity);
|
||||
return pl;
|
||||
}
|
||||
|
||||
void vektor_polyline_add_point(VektorPolyline *pl, V2 point) {
|
||||
if (pl->count >= pl->capacity) {
|
||||
pl->capacity *= 2;
|
||||
pl->points = realloc(pl->points, sizeof(V2) * pl->capacity);
|
||||
}
|
||||
pl->points[pl->count++] = point;
|
||||
if (pl->count >= pl->capacity) {
|
||||
pl->capacity *= 2;
|
||||
pl->points = realloc(pl->points, sizeof(V2) * pl->capacity);
|
||||
}
|
||||
pl->points[pl->count++] = point;
|
||||
}
|
||||
|
||||
void vektor_polyline_free(VektorPolyline *pl) {
|
||||
if (!pl)
|
||||
return;
|
||||
free(pl->points);
|
||||
free(pl);
|
||||
if (!pl)
|
||||
return;
|
||||
free(pl->points);
|
||||
free(pl);
|
||||
}
|
||||
|
||||
VektorPolygon *vektor_polygon_new(void) {
|
||||
VektorPolygon *pg = malloc(sizeof(VektorPolygon));
|
||||
pg->count = 0;
|
||||
pg->capacity = 4;
|
||||
pg->points = malloc(sizeof(V2) * pg->capacity);
|
||||
return pg;
|
||||
VektorPolygon *pg = malloc(sizeof(VektorPolygon));
|
||||
pg->count = 0;
|
||||
pg->capacity = 4;
|
||||
pg->points = malloc(sizeof(V2) * pg->capacity);
|
||||
return pg;
|
||||
}
|
||||
|
||||
void vektor_polygon_add_point(VektorPolygon *pg, V2 point) {
|
||||
if (pg->count >= pg->capacity) {
|
||||
pg->capacity *= 2;
|
||||
pg->points = realloc(pg->points, sizeof(V2) * pg->capacity);
|
||||
}
|
||||
pg->points[pg->count++] = point;
|
||||
if (pg->count >= pg->capacity) {
|
||||
pg->capacity *= 2;
|
||||
pg->points = realloc(pg->points, sizeof(V2) * pg->capacity);
|
||||
}
|
||||
pg->points[pg->count++] = point;
|
||||
}
|
||||
|
||||
void vektor_polygon_free(VektorPolygon *pg) {
|
||||
if (!pg)
|
||||
return;
|
||||
free(pg->points);
|
||||
free(pg);
|
||||
if (!pg)
|
||||
return;
|
||||
free(pg->points);
|
||||
free(pg);
|
||||
}
|
||||
|
||||
void vektor_primitivebuffer_add_primitive(VektorPrimitiveBuffer *buffer,
|
||||
VektorPrimitive prim) {
|
||||
if (buffer->count >= buffer->capacity) {
|
||||
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
|
||||
buffer->primitives =
|
||||
realloc(buffer->primitives, sizeof(VektorPrimitive) * buffer->capacity);
|
||||
}
|
||||
buffer->primitives[buffer->count++] = prim;
|
||||
if (buffer->count >= buffer->capacity) {
|
||||
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
|
||||
buffer->primitives = realloc(
|
||||
buffer->primitives, sizeof(VektorPrimitive) * buffer->capacity);
|
||||
}
|
||||
buffer->primitives[buffer->count++] = prim;
|
||||
}
|
||||
|
||||
@@ -6,42 +6,42 @@
|
||||
#include "vector.h"
|
||||
|
||||
typedef struct {
|
||||
V2 p1;
|
||||
V2 p2;
|
||||
V2 p1;
|
||||
V2 p2;
|
||||
} VektorLine;
|
||||
|
||||
typedef struct {
|
||||
V2 *points;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
V2 *points;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} VektorPolyline;
|
||||
|
||||
typedef struct {
|
||||
V2 *points;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
V2 *points;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} VektorPolygon;
|
||||
|
||||
typedef struct {
|
||||
V2 center;
|
||||
double radius;
|
||||
V2 center;
|
||||
double radius;
|
||||
} VektorCircle;
|
||||
|
||||
typedef enum {
|
||||
VEKTOR_LINE,
|
||||
VEKTOR_POLYLINE,
|
||||
VEKTOR_POLYGON,
|
||||
VEKTOR_CIRCLE
|
||||
VEKTOR_LINE,
|
||||
VEKTOR_POLYLINE,
|
||||
VEKTOR_POLYGON,
|
||||
VEKTOR_CIRCLE
|
||||
} VektorPrimitiveKind;
|
||||
|
||||
typedef struct {
|
||||
VektorPrimitiveKind kind;
|
||||
union {
|
||||
VektorLine line;
|
||||
VektorPolyline *polyline;
|
||||
VektorPolygon *polygon;
|
||||
VektorCircle circle;
|
||||
};
|
||||
VektorPrimitiveKind kind;
|
||||
union {
|
||||
VektorLine line;
|
||||
VektorPolyline *polyline;
|
||||
VektorPolygon *polygon;
|
||||
VektorCircle circle;
|
||||
};
|
||||
} VektorPrimitive;
|
||||
|
||||
VektorPolyline *vektor_polyline_new(void);
|
||||
@@ -53,9 +53,9 @@ void vektor_polygon_add_point(VektorPolygon *pl, V2 point);
|
||||
void vektor_polygon_free(VektorPolygon *pl);
|
||||
|
||||
typedef struct {
|
||||
VektorPrimitive *primitives;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
VektorPrimitive *primitives;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} VektorPrimitiveBuffer;
|
||||
|
||||
void vektor_primitivebuffer_add_primitive(VektorPrimitiveBuffer *edges,
|
||||
|
||||
@@ -4,112 +4,123 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void vektor_edgebuffer_add_edge(EdgeBuffer *buffer, Edge edge) {
|
||||
if (buffer->count >= buffer->capacity) {
|
||||
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
|
||||
buffer->edges = realloc(buffer->edges, sizeof(Edge) * buffer->capacity);
|
||||
}
|
||||
buffer->edges[buffer->count++] = edge;
|
||||
if (buffer->count >= buffer->capacity) {
|
||||
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
|
||||
buffer->edges = realloc(buffer->edges, sizeof(Edge) * buffer->capacity);
|
||||
}
|
||||
buffer->edges[buffer->count++] = edge;
|
||||
}
|
||||
|
||||
void vektor_line_flatten(EdgeBuffer *buffer, VektorLine line) {
|
||||
vektor_edgebuffer_add_edge(buffer, (Edge){line.p1, line.p2, 0});
|
||||
vektor_edgebuffer_add_edge(buffer, (Edge){line.p1, line.p2, 0});
|
||||
}
|
||||
|
||||
void vektor_polyline_flatten(EdgeBuffer *buffer, VektorPolyline *line) {
|
||||
for (size_t i = 0; i + 1 < line->count; i++) {
|
||||
vektor_edgebuffer_add_edge(buffer,
|
||||
(Edge){line->points[i], line->points[i + 1], 0});
|
||||
}
|
||||
for (size_t i = 0; i + 1 < line->count; i++) {
|
||||
vektor_edgebuffer_add_edge(
|
||||
buffer, (Edge){line->points[i], line->points[i + 1], 0});
|
||||
}
|
||||
}
|
||||
|
||||
void vektor_polygon_flatten(EdgeBuffer *buffer, VektorPolygon *pg) {
|
||||
size_t n = pg->count;
|
||||
if (n < 3)
|
||||
return;
|
||||
size_t n = pg->count;
|
||||
if (n < 3)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
V2 p1 = pg->points[i];
|
||||
V2 p2 = pg->points[(i + 1) % n];
|
||||
int winding = (p1.y < p2.y) ? +1 : -1;
|
||||
vektor_edgebuffer_add_edge(buffer, (Edge){p1, p2, winding});
|
||||
}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
V2 p1 = pg->points[i];
|
||||
V2 p2 = pg->points[(i + 1) % n];
|
||||
int winding = (p1.y < p2.y) ? +1 : -1;
|
||||
vektor_edgebuffer_add_edge(buffer, (Edge){p1, p2, winding});
|
||||
}
|
||||
}
|
||||
|
||||
inline VektorFramebuffer vektor_framebuffer_new(unsigned int W,
|
||||
unsigned int H) {
|
||||
VektorFramebuffer fb = {
|
||||
.width = W, .height = H, .pixels = calloc(W * H * 4, 1)};
|
||||
return fb;
|
||||
VektorFramebuffer fb = {
|
||||
.width = W, .height = H, .pixels = calloc(W * H * 4, 1)};
|
||||
return fb;
|
||||
}
|
||||
|
||||
inline void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y,
|
||||
VektorColor color) {
|
||||
if ((unsigned)x >= fb->width || (unsigned)y >= fb->height)
|
||||
return;
|
||||
if ((unsigned)x >= fb->width || (unsigned)y >= fb->height)
|
||||
return;
|
||||
|
||||
int i = (y * fb->width + x) * 4;
|
||||
fb->pixels[i + 0] = color.r;
|
||||
fb->pixels[i + 1] = color.g;
|
||||
fb->pixels[i + 2] = color.b;
|
||||
fb->pixels[i + 3] = color.a;
|
||||
int i = (y * fb->width + x) * 4;
|
||||
fb->pixels[i + 0] = color.r;
|
||||
fb->pixels[i + 1] = color.g;
|
||||
fb->pixels[i + 2] = color.b;
|
||||
fb->pixels[i + 3] = color.a;
|
||||
}
|
||||
|
||||
void draw_filled_circle(VektorFramebuffer *fb, int cx, int cy, int r,
|
||||
VektorColor color) {
|
||||
for (int y = -r; y <= r; y++) {
|
||||
int dx = (int)sqrt(r * r - y * y);
|
||||
for (int x = -dx; x <= dx; x++) {
|
||||
vektor_framebuffer_putpixel(fb, cx + x, cy + y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b,
|
||||
VektorColor color) {
|
||||
int x0 = (int)a.x;
|
||||
int y0 = (int)a.y;
|
||||
int x1 = (int)b.x;
|
||||
int y1 = (int)b.y;
|
||||
VektorColor color, double thickness) {
|
||||
int x0 = (int)a.x;
|
||||
int y0 = (int)a.y;
|
||||
int x1 = (int)b.x;
|
||||
int y1 = (int)b.y;
|
||||
|
||||
int dx = abs(x1 - x0);
|
||||
int sx = x0 < x1 ? 1 : -1;
|
||||
int dy = -abs(y1 - y0);
|
||||
int sy = y0 < y1 ? 1 : -1;
|
||||
int err = dx + dy;
|
||||
int dx = abs(x1 - x0);
|
||||
int sx = x0 < x1 ? 1 : -1;
|
||||
int dy = -abs(y1 - y0);
|
||||
int sy = y0 < y1 ? 1 : -1;
|
||||
int err = dx + dy;
|
||||
|
||||
for (;;) {
|
||||
vektor_framebuffer_putpixel(fb, x0, y0, color);
|
||||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
for (;;) {
|
||||
draw_filled_circle(fb, x0, y0, thickness / 2, color);
|
||||
if (x0 == x1 && y0 == y1)
|
||||
break;
|
||||
|
||||
int e2 = 2 * err;
|
||||
if (e2 >= dy) {
|
||||
err += dy;
|
||||
x0 += sx;
|
||||
int e2 = 2 * err;
|
||||
if (e2 >= dy) {
|
||||
err += dy;
|
||||
x0 += sx;
|
||||
}
|
||||
if (e2 <= dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
if (e2 <= dx) {
|
||||
err += dx;
|
||||
y0 += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void vektor_framebuffer_rasterize(VektorFramebuffer *fb, VektorPrimitiveBuffer *prims) {
|
||||
EdgeBuffer edges = {0};
|
||||
for (size_t i = 0; i < prims->count; i++) {
|
||||
VektorPrimitive *p = &prims->primitives[i];
|
||||
void vektor_framebuffer_rasterize(VektorFramebuffer *fb,
|
||||
VektorPrimitiveBuffer *prims) {
|
||||
EdgeBuffer edges = {0};
|
||||
for (size_t i = 0; i < prims->count; i++) {
|
||||
VektorPrimitive *p = &prims->primitives[i];
|
||||
|
||||
switch (p->kind) {
|
||||
case VEKTOR_LINE:
|
||||
vektor_line_flatten(&edges, p->line);
|
||||
break;
|
||||
switch (p->kind) {
|
||||
case VEKTOR_LINE:
|
||||
vektor_line_flatten(&edges, p->line);
|
||||
break;
|
||||
|
||||
case VEKTOR_POLYLINE:
|
||||
vektor_polyline_flatten(&edges, p->polyline);
|
||||
break;
|
||||
case VEKTOR_POLYLINE:
|
||||
vektor_polyline_flatten(&edges, p->polyline);
|
||||
break;
|
||||
|
||||
case VEKTOR_POLYGON:
|
||||
vektor_polygon_flatten(&edges, p->polygon);
|
||||
break;
|
||||
case VEKTOR_POLYGON:
|
||||
vektor_polygon_flatten(&edges, p->polygon);
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO fill in all primitives
|
||||
break;
|
||||
default:
|
||||
// TODO fill in all primitives
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < edges.count; i++) {
|
||||
vektor_framebuffer_drawline(fb, edges.edges[i].p1, edges.edges[i].p2,
|
||||
vektor_color_solid(255, 0, 255));
|
||||
}
|
||||
for (size_t i = 0; i < edges.count; i++) {
|
||||
vektor_framebuffer_drawline(fb, edges.edges[i].p1, edges.edges[i].p2,
|
||||
vektor_color_solid(255, 0, 255), 4);
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,15 @@
|
||||
#include "vector.h"
|
||||
|
||||
typedef struct {
|
||||
V2 p1;
|
||||
V2 p2;
|
||||
int winding;
|
||||
V2 p1;
|
||||
V2 p2;
|
||||
int winding;
|
||||
} Edge;
|
||||
|
||||
typedef struct {
|
||||
Edge *edges;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
Edge *edges;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} EdgeBuffer;
|
||||
|
||||
void vektor_edgebuffer_add_edge(EdgeBuffer *edges, Edge edge);
|
||||
@@ -26,9 +26,9 @@ void vektor_polyline_flatten(EdgeBuffer *edges, VektorPolyline *line);
|
||||
void vektor_polygon_flatten(EdgeBuffer *buffer, VektorPolygon *line);
|
||||
|
||||
typedef struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned char *pixels; // Flat RGBA8 array
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned char *pixels; // Flat RGBA8 array
|
||||
} VektorFramebuffer;
|
||||
|
||||
VektorFramebuffer vektor_framebuffer_new(unsigned int width,
|
||||
@@ -38,8 +38,9 @@ void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y,
|
||||
VektorColor color);
|
||||
|
||||
void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b,
|
||||
VektorColor color);
|
||||
VektorColor color, double thickness);
|
||||
|
||||
void vektor_framebuffer_rasterize(VektorFramebuffer *fb, VektorPrimitiveBuffer *primitives);
|
||||
void vektor_framebuffer_rasterize(VektorFramebuffer *fb,
|
||||
VektorPrimitiveBuffer *primitives);
|
||||
|
||||
#endif // RASTER_H_
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
#include "math.h"
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double x;
|
||||
double y;
|
||||
} V2;
|
||||
|
||||
typedef struct {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
} V3;
|
||||
|
||||
static inline V3 vec2_vector(const V2 v) { return (V3){v.x, v.y, 0}; }
|
||||
@@ -19,39 +19,39 @@ static inline V3 vec2_vector(const V2 v) { return (V3){v.x, v.y, 0}; }
|
||||
static inline V3 vec2_point(const V2 v) { return (V3){v.x, v.y, 1}; }
|
||||
|
||||
static inline V2 vec2_add(const V2 v1, const V2 v2) {
|
||||
return (V2){v1.x + v2.x, v1.y + v2.y};
|
||||
return (V2){v1.x + v2.x, v1.y + v2.y};
|
||||
}
|
||||
|
||||
static inline V2 vec2_sub(const V2 v1, const V2 v2) {
|
||||
return (V2){v1.x - v2.x, v1.y - v2.y};
|
||||
return (V2){v1.x - v2.x, v1.y - v2.y};
|
||||
}
|
||||
|
||||
static inline V2 vec2_mul(const V2 v1, const V2 v2) {
|
||||
return (V2){v1.x * v2.x, v1.y * v2.y};
|
||||
return (V2){v1.x * v2.x, v1.y * v2.y};
|
||||
}
|
||||
|
||||
static inline V2 vec2_scale(const V2 v, const double k) {
|
||||
return (V2){v.x * k, v.y * k};
|
||||
return (V2){v.x * k, v.y * k};
|
||||
}
|
||||
|
||||
static inline double vec2_dot(const V2 v1, const V2 v2) {
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
return v1.x * v2.x + v1.y * v2.y;
|
||||
}
|
||||
|
||||
static inline double vec2_cross(const V2 a, const V2 b) {
|
||||
return a.x * b.y - a.y * b.x;
|
||||
return a.x * b.y - a.y * b.x;
|
||||
}
|
||||
|
||||
static inline double vec2_norm(const V2 v) {
|
||||
return sqrt(v.x * v.x + v.y * v.y);
|
||||
return sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
static inline double vec2_quadrance(const V2 v) {
|
||||
return (v.x * v.x + v.y * v.y);
|
||||
return (v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
static inline V2 vec2_normalize(const V2 v) {
|
||||
return vec2_scale(v, 1 / vec2_norm(v));
|
||||
return vec2_scale(v, 1 / vec2_norm(v));
|
||||
}
|
||||
|
||||
#endif // VECTOR_H_
|
||||
|
||||
Reference in New Issue
Block a user