Fix checking barycentric coordinates

This commit is contained in:
Abdelrahman Said 2024-08-10 17:38:13 +01:00
parent b111058f31
commit 1ad2ca1a47
3 changed files with 37 additions and 14 deletions

View File

@ -28,6 +28,7 @@ u8 *_get_pixel(Buffer *buffer, u64 x, u64 y, u64 base_size) {
void _set_pixel(Buffer *buffer, u64 x, u64 y, void *value, u64 base_size) {
u64 idx = calculate_pixel_index(buffer, x, y, base_size);
memcpy(((u8 *)(buffer->buf)) + idx, value, base_size);
return;
}
void _clear_buffer(Buffer *buffer, void *value, u64 base_size) {

View File

@ -7,6 +7,9 @@
#include <string.h>
#include <time.h>
#define SIZE 1200
#define RESOURCE(NAME) "resources/" NAME
enum {
TINY_EXIT_SUCCESS,
TINY_EXIT_ARENA_INIT_FAILED,
@ -27,12 +30,12 @@ int main(void) {
Colour teal = {.r = 14, .g = 156, .b = 208, .a = 255};
Colour orange = {.r = 242, .g = 100, .b = 48, .a = 255};
Render render;
if (!init_render(arena, &render, 1200, 1200)) {
if (!init_render(arena, &render, SIZE, SIZE)) {
return TINY_EXIT_RENDER_INIT_FAILED;
}
Model model =
load_obj_file(arena, "resources/head.obj", "resources/head.pnm");
load_obj_file(arena, RESOURCE("head.obj"), RESOURCE("head.pnm"));
if (INVALID_MODEL(model)) {
return TINY_EXIT_MODEL_LOAD_FAILED;
}

View File

@ -49,6 +49,12 @@ struct i64x2 {
i64 y;
};
typedef struct u64x2 V2u;
struct u64x2 {
u64 x;
u64 y;
};
typedef struct f32x3 V3f;
struct f32x3 {
f32 x;
@ -75,6 +81,8 @@ internal void render_triangle(const Triangle *triangle, const Model *model,
internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
TexCoord coordinates[TRIANGLE_VERTICES],
Colour colour, f32 intensity, Image *texture);
internal void reorder_points(V2u vertices[TRIANGLE_VERTICES],
TexCoord coordinates[TRIANGLE_VERTICES]);
internal TriangleBBox get_triangle_bbox(const Image *img,
Vertex vertices[TRIANGLE_VERTICES]);
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
@ -162,7 +170,7 @@ bool init_render(Arena *arena, Render *render, u64 width, u64 height) {
return false;
}
f32 inf = -1.0f * INFINITY;
f32 inf = -INFINITY;
clear_buffer(&(render->depth), &inf);
return true;
@ -239,17 +247,17 @@ internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
Depth *depth = &(render->depth);
TriangleBBox bbox = get_triangle_bbox(img, vertices);
u64 v0x, v0y, v1x, v1y, v2x, v2y;
get_image_coordinates(vertices[0].x, vertices[0].y, img, &v0x, &v0y);
get_image_coordinates(vertices[1].x, vertices[1].y, img, &v1x, &v1y);
get_image_coordinates(vertices[2].x, vertices[2].y, img, &v2x, &v2y);
V2u v0, v1, v2;
get_image_coordinates(vertices[0].x, vertices[0].y, img, &(v0.x), &(v0.y));
get_image_coordinates(vertices[1].x, vertices[1].y, img, &(v1.x), &(v1.y));
get_image_coordinates(vertices[2].x, vertices[2].y, img, &(v2.x), &(v2.y));
V2i ab = V2(V2i, i64, v0x, v0y, v1x, v1y);
V2i ac = V2(V2i, i64, v0x, v0y, v2x, v2y);
V2i ab = V2(V2i, i64, v0.x, v0.y, v1.x, v1.y);
V2i ac = V2(V2i, i64, v0.x, v0.y, v2.x, v2.y);
f32 d00 = dot_v2(ab, ab);
f32 d01 = dot_v2(ab, ac);
f32 d11 = dot_v2(ac, ac);
f32 denom = (f32)d00 * (f32)d11 - (f32)d01 * (f32)d01;
f32 denom = d00 * d11 - d01 * d01;
V2i ap;
V3f coords;
f32 z;
@ -263,11 +271,11 @@ internal void fill_triangle(Render *render, Vertex vertices[TRIANGLE_VERTICES],
colour.b *= intensity;
}
for (u64 y = bbox.y0; y < bbox.y1; ++y) {
for (u64 x = bbox.x0; x < bbox.x1; ++x) {
ap = V2(V2i, i64, v0x, v0y, x, y);
for (u64 y = bbox.y0; y <= bbox.y1; ++y) {
for (u64 x = bbox.x0; x <= bbox.x1; ++x) {
ap = V2(V2i, i64, v0.x, v0.y, x, y);
coords = get_barycentric_coords(d00, d01, d11, denom, &ab, &ac, &ap);
if (coords.x < 0.0f || coords.y < 0.0f || coords.z < 0.0f) {
if (coords.x < 0.0f || coords.y < 0.0f || coords.x + coords.y > 1.0f) {
continue;
}
@ -317,6 +325,10 @@ internal TriangleBBox get_triangle_bbox(const Image *img,
internal V3f get_barycentric_coords(f32 d00, f32 d01, f32 d11, f32 denom,
const V2i *ab, const V2i *ac,
const V2i *ap) {
if (denom == 0.0f) {
return (V3f){-INFINITY, -INFINITY, -INFINITY};
}
f32 d20 = dot_v2((*ap), (*ab));
f32 d21 = dot_v2((*ap), (*ac));
@ -331,6 +343,13 @@ internal void get_image_coordinates(f32 norm_x, f32 norm_y, const Image *img,
u64 *x, u64 *y) {
*x = ndc_to_image_coordinate(norm_x, img->width);
*y = ndc_to_image_coordinate(0.0f - norm_y, img->height);
if (*x >= img->width) {
*x = img->width - 1;
}
if (*y >= img->height) {
*y = img->height - 1;
}
}
internal u64 ndc_to_image_coordinate(f32 value, u64 max) {