Start implementing clipping triangles

This commit is contained in:
Abdelrahman Said 2024-07-10 00:18:10 +01:00
parent ae072ec70e
commit 3c293198bb
2 changed files with 47 additions and 8 deletions

View File

@ -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;

View File

@ -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) {