Initial implementation of bounding sphere clipping
This commit is contained in:
parent
c3e1aac779
commit
ae072ec70e
@ -40,6 +40,8 @@ typedef struct {
|
||||
list_vec3f_t *vertices;
|
||||
list_scene_triangle_t *triangles;
|
||||
} model_t;
|
||||
#define NULL_MODEL ((model_t){0})
|
||||
#define IS_NULL_MODEL(MODEL) (MODEL.vertices == NULL && MODEL.triangles == NULL)
|
||||
|
||||
typedef struct {
|
||||
f32 scale;
|
||||
@ -47,6 +49,11 @@ typedef struct {
|
||||
vec3f_t position;
|
||||
} transform_t;
|
||||
|
||||
typedef struct {
|
||||
vec3f_t centre;
|
||||
f32 radius;
|
||||
} bounding_sphere_t;
|
||||
|
||||
typedef struct {
|
||||
model_t *model;
|
||||
transform_t transform;
|
||||
@ -57,21 +64,16 @@ typedef struct {
|
||||
f32 distance;
|
||||
} clipping_plane_t;
|
||||
|
||||
#define CLIPPING_PLANE_COUNT 5
|
||||
typedef struct {
|
||||
u64 instance_count;
|
||||
instance_t *instances;
|
||||
camera_t *camera;
|
||||
const mat3x4f_t *proj_matrix;
|
||||
clipping_plane_t near;
|
||||
clipping_plane_t left;
|
||||
clipping_plane_t right;
|
||||
clipping_plane_t bottom;
|
||||
clipping_plane_t top;
|
||||
clipping_plane_t planes[CLIPPING_PLANE_COUNT];
|
||||
} rasteriser_scene_t;
|
||||
|
||||
void render_scene(window_t *wnd, Arena *arena, const rasteriser_scene_t *scene);
|
||||
void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
||||
mat3x4f_t projection_matrix, const instance_t *instance);
|
||||
void draw_wireframe_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||
void draw_filled_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||
|
@ -107,30 +107,35 @@ int main(void) {
|
||||
.instances = instances,
|
||||
.camera = &camera,
|
||||
.proj_matrix = &proj_matrix,
|
||||
.near =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
||||
.distance = viewport.z,
|
||||
},
|
||||
.left =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
.right =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
.bottom =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
.top =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
.planes =
|
||||
{
|
||||
[0] =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
||||
.distance = viewport.z,
|
||||
},
|
||||
[1] =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
[2] =
|
||||
(clipping_plane_t){
|
||||
.normal =
|
||||
(vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
[3] =
|
||||
(clipping_plane_t){
|
||||
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
[4] =
|
||||
(clipping_plane_t){
|
||||
.normal =
|
||||
(vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
||||
.distance = 0.0f,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -11,8 +11,17 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||
Arena *arena, mat4x4f_t camera_matrix,
|
||||
mat3x4f_t projection_matrix,
|
||||
const instance_t *instance);
|
||||
internal void clip_instance(model_t *model, const rasteriser_scene_t *scene);
|
||||
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
|
||||
get_bounding_sphere(const list_vec3f_t *vertices);
|
||||
internal inline f32 signed_distance(const vec3f_t *vertex,
|
||||
const clipping_plane_t *plane);
|
||||
|
||||
void render_scene(window_t *wnd, Arena *arena,
|
||||
const rasteriser_scene_t *scene) {
|
||||
@ -24,15 +33,17 @@ void render_scene(window_t *wnd, Arena *arena,
|
||||
mul_mat4x4f(cam_inverse_rotation, cam_inverse_translation);
|
||||
|
||||
for (u64 i = 0; i < scene->instance_count; ++i) {
|
||||
render_instance(wnd, arena, cam_matrix, *(scene->proj_matrix),
|
||||
render_instance(wnd, scene, arena, cam_matrix, *(scene->proj_matrix),
|
||||
&(scene->instances[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
||||
mat3x4f_t projection_matrix, const instance_t *instance) {
|
||||
list_vec4f_t *transformed = list_create_with_capacity(
|
||||
vec4f_t, arena, instance->model->vertices->count * sizeof(vec4f_t));
|
||||
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||
Arena *arena, mat4x4f_t camera_matrix,
|
||||
mat3x4f_t projection_matrix,
|
||||
const instance_t *instance) {
|
||||
list_vec3f_t *transformed = list_create_with_capacity(
|
||||
vec3f_t, arena, instance->model->vertices->count * sizeof(vec3f_t));
|
||||
if (!transformed) {
|
||||
return;
|
||||
}
|
||||
@ -51,9 +62,20 @@ void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
||||
vec4f_t xf_vertex = {0};
|
||||
for (u64 i = 0; i < instance->model->vertices->count; ++i) {
|
||||
vertex = list_get(instance->model->vertices, i);
|
||||
|
||||
xf_vertex = mul_mat4x4f_by_vec4f(
|
||||
xf_cam_mat, (vec4f_t){vertex.x, vertex.y, vertex.z, 1.0f});
|
||||
list_append(vec4f_t, arena, transformed, xf_vertex);
|
||||
xf_vertex = vec_div_num(vec4f_t, xf_vertex, xf_vertex.w);
|
||||
|
||||
vertex = (vec3f_t){xf_vertex.x, xf_vertex.y, xf_vertex.z};
|
||||
|
||||
list_append(vec3f_t, arena, transformed, vertex);
|
||||
}
|
||||
|
||||
model_t model = {transformed, instance->model->triangles};
|
||||
clip_instance(&model, scene);
|
||||
if (IS_NULL_MODEL(model)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_vec2i_t *projected = list_create_with_capacity(
|
||||
@ -64,8 +86,9 @@ void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
||||
|
||||
vec2i_t point = {0};
|
||||
for (u64 i = 0; i < transformed->count; ++i) {
|
||||
xf_vertex = list_get(transformed, i);
|
||||
vertex = mul_mat3x4f_by_vec4f(projection_matrix, xf_vertex);
|
||||
vertex = list_get(transformed, i);
|
||||
vertex = mul_mat3x4f_by_vec4f(
|
||||
projection_matrix, (vec4f_t){vertex.x, vertex.y, vertex.z, 1.0f});
|
||||
point = (vec2i_t){(i32)(vertex.x / vertex.z), (i32)(vertex.y / vertex.z)};
|
||||
list_append(vec2i_t, arena, projected, point);
|
||||
}
|
||||
@ -238,6 +261,22 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1) {
|
||||
list_float *values;
|
||||
if (i0 == i1) {
|
||||
@ -279,3 +318,32 @@ internal inline void order_triangle_points(triangle_t *triangle) {
|
||||
swap(f32, triangle->h1, triangle->h2);
|
||||
}
|
||||
}
|
||||
|
||||
internal inline bounding_sphere_t
|
||||
get_bounding_sphere(const list_vec3f_t *vertices) {
|
||||
vec3f_t sum = {0};
|
||||
for (u64 i = 0; i < vertices->count; ++i) {
|
||||
sum = vec_add(vec3f_t, list_get(vertices, i), sum);
|
||||
}
|
||||
|
||||
vec3f_t centre = vec_div_num(vec3f_t, sum, vertices->count);
|
||||
f32 radius = 0.0f;
|
||||
f32 tmp = 0.0f;
|
||||
vec3f_t dst = {0};
|
||||
for (u64 i = 0; i < vertices->count; ++i) {
|
||||
dst = vec_sub(vec3f_t, list_get(vertices, i), centre);
|
||||
tmp = vec_magnitude(vec3f_t, dst);
|
||||
radius = tmp > radius ? tmp : radius;
|
||||
}
|
||||
|
||||
return (bounding_sphere_t){
|
||||
.centre = centre,
|
||||
.radius = radius,
|
||||
};
|
||||
}
|
||||
|
||||
internal inline f32 signed_distance(const vec3f_t *vertex,
|
||||
const clipping_plane_t *plane) {
|
||||
return (vertex->x * plane->normal.x) + (vertex->y + plane->normal.y) +
|
||||
(vertex->z + plane->normal.z) + plane->distance;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user