5 // ------ geosphere ------
8 /* icosahedron points */
9 static Vec3 icosa_pt[] = {
23 /* indices that map to 20hedron pts to create the polygons */
24 enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
25 static int icosa_idx[] = {
51 static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
60 /* we find mid points of the 3 vertices + normalize */
62 Vec3 v12 = normalize(v1 + v2);
63 Vec3 v23 = normalize(v2 + v3);
64 Vec3 v31 = normalize(v3 + v1);
66 /* create 4 triangles (recursive subdivision of the initial icosahedron */
68 geosphere(verts, v1, v12, v31, iter - 1);
69 geosphere(verts, v2, v23, v12, iter - 1);
70 geosphere(verts, v3, v31, v23, iter - 1);
71 geosphere(verts, v12, v23, v31, iter - 1);
74 void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
76 /* the triangles of the icosahedron (fixed) */
77 int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
79 std::vector<Vec3> verts;
80 for(int i=0; i<num_tri; i++) {
83 /* we select the 3 vertices from the i-th triangle of the 20hedron */
84 for(int j=0; j<3; j++) {
85 int vidx = icosa_idx[i * 3 + j];
86 v[j] = normalize(icosa_pt[vidx]);
89 /* if hemi, we discard the triangles of the lower part of the 20hedron */
90 if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
94 geosphere(&verts, v[0], v[1], v[2], subdiv);
97 /* now the verts contains all the sphere vertices */
99 int num_verts = (int)verts.size();
101 mesh->vertices.resize(num_verts);
102 mesh->normals.resize(num_verts);
103 mesh->tex_coords.resize(num_verts);
105 for(int i=0; i<num_verts; i++) {
106 mesh->vertices[i] = verts[i] * rad;
107 mesh->normals[i] = verts[i];
109 float theta = atan2(verts[i].z, verts[i].x);
110 float phi = acos(verts[i].y);
112 float u = 0.5 * theta / M_PI + 0.5;
113 float v = phi / M_PI;
114 mesh->tex_coords[i] = Vec2(u, v);
117 /* TODO: optimize indices by detecting the common vertices */
118 mesh->indices.resize(num_verts);
119 for(int i=0; i<num_verts; i++) {
120 mesh->indices[i] = i;
122 mesh->update_vertex_data();