#ifndef WORLD_TERRAIN_H #define WORLD_TERRAIN_H /* * Uneven meadow ground (heightfield) with a wear map. * * Walking characters trample the grass: first it bends, then it becomes a * bare earth path that sinks a little. Untouched grass recovers slowly * (TERRAIN_RECOVERY_DAYS in game time). * * The ground is flattened under and around static objects so buildings, * trees and walls stand level. Roads and paths are part of it (a surface * map, and their height in the ground), so everything stands on them alike. * Water on and in it: see wetness.h. */ #include #include #include "core/gl.h" #include "world/object.h" #include "render/mesh.h" #include "world/wetness.h" #define TERRAIN_SIZE 340.0f /* square edge length in meters, centered on 0 */ #define TERRAIN_GRASS_DEPTH 0.08f /* how far fully trampled ground sinks */ #define TERRAIN_RECOVERY_DAYS 2.0f /* game days for a bare path to grow back */ #define TERRAIN_TILES 8 /* the ground mesh is cut into TILES x TILES pieces */ #define TERRAIN_SURFACE_RES 2048 /* surface map cells per side (1/6 m) */ /* A hole in the ground (a basement under a building): no ground drawn there, and the ground's height in it is its floor. A rectangle turned by yaw. */ #define TERRAIN_PITS 8 typedef struct { float x, z, cos_yaw, sin_yaw; /* its middle; local x is (cos, sin) */ float half_x, half_z; float floor; } TerrainPit; typedef struct Terrain { float *heights; /* (TERRAIN_GRID + 1)^2 base heights */ float *wear; /* TERRAIN_WEAR_RES^2, 0 = meadow, 1 = bare path */ unsigned char *wear_bytes; /* upload buffer for the wear texture */ bool wear_dirty; GLuint wear_texture; unsigned char *hard; /* TERRAIN_SURFACE_RES^2: how paved (0 meadow .. 255 tar or concrete) */ GLuint surface_texture; /* RGBA8: asphalt, concrete, gravel, bare earth (see Site_surface) */ Mesh tiles[TERRAIN_TILES * TERRAIN_TILES]; /* the ground, in tiles (drawn only in view) */ Wetness wet; TerrainPit pits[TERRAIN_PITS]; int pit_count; } Terrain; /* A hole in the ground (see TerrainPit; yaw as objects turn). May be dug before Terrain_init (buildings come first): it keeps them. */ bool Terrain_addPit(Terrain *t, Vec3 center, float yaw, float half_x, float half_z, float floor_y); /* In a pit here? (its floor, if so) */ bool Terrain_inPit(const Terrain *t, float x, float z, float *floor_y); /* Builds the ground and flattens it around the static objects given. */ bool Terrain_init(Terrain *t, Object *const *objects, int count); void Terrain_destroy(Terrain *t); /* Ground height at a world position, including trampled paths. Returns a very low value outside the terrain (objects fall off). */ float Terrain_height(const Terrain *t, float x, float z); /* The ground as if no pit were dug there (what a building stands on). */ float Terrain_naturalHeight(const Terrain *t, float x, float z); /* Ground height without the trampled paths (as built). */ float Terrain_baseHeight(const Terrain *t, float x, float z); /* The meadow's own color here (before trampling). */ Vec3 Terrain_grassColor(float x, float z); /* How trampled (0 meadow .. 1 bare path). */ float Terrain_wear(const Terrain *t, float x, float z); /* Saves: the worn paths out to / in from a file. */ bool Terrain_writeWear(const Terrain *t, FILE *f); bool Terrain_readWear(Terrain *t, FILE *f); /* How hard the surface is (0 meadow .. 1 tar or concrete; gravel in between). */ float Terrain_hardness(const Terrain *t, float x, float z); /* Wears the grass down at a footstep (real seconds); wet soft ground wears faster, paved ground not at all. */ void Terrain_trample(Terrain *t, float x, float z, float dt); /* Something lies on the ground here: the grass under it lies flat (sick). */ void Terrain_soak(Terrain *t, float x, float z, float radius); /* Lets grass grow back (game seconds). */ void Terrain_recover(Terrain *t, float game_dt); /* Uploads the wear map and the wet ground to the GPU where they changed. */ void Terrain_syncTexture(Terrain *t); #endif /* WORLD_TERRAIN_H */