added function that procedurally generates heightfield
[demo] / src / meshgen.cc
index fb4fae2..ff7906d 100644 (file)
@@ -120,4 +120,99 @@ void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
                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();
+}