diff --git a/include/rasteriser/rasteriser.h b/include/rasteriser/rasteriser.h index f294f6a..6735864 100644 --- a/include/rasteriser/rasteriser.h +++ b/include/rasteriser/rasteriser.h @@ -41,7 +41,8 @@ typedef struct { list_scene_triangle_t *triangles; } model_t; #define NULL_MODEL ((model_t){0}) -#define IS_NULL_MODEL(MODEL) (MODEL.vertices == NULL && MODEL.triangles == NULL) +#define IS_NULL_MODEL(MODEL_PTR) \ + (MODEL_PTR->vertices == NULL && MODEL_PTR->triangles == NULL) typedef struct { f32 scale; diff --git a/src/rasteriser/rasteriser.c b/src/rasteriser/rasteriser.c index 4bb08bc..c0fea9f 100644 --- a/src/rasteriser/rasteriser.c +++ b/src/rasteriser/rasteriser.c @@ -16,6 +16,13 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, mat3x4f_t projection_matrix, const instance_t *instance); internal void clip_instance(model_t *model, const rasteriser_scene_t *scene); +internal void clip_instance_against_plane(model_t *model, + const bounding_sphere_t *sphere, + const clipping_plane_t *plane); +internal void clip_triangles_against_plane(model_t *model, + const clipping_plane_t *plane); +internal void clip_triangle_against_plane(vec3f_t *v0, vec3f_t *v1, vec3f_t *v2, + const clipping_plane_t *plane); internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1); internal inline void order_triangle_points(triangle_t *triangle); internal inline bounding_sphere_t @@ -74,7 +81,8 @@ internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene, model_t model = {transformed, instance->model->triangles}; clip_instance(&model, scene); - if (IS_NULL_MODEL(model)) { + model_t *mdl = &model; + if (IS_NULL_MODEL(mdl)) { return; } @@ -263,20 +271,50 @@ void draw_line(window_t *wnd, Arena *arena, line_t line, colour_t colour) { internal void clip_instance(model_t *model, const rasteriser_scene_t *scene) { bounding_sphere_t sphere = get_bounding_sphere(model->vertices); - f32 distance = 0.0; - f32 neg_radius = -1.0f * sphere.radius; const clipping_plane_t *plane = NULL; for (u64 i = 0; i < CLIPPING_PLANE_COUNT; ++i) { plane = &(scene->planes[i]); - - distance = signed_distance(&(sphere.centre), plane); - if (distance < neg_radius) { - *model = NULL_MODEL; + clip_instance_against_plane(model, &sphere, plane); + if (IS_NULL_MODEL(model)) { + return; } } } +internal void clip_instance_against_plane(model_t *model, + const bounding_sphere_t *sphere, + const clipping_plane_t *plane) { + f32 distance = signed_distance(&(sphere->centre), plane); + f32 neg_radius = -1.0f * sphere->radius; + + if (distance > sphere->radius) { + return; + } else if (distance < neg_radius) { + *model = NULL_MODEL; + } else { + clip_triangles_against_plane(model, plane); + } +} + +internal void clip_triangles_against_plane(model_t *model, + const clipping_plane_t *plane) { + for (u64 i = 0; i < model->triangles->count; ++i) { + scene_triangle_t *triangle = list_get(model->triangles, i); + vec3f_t *v0 = &(list_get(model->vertices, triangle->idx0)); + vec3f_t *v1 = &(list_get(model->vertices, triangle->idx1)); + vec3f_t *v2 = &(list_get(model->vertices, triangle->idx2)); + clip_triangle_against_plane(triangle, plane); + } +} + +internal void clip_triangle_against_plane(vec3f_t *v0, vec3f_t *v1, vec3f_t *v2, + const clipping_plane_t *plane) { + f32 d0 = signed_distance(v0, plane); + f32 d1 = signed_distance(v1, plane); + f32 d2 = signed_distance(v2, plane); +} + internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1) { list_float *values; if (i0 == i1) {