quick backup of geosphere generation etc
[demo] / src / meshgen.cc
diff --git a/src/meshgen.cc b/src/meshgen.cc
new file mode 100644 (file)
index 0000000..fb4fae2
--- /dev/null
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include "meshgen.h"
+#include "mesh.h"
+
+// ------ geosphere ------
+#define PHI            1.618034
+
+/* icosahedron points */
+static Vec3 icosa_pt[] = {
+       Vec3(PHI, 1, 0),
+       Vec3(-PHI, 1, 0),
+       Vec3(PHI, -1, 0),
+       Vec3(-PHI, -1, 0),
+       Vec3(1, 0, PHI),
+       Vec3(1, 0, -PHI),
+       Vec3(-1, 0, PHI),
+       Vec3(-1, 0, -PHI),
+       Vec3(0, PHI, 1),
+       Vec3(0, -PHI, 1),
+       Vec3(0, PHI, -1),
+       Vec3(0, -PHI, -1)
+};
+/* indices that map to 20hedron pts to create the polygons */
+enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
+static int icosa_idx[] = {
+       P11, P31, P21,
+       P11, P22, P33,
+       P13, P21, P32,
+       P13, P34, P22,
+       P12, P23, P31,
+       P12, P33, P24,
+       P14, P32, P23,
+       P14, P24, P34,
+
+       P11, P33, P31,
+       P12, P31, P33,
+       P13, P32, P34,
+       P14, P34, P32,
+
+       P21, P13, P11,
+       P22, P11, P13,
+       P23, P12, P14,
+       P24, P14, P12,
+
+       P31, P23, P21,
+       P32, P21, P23,
+       P33, P22, P24,
+       P34, P24, P22
+};
+
+static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
+{
+       if(!iter) {
+               verts->push_back(v1);
+               verts->push_back(v2);
+               verts->push_back(v3);
+               return;
+       }
+
+       /* we find mid points of the 3 vertices + normalize */
+
+       Vec3 v12 = normalize(v1 + v2);
+       Vec3 v23 = normalize(v2 + v3);
+       Vec3 v31 = normalize(v3 + v1);
+
+       /* create 4 triangles (recursive subdivision of the initial icosahedron */
+
+       geosphere(verts, v1, v12, v31, iter - 1);
+       geosphere(verts, v2, v23, v12, iter - 1);
+       geosphere(verts, v3, v31, v23, iter - 1);
+       geosphere(verts, v12, v23, v31, iter - 1);
+}
+
+void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
+{
+       /* the triangles of the icosahedron (fixed) */
+       int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
+
+       std::vector<Vec3> verts;
+       for(int i=0; i<num_tri; i++) {
+               Vec3 v[3];
+
+               /* we select the 3 vertices from the i-th triangle of the 20hedron */
+               for(int j=0; j<3; j++) {
+                       int vidx = icosa_idx[i * 3 + j];
+                       v[j] = normalize(icosa_pt[vidx]);
+               }
+
+               /* if hemi, we discard the triangles of the lower part of the 20hedron */
+               if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
+                       continue;
+               }
+
+               geosphere(&verts, v[0], v[1], v[2], subdiv);
+       }
+
+       /* now the verts contains all the sphere vertices */
+
+       int num_verts = (int)verts.size();
+
+       mesh->vertices.resize(num_verts);
+       mesh->normals.resize(num_verts);
+       mesh->tex_coords.resize(num_verts);
+
+       for(int i=0; i<num_verts; i++) {
+               mesh->vertices[i] = verts[i] * rad;
+               mesh->normals[i] = verts[i];
+
+               float theta = atan2(verts[i].z, verts[i].x);
+               float phi = acos(verts[i].y);
+
+               float u = 0.5 * theta / M_PI + 0.5;
+               float v = phi / M_PI;
+               mesh->tex_coords[i] = Vec2(u, v);
+       }
+
+       /* TODO: optimize indices by detecting the common vertices */
+       mesh->indices.resize(num_verts);
+       for(int i=0; i<num_verts; i++) {
+               mesh->indices[i] = i;
+       }
+       mesh->update_vertex_data();
+}
\ No newline at end of file