From: Eleni Maria Stea Date: Sun, 20 Aug 2017 20:31:04 +0000 (+0300) Subject: get height, camera + cow movement with keys X-Git-Url: https://eleni.mutantstargoat.com/git/?p=demo;a=commitdiff_plain;h=0d3454cbd5e803b8dea601110d403cd5563df9be get height, camera + cow movement with keys --- diff --git a/src/camera.cc b/src/camera.cc index 73980b8..b3ad077 100644 --- a/src/camera.cc +++ b/src/camera.cc @@ -30,6 +30,7 @@ void OrbitCamera::set_orbit_params(float theta, float phi, float distance) Mat4 OrbitCamera::get_view_matrix() const { Mat4 view_matrix; + view_matrix.translation(-position); view_matrix.rotate_y(theta * (float)M_PI / 180); view_matrix.rotate_x(phi * (float)M_PI / 180); view_matrix.translate(Vec3(0, 0, -distance)); @@ -55,4 +56,11 @@ Mat4 calc_projection_matrix(float fov_deg, float aspect, float n, float f) ); return pmat; +} + +void OrbitCamera::set_position(float x, float y, float z) +{ + position.x = x; + position.y = y; + position.z = z; } \ No newline at end of file diff --git a/src/camera.h b/src/camera.h index 62120f1..1fbbf9c 100644 --- a/src/camera.h +++ b/src/camera.h @@ -18,6 +18,8 @@ protected: float phi; float distance; + Vec3 position; + public: OrbitCamera(); virtual ~OrbitCamera(); @@ -25,6 +27,7 @@ public: virtual Mat4 get_view_matrix() const override; void set_orbit_params(float theta, float phi, float distance); + void set_position(float x, float y, float z); }; Mat4 calc_projection_matrix(float fov_deg, float aspect, float n, float f); diff --git a/src/main.cc b/src/main.cc index e5572e2..d4d4226 100644 --- a/src/main.cc +++ b/src/main.cc @@ -43,28 +43,29 @@ GLFWwindow *win; int win_w = 800; int win_h = 600; -float phi = 25; -float theta = 0; -float dist = 16; ShaderManager *sdr_man; /* variables */ +static bool move_camera; + +static float cam_phi = 25; +static float cam_theta = 0; +static float cam_dist = 16; +static Vec3 cam_pos; static float aspect; static OrbitCamera *camera; static Scene *cow_scene; +static Object *cow_object; static Renderer *cow_rend; -static Scene *ground_scene; -static Renderer *ground_rend; // default renderer +static Terrain terrain; static Texture *skybox_tex; - -static Renderer *terrain_rend; -static Material terrain_mat; static Texture *terrain_tex; -static Terrain terrain; +static Material terrain_mat; +static Renderer *terrain_rend; /* *** */ @@ -121,25 +122,6 @@ static bool init(Gfx_API api) camera = new OrbitCamera; - // ground_scene = new Scene; - // if(!ground_scene->load("data/ground.obj")) { - // fprintf(stderr, "Failed to load scene: ground.obj.\n"); - // return false; - // } - - // ground_rend = new Renderer; - // ground_rend->camera = camera; - // ground_rend->scene = ground_scene; - - // if(!ground_rend->create()) { - // fprintf(stderr, "Failed to create default renderer.\n"); - // return false; - // } - - // skybox_tex = gfx_create_texture(); - // skybox_tex->load("data/cubemap/cubemap.hdr"); - // ground_rend->set_sky_tex(skybox_tex); - cow_scene = new Scene; if(!cow_scene->load("data/spot/spot.obj")) { fprintf(stderr, "Failed to load scene: spot.obj.\n"); @@ -155,6 +137,8 @@ static bool init(Gfx_API api) return false; } + cow_object = cow_scene->objects[0]; + terrain_tex = gfx_create_texture(); if(!terrain_tex->load("data/grass.jpeg")) { fprintf(stderr, "Failed to load ground texture.\n"); @@ -168,16 +152,16 @@ static bool init(Gfx_API api) } TerrainParams p; - p.xsz = 50; - p.ysz = 50; - p.max_height = 5; - p.xtiles = 20; - p.ytiles = 20; + p.xsz = 200; + p.ysz = 200; + p.max_height = 30; + p.xtiles = 40; + p.ytiles = 40; p.tile_usub = 10; p.tile_vsub = 10; p.num_octaves = 3; - p.noise_freq = 10; - p.coarse_heightmap = &ter_hmap; + p.noise_freq = 5; + p.coarse_heightmap = ter_hmap; terrain.init(); terrain.generate(p); @@ -193,20 +177,16 @@ static bool init(Gfx_API api) terrain_rend = new Renderer; terrain_rend->camera = camera; terrain_rend->scene = terrain.get_visible(camera); + + skybox_tex = gfx_create_texture(); + skybox_tex->load("data/cubemap/cubemap.hdr"); + terrain_rend->set_sky_tex(skybox_tex); + if(!terrain_rend->create()) { fprintf(stderr, "terrain fail\n"); return false; } - -// TODO delete: debugging - // for(size_t i=0; iobjects.size(); ++i) { - // printf("object: %d\n", (int)i); - // printf("mesh: %s\n", ground_scene->objects[i]->mesh->name.c_str()); - // printf("material: %s\n", ground_scene->objects[i]->material->name.c_str()); - // printf("transform:\n"); - // ground_scene->objects[i]->transform.print(); - // } return true; } @@ -218,19 +198,37 @@ static void cleanup() delete cow_scene; delete cow_rend; - // delete ground_scene; - // delete ground_rend; - //TODO delete terrain_tex; delete terrain_rend; gfx_cleanup(); } +static float cow_speed = 10; +static Vec3 cow_pos; +static bool keystate[256]; + static void clbk_key(GLFWwindow *win, int key, int scancode, int action, int mods) { - if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { - glfwSetWindowShouldClose(win, GLFW_TRUE); + if(action == GLFW_REPEAT) return; + + if(action == GLFW_PRESS) { + switch(key) { + case GLFW_KEY_ESCAPE: + glfwSetWindowShouldClose(win, GLFW_TRUE); + return; + + case ' ': + move_camera = !move_camera; + break; + + default: + break; + } + } + + if(key < 256) { + keystate[key] = action == GLFW_PRESS; } } @@ -246,22 +244,22 @@ static void clbk_motion(GLFWwindow *win, double x, double y) prev_y = y; if(button[0]) { - theta += dx * 0.5; - phi += dy * 0.5; + cam_theta += dx * 0.5; + cam_phi += dy * 0.5; - if(phi < 0) - phi = 0; - if(phi > 90) - phi = 90; + if(cam_phi < 0) + cam_phi = 0; + if(cam_phi > 90) + cam_phi = 90; } if(button[1]) { - dist += dy * 0.1; - if(dist < 0.0) { - dist = 0.0; + cam_dist += dy * 0.1; + if(cam_dist < 0.0) { + cam_dist = 0.0; } } -} + } static void clbk_mouse(GLFWwindow *win, int bn, int action, int mods) { @@ -279,14 +277,43 @@ static void clbk_reshape(GLFWwindow *win, int width, int height) win_w = width; } +static void update(float dt) +{ + Vec3 dir; + + if(keystate['D']) + dir.x += cow_speed * dt; + if(keystate['A']) + dir.x -= cow_speed * dt; + if(keystate['W']) + dir.z -= cow_speed * dt; + if(keystate['S']) + dir.z += cow_speed * dt; + + Vec3 *pos = move_camera ? &cam_pos : &cow_pos; + float theta = cam_theta / 180.0 * M_PI; + pos->x += dir.x * cos(theta) - dir.z * sin(theta); + pos->z += dir.x * sin(theta) + dir.z * cos(theta); +} + static void display() { - camera->set_orbit_params(theta, phi, dist); + static float prev_tsec; + float tsec = glfwGetTime(); + float dt = tsec - prev_tsec; + prev_tsec = tsec; + + update(dt); + + cam_pos.y = terrain.get_height(cam_pos) + 0.5; + camera->set_orbit_params(cam_theta, cam_phi, cam_dist); + camera->set_position(cam_pos.x, cam_pos.y, cam_pos.z); - // gfx_clear(0.76, 0.3, 0.43); gfx_clear(0.1, 0.1, 0.1); terrain_rend->draw(); -// ground_rend->draw(); + + cow_pos.y = terrain.get_height(cow_pos); + cow_object->transform.translation(cow_pos); cow_rend->draw(); } \ No newline at end of file diff --git a/src/renderer.cc b/src/renderer.cc index 816e924..380cf69 100644 --- a/src/renderer.cc +++ b/src/renderer.cc @@ -14,6 +14,8 @@ #include "shader_manager.h" #include "texture.h" +#undef DRAW_NORMALS + /* skybox */ static Mesh *skymesh; /* it will be used by many renderers => no destroy */ @@ -110,7 +112,8 @@ void Renderer::draw_object(Object *object) const object->mesh->draw(); - /* debug + // debug +#ifdef DRAW_NORMALS if(nprog) { int loc = nprog->get_uniform_location("mmviewproj"); if(loc != -1) { @@ -119,10 +122,7 @@ void Renderer::draw_object(Object *object) const nprog->use(); object->mesh->draw_normals(1.0); } - */ - - // if(m->dtex) - // m->dtex->unbind(); +#endif } void Renderer::set_sky_tex(Texture *stex) diff --git a/src/terrain.cc b/src/terrain.cc index ff54f46..c4db7ed 100644 --- a/src/terrain.cc +++ b/src/terrain.cc @@ -2,7 +2,6 @@ #include "camera.h" #include "gfxapi.h" -#include "image.h" #include "mesh.h" #include "meshgen.h" #include "object.h" @@ -33,6 +32,7 @@ void Terrain::destroy() } struct GenData { + const Terrain *terrain; const TerrainParams *tp; float xoffs; float yoffs; @@ -41,6 +41,7 @@ struct GenData { bool Terrain::generate(const TerrainParams ¶ms) { tiles.clear(); + this->params = params; float txsz = params.xsz / params.xtiles; float tysz = params.ysz / params.ytiles; @@ -51,6 +52,7 @@ bool Terrain::generate(const TerrainParams ¶ms) tile.mesh = gfx_create_mesh(); GenData data; + data.terrain = this; data.tp = ¶ms; data.xoffs = (float)j / (float)params.xtiles; data.yoffs = (float)i / (float)params.ytiles; @@ -88,24 +90,44 @@ Scene *Terrain::get_visible(const Camera *camera) const return vis_scene; } -static float calc_height(float u, float v, void *ptr) +float Terrain::get_height(const Vec3 &pos) const { - if(!ptr) { - fprintf(stderr, "Terrain parameters not found.\n"); + float x = pos.x; + float y = pos.z; + + float half_width = params.xsz / 2.0; + float half_height = params.ysz / 2.0; + + if(x < -half_width || x > half_width) return 0; + if(y < -half_height || y > half_height) + return 0; + + float u = (x + half_width) / params.xsz; + float v = (y + half_height) / params.ysz; + + return get_height(u, v) * params.max_height; +} + +float Terrain::get_height(float u, float v) const +{ + float sn = gph::fbm(u * params.noise_freq, v * params.noise_freq, params.num_octaves); + sn = sn * 0.5 + 0.5; + + if(params.coarse_heightmap.pixels) { + Vec4 texel = params.coarse_heightmap.lookup_nearest(u, v); + sn *= texel.x; } + return sn; +} +static float calc_height(float u, float v, void *ptr) +{ GenData *data = (GenData*)ptr; const TerrainParams *tp = data->tp; u = u / tp->xtiles + data->xoffs; v = v / tp->ytiles + data->yoffs; - float sn = gph::fbm(u * tp->noise_freq, v * tp->noise_freq, tp->num_octaves); - - if(tp->coarse_heightmap) { - Vec4 texel = tp->coarse_heightmap->lookup_nearest(u, v); - sn *= texel.x; - } - return sn; + return data->terrain->get_height(u, v); } \ No newline at end of file diff --git a/src/terrain.h b/src/terrain.h index bf9df09..db9464d 100644 --- a/src/terrain.h +++ b/src/terrain.h @@ -1,8 +1,9 @@ #ifndef TERRAIN_H_ #define TERRAIN_H_ +#include "image.h" + class Camera; -class Image; class Scene; // terrain 8a ftiaxnei skini k taisma renderer @@ -25,7 +26,7 @@ struct TerrainParams { int tile_vsub; int num_octaves; /* Perlin noise sums */ float noise_freq; /* Perlin noise scaling factor */ - Image *coarse_heightmap; /* mask for low detail heightmap */ + Image coarse_heightmap; /* mask for low detail heightmap */ }; class Terrain { @@ -46,6 +47,9 @@ public: bool generate(const TerrainParams ¶ms); Scene *get_visible(const Camera *camera) const; + + float get_height(float u, float v) const; + float get_height(const Vec3 &pos) const; /* world coordinates */ }; #endif // TERRAIN_H_ \ No newline at end of file