cubemapper
view src/meshgen.cc @ 3:f5cc465eb735
save cubemaps of the same file format as the opened file
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 28 Jul 2017 15:50:00 +0300 |
parents | |
children | 2bfafdced01a |
line source
1 #include <stdio.h>
2 #include "meshgen.h"
3 #include "mesh.h"
5 // -------- sphere --------
7 #define SURAD(u) ((u) * 2.0 * M_PI)
8 #define SVRAD(v) ((v) * M_PI)
10 static Vec3 sphvec(float theta, float phi)
11 {
12 return Vec3(sin(theta) * sin(phi),
13 cos(phi),
14 cos(theta) * sin(phi));
15 }
17 void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
18 {
19 if(usub < 4) usub = 4;
20 if(vsub < 2) vsub = 2;
22 int uverts = usub + 1;
23 int vverts = vsub + 1;
25 int num_verts = uverts * vverts;
26 int num_quads = usub * vsub;
27 int num_tri = num_quads * 2;
29 mesh->clear();
30 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
31 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
32 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
33 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
34 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
36 float du = urange / (float)(uverts - 1);
37 float dv = vrange / (float)(vverts - 1);
39 float u = 0.0;
40 for(int i=0; i<uverts; i++) {
41 float theta = u * 2.0 * M_PI;
43 float v = 0.0;
44 for(int j=0; j<vverts; j++) {
45 float phi = v * M_PI;
47 Vec3 pos = sphvec(theta, phi);
49 *varr++ = pos * rad;
50 *narr++ = pos;
51 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
52 *uvarr++ = Vec2(u * urange, v * vrange);
54 if(i < usub && j < vsub) {
55 int idx = i * vverts + j;
56 *idxarr++ = idx;
57 *idxarr++ = idx + 1;
58 *idxarr++ = idx + vverts + 1;
60 *idxarr++ = idx;
61 *idxarr++ = idx + vverts + 1;
62 *idxarr++ = idx + vverts;
63 }
65 v += dv;
66 }
67 u += du;
68 }
69 }
71 // ------ geosphere ------
72 #define PHI 1.618034
74 static Vec3 icosa_pt[] = {
75 Vec3(PHI, 1, 0),
76 Vec3(-PHI, 1, 0),
77 Vec3(PHI, -1, 0),
78 Vec3(-PHI, -1, 0),
79 Vec3(1, 0, PHI),
80 Vec3(1, 0, -PHI),
81 Vec3(-1, 0, PHI),
82 Vec3(-1, 0, -PHI),
83 Vec3(0, PHI, 1),
84 Vec3(0, -PHI, 1),
85 Vec3(0, PHI, -1),
86 Vec3(0, -PHI, -1)
87 };
88 enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
89 static int icosa_idx[] = {
90 P11, P31, P21,
91 P11, P22, P33,
92 P13, P21, P32,
93 P13, P34, P22,
94 P12, P23, P31,
95 P12, P33, P24,
96 P14, P32, P23,
97 P14, P24, P34,
99 P11, P33, P31,
100 P12, P31, P33,
101 P13, P32, P34,
102 P14, P34, P32,
104 P21, P13, P11,
105 P22, P11, P13,
106 P23, P12, P14,
107 P24, P14, P12,
109 P31, P23, P21,
110 P32, P21, P23,
111 P33, P22, P24,
112 P34, P24, P22
113 };
115 static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
116 {
117 if(!iter) {
118 verts->push_back(v1);
119 verts->push_back(v2);
120 verts->push_back(v3);
121 return;
122 }
124 Vec3 v12 = normalize(v1 + v2);
125 Vec3 v23 = normalize(v2 + v3);
126 Vec3 v31 = normalize(v3 + v1);
128 geosphere(verts, v1, v12, v31, iter - 1);
129 geosphere(verts, v2, v23, v12, iter - 1);
130 geosphere(verts, v3, v31, v23, iter - 1);
131 geosphere(verts, v12, v23, v31, iter - 1);
132 }
134 void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
135 {
136 int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
138 std::vector<Vec3> verts;
139 for(int i=0; i<num_tri; i++) {
140 Vec3 v[3];
142 for(int j=0; j<3; j++) {
143 int vidx = icosa_idx[i * 3 + j];
144 v[j] = normalize(icosa_pt[vidx]);
145 }
147 if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
148 continue;
149 }
151 geosphere(&verts, v[0], v[1], v[2], subdiv);
152 }
154 int num_verts = (int)verts.size();
156 mesh->clear();
157 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
158 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
159 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
160 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
162 for(int i=0; i<num_verts; i++) {
163 *varr++ = verts[i] * rad;
164 *narr++ = verts[i];
166 float theta = atan2(verts[i].z, verts[i].x);
167 float phi = acos(verts[i].y);
169 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
171 float u = 0.5 * theta / M_PI + 0.5;
172 float v = phi / M_PI;
173 *uvarr++ = Vec2(u, v);
174 }
175 }
177 // -------- torus -----------
178 static Vec3 torusvec(float theta, float phi, float mr, float rr)
179 {
180 theta = -theta;
182 float rx = -cos(phi) * rr + mr;
183 float ry = sin(phi) * rr;
184 float rz = 0.0;
186 float x = rx * sin(theta) + rz * cos(theta);
187 float y = ry;
188 float z = -rx * cos(theta) + rz * sin(theta);
190 return Vec3(x, y, z);
191 }
193 void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange)
194 {
195 if(usub < 4) usub = 4;
196 if(vsub < 2) vsub = 2;
198 int uverts = usub + 1;
199 int vverts = vsub + 1;
201 int num_verts = uverts * vverts;
202 int num_quads = usub * vsub;
203 int num_tri = num_quads * 2;
205 mesh->clear();
206 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
207 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
208 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
209 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
210 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
212 float du = urange / (float)(uverts - 1);
213 float dv = vrange / (float)(vverts - 1);
215 float u = 0.0;
216 for(int i=0; i<uverts; i++) {
217 float theta = u * 2.0 * M_PI;
219 float v = 0.0;
220 for(int j=0; j<vverts; j++) {
221 float phi = v * 2.0 * M_PI;
223 Vec3 pos = torusvec(theta, phi, mainrad, ringrad);
224 Vec3 cent = torusvec(theta, phi, mainrad, 0.0);
226 *varr++ = pos;
227 *narr++ = (pos - cent) / ringrad;
229 Vec3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad);
230 Vec3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad);
232 *tarr++ = normalize(pnext - pprev);
233 *uvarr++ = Vec2(u * urange, v * vrange);
235 if(i < usub && j < vsub) {
236 int idx = i * vverts + j;
237 *idxarr++ = idx;
238 *idxarr++ = idx + 1;
239 *idxarr++ = idx + vverts + 1;
241 *idxarr++ = idx;
242 *idxarr++ = idx + vverts + 1;
243 *idxarr++ = idx + vverts;
244 }
246 v += dv;
247 }
248 u += du;
249 }
250 }
253 // -------- cylinder --------
255 static Vec3 cylvec(float theta, float height)
256 {
257 return Vec3(sin(theta), height, cos(theta));
258 }
260 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
261 {
262 if(usub < 4) usub = 4;
263 if(vsub < 1) vsub = 1;
265 int uverts = usub + 1;
266 int vverts = vsub + 1;
268 int num_body_verts = uverts * vverts;
269 int num_body_quads = usub * vsub;
270 int num_body_tri = num_body_quads * 2;
272 int capvverts = capsub ? capsub + 1 : 0;
273 int num_cap_verts = uverts * capvverts;
274 int num_cap_quads = usub * capsub;
275 int num_cap_tri = num_cap_quads * 2;
277 int num_verts = num_body_verts + num_cap_verts * 2;
278 int num_tri = num_body_tri + num_cap_tri * 2;
280 mesh->clear();
281 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
282 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
283 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
284 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
285 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
287 float du = urange / (float)(uverts - 1);
288 float dv = vrange / (float)(vverts - 1);
290 float u = 0.0;
291 for(int i=0; i<uverts; i++) {
292 float theta = SURAD(u);
294 float v = 0.0;
295 for(int j=0; j<vverts; j++) {
296 float y = (v - 0.5) * height;
297 Vec3 pos = cylvec(theta, y);
299 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
300 *narr++ = Vec3(pos.x, 0.0, pos.z);
301 *tarr++ = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
302 *uvarr++ = Vec2(u * urange, v * vrange);
304 if(i < usub && j < vsub) {
305 int idx = i * vverts + j;
307 *idxarr++ = idx;
308 *idxarr++ = idx + vverts + 1;
309 *idxarr++ = idx + 1;
311 *idxarr++ = idx;
312 *idxarr++ = idx + vverts;
313 *idxarr++ = idx + vverts + 1;
314 }
316 v += dv;
317 }
318 u += du;
319 }
322 // now the cap!
323 if(!capsub) {
324 return;
325 }
327 dv = 1.0 / (float)(capvverts - 1);
329 u = 0.0;
330 for(int i=0; i<uverts; i++) {
331 float theta = SURAD(u);
333 float v = 0.0;
334 for(int j=0; j<capvverts; j++) {
335 float r = v * rad;
337 Vec3 pos = cylvec(theta, height / 2.0) * r;
338 pos.y = height / 2.0;
339 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
341 *varr++ = pos;
342 *narr++ = Vec3(0, 1, 0);
343 *tarr++ = tang;
344 *uvarr++ = Vec2(u * urange, v);
346 pos.y = -height / 2.0;
347 *varr++ = pos;
348 *narr++ = Vec3(0, -1, 0);
349 *tarr++ = -tang;
350 *uvarr++ = Vec2(u * urange, v);
352 if(i < usub && j < capsub) {
353 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
355 unsigned int vidx[4] = {
356 idx,
357 idx + capvverts * 2,
358 idx + (capvverts + 1) * 2,
359 idx + 2
360 };
362 *idxarr++ = vidx[0];
363 *idxarr++ = vidx[2];
364 *idxarr++ = vidx[1];
365 *idxarr++ = vidx[0];
366 *idxarr++ = vidx[3];
367 *idxarr++ = vidx[2];
369 *idxarr++ = vidx[0] + 1;
370 *idxarr++ = vidx[1] + 1;
371 *idxarr++ = vidx[2] + 1;
372 *idxarr++ = vidx[0] + 1;
373 *idxarr++ = vidx[2] + 1;
374 *idxarr++ = vidx[3] + 1;
375 }
377 v += dv;
378 }
379 u += du;
380 }
381 }
383 // -------- cone --------
385 static Vec3 conevec(float theta, float y, float height)
386 {
387 float scale = 1.0 - y / height;
388 return Vec3(sin(theta) * scale, y, cos(theta) * scale);
389 }
391 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
392 {
393 if(usub < 4) usub = 4;
394 if(vsub < 1) vsub = 1;
396 int uverts = usub + 1;
397 int vverts = vsub + 1;
399 int num_body_verts = uverts * vverts;
400 int num_body_quads = usub * vsub;
401 int num_body_tri = num_body_quads * 2;
403 int capvverts = capsub ? capsub + 1 : 0;
404 int num_cap_verts = uverts * capvverts;
405 int num_cap_quads = usub * capsub;
406 int num_cap_tri = num_cap_quads * 2;
408 int num_verts = num_body_verts + num_cap_verts;
409 int num_tri = num_body_tri + num_cap_tri;
411 mesh->clear();
412 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
413 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
414 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
415 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
416 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
418 float du = urange / (float)(uverts - 1);
419 float dv = vrange / (float)(vverts - 1);
421 float u = 0.0;
422 for(int i=0; i<uverts; i++) {
423 float theta = SURAD(u);
425 float v = 0.0;
426 for(int j=0; j<vverts; j++) {
427 float y = v * height;
428 Vec3 pos = conevec(theta, y, height);
430 Vec3 tang = normalize(conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height));
431 Vec3 bitang = normalize(conevec(theta, y + 0.1, height) - pos);
433 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
434 *narr++ = cross(tang, bitang);
435 *tarr++ = tang;
436 *uvarr++ = Vec2(u * urange, v * vrange);
438 if(i < usub && j < vsub) {
439 int idx = i * vverts + j;
441 *idxarr++ = idx;
442 *idxarr++ = idx + vverts + 1;
443 *idxarr++ = idx + 1;
445 *idxarr++ = idx;
446 *idxarr++ = idx + vverts;
447 *idxarr++ = idx + vverts + 1;
448 }
450 v += dv;
451 }
452 u += du;
453 }
456 // now the bottom cap!
457 if(!capsub) {
458 return;
459 }
461 dv = 1.0 / (float)(capvverts - 1);
463 u = 0.0;
464 for(int i=0; i<uverts; i++) {
465 float theta = SURAD(u);
467 float v = 0.0;
468 for(int j=0; j<capvverts; j++) {
469 float r = v * rad;
471 Vec3 pos = conevec(theta, 0.0, height) * r;
472 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
474 *varr++ = pos;
475 *narr++ = Vec3(0, -1, 0);
476 *tarr++ = tang;
477 *uvarr++ = Vec2(u * urange, v);
479 if(i < usub && j < capsub) {
480 unsigned int idx = num_body_verts + i * capvverts + j;
482 unsigned int vidx[4] = {
483 idx,
484 idx + capvverts,
485 idx + (capvverts + 1),
486 idx + 1
487 };
489 *idxarr++ = vidx[0];
490 *idxarr++ = vidx[1];
491 *idxarr++ = vidx[2];
492 *idxarr++ = vidx[0];
493 *idxarr++ = vidx[2];
494 *idxarr++ = vidx[3];
495 }
497 v += dv;
498 }
499 u += du;
500 }
501 }
504 // -------- plane --------
506 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
507 {
508 gen_heightmap(mesh, width, height, usub, vsub, 0);
509 }
512 // ----- heightmap ------
514 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
515 {
516 if(usub < 1) usub = 1;
517 if(vsub < 1) vsub = 1;
519 mesh->clear();
521 int uverts = usub + 1;
522 int vverts = vsub + 1;
523 int num_verts = uverts * vverts;
525 int num_quads = usub * vsub;
526 int num_tri = num_quads * 2;
528 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
529 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
530 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
531 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
532 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
534 float du = 1.0 / (float)usub;
535 float dv = 1.0 / (float)vsub;
537 float u = 0.0;
538 for(int i=0; i<uverts; i++) {
539 float v = 0.0;
540 for(int j=0; j<vverts; j++) {
541 float x = (u - 0.5) * width;
542 float y = (v - 0.5) * height;
543 float z = hf ? hf(u, v, hfdata) : 0.0;
545 Vec3 normal = Vec3(0, 0, 1);
546 if(hf) {
547 float u1z = hf(u + du, v, hfdata);
548 float v1z = hf(u, v + dv, hfdata);
550 Vec3 tang = Vec3(du * width, 0, u1z - z);
551 Vec3 bitan = Vec3(0, dv * height, v1z - z);
552 normal = normalize(cross(tang, bitan));
553 }
555 *varr++ = Vec3(x, y, z);
556 *narr++ = normal;
557 *tarr++ = Vec3(1, 0, 0);
558 *uvarr++ = Vec2(u, v);
560 if(i < usub && j < vsub) {
561 int idx = i * vverts + j;
563 *idxarr++ = idx;
564 *idxarr++ = idx + vverts + 1;
565 *idxarr++ = idx + 1;
567 *idxarr++ = idx;
568 *idxarr++ = idx + vverts;
569 *idxarr++ = idx + vverts + 1;
570 }
572 v += dv;
573 }
574 u += du;
575 }
576 }
578 // ----- box ------
579 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
580 {
581 static const float face_angles[][2] = {
582 {0, 0},
583 {M_PI / 2.0, 0},
584 {M_PI, 0},
585 {3.0 * M_PI / 2.0, 0},
586 {0, M_PI / 2.0},
587 {0, -M_PI / 2.0}
588 };
590 if(usub < 1) usub = 1;
591 if(vsub < 1) vsub = 1;
593 mesh->clear();
595 for(int i=0; i<6; i++) {
596 Mat4 xform, dir_xform;
597 Mesh m;
599 gen_plane(&m, 1, 1, usub, vsub);
600 xform.rotate(Vec3(face_angles[i][1], face_angles[i][0], 0));
601 dir_xform = xform;
602 xform.translate(Vec3(0, 0, 0.5));
603 m.apply_xform(xform, dir_xform);
605 mesh->append(m);
606 }
608 Mat4 scale;
609 scale.scaling(xsz, ysz, zsz);
610 mesh->apply_xform(scale, Mat4::identity);
611 }
613 /*
614 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
615 {
616 mesh->clear();
618 const int num_faces = 6;
619 int num_verts = num_faces * 4;
620 int num_tri = num_faces * 2;
622 float x = xsz / 2.0;
623 float y = ysz / 2.0;
624 float z = zsz / 2.0;
626 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
627 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
628 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
629 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
630 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
632 static const Vec2 uv[] = { Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1) };
634 // front
635 for(int i=0; i<4; i++) {
636 *narr++ = Vec3(0, 0, 1);
637 *tarr++ = Vec3(1, 0, 0);
638 *uvarr++ = uv[i];
639 }
640 *varr++ = Vec3(-x, -y, z);
641 *varr++ = Vec3(x, -y, z);
642 *varr++ = Vec3(x, y, z);
643 *varr++ = Vec3(-x, y, z);
644 // right
645 for(int i=0; i<4; i++) {
646 *narr++ = Vec3(1, 0, 0);
647 *tarr++ = Vec3(0, 0, -1);
648 *uvarr++ = uv[i];
649 }
650 *varr++ = Vec3(x, -y, z);
651 *varr++ = Vec3(x, -y, -z);
652 *varr++ = Vec3(x, y, -z);
653 *varr++ = Vec3(x, y, z);
654 // back
655 for(int i=0; i<4; i++) {
656 *narr++ = Vec3(0, 0, -1);
657 *tarr++ = Vec3(-1, 0, 0);
658 *uvarr++ = uv[i];
659 }
660 *varr++ = Vec3(x, -y, -z);
661 *varr++ = Vec3(-x, -y, -z);
662 *varr++ = Vec3(-x, y, -z);
663 *varr++ = Vec3(x, y, -z);
664 // left
665 for(int i=0; i<4; i++) {
666 *narr++ = Vec3(-1, 0, 0);
667 *tarr++ = Vec3(0, 0, 1);
668 *uvarr++ = uv[i];
669 }
670 *varr++ = Vec3(-x, -y, -z);
671 *varr++ = Vec3(-x, -y, z);
672 *varr++ = Vec3(-x, y, z);
673 *varr++ = Vec3(-x, y, -z);
674 // top
675 for(int i=0; i<4; i++) {
676 *narr++ = Vec3(0, 1, 0);
677 *tarr++ = Vec3(1, 0, 0);
678 *uvarr++ = uv[i];
679 }
680 *varr++ = Vec3(-x, y, z);
681 *varr++ = Vec3(x, y, z);
682 *varr++ = Vec3(x, y, -z);
683 *varr++ = Vec3(-x, y, -z);
684 // bottom
685 for(int i=0; i<4; i++) {
686 *narr++ = Vec3(0, -1, 0);
687 *tarr++ = Vec3(1, 0, 0);
688 *uvarr++ = uv[i];
689 }
690 *varr++ = Vec3(-x, -y, -z);
691 *varr++ = Vec3(x, -y, -z);
692 *varr++ = Vec3(x, -y, z);
693 *varr++ = Vec3(-x, -y, z);
695 // index array
696 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
697 for(int i=0; i<num_faces; i++) {
698 for(int j=0; j<6; j++) {
699 *idxarr++ = faceidx[j] + i * 4;
700 }
701 }
702 }
703 */
705 static inline Vec3 rev_vert(float u, float v, Vec2 (*rf)(float, float, void*), void *cls)
706 {
707 Vec2 pos = rf(u, v, cls);
709 float angle = u * 2.0 * M_PI;
710 float x = pos.x * cos(angle);
711 float y = pos.y;
712 float z = pos.x * sin(angle);
714 return Vec3(x, y, z);
715 }
717 // ------ surface of revolution -------
718 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*), void *cls)
719 {
720 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
721 }
723 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*),
724 Vec2 (*nfunc)(float, float, void*), void *cls)
725 {
726 if(!rfunc) return;
727 if(usub < 3) usub = 3;
728 if(vsub < 1) vsub = 1;
730 mesh->clear();
732 int uverts = usub + 1;
733 int vverts = vsub + 1;
734 int num_verts = uverts * vverts;
736 int num_quads = usub * vsub;
737 int num_tri = num_quads * 2;
739 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
740 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
741 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
742 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
743 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
745 float du = 1.0 / (float)(uverts - 1);
746 float dv = 1.0 / (float)(vverts - 1);
748 float u = 0.0;
749 for(int i=0; i<uverts; i++) {
750 float v = 0.0;
751 for(int j=0; j<vverts; j++) {
752 Vec3 pos = rev_vert(u, v, rfunc, cls);
754 Vec3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
755 Vec3 tang = nextu - pos;
756 if(length_sq(tang) < 1e-6) {
757 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
758 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
759 tang = nextu - pos;
760 }
762 Vec3 normal;
763 if(nfunc) {
764 normal = rev_vert(u, v, nfunc, cls);
765 } else {
766 Vec3 nextv = rev_vert(u, v + dv, rfunc, cls);
767 Vec3 bitan = nextv - pos;
768 if(length_sq(bitan) < 1e-6) {
769 nextv = rev_vert(u, v - dv, rfunc, cls);
770 bitan = pos - nextv;
771 }
773 normal = cross(tang, bitan);
774 }
776 *varr++ = pos;
777 *narr++ = normalize(normal);
778 *tarr++ = normalize(tang);
779 *uvarr++ = Vec2(u, v);
781 if(i < usub && j < vsub) {
782 int idx = i * vverts + j;
784 *idxarr++ = idx;
785 *idxarr++ = idx + vverts + 1;
786 *idxarr++ = idx + 1;
788 *idxarr++ = idx;
789 *idxarr++ = idx + vverts;
790 *idxarr++ = idx + vverts + 1;
791 }
793 v += dv;
794 }
795 u += du;
796 }
797 }
800 static inline Vec3 sweep_vert(float u, float v, float height, Vec2 (*sf)(float, float, void*), void *cls)
801 {
802 Vec2 pos = sf(u, v, cls);
804 float x = pos.x;
805 float y = v * height;
806 float z = pos.y;
808 return Vec3(x, y, z);
809 }
811 // ---- sweep shape along a path ----
812 void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vec2 (*sfunc)(float, float, void*), void *cls)
813 {
814 if(!sfunc) return;
815 if(usub < 3) usub = 3;
816 if(vsub < 1) vsub = 1;
818 mesh->clear();
820 int uverts = usub + 1;
821 int vverts = vsub + 1;
822 int num_verts = uverts * vverts;
824 int num_quads = usub * vsub;
825 int num_tri = num_quads * 2;
827 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
828 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
829 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
830 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
831 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
833 float du = 1.0 / (float)(uverts - 1);
834 float dv = 1.0 / (float)(vverts - 1);
836 float u = 0.0;
837 for(int i=0; i<uverts; i++) {
838 float v = 0.0;
839 for(int j=0; j<vverts; j++) {
840 Vec3 pos = sweep_vert(u, v, height, sfunc, cls);
842 Vec3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls);
843 Vec3 tang = nextu - pos;
844 if(length_sq(tang) < 1e-6) {
845 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
846 nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls);
847 tang = nextu - pos;
848 }
850 Vec3 normal;
851 Vec3 nextv = sweep_vert(u, v + dv, height, sfunc, cls);
852 Vec3 bitan = nextv - pos;
853 if(length_sq(bitan) < 1e-6) {
854 nextv = sweep_vert(u, v - dv, height, sfunc, cls);
855 bitan = pos - nextv;
856 }
858 normal = cross(tang, bitan);
860 *varr++ = pos;
861 *narr++ = normalize(normal);
862 *tarr++ = normalize(tang);
863 *uvarr++ = Vec2(u, v);
865 if(i < usub && j < vsub) {
866 int idx = i * vverts + j;
868 *idxarr++ = idx;
869 *idxarr++ = idx + vverts + 1;
870 *idxarr++ = idx + 1;
872 *idxarr++ = idx;
873 *idxarr++ = idx + vverts;
874 *idxarr++ = idx + vverts + 1;
875 }
877 v += dv;
878 }
879 u += du;
880 }
881 }