mesh->indices[i] = i;
}
mesh->update_vertex_data();
-}
\ No newline at end of file
+}
+
+// ------ heightfield ------
+
+static Vec3 hfield_vertex(float u, float v, float h, float xsz,
+ float ysz, float height)
+{
+ float x = u * xsz - xsz / 2.0;
+ float y = h * height;
+ float z = v * ysz - ysz / 2.0;
+
+ return Vec3(x, y, z);
+}
+
+void gen_heightfield(Mesh *mesh, float xsz, float ysz, float height, int usub,
+ int vsub, float (*calc_height)(float u, float v, void *ptr), void *ptr)
+{
+ /*
+ usub and vsub is the number of subdivision at each axis
+ (heightfield = grid)
+ */
+ if(usub < 1)
+ usub = 1;
+
+ if(vsub < 1)
+ vsub = 1;
+
+ int num_uvertices = usub + 1;
+ int num_vvertices = vsub + 1;
+
+ int num_quads = usub * vsub;
+ int num_triangles = num_quads * 2;
+
+ int num_vertices = num_uvertices * num_vvertices;
+
+ mesh->vertices.resize(num_vertices);
+ mesh->normals.resize(num_vertices);
+ mesh->tex_coords.resize(num_vertices);
+ mesh->indices.resize(num_triangles * 3);
+
+ int vidx = 0;
+ float du = 1.0 / (float)num_uvertices;
+ float dv = 1.0 / (float)num_vvertices;
+
+ for(int i=0; i<num_vvertices; i++) {
+ float v = (float)i / (float)num_vvertices;
+ for(int j=0; j<num_uvertices; j++) {
+ float u = (float)j / (float)num_uvertices;
+ Vec3 vtx = hfield_vertex(u, v, calc_height(u, v, ptr), xsz, ysz, height);
+
+ /* calculating normal with forward differences:
+ slopes in x, z, axis */
+
+ Vec3 tangent = hfield_vertex(u + du, v, calc_height(u + du, v, ptr),
+ xsz, ysz, height) - vtx;
+
+ Vec3 bitangent = hfield_vertex(u, v + dv, calc_height(u, v + dv, ptr),
+ xsz, ysz, height) - vtx;
+
+ Vec3 normal = normalize(cross(tangent, bitangent));
+
+ mesh->vertices[vidx] = vtx;
+ mesh->normals[vidx] = normal;
+ mesh->tex_coords[vidx] = Vec2(u, v);
+
+ vidx++;
+ }
+ }
+
+ /*
+ indices:
+ */
+ uint16_t *iptr = &mesh->indices[0];
+
+ for(int i=0; i<vsub; i++) {
+ for(int j=0; j<usub; j++) {
+ int a = num_vvertices * i + j;
+ int b = a + 1;
+ int d = num_vvertices * (i + 1) + j;
+ int c = d + 1;
+
+ /* 1st triangle */
+
+ *iptr++ = a;
+ *iptr++ = b;
+ *iptr++ = c;
+
+ /* 2nd triangle */
+
+ *iptr++ = c;
+ *iptr++ = d;
+ *iptr++ = a;
+ }
+ }
+ mesh->update_vertex_data();
+}
#ifndef TERRAIN_H_
#define TERRAIN_H_
+class Camera;
+class Image;
+class Scene;
+// terrain 8a ftiaxnei skini k taisma renderer
+class TerrainTile {
+private:
+ Mesh *mesh;
+
+};
+
+/* parameters needed in terrain generation */
+
+struct TerrainParams {
+ float xsz; /* terrain size in x axis */
+ float ysz; /* terrain size in y axis */
+ float max_height; /* max height of the heightfield */
+ int xtiles; /* number of tiles in x axis */
+ int ytiles; /* number of tiles in y axis */
+ int tile_usub;
+ int tile_vsub;
+ int num_octaves; /* Perlin noise sums */
+ Image *coarse_heightmap; /* mask for low detail heightmap */
+};
+
+class Terrain {
+private:
+ TerrainParams params;
+ mutable Scene *vis_scene; /* set of visible tiles returned by get_visible */
+
+ std::vector<TerrainTile> tiles;
+
+public:
+ Terrain();
+ ~Terrain();
+
+ bool generate(const TerrainParams ¶ms);
+ Scene *get_visible(const Camera *camera) const;
+};
#endif // TERRAIN_H_
\ No newline at end of file