ld33_umonster

view src/meshgen.cc @ 10:1b30bd381667

sweep curve mesh gen and dragon horns
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 27 Aug 2015 05:25:04 +0300
parents 7b1fa527b51b
children
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 Vector3 sphvec(float theta, float phi)
11 {
12 return Vector3(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 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
31 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
32 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
33 Vector2 *uvarr = (Vector2*)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 Vector3 pos = sphvec(theta, phi);
49 *varr++ = pos * rad;
50 *narr++ = pos;
51 *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized();
52 *uvarr++ = Vector2(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 // -------- torus -----------
72 static Vector3 torusvec(float theta, float phi, float mr, float rr)
73 {
74 theta = -theta;
76 float rx = -cos(phi) * rr + mr;
77 float ry = sin(phi) * rr;
78 float rz = 0.0;
80 float x = rx * sin(theta) + rz * cos(theta);
81 float y = ry;
82 float z = -rx * cos(theta) + rz * sin(theta);
84 return Vector3(x, y, z);
85 }
87 void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange)
88 {
89 if(usub < 4) usub = 4;
90 if(vsub < 2) vsub = 2;
92 int uverts = usub + 1;
93 int vverts = vsub + 1;
95 int num_verts = uverts * vverts;
96 int num_quads = usub * vsub;
97 int num_tri = num_quads * 2;
99 mesh->clear();
100 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
101 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
102 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
103 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
104 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
106 float du = urange / (float)(uverts - 1);
107 float dv = vrange / (float)(vverts - 1);
109 float u = 0.0;
110 for(int i=0; i<uverts; i++) {
111 float theta = u * 2.0 * M_PI;
113 float v = 0.0;
114 for(int j=0; j<vverts; j++) {
115 float phi = v * 2.0 * M_PI;
117 Vector3 pos = torusvec(theta, phi, mainrad, ringrad);
118 Vector3 cent = torusvec(theta, phi, mainrad, 0.0);
120 *varr++ = pos;
121 *narr++ = (pos - cent) / ringrad;
123 Vector3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad);
124 Vector3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad);
126 *tarr++ = (pnext - pprev).normalized();
127 *uvarr++ = Vector2(u * urange, v * vrange);
129 if(i < usub && j < vsub) {
130 int idx = i * vverts + j;
131 *idxarr++ = idx;
132 *idxarr++ = idx + 1;
133 *idxarr++ = idx + vverts + 1;
135 *idxarr++ = idx;
136 *idxarr++ = idx + vverts + 1;
137 *idxarr++ = idx + vverts;
138 }
140 v += dv;
141 }
142 u += du;
143 }
144 }
147 // -------- cylinder --------
149 static Vector3 cylvec(float theta, float height)
150 {
151 return Vector3(sin(theta), height, cos(theta));
152 }
154 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
155 {
156 if(usub < 4) usub = 4;
157 if(vsub < 1) vsub = 1;
159 int uverts = usub + 1;
160 int vverts = vsub + 1;
162 int num_body_verts = uverts * vverts;
163 int num_body_quads = usub * vsub;
164 int num_body_tri = num_body_quads * 2;
166 int capvverts = capsub ? capsub + 1 : 0;
167 int num_cap_verts = uverts * capvverts;
168 int num_cap_quads = usub * capsub;
169 int num_cap_tri = num_cap_quads * 2;
171 int num_verts = num_body_verts + num_cap_verts * 2;
172 int num_tri = num_body_tri + num_cap_tri * 2;
174 mesh->clear();
175 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
176 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
177 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
178 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
179 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
181 float du = urange / (float)(uverts - 1);
182 float dv = vrange / (float)(vverts - 1);
184 float u = 0.0;
185 for(int i=0; i<uverts; i++) {
186 float theta = SURAD(u);
188 float v = 0.0;
189 for(int j=0; j<vverts; j++) {
190 float y = (v - 0.5) * height;
191 Vector3 pos = cylvec(theta, y);
193 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
194 *narr++ = Vector3(pos.x, 0.0, pos.z);
195 *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
196 *uvarr++ = Vector2(u * urange, v * vrange);
198 if(i < usub && j < vsub) {
199 int idx = i * vverts + j;
201 *idxarr++ = idx;
202 *idxarr++ = idx + vverts + 1;
203 *idxarr++ = idx + 1;
205 *idxarr++ = idx;
206 *idxarr++ = idx + vverts;
207 *idxarr++ = idx + vverts + 1;
208 }
210 v += dv;
211 }
212 u += du;
213 }
216 // now the cap!
217 if(!capsub) {
218 return;
219 }
221 dv = 1.0 / (float)(capvverts - 1);
223 u = 0.0;
224 for(int i=0; i<uverts; i++) {
225 float theta = SURAD(u);
227 float v = 0.0;
228 for(int j=0; j<capvverts; j++) {
229 float r = v * rad;
231 Vector3 pos = cylvec(theta, height / 2.0) * r;
232 pos.y = height / 2.0;
233 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
235 *varr++ = pos;
236 *narr++ = Vector3(0, 1, 0);
237 *tarr++ = tang;
238 *uvarr++ = Vector2(u * urange, v);
240 pos.y = -height / 2.0;
241 *varr++ = pos;
242 *narr++ = Vector3(0, -1, 0);
243 *tarr++ = -tang;
244 *uvarr++ = Vector2(u * urange, v);
246 if(i < usub && j < capsub) {
247 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
249 unsigned int vidx[4] = {
250 idx,
251 idx + capvverts * 2,
252 idx + (capvverts + 1) * 2,
253 idx + 2
254 };
256 *idxarr++ = vidx[0];
257 *idxarr++ = vidx[2];
258 *idxarr++ = vidx[1];
259 *idxarr++ = vidx[0];
260 *idxarr++ = vidx[3];
261 *idxarr++ = vidx[2];
263 *idxarr++ = vidx[0] + 1;
264 *idxarr++ = vidx[1] + 1;
265 *idxarr++ = vidx[2] + 1;
266 *idxarr++ = vidx[0] + 1;
267 *idxarr++ = vidx[2] + 1;
268 *idxarr++ = vidx[3] + 1;
269 }
271 v += dv;
272 }
273 u += du;
274 }
275 }
277 // -------- cone --------
279 static Vector3 conevec(float theta, float y, float height)
280 {
281 float scale = 1.0 - y / height;
282 return Vector3(sin(theta) * scale, y, cos(theta) * scale);
283 }
285 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
286 {
287 if(usub < 4) usub = 4;
288 if(vsub < 1) vsub = 1;
290 int uverts = usub + 1;
291 int vverts = vsub + 1;
293 int num_body_verts = uverts * vverts;
294 int num_body_quads = usub * vsub;
295 int num_body_tri = num_body_quads * 2;
297 int capvverts = capsub ? capsub + 1 : 0;
298 int num_cap_verts = uverts * capvverts;
299 int num_cap_quads = usub * capsub;
300 int num_cap_tri = num_cap_quads * 2;
302 int num_verts = num_body_verts + num_cap_verts;
303 int num_tri = num_body_tri + num_cap_tri;
305 mesh->clear();
306 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
307 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
308 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
309 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
310 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
312 float du = urange / (float)(uverts - 1);
313 float dv = vrange / (float)(vverts - 1);
315 float u = 0.0;
316 for(int i=0; i<uverts; i++) {
317 float theta = SURAD(u);
319 float v = 0.0;
320 for(int j=0; j<vverts; j++) {
321 float y = v * height;
322 Vector3 pos = conevec(theta, y, height);
324 Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
325 Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
327 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
328 *narr++ = cross_product(tang, bitang);
329 *tarr++ = tang;
330 *uvarr++ = Vector2(u * urange, v * vrange);
332 if(i < usub && j < vsub) {
333 int idx = i * vverts + j;
335 *idxarr++ = idx;
336 *idxarr++ = idx + vverts + 1;
337 *idxarr++ = idx + 1;
339 *idxarr++ = idx;
340 *idxarr++ = idx + vverts;
341 *idxarr++ = idx + vverts + 1;
342 }
344 v += dv;
345 }
346 u += du;
347 }
350 // now the bottom cap!
351 if(!capsub) {
352 return;
353 }
355 dv = 1.0 / (float)(capvverts - 1);
357 u = 0.0;
358 for(int i=0; i<uverts; i++) {
359 float theta = SURAD(u);
361 float v = 0.0;
362 for(int j=0; j<capvverts; j++) {
363 float r = v * rad;
365 Vector3 pos = conevec(theta, 0.0, height) * r;
366 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
368 *varr++ = pos;
369 *narr++ = Vector3(0, -1, 0);
370 *tarr++ = tang;
371 *uvarr++ = Vector2(u * urange, v);
373 if(i < usub && j < capsub) {
374 unsigned int idx = num_body_verts + i * capvverts + j;
376 unsigned int vidx[4] = {
377 idx,
378 idx + capvverts,
379 idx + (capvverts + 1),
380 idx + 1
381 };
383 *idxarr++ = vidx[0];
384 *idxarr++ = vidx[1];
385 *idxarr++ = vidx[2];
386 *idxarr++ = vidx[0];
387 *idxarr++ = vidx[2];
388 *idxarr++ = vidx[3];
389 }
391 v += dv;
392 }
393 u += du;
394 }
395 }
398 // -------- plane --------
400 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
401 {
402 gen_heightmap(mesh, width, height, usub, vsub, 0);
403 }
406 // ----- heightmap ------
408 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
409 {
410 if(usub < 1) usub = 1;
411 if(vsub < 1) vsub = 1;
413 mesh->clear();
415 int uverts = usub + 1;
416 int vverts = vsub + 1;
417 int num_verts = uverts * vverts;
419 int num_quads = usub * vsub;
420 int num_tri = num_quads * 2;
422 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
423 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
424 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
425 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
426 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
428 float du = 1.0 / (float)usub;
429 float dv = 1.0 / (float)vsub;
431 float u = 0.0;
432 for(int i=0; i<uverts; i++) {
433 float v = 0.0;
434 for(int j=0; j<vverts; j++) {
435 float x = (u - 0.5) * width;
436 float y = (v - 0.5) * height;
437 float z = hf ? hf(u, v, hfdata) : 0.0;
439 Vector3 normal = Vector3(0, 0, 1);
440 if(hf) {
441 float u1z = hf(u + du, v, hfdata);
442 float v1z = hf(u, v + dv, hfdata);
444 Vector3 tang = Vector3(du * width, 0, u1z - z);
445 Vector3 bitan = Vector3(0, dv * height, v1z - z);
446 normal = cross_product(tang, bitan).normalized();
447 }
449 *varr++ = Vector3(x, y, z);
450 *narr++ = normal;
451 *tarr++ = Vector3(1, 0, 0);
452 *uvarr++ = Vector2(u, v);
454 if(i < usub && j < vsub) {
455 int idx = i * vverts + j;
457 *idxarr++ = idx;
458 *idxarr++ = idx + vverts + 1;
459 *idxarr++ = idx + 1;
461 *idxarr++ = idx;
462 *idxarr++ = idx + vverts;
463 *idxarr++ = idx + vverts + 1;
464 }
466 v += dv;
467 }
468 u += du;
469 }
470 }
472 // ----- box ------
473 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
474 {
475 static const float face_angles[][2] = {
476 {0, 0},
477 {M_PI / 2.0, 0},
478 {M_PI, 0},
479 {3.0 * M_PI / 2.0, 0},
480 {0, M_PI / 2.0},
481 {0, -M_PI / 2.0}
482 };
484 if(usub < 1) usub = 1;
485 if(vsub < 1) vsub = 1;
487 mesh->clear();
489 for(int i=0; i<6; i++) {
490 Matrix4x4 xform, dir_xform;
491 Mesh m;
493 gen_plane(&m, 1, 1, usub, vsub);
494 xform.rotate(Vector3(face_angles[i][1], face_angles[i][0], 0));
495 dir_xform = xform;
496 xform.translate(Vector3(0, 0, 0.5));
497 m.apply_xform(xform, dir_xform);
499 mesh->append(m);
500 }
502 Matrix4x4 scale;
503 scale.set_scaling(Vector3(xsz, ysz, zsz));
504 mesh->apply_xform(scale, Matrix4x4::identity);
505 }
507 /*
508 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
509 {
510 mesh->clear();
512 const int num_faces = 6;
513 int num_verts = num_faces * 4;
514 int num_tri = num_faces * 2;
516 float x = xsz / 2.0;
517 float y = ysz / 2.0;
518 float z = zsz / 2.0;
520 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
521 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
522 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
523 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
524 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
526 static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) };
528 // front
529 for(int i=0; i<4; i++) {
530 *narr++ = Vector3(0, 0, 1);
531 *tarr++ = Vector3(1, 0, 0);
532 *uvarr++ = uv[i];
533 }
534 *varr++ = Vector3(-x, -y, z);
535 *varr++ = Vector3(x, -y, z);
536 *varr++ = Vector3(x, y, z);
537 *varr++ = Vector3(-x, y, z);
538 // right
539 for(int i=0; i<4; i++) {
540 *narr++ = Vector3(1, 0, 0);
541 *tarr++ = Vector3(0, 0, -1);
542 *uvarr++ = uv[i];
543 }
544 *varr++ = Vector3(x, -y, z);
545 *varr++ = Vector3(x, -y, -z);
546 *varr++ = Vector3(x, y, -z);
547 *varr++ = Vector3(x, y, z);
548 // back
549 for(int i=0; i<4; i++) {
550 *narr++ = Vector3(0, 0, -1);
551 *tarr++ = Vector3(-1, 0, 0);
552 *uvarr++ = uv[i];
553 }
554 *varr++ = Vector3(x, -y, -z);
555 *varr++ = Vector3(-x, -y, -z);
556 *varr++ = Vector3(-x, y, -z);
557 *varr++ = Vector3(x, y, -z);
558 // left
559 for(int i=0; i<4; i++) {
560 *narr++ = Vector3(-1, 0, 0);
561 *tarr++ = Vector3(0, 0, 1);
562 *uvarr++ = uv[i];
563 }
564 *varr++ = Vector3(-x, -y, -z);
565 *varr++ = Vector3(-x, -y, z);
566 *varr++ = Vector3(-x, y, z);
567 *varr++ = Vector3(-x, y, -z);
568 // top
569 for(int i=0; i<4; i++) {
570 *narr++ = Vector3(0, 1, 0);
571 *tarr++ = Vector3(1, 0, 0);
572 *uvarr++ = uv[i];
573 }
574 *varr++ = Vector3(-x, y, z);
575 *varr++ = Vector3(x, y, z);
576 *varr++ = Vector3(x, y, -z);
577 *varr++ = Vector3(-x, y, -z);
578 // bottom
579 for(int i=0; i<4; i++) {
580 *narr++ = Vector3(0, -1, 0);
581 *tarr++ = Vector3(1, 0, 0);
582 *uvarr++ = uv[i];
583 }
584 *varr++ = Vector3(-x, -y, -z);
585 *varr++ = Vector3(x, -y, -z);
586 *varr++ = Vector3(x, -y, z);
587 *varr++ = Vector3(-x, -y, z);
589 // index array
590 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
591 for(int i=0; i<num_faces; i++) {
592 for(int j=0; j<6; j++) {
593 *idxarr++ = faceidx[j] + i * 4;
594 }
595 }
596 }
597 */
599 static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls)
600 {
601 Vector2 pos = rf(u, v, cls);
603 float angle = u * 2.0 * M_PI;
604 float x = pos.x * cos(angle);
605 float y = pos.y;
606 float z = pos.x * sin(angle);
608 return Vector3(x, y, z);
609 }
611 // ------ surface of revolution -------
612 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls)
613 {
614 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
615 }
617 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*),
618 Vector2 (*nfunc)(float, float, void*), void *cls)
619 {
620 if(!rfunc) return;
621 if(usub < 3) usub = 3;
622 if(vsub < 1) vsub = 1;
624 mesh->clear();
626 int uverts = usub + 1;
627 int vverts = vsub + 1;
628 int num_verts = uverts * vverts;
630 int num_quads = usub * vsub;
631 int num_tri = num_quads * 2;
633 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
634 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
635 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
636 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
637 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
639 float du = 1.0 / (float)(uverts - 1);
640 float dv = 1.0 / (float)(vverts - 1);
642 float u = 0.0;
643 for(int i=0; i<uverts; i++) {
644 float v = 0.0;
645 for(int j=0; j<vverts; j++) {
646 Vector3 pos = rev_vert(u, v, rfunc, cls);
648 Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
649 Vector3 tang = nextu - pos;
650 if(tang.length_sq() < 1e-6) {
651 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
652 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
653 tang = nextu - pos;
654 }
656 Vector3 normal;
657 if(nfunc) {
658 normal = rev_vert(u, v, nfunc, cls);
659 } else {
660 Vector3 nextv = rev_vert(u, v + dv, rfunc, cls);
661 Vector3 bitan = nextv - pos;
662 if(bitan.length_sq() < 1e-6) {
663 nextv = rev_vert(u, v - dv, rfunc, cls);
664 bitan = pos - nextv;
665 }
667 normal = cross_product(tang, bitan);
668 }
670 *varr++ = pos;
671 *narr++ = normal.normalized();
672 *tarr++ = tang.normalized();
673 *uvarr++ = Vector2(u, v);
675 if(i < usub && j < vsub) {
676 int idx = i * vverts + j;
678 *idxarr++ = idx;
679 *idxarr++ = idx + vverts + 1;
680 *idxarr++ = idx + 1;
682 *idxarr++ = idx;
683 *idxarr++ = idx + vverts;
684 *idxarr++ = idx + vverts + 1;
685 }
687 v += dv;
688 }
689 u += du;
690 }
691 }
694 static inline Vector3 sweep_vert(float u, float v, float height, Vector2 (*sf)(float, float, void*), void *cls)
695 {
696 Vector2 pos = sf(u, v, cls);
698 float x = pos.x;
699 float y = v * height;
700 float z = pos.y;
702 return Vector3(x, y, z);
703 }
705 // ---- sweep shape along a path ----
706 void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vector2 (*sfunc)(float, float, void*), void *cls)
707 {
708 if(!sfunc) return;
709 if(usub < 3) usub = 3;
710 if(vsub < 1) vsub = 1;
712 mesh->clear();
714 int uverts = usub + 1;
715 int vverts = vsub + 1;
716 int num_verts = uverts * vverts;
718 int num_quads = usub * vsub;
719 int num_tri = num_quads * 2;
721 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
722 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
723 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
724 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
725 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
727 float du = 1.0 / (float)(uverts - 1);
728 float dv = 1.0 / (float)(vverts - 1);
730 float u = 0.0;
731 for(int i=0; i<uverts; i++) {
732 float v = 0.0;
733 for(int j=0; j<vverts; j++) {
734 Vector3 pos = sweep_vert(u, v, height, sfunc, cls);
736 Vector3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls);
737 Vector3 tang = nextu - pos;
738 if(tang.length_sq() < 1e-6) {
739 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
740 nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls);
741 tang = nextu - pos;
742 }
744 Vector3 normal;
745 Vector3 nextv = sweep_vert(u, v + dv, height, sfunc, cls);
746 Vector3 bitan = nextv - pos;
747 if(bitan.length_sq() < 1e-6) {
748 nextv = sweep_vert(u, v - dv, height, sfunc, cls);
749 bitan = pos - nextv;
750 }
752 normal = cross_product(tang, bitan);
754 *varr++ = pos;
755 *narr++ = normal.normalized();
756 *tarr++ = tang.normalized();
757 *uvarr++ = Vector2(u, v);
759 if(i < usub && j < vsub) {
760 int idx = i * vverts + j;
762 *idxarr++ = idx;
763 *idxarr++ = idx + vverts + 1;
764 *idxarr++ = idx + 1;
766 *idxarr++ = idx;
767 *idxarr++ = idx + vverts;
768 *idxarr++ = idx + vverts + 1;
769 }
771 v += dv;
772 }
773 u += du;
774 }
775 }