diff --git a/apps/demos/scenery/scenes/ingame.c b/apps/demos/scenery/scenes/ingame.c index 2b8de99..ac192a2 100644 --- a/apps/demos/scenery/scenes/ingame.c +++ b/apps/demos/scenery/scenes/ingame.c @@ -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; } diff --git a/apps/demos/scenery/scenes/ingame.h b/apps/demos/scenery/scenes/ingame.h index eadec51..e97f5d5 100644 --- a/apps/demos/scenery/scenes/ingame.h +++ b/apps/demos/scenery/scenes/ingame.h @@ -12,6 +12,8 @@ typedef struct SceneIngame { Scene base; + Vec3 looking_direction; + Vec3 pos; float yaw; float pitch; diff --git a/include/twn_vec.h b/include/twn_vec.h index 43ade04..3ca3936 100644 --- a/include/twn_vec.h +++ b/include/twn_vec.h @@ -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 }; }