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)
12 return Vec3(sin(theta) * sin(phi),
14 cos(theta) * sin(phi));
17 void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
19 if(urange == 0.0 || vrange == 0.0) return;
21 if(usub < 4) usub = 4;
22 if(vsub < 2) vsub = 2;
24 int uverts = usub + 1;
25 int vverts = vsub + 1;
27 int num_verts = uverts * vverts;
28 int num_quads = usub * vsub;
29 int num_tri = num_quads * 2;
32 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
33 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
34 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
35 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
36 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
38 float du = urange / (float)(uverts - 1);
39 float dv = vrange / (float)(vverts - 1);
42 for(int i=0; i<uverts; i++) {
43 float theta = u * 2.0 * M_PI;
46 for(int j=0; j<vverts; j++) {
49 Vec3 pos = sphvec(theta, phi);
53 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
54 *uvarr++ = Vec2(u / urange, v / vrange);
56 if(i < usub && j < vsub) {
57 int idx = i * vverts + j;
60 *idxarr++ = idx + vverts + 1;
63 *idxarr++ = idx + vverts + 1;
64 *idxarr++ = idx + vverts;
73 // ------ geosphere ------
76 static Vec3 icosa_pt[] = {
90 enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 };
91 static int icosa_idx[] = {
117 static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter)
120 verts->push_back(v1);
121 verts->push_back(v2);
122 verts->push_back(v3);
126 Vec3 v12 = normalize(v1 + v2);
127 Vec3 v23 = normalize(v2 + v3);
128 Vec3 v31 = normalize(v3 + v1);
130 geosphere(verts, v1, v12, v31, iter - 1);
131 geosphere(verts, v2, v23, v12, iter - 1);
132 geosphere(verts, v3, v31, v23, iter - 1);
133 geosphere(verts, v12, v23, v31, iter - 1);
136 void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi)
138 int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3;
140 std::vector<Vec3> verts;
141 for(int i=0; i<num_tri; i++) {
144 for(int j=0; j<3; j++) {
145 int vidx = icosa_idx[i * 3 + j];
146 v[j] = normalize(icosa_pt[vidx]);
149 if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) {
153 geosphere(&verts, v[0], v[1], v[2], subdiv);
156 int num_verts = (int)verts.size();
159 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
160 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
161 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
162 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
164 for(int i=0; i<num_verts; i++) {
165 *varr++ = verts[i] * rad;
168 float theta = atan2(verts[i].z, verts[i].x);
169 float phi = acos(verts[i].y);
171 *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f));
173 float u = 0.5 * theta / M_PI + 0.5;
174 float v = phi / M_PI;
175 *uvarr++ = Vec2(u, v);
179 // -------- torus -----------
180 static Vec3 torusvec(float theta, float phi, float mr, float rr)
184 float rx = -cos(phi) * rr + mr;
185 float ry = sin(phi) * rr;
188 float x = rx * sin(theta) + rz * cos(theta);
190 float z = -rx * cos(theta) + rz * sin(theta);
192 return Vec3(x, y, z);
195 void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange)
197 if(usub < 4) usub = 4;
198 if(vsub < 2) vsub = 2;
200 int uverts = usub + 1;
201 int vverts = vsub + 1;
203 int num_verts = uverts * vverts;
204 int num_quads = usub * vsub;
205 int num_tri = num_quads * 2;
208 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
209 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
210 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
211 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
212 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
214 float du = urange / (float)(uverts - 1);
215 float dv = vrange / (float)(vverts - 1);
218 for(int i=0; i<uverts; i++) {
219 float theta = u * 2.0 * M_PI;
222 for(int j=0; j<vverts; j++) {
223 float phi = v * 2.0 * M_PI;
225 Vec3 pos = torusvec(theta, phi, mainrad, ringrad);
226 Vec3 cent = torusvec(theta, phi, mainrad, 0.0);
229 *narr++ = (pos - cent) / ringrad;
231 Vec3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad);
232 Vec3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad);
234 *tarr++ = normalize(pnext - pprev);
235 *uvarr++ = Vec2(u * urange, v * vrange);
237 if(i < usub && j < vsub) {
238 int idx = i * vverts + j;
241 *idxarr++ = idx + vverts + 1;
244 *idxarr++ = idx + vverts + 1;
245 *idxarr++ = idx + vverts;
255 // -------- cylinder --------
257 static Vec3 cylvec(float theta, float height)
259 return Vec3(sin(theta), height, cos(theta));
262 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
264 if(usub < 4) usub = 4;
265 if(vsub < 1) vsub = 1;
267 int uverts = usub + 1;
268 int vverts = vsub + 1;
270 int num_body_verts = uverts * vverts;
271 int num_body_quads = usub * vsub;
272 int num_body_tri = num_body_quads * 2;
274 int capvverts = capsub ? capsub + 1 : 0;
275 int num_cap_verts = uverts * capvverts;
276 int num_cap_quads = usub * capsub;
277 int num_cap_tri = num_cap_quads * 2;
279 int num_verts = num_body_verts + num_cap_verts * 2;
280 int num_tri = num_body_tri + num_cap_tri * 2;
283 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
284 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
285 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
286 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
287 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
289 float du = urange / (float)(uverts - 1);
290 float dv = vrange / (float)(vverts - 1);
293 for(int i=0; i<uverts; i++) {
294 float theta = SURAD(u);
297 for(int j=0; j<vverts; j++) {
298 float y = (v - 0.5) * height;
299 Vec3 pos = cylvec(theta, y);
301 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
302 *narr++ = Vec3(pos.x, 0.0, pos.z);
303 *tarr++ = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
304 *uvarr++ = Vec2(u * urange, v * vrange);
306 if(i < usub && j < vsub) {
307 int idx = i * vverts + j;
310 *idxarr++ = idx + vverts + 1;
314 *idxarr++ = idx + vverts;
315 *idxarr++ = idx + vverts + 1;
329 dv = 1.0 / (float)(capvverts - 1);
332 for(int i=0; i<uverts; i++) {
333 float theta = SURAD(u);
336 for(int j=0; j<capvverts; j++) {
339 Vec3 pos = cylvec(theta, height / 2.0) * r;
340 pos.y = height / 2.0;
341 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
344 *narr++ = Vec3(0, 1, 0);
346 *uvarr++ = Vec2(u * urange, v);
348 pos.y = -height / 2.0;
350 *narr++ = Vec3(0, -1, 0);
352 *uvarr++ = Vec2(u * urange, v);
354 if(i < usub && j < capsub) {
355 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
357 unsigned int vidx[4] = {
360 idx + (capvverts + 1) * 2,
371 *idxarr++ = vidx[0] + 1;
372 *idxarr++ = vidx[1] + 1;
373 *idxarr++ = vidx[2] + 1;
374 *idxarr++ = vidx[0] + 1;
375 *idxarr++ = vidx[2] + 1;
376 *idxarr++ = vidx[3] + 1;
385 // -------- cone --------
387 static Vec3 conevec(float theta, float y, float height)
389 float scale = 1.0 - y / height;
390 return Vec3(sin(theta) * scale, y, cos(theta) * scale);
393 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
395 if(usub < 4) usub = 4;
396 if(vsub < 1) vsub = 1;
398 int uverts = usub + 1;
399 int vverts = vsub + 1;
401 int num_body_verts = uverts * vverts;
402 int num_body_quads = usub * vsub;
403 int num_body_tri = num_body_quads * 2;
405 int capvverts = capsub ? capsub + 1 : 0;
406 int num_cap_verts = uverts * capvverts;
407 int num_cap_quads = usub * capsub;
408 int num_cap_tri = num_cap_quads * 2;
410 int num_verts = num_body_verts + num_cap_verts;
411 int num_tri = num_body_tri + num_cap_tri;
414 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
415 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
416 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
417 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
418 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
420 float du = urange / (float)(uverts - 1);
421 float dv = vrange / (float)(vverts - 1);
424 for(int i=0; i<uverts; i++) {
425 float theta = SURAD(u);
428 for(int j=0; j<vverts; j++) {
429 float y = v * height;
430 Vec3 pos = conevec(theta, y, height);
432 Vec3 tang = normalize(conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height));
433 Vec3 bitang = normalize(conevec(theta, y + 0.1, height) - pos);
435 *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad);
436 *narr++ = cross(tang, bitang);
438 *uvarr++ = Vec2(u * urange, v * vrange);
440 if(i < usub && j < vsub) {
441 int idx = i * vverts + j;
444 *idxarr++ = idx + vverts + 1;
448 *idxarr++ = idx + vverts;
449 *idxarr++ = idx + vverts + 1;
458 // now the bottom cap!
463 dv = 1.0 / (float)(capvverts - 1);
466 for(int i=0; i<uverts; i++) {
467 float theta = SURAD(u);
470 for(int j=0; j<capvverts; j++) {
473 Vec3 pos = conevec(theta, 0.0, height) * r;
474 Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0));
477 *narr++ = Vec3(0, -1, 0);
479 *uvarr++ = Vec2(u * urange, v);
481 if(i < usub && j < capsub) {
482 unsigned int idx = num_body_verts + i * capvverts + j;
484 unsigned int vidx[4] = {
487 idx + (capvverts + 1),
506 // -------- plane --------
508 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
510 gen_heightmap(mesh, width, height, usub, vsub, 0);
514 // ----- heightmap ------
516 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
518 if(usub < 1) usub = 1;
519 if(vsub < 1) vsub = 1;
523 int uverts = usub + 1;
524 int vverts = vsub + 1;
525 int num_verts = uverts * vverts;
527 int num_quads = usub * vsub;
528 int num_tri = num_quads * 2;
530 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
531 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
532 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
533 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
534 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
536 float du = 1.0 / (float)usub;
537 float dv = 1.0 / (float)vsub;
540 for(int i=0; i<uverts; i++) {
542 for(int j=0; j<vverts; j++) {
543 float x = (u - 0.5) * width;
544 float y = (v - 0.5) * height;
545 float z = hf ? hf(u, v, hfdata) : 0.0;
547 Vec3 normal = Vec3(0, 0, 1);
549 float u1z = hf(u + du, v, hfdata);
550 float v1z = hf(u, v + dv, hfdata);
552 Vec3 tang = Vec3(du * width, 0, u1z - z);
553 Vec3 bitan = Vec3(0, dv * height, v1z - z);
554 normal = normalize(cross(tang, bitan));
557 *varr++ = Vec3(x, y, z);
559 *tarr++ = Vec3(1, 0, 0);
560 *uvarr++ = Vec2(u, v);
562 if(i < usub && j < vsub) {
563 int idx = i * vverts + j;
566 *idxarr++ = idx + vverts + 1;
570 *idxarr++ = idx + vverts;
571 *idxarr++ = idx + vverts + 1;
581 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
583 static const float face_angles[][2] = {
587 {3.0 * M_PI / 2.0, 0},
592 if(usub < 1) usub = 1;
593 if(vsub < 1) vsub = 1;
597 for(int i=0; i<6; i++) {
598 Mat4 xform, dir_xform;
601 gen_plane(&m, 1, 1, usub, vsub);
602 xform.translate(Vec3(0, 0, 0.5));
603 xform.rotate(Vec3(face_angles[i][1], face_angles[i][0], 0));
605 m.apply_xform(xform, dir_xform);
611 scale.scaling(xsz, ysz, zsz);
612 mesh->apply_xform(scale, Mat4::identity);
616 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
620 const int num_faces = 6;
621 int num_verts = num_faces * 4;
622 int num_tri = num_faces * 2;
628 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
629 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
630 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
631 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
632 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
634 static const Vec2 uv[] = { Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1) };
637 for(int i=0; i<4; i++) {
638 *narr++ = Vec3(0, 0, 1);
639 *tarr++ = Vec3(1, 0, 0);
642 *varr++ = Vec3(-x, -y, z);
643 *varr++ = Vec3(x, -y, z);
644 *varr++ = Vec3(x, y, z);
645 *varr++ = Vec3(-x, y, z);
647 for(int i=0; i<4; i++) {
648 *narr++ = Vec3(1, 0, 0);
649 *tarr++ = Vec3(0, 0, -1);
652 *varr++ = Vec3(x, -y, z);
653 *varr++ = Vec3(x, -y, -z);
654 *varr++ = Vec3(x, y, -z);
655 *varr++ = Vec3(x, y, z);
657 for(int i=0; i<4; i++) {
658 *narr++ = Vec3(0, 0, -1);
659 *tarr++ = Vec3(-1, 0, 0);
662 *varr++ = Vec3(x, -y, -z);
663 *varr++ = Vec3(-x, -y, -z);
664 *varr++ = Vec3(-x, y, -z);
665 *varr++ = Vec3(x, y, -z);
667 for(int i=0; i<4; i++) {
668 *narr++ = Vec3(-1, 0, 0);
669 *tarr++ = Vec3(0, 0, 1);
672 *varr++ = Vec3(-x, -y, -z);
673 *varr++ = Vec3(-x, -y, z);
674 *varr++ = Vec3(-x, y, z);
675 *varr++ = Vec3(-x, y, -z);
677 for(int i=0; i<4; i++) {
678 *narr++ = Vec3(0, 1, 0);
679 *tarr++ = Vec3(1, 0, 0);
682 *varr++ = Vec3(-x, y, z);
683 *varr++ = Vec3(x, y, z);
684 *varr++ = Vec3(x, y, -z);
685 *varr++ = Vec3(-x, y, -z);
687 for(int i=0; i<4; i++) {
688 *narr++ = Vec3(0, -1, 0);
689 *tarr++ = Vec3(1, 0, 0);
692 *varr++ = Vec3(-x, -y, -z);
693 *varr++ = Vec3(x, -y, -z);
694 *varr++ = Vec3(x, -y, z);
695 *varr++ = Vec3(-x, -y, z);
698 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
699 for(int i=0; i<num_faces; i++) {
700 for(int j=0; j<6; j++) {
701 *idxarr++ = faceidx[j] + i * 4;
707 static inline Vec3 rev_vert(float u, float v, Vec2 (*rf)(float, float, void*), void *cls)
709 Vec2 pos = rf(u, v, cls);
711 float angle = u * 2.0 * M_PI;
712 float x = pos.x * cos(angle);
714 float z = pos.x * sin(angle);
716 return Vec3(x, y, z);
719 // ------ surface of revolution -------
720 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*), void *cls)
722 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
725 void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*),
726 Vec2 (*nfunc)(float, float, void*), void *cls)
729 if(usub < 3) usub = 3;
730 if(vsub < 1) vsub = 1;
734 int uverts = usub + 1;
735 int vverts = vsub + 1;
736 int num_verts = uverts * vverts;
738 int num_quads = usub * vsub;
739 int num_tri = num_quads * 2;
741 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
742 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
743 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
744 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
745 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
747 float du = 1.0 / (float)(uverts - 1);
748 float dv = 1.0 / (float)(vverts - 1);
751 for(int i=0; i<uverts; i++) {
753 for(int j=0; j<vverts; j++) {
754 Vec3 pos = rev_vert(u, v, rfunc, cls);
756 Vec3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
757 Vec3 tang = nextu - pos;
758 if(length_sq(tang) < 1e-6) {
759 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
760 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
766 normal = rev_vert(u, v, nfunc, cls);
768 Vec3 nextv = rev_vert(u, v + dv, rfunc, cls);
769 Vec3 bitan = nextv - pos;
770 if(length_sq(bitan) < 1e-6) {
771 nextv = rev_vert(u, v - dv, rfunc, cls);
775 normal = cross(tang, bitan);
779 *narr++ = normalize(normal);
780 *tarr++ = normalize(tang);
781 *uvarr++ = Vec2(u, v);
783 if(i < usub && j < vsub) {
784 int idx = i * vverts + j;
787 *idxarr++ = idx + vverts + 1;
791 *idxarr++ = idx + vverts;
792 *idxarr++ = idx + vverts + 1;
802 static inline Vec3 sweep_vert(float u, float v, float height, Vec2 (*sf)(float, float, void*), void *cls)
804 Vec2 pos = sf(u, v, cls);
807 float y = v * height;
810 return Vec3(x, y, z);
813 // ---- sweep shape along a path ----
814 void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vec2 (*sfunc)(float, float, void*), void *cls)
817 if(usub < 3) usub = 3;
818 if(vsub < 1) vsub = 1;
822 int uverts = usub + 1;
823 int vverts = vsub + 1;
824 int num_verts = uverts * vverts;
826 int num_quads = usub * vsub;
827 int num_tri = num_quads * 2;
829 Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
830 Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
831 Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
832 Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
833 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
835 float du = 1.0 / (float)(uverts - 1);
836 float dv = 1.0 / (float)(vverts - 1);
839 for(int i=0; i<uverts; i++) {
841 for(int j=0; j<vverts; j++) {
842 Vec3 pos = sweep_vert(u, v, height, sfunc, cls);
844 Vec3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls);
845 Vec3 tang = nextu - pos;
846 if(length_sq(tang) < 1e-6) {
847 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
848 nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls);
853 Vec3 nextv = sweep_vert(u, v + dv, height, sfunc, cls);
854 Vec3 bitan = nextv - pos;
855 if(length_sq(bitan) < 1e-6) {
856 nextv = sweep_vert(u, v - dv, height, sfunc, cls);
860 normal = cross(tang, bitan);
863 *narr++ = normalize(normal);
864 *tarr++ = normalize(tang);
865 *uvarr++ = Vec2(u, v);
867 if(i < usub && j < vsub) {
868 int idx = i * vverts + j;
871 *idxarr++ = idx + vverts + 1;
875 *idxarr++ = idx + vverts;
876 *idxarr++ = idx + vverts + 1;