/apps/demos/scenery: culling

This commit is contained in:
veclavtalica 2025-02-26 17:08:45 +03:00
parent 6812c7c13d
commit ed2afec5a7
3 changed files with 30 additions and 6 deletions

View File

@ -17,7 +17,7 @@
#define TERRAIN_DISTANCE (TERRAIN_RADIUS * 2)
#define HALF_TERRAIN_DISTANCE ((float)TERRAIN_DISTANCE / 2)
#define PLAYER_HEIGHT 0.6f
#define TREE_DENSITY 0.02f
#define TREE_DENSITY 0.03f
/* TODO: pregenerate grid of levels of detail */
static float heightmap[TERRAIN_DISTANCE][TERRAIN_DISTANCE];
@ -29,6 +29,8 @@ static void process_fly_mode(State *state) {
DrawCameraFromPrincipalAxesResult dir_and_up =
draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1, TERRAIN_RADIUS * sqrtf(3));
scn->looking_direction = dir_and_up.direction;
const Vec3 right = m_vec_norm(m_vec_cross(dir_and_up.direction, dir_and_up.up));
const float speed = 0.04f; /* TODO: put this in a better place */
if (input_action_pressed("player_left"))
@ -86,6 +88,8 @@ static void process_ground_mode(State *state) {
DrawCameraFromPrincipalAxesResult dir_and_up =
draw_camera_from_principal_axes(scn->pos, scn->roll, scn->pitch, scn->yaw, (float)M_PI_2 * 0.8f, 1, TERRAIN_RADIUS * sqrtf(3));
scn->looking_direction = dir_and_up.direction;
dir_and_up.direction.y = 0;
dir_and_up.direction = vec3_norm(dir_and_up.direction);
@ -169,6 +173,10 @@ static uint32_t adler32(const void *buf, size_t buflength) {
static void draw_terrain(SceneIngame *scn) {
/* used to cull invisible tiles over field of view (to horizon) */
Vec2 const d = vec2_norm((Vec2){ .x = scn->looking_direction.x, .y = scn->looking_direction.z });
float const c = cosf((float)M_PI_2 * 0.8f);
/* draw terrain in circle */
int32_t const rsi = (int32_t)TERRAIN_RADIUS * (int32_t)TERRAIN_RADIUS;
for (int32_t iy = -(int32_t)TERRAIN_RADIUS; iy <= (int32_t)TERRAIN_RADIUS - 1; ++iy) {
@ -177,8 +185,12 @@ static void draw_terrain(SceneIngame *scn) {
int32_t lx = ix + TERRAIN_RADIUS;
int32_t ly = iy + TERRAIN_RADIUS;
int32_t x = (int32_t)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
int32_t y = (int32_t)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
float x = (float)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
float y = (float)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
/* cull tiles outside of vision */
if (vec2_dot(vec2_norm((Vec2){x - scn->pos.x + d.x * 2, y - scn->pos.z + d.y * 2}), d) < c)
continue;
float d0 = heightmap[lx][ly];
float d1 = heightmap[lx + 1][ly];
@ -209,8 +221,8 @@ static void draw_terrain(SceneIngame *scn) {
int32_t lx = ix + TERRAIN_RADIUS;
int32_t ly = iy + TERRAIN_RADIUS;
int32_t x = (int32_t)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
int32_t y = (int32_t)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
float x = (float)(floorf(scn->pos.x - HALF_TERRAIN_DISTANCE + (float)lx));
float y = (float)(floorf(scn->pos.z - HALF_TERRAIN_DISTANCE + (float)ly));
float d0 = heightmap[lx][ly];
@ -268,7 +280,7 @@ static void ingame_tick(State *state) {
draw_skybox("/assets/miramar/miramar_*.tga");
ctx.fog_color = (Color){ 140, 147, 160, 255 };
ctx.fog_density = 0.02f;
ctx.fog_density = 0.015f;
}

View File

@ -12,6 +12,8 @@
typedef struct SceneIngame {
Scene base;
Vec3 looking_direction;
Vec3 pos;
float yaw;
float pitch;

View File

@ -29,10 +29,20 @@ static inline Vec2 vec2_scale(Vec2 a, float s) {
return (Vec2) { a.x * s, a.y * s };
}
static inline float vec2_dot(Vec2 a, Vec2 b) {
return a.x * b.x + a.y * b.y;
}
static inline float vec2_length(Vec2 a) {
return sqrtf(a.x * a.x + a.y * a.y);
}
static inline Vec2 vec2_norm(Vec2 a) {
const float n = sqrtf(vec2_dot(a, a));
/* TODO: do we need truncating over epsilon as cglm does? */
return vec2_scale(a, 1.0f / n);
}
static inline Vec3 vec3_add(Vec3 a, Vec3 b) {
return (Vec3) { a.x + b.x, a.y + b.y, a.z + b.z };
}