frustum culling
parent
708629c80f
commit
d3cbd939c7
|
@ -385267,11 +385267,66 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
#if 0
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||
#else
|
||||
// for (int j = 0; j < )
|
||||
int first_triangle = mesh->first_triangle;
|
||||
int num_triangles = mesh->num_triangles;
|
||||
int vertex_count = 0;
|
||||
vec3 center = {0};
|
||||
aabb box = {
|
||||
.min = {FLT_MAX, FLT_MAX, FLT_MAX},
|
||||
.max = {-FLT_MAX, -FLT_MAX, -FLT_MAX}
|
||||
};
|
||||
float max_distance_squared = 0.0f;
|
||||
for (int j = first_triangle; j < num_triangles+first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
// calculate mesh center
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
iqm_vertex *v = &verts[tri->vertex[k]];
|
||||
GLfloat *pos = v->position;
|
||||
center.x += pos[0];
|
||||
center.y += pos[1];
|
||||
center.z += pos[2];
|
||||
vertex_count++;
|
||||
|
||||
// Update AABB
|
||||
box.min.x = fminf(box.min.x, pos[0]);
|
||||
box.min.y = fminf(box.min.y, pos[1]);
|
||||
box.min.z = fminf(box.min.z, pos[2]);
|
||||
box.max.x = fmaxf(box.max.x, pos[0]);
|
||||
box.max.y = fmaxf(box.max.y, pos[1]);
|
||||
box.max.z = fmaxf(box.max.z, pos[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vertex_count) {
|
||||
center.x /= vertex_count;
|
||||
center.y /= vertex_count;
|
||||
center.z /= vertex_count;
|
||||
}
|
||||
|
||||
// Compute bounding sphere radius
|
||||
for (int j = first_triangle; j < num_triangles + first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
int vertex_index = tri->vertex[k];
|
||||
GLfloat *pos = verts[vertex_index].position;
|
||||
|
||||
float dx = pos[0] - center.x;
|
||||
float dy = pos[1] - center.y;
|
||||
float dz = pos[2] - center.z;
|
||||
float distance_squared = dx*dx + dy*dy + dz*dz;
|
||||
max_distance_squared = fmaxf(max_distance_squared, distance_squared);
|
||||
}
|
||||
}
|
||||
|
||||
m->meshcenters[i] = center;
|
||||
m->meshbounds[i] = box;
|
||||
m->meshradii[i] = sqrtf(max_distance_squared);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -385939,6 +385994,28 @@ void model_clear_frustum(model_t *m) {
|
|||
m->frustum_enabled = 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||
if(!m.iqm) return false;
|
||||
if(!m.frustum_enabled) return true;
|
||||
|
||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||
|
||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aabb box = m.meshbounds[mesh];
|
||||
box.min = transform344(model_mat, box.min);
|
||||
box.max = transform344(model_mat, box.max);
|
||||
|
||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
if(!m.iqm) return;
|
||||
|
@ -385971,11 +386048,14 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
drawcall_t call;
|
||||
|
@ -385991,6 +386071,8 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
drawcall_t call;
|
||||
|
@ -388087,8 +388169,22 @@ int scene_obj_distance_compare(const void *a, const void *b) {
|
|||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
#if 1
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum frustum_state = frustum_build(projview);
|
||||
#else
|
||||
static frustum frustum_state;
|
||||
do_once {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
|
||||
if (input_down(KEY_T)) {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(flags & SCENE_BACKGROUND) {
|
||||
if(last_scene->skybox.program) {
|
||||
|
|
|
@ -3611,11 +3611,66 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
#if 0
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||
#else
|
||||
// for (int j = 0; j < )
|
||||
int first_triangle = mesh->first_triangle;
|
||||
int num_triangles = mesh->num_triangles;
|
||||
int vertex_count = 0;
|
||||
vec3 center = {0};
|
||||
aabb box = {
|
||||
.min = {FLT_MAX, FLT_MAX, FLT_MAX},
|
||||
.max = {-FLT_MAX, -FLT_MAX, -FLT_MAX}
|
||||
};
|
||||
float max_distance_squared = 0.0f;
|
||||
for (int j = first_triangle; j < num_triangles+first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
// calculate mesh center
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
iqm_vertex *v = &verts[tri->vertex[k]];
|
||||
GLfloat *pos = v->position;
|
||||
center.x += pos[0];
|
||||
center.y += pos[1];
|
||||
center.z += pos[2];
|
||||
vertex_count++;
|
||||
|
||||
// Update AABB
|
||||
box.min.x = fminf(box.min.x, pos[0]);
|
||||
box.min.y = fminf(box.min.y, pos[1]);
|
||||
box.min.z = fminf(box.min.z, pos[2]);
|
||||
box.max.x = fmaxf(box.max.x, pos[0]);
|
||||
box.max.y = fmaxf(box.max.y, pos[1]);
|
||||
box.max.z = fmaxf(box.max.z, pos[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vertex_count) {
|
||||
center.x /= vertex_count;
|
||||
center.y /= vertex_count;
|
||||
center.z /= vertex_count;
|
||||
}
|
||||
|
||||
// Compute bounding sphere radius
|
||||
for (int j = first_triangle; j < num_triangles + first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
int vertex_index = tri->vertex[k];
|
||||
GLfloat *pos = verts[vertex_index].position;
|
||||
|
||||
float dx = pos[0] - center.x;
|
||||
float dy = pos[1] - center.y;
|
||||
float dz = pos[2] - center.z;
|
||||
float distance_squared = dx*dx + dy*dy + dz*dz;
|
||||
max_distance_squared = fmaxf(max_distance_squared, distance_squared);
|
||||
}
|
||||
}
|
||||
|
||||
m->meshcenters[i] = center;
|
||||
m->meshbounds[i] = box;
|
||||
m->meshradii[i] = sqrtf(max_distance_squared);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4283,6 +4338,28 @@ void model_clear_frustum(model_t *m) {
|
|||
m->frustum_enabled = 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||
if(!m.iqm) return false;
|
||||
if(!m.frustum_enabled) return true;
|
||||
|
||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||
|
||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aabb box = m.meshbounds[mesh];
|
||||
box.min = transform344(model_mat, box.min);
|
||||
box.max = transform344(model_mat, box.max);
|
||||
|
||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
if(!m.iqm) return;
|
||||
|
@ -4315,11 +4392,14 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
drawcall_t call;
|
||||
|
@ -4335,6 +4415,8 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
drawcall_t call;
|
||||
|
|
|
@ -513,8 +513,22 @@ int scene_obj_distance_compare(const void *a, const void *b) {
|
|||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
#if 1
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum frustum_state = frustum_build(projview);
|
||||
#else
|
||||
static frustum frustum_state;
|
||||
do_once {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
|
||||
if (input_down(KEY_T)) {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(flags & SCENE_BACKGROUND) {
|
||||
if(last_scene->skybox.program) {
|
||||
|
|
100
engine/v4k.c
100
engine/v4k.c
|
@ -20410,11 +20410,66 @@ bool model_load_meshes(iqm_t *q, const struct iqmheader *hdr, model_t *m) {
|
|||
int invalid = texture_checker().id;
|
||||
q->textures[i] = invalid;
|
||||
struct iqmmesh *mesh = &q->meshes[i];
|
||||
#if 1
|
||||
#if 0
|
||||
GLfloat *pos = verts[q->meshes[i].first_vertex].position;
|
||||
m->meshcenters[i] = vec3(pos[0], pos[1], pos[2]);
|
||||
#else
|
||||
// for (int j = 0; j < )
|
||||
int first_triangle = mesh->first_triangle;
|
||||
int num_triangles = mesh->num_triangles;
|
||||
int vertex_count = 0;
|
||||
vec3 center = {0};
|
||||
aabb box = {
|
||||
.min = {FLT_MAX, FLT_MAX, FLT_MAX},
|
||||
.max = {-FLT_MAX, -FLT_MAX, -FLT_MAX}
|
||||
};
|
||||
float max_distance_squared = 0.0f;
|
||||
for (int j = first_triangle; j < num_triangles+first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
// calculate mesh center
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
iqm_vertex *v = &verts[tri->vertex[k]];
|
||||
GLfloat *pos = v->position;
|
||||
center.x += pos[0];
|
||||
center.y += pos[1];
|
||||
center.z += pos[2];
|
||||
vertex_count++;
|
||||
|
||||
// Update AABB
|
||||
box.min.x = fminf(box.min.x, pos[0]);
|
||||
box.min.y = fminf(box.min.y, pos[1]);
|
||||
box.min.z = fminf(box.min.z, pos[2]);
|
||||
box.max.x = fmaxf(box.max.x, pos[0]);
|
||||
box.max.y = fmaxf(box.max.y, pos[1]);
|
||||
box.max.z = fmaxf(box.max.z, pos[2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (vertex_count) {
|
||||
center.x /= vertex_count;
|
||||
center.y /= vertex_count;
|
||||
center.z /= vertex_count;
|
||||
}
|
||||
|
||||
// Compute bounding sphere radius
|
||||
for (int j = first_triangle; j < num_triangles + first_triangle; ++j) {
|
||||
struct iqmtriangle *tri = &tris[j];
|
||||
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
int vertex_index = tri->vertex[k];
|
||||
GLfloat *pos = verts[vertex_index].position;
|
||||
|
||||
float dx = pos[0] - center.x;
|
||||
float dy = pos[1] - center.y;
|
||||
float dz = pos[2] - center.z;
|
||||
float distance_squared = dx*dx + dy*dy + dz*dz;
|
||||
max_distance_squared = fmaxf(max_distance_squared, distance_squared);
|
||||
}
|
||||
}
|
||||
|
||||
m->meshcenters[i] = center;
|
||||
m->meshbounds[i] = box;
|
||||
m->meshradii[i] = sqrtf(max_distance_squared);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -21082,6 +21137,28 @@ void model_clear_frustum(model_t *m) {
|
|||
m->frustum_enabled = 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool model_is_visible(model_t m, int mesh, mat44 model_mat) {
|
||||
if(!m.iqm) return false;
|
||||
if(!m.frustum_enabled) return true;
|
||||
|
||||
sphere s; s.c = transform344(model_mat, m.meshcenters[mesh]); s.r = m.meshradii[mesh];
|
||||
|
||||
if (!frustum_test_sphere(m.frustum_state, s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aabb box = m.meshbounds[mesh];
|
||||
box.min = transform344(model_mat, box.min);
|
||||
box.max = transform344(model_mat, box.max);
|
||||
|
||||
if (!frustum_test_aabb(m.frustum_state, box)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_mat) {
|
||||
if(!m.iqm) return;
|
||||
|
@ -21114,11 +21191,14 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if (rs_idx > RENDER_PASS_OVERRIDES_BEGIN) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
array_push(drawcalls, (drawcall_t){i, -1});
|
||||
}
|
||||
} else {
|
||||
if(pass == -1 || pass == RENDER_PASS_OPAQUE) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect opaque drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_OPAQUE) {
|
||||
drawcall_t call;
|
||||
|
@ -21134,6 +21214,8 @@ void model_draw_call(model_t m, int shader, int pass, vec3 cam_pos, mat44 model_
|
|||
|
||||
if(pass == -1 || pass == RENDER_PASS_TRANSPARENT) {
|
||||
for(int i = 0; i < q->nummeshes; i++) {
|
||||
if (!model_is_visible(m, i, model_mat)) continue;
|
||||
|
||||
// collect transparent drawcalls
|
||||
if (required_rs[i] == RENDER_PASS_TRANSPARENT) {
|
||||
drawcall_t call;
|
||||
|
@ -23230,8 +23312,22 @@ int scene_obj_distance_compare(const void *a, const void *b) {
|
|||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
#if 1
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum frustum_state = frustum_build(projview);
|
||||
#else
|
||||
static frustum frustum_state;
|
||||
do_once {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
|
||||
if (input_down(KEY_T)) {
|
||||
mat44 projview; multiply44x2(projview, cam->proj, cam->view);
|
||||
frustum_state = frustum_build(projview);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(flags & SCENE_BACKGROUND) {
|
||||
if(last_scene->skybox.program) {
|
||||
|
|
Loading…
Reference in New Issue