get height, camera + cow movement with keys
[demo] / src / terrain.cc
1 #include <gmath/gmath.h>
2
3 #include "camera.h"
4 #include "gfxapi.h"
5 #include "mesh.h"
6 #include "meshgen.h"
7 #include "object.h"
8 #include "scene.h"
9 #include "terrain.h"
10
11 static float calc_height(float u, float v, void *ptr);
12
13 Terrain::Terrain()
14 {
15         vis_scene = 0;
16 }
17
18 Terrain::~Terrain()
19 {
20 }
21
22 bool Terrain::init()
23 {
24         vis_scene = new Scene;
25
26         return true;
27 }
28
29 void Terrain::destroy()
30 {
31         delete vis_scene;
32 }
33
34 struct GenData {
35         const Terrain *terrain;
36         const TerrainParams *tp;
37         float xoffs;
38         float yoffs;
39 };
40
41 bool Terrain::generate(const TerrainParams &params)
42 {
43         tiles.clear();
44         this->params = params;
45
46         float txsz = params.xsz / params.xtiles;
47         float tysz = params.ysz / params.ytiles;
48
49         for(int i=0; i<params.ytiles; i++) {
50                 for(int j=0; j<params.xtiles; j++) {
51                         TerrainTile tile;
52                         tile.mesh = gfx_create_mesh();
53
54                         GenData data;
55                         data.terrain = this;
56                         data.tp = &params;
57                         data.xoffs = (float)j / (float)params.xtiles;
58                         data.yoffs = (float)i / (float)params.ytiles;
59
60                         gen_heightfield(tile.mesh, txsz, tysz, params.max_height,
61                                         params.tile_usub, params.tile_vsub, calc_height,
62                                         (void*)&data);
63
64                         float xoffs = j * txsz - params.xsz / 2.0 + txsz / 2.0;
65                         float yoffs = i * tysz - params.ysz / 2.0 + tysz / 2.0;
66
67                         Mat4 offmat;
68                         offmat.translation(xoffs, 0, yoffs);
69                         tile.mesh->transform(offmat);
70
71                         tiles.push_back(tile);
72
73 /*
74         the terrain scene stores objects only
75         no need to fill the mat, mesh std::vectors
76 */
77                         Object *o = new Object;
78                         o->mesh = tile.mesh;
79                         o->material = &material;
80                         o->transform = Mat4::identity;
81
82                         vis_scene->objects.push_back(o);
83                 }
84         }
85         return true;
86 }
87
88 Scene *Terrain::get_visible(const Camera *camera) const
89 {
90         return vis_scene;
91 }
92
93 float Terrain::get_height(const Vec3 &pos) const
94 {
95         float x = pos.x;
96         float y = pos.z;
97
98         float half_width = params.xsz / 2.0;
99         float half_height = params.ysz / 2.0;
100
101         if(x < -half_width || x > half_width)
102                 return 0;
103         if(y < -half_height || y > half_height)
104                 return 0;
105
106         float u = (x + half_width) / params.xsz;
107         float v = (y + half_height) / params.ysz;
108
109         return get_height(u, v) * params.max_height;
110 }
111
112 float Terrain::get_height(float u, float v) const
113 {
114         float sn = gph::fbm(u * params.noise_freq, v * params.noise_freq, params.num_octaves);
115         sn = sn * 0.5 + 0.5;
116
117         if(params.coarse_heightmap.pixels) {
118                 Vec4 texel = params.coarse_heightmap.lookup_nearest(u, v);
119                 sn *= texel.x;
120         }
121         return sn;
122 }
123
124 static float calc_height(float u, float v, void *ptr)
125 {
126         GenData *data = (GenData*)ptr;
127         const TerrainParams *tp = data->tp;
128
129         u = u / tp->xtiles + data->xoffs;
130         v = v / tp->ytiles + data->yoffs;
131
132         return data->terrain->get_height(u, v);
133 }