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_vec3f_t *vertices;
|
||||||
list_scene_triangle_t *triangles;
|
list_scene_triangle_t *triangles;
|
||||||
} model_t;
|
} model_t;
|
||||||
|
#define NULL_MODEL ((model_t){0})
|
||||||
|
#define IS_NULL_MODEL(MODEL) (MODEL.vertices == NULL && MODEL.triangles == NULL)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
f32 scale;
|
f32 scale;
|
||||||
@ -47,6 +49,11 @@ typedef struct {
|
|||||||
vec3f_t position;
|
vec3f_t position;
|
||||||
} transform_t;
|
} transform_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3f_t centre;
|
||||||
|
f32 radius;
|
||||||
|
} bounding_sphere_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
model_t *model;
|
model_t *model;
|
||||||
transform_t transform;
|
transform_t transform;
|
||||||
@ -57,21 +64,16 @@ typedef struct {
|
|||||||
f32 distance;
|
f32 distance;
|
||||||
} clipping_plane_t;
|
} clipping_plane_t;
|
||||||
|
|
||||||
|
#define CLIPPING_PLANE_COUNT 5
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 instance_count;
|
u64 instance_count;
|
||||||
instance_t *instances;
|
instance_t *instances;
|
||||||
camera_t *camera;
|
camera_t *camera;
|
||||||
const mat3x4f_t *proj_matrix;
|
const mat3x4f_t *proj_matrix;
|
||||||
clipping_plane_t near;
|
clipping_plane_t planes[CLIPPING_PLANE_COUNT];
|
||||||
clipping_plane_t left;
|
|
||||||
clipping_plane_t right;
|
|
||||||
clipping_plane_t bottom;
|
|
||||||
clipping_plane_t top;
|
|
||||||
} rasteriser_scene_t;
|
} rasteriser_scene_t;
|
||||||
|
|
||||||
void render_scene(window_t *wnd, Arena *arena, const rasteriser_scene_t *scene);
|
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_wireframe_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||||
void draw_filled_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);
|
void draw_shaded_triangle(window_t *wnd, Arena *arena, triangle_t triangle);
|
||||||
|
@ -107,31 +107,36 @@ int main(void) {
|
|||||||
.instances = instances,
|
.instances = instances,
|
||||||
.camera = &camera,
|
.camera = &camera,
|
||||||
.proj_matrix = &proj_matrix,
|
.proj_matrix = &proj_matrix,
|
||||||
.near =
|
.planes =
|
||||||
|
{
|
||||||
|
[0] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
.normal = (vec3f_t){0.0f, 0.0f, 1.0f},
|
||||||
.distance = viewport.z,
|
.distance = viewport.z,
|
||||||
},
|
},
|
||||||
.left =
|
[1] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
.normal = (vec3f_t){one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.right =
|
[2] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
.normal =
|
||||||
|
(vec3f_t){neg_one_div_sqrt_2, 0.0f, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.bottom =
|
[3] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
.normal = (vec3f_t){0.0f, one_div_sqrt_2, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
.top =
|
[4] =
|
||||||
(clipping_plane_t){
|
(clipping_plane_t){
|
||||||
.normal = (vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
.normal =
|
||||||
|
(vec3f_t){0.0f, neg_one_div_sqrt_2, one_div_sqrt_2},
|
||||||
.distance = 0.0f,
|
.distance = 0.0f,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
@ -11,8 +11,17 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.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 list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1);
|
||||||
internal inline void order_triangle_points(triangle_t *triangle);
|
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,
|
void render_scene(window_t *wnd, Arena *arena,
|
||||||
const rasteriser_scene_t *scene) {
|
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);
|
mul_mat4x4f(cam_inverse_rotation, cam_inverse_translation);
|
||||||
|
|
||||||
for (u64 i = 0; i < scene->instance_count; ++i) {
|
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]));
|
&(scene->instances[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
internal void render_instance(window_t *wnd, const rasteriser_scene_t *scene,
|
||||||
mat3x4f_t projection_matrix, const instance_t *instance) {
|
Arena *arena, mat4x4f_t camera_matrix,
|
||||||
list_vec4f_t *transformed = list_create_with_capacity(
|
mat3x4f_t projection_matrix,
|
||||||
vec4f_t, arena, instance->model->vertices->count * sizeof(vec4f_t));
|
const instance_t *instance) {
|
||||||
|
list_vec3f_t *transformed = list_create_with_capacity(
|
||||||
|
vec3f_t, arena, instance->model->vertices->count * sizeof(vec3f_t));
|
||||||
if (!transformed) {
|
if (!transformed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -51,9 +62,20 @@ void render_instance(window_t *wnd, Arena *arena, mat4x4f_t camera_matrix,
|
|||||||
vec4f_t xf_vertex = {0};
|
vec4f_t xf_vertex = {0};
|
||||||
for (u64 i = 0; i < instance->model->vertices->count; ++i) {
|
for (u64 i = 0; i < instance->model->vertices->count; ++i) {
|
||||||
vertex = list_get(instance->model->vertices, i);
|
vertex = list_get(instance->model->vertices, i);
|
||||||
|
|
||||||
xf_vertex = mul_mat4x4f_by_vec4f(
|
xf_vertex = mul_mat4x4f_by_vec4f(
|
||||||
xf_cam_mat, (vec4f_t){vertex.x, vertex.y, vertex.z, 1.0f});
|
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(
|
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};
|
vec2i_t point = {0};
|
||||||
for (u64 i = 0; i < transformed->count; ++i) {
|
for (u64 i = 0; i < transformed->count; ++i) {
|
||||||
xf_vertex = list_get(transformed, i);
|
vertex = list_get(transformed, i);
|
||||||
vertex = mul_mat3x4f_by_vec4f(projection_matrix, xf_vertex);
|
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)};
|
point = (vec2i_t){(i32)(vertex.x / vertex.z), (i32)(vertex.y / vertex.z)};
|
||||||
list_append(vec2i_t, arena, projected, point);
|
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) {
|
internal list_float *interpolate(Arena *arena, i32 i0, f32 d0, i32 i1, f32 d1) {
|
||||||
list_float *values;
|
list_float *values;
|
||||||
if (i0 == i1) {
|
if (i0 == i1) {
|
||||||
@ -279,3 +318,32 @@ internal inline void order_triangle_points(triangle_t *triangle) {
|
|||||||
swap(f32, triangle->h1, triangle->h2);
|
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