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;
125 // ------ heightfield ------
127 static Vec3 hfield_vertex(float u, float v, float h, float xsz,
128 float ysz, float height)
130 float x = u * xsz - xsz / 2.0;
131 float y = h * height;
132 float z = v * ysz - ysz / 2.0;
134 return Vec3(x, y, z);
137 void gen_heightfield(Mesh *mesh, float xsz, float ysz, float height, int usub,
138 int vsub, float (*calc_height)(float u, float v, void *ptr), void *ptr)
141 usub and vsub is the number of subdivision at each axis
150 int num_uvertices = usub + 1;
151 int num_vvertices = vsub + 1;
153 int num_quads = usub * vsub;
154 int num_triangles = num_quads * 2;
156 int num_vertices = num_uvertices * num_vvertices;
158 mesh->vertices.resize(num_vertices);
159 mesh->normals.resize(num_vertices);
160 mesh->tex_coords.resize(num_vertices);
161 mesh->indices.resize(num_triangles * 3);
164 float du = 1.0 / (float)num_uvertices;
165 float dv = 1.0 / (float)num_vvertices;
167 for(int i=0; i<num_vvertices; i++) {
168 float v = 1 - (float)i / (float)(num_vvertices - 1);
169 for(int j=0; j<num_uvertices; j++) {
170 float u = (float)j / (float)(num_uvertices - 1);
171 Vec3 vtx = hfield_vertex(u, v, calc_height(u, v, ptr), xsz, ysz, height);
173 /* calculating normal with forward differences:
174 slopes in x, z, axis */
176 Vec3 tangent = hfield_vertex(u + du, v, calc_height(u + du, v, ptr),
177 xsz, ysz, height) - vtx;
179 Vec3 bitangent = hfield_vertex(u, v + dv, calc_height(u, v + dv, ptr),
180 xsz, ysz, height) - vtx;
182 Vec3 normal = normalize(cross(bitangent, tangent));
184 mesh->vertices[vidx] = vtx;
185 mesh->normals[vidx] = normal;
186 mesh->tex_coords[vidx] = Vec2(u, v);
195 uint16_t *iptr = &mesh->indices[0];
197 for(int i=0; i<vsub; i++) {
198 for(int j=0; j<usub; j++) {
199 int a = num_vvertices * i + j;
201 int d = num_vvertices * (i + 1) + j;