ld33_umonster

view src/meshgen.cc @ 2:35349df5392d

wtf?
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 22 Aug 2015 23:55:21 +0300
parents bed0e207acb6
children 7b1fa527b51b
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 = SURAD(u * urange);
43 float v = 0.0;
44 for(int j=0; j<vverts; j++) {
45 float phi = SVRAD(v * vrange);
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 }
72 // -------- cylinder --------
74 static Vector3 cylvec(float theta, float height)
75 {
76 return Vector3(sin(theta), height, cos(theta));
77 }
79 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
80 {
81 if(usub < 4) usub = 4;
82 if(vsub < 1) vsub = 1;
84 int uverts = usub + 1;
85 int vverts = vsub + 1;
87 int num_body_verts = uverts * vverts;
88 int num_body_quads = usub * vsub;
89 int num_body_tri = num_body_quads * 2;
91 int capvverts = capsub ? capsub + 1 : 0;
92 int num_cap_verts = uverts * capvverts;
93 int num_cap_quads = usub * capsub;
94 int num_cap_tri = num_cap_quads * 2;
96 int num_verts = num_body_verts + num_cap_verts * 2;
97 int num_tri = num_body_tri + num_cap_tri * 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 = SURAD(u);
113 float v = 0.0;
114 for(int j=0; j<vverts; j++) {
115 float y = (v - 0.5) * height;
116 Vector3 pos = cylvec(theta, y);
118 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
119 *narr++ = Vector3(pos.x, 0.0, pos.z);
120 *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
121 *uvarr++ = Vector2(u * urange, v * vrange);
123 if(i < usub && j < vsub) {
124 int idx = i * vverts + j;
126 *idxarr++ = idx;
127 *idxarr++ = idx + vverts + 1;
128 *idxarr++ = idx + 1;
130 *idxarr++ = idx;
131 *idxarr++ = idx + vverts;
132 *idxarr++ = idx + vverts + 1;
133 }
135 v += dv;
136 }
137 u += du;
138 }
141 // now the cap!
142 if(!capsub) {
143 return;
144 }
146 dv = 1.0 / (float)(capvverts - 1);
148 u = 0.0;
149 for(int i=0; i<uverts; i++) {
150 float theta = SURAD(u);
152 float v = 0.0;
153 for(int j=0; j<capvverts; j++) {
154 float r = v * rad;
156 Vector3 pos = cylvec(theta, height / 2.0) * r;
157 pos.y = height / 2.0;
158 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
160 *varr++ = pos;
161 *narr++ = Vector3(0, 1, 0);
162 *tarr++ = tang;
163 *uvarr++ = Vector2(u * urange, v);
165 pos.y = -height / 2.0;
166 *varr++ = pos;
167 *narr++ = Vector3(0, -1, 0);
168 *tarr++ = -tang;
169 *uvarr++ = Vector2(u * urange, v);
171 if(i < usub && j < capsub) {
172 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
174 unsigned int vidx[4] = {
175 idx,
176 idx + capvverts * 2,
177 idx + (capvverts + 1) * 2,
178 idx + 2
179 };
181 *idxarr++ = vidx[0];
182 *idxarr++ = vidx[2];
183 *idxarr++ = vidx[1];
184 *idxarr++ = vidx[0];
185 *idxarr++ = vidx[3];
186 *idxarr++ = vidx[2];
188 *idxarr++ = vidx[0] + 1;
189 *idxarr++ = vidx[1] + 1;
190 *idxarr++ = vidx[2] + 1;
191 *idxarr++ = vidx[0] + 1;
192 *idxarr++ = vidx[2] + 1;
193 *idxarr++ = vidx[3] + 1;
194 }
196 v += dv;
197 }
198 u += du;
199 }
200 }
202 // -------- cone --------
204 static Vector3 conevec(float theta, float y, float height)
205 {
206 float scale = 1.0 - y / height;
207 return Vector3(sin(theta) * scale, y, cos(theta) * scale);
208 }
210 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
211 {
212 if(usub < 4) usub = 4;
213 if(vsub < 1) vsub = 1;
215 int uverts = usub + 1;
216 int vverts = vsub + 1;
218 int num_body_verts = uverts * vverts;
219 int num_body_quads = usub * vsub;
220 int num_body_tri = num_body_quads * 2;
222 int capvverts = capsub ? capsub + 1 : 0;
223 int num_cap_verts = uverts * capvverts;
224 int num_cap_quads = usub * capsub;
225 int num_cap_tri = num_cap_quads * 2;
227 int num_verts = num_body_verts + num_cap_verts;
228 int num_tri = num_body_tri + num_cap_tri;
230 mesh->clear();
231 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
232 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
233 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
234 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
235 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
237 float du = urange / (float)(uverts - 1);
238 float dv = vrange / (float)(vverts - 1);
240 float u = 0.0;
241 for(int i=0; i<uverts; i++) {
242 float theta = SURAD(u);
244 float v = 0.0;
245 for(int j=0; j<vverts; j++) {
246 float y = v * height;
247 Vector3 pos = conevec(theta, y, height);
249 Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
250 Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
252 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
253 *narr++ = cross_product(tang, bitang);
254 *tarr++ = tang;
255 *uvarr++ = Vector2(u * urange, v * vrange);
257 if(i < usub && j < vsub) {
258 int idx = i * vverts + j;
260 *idxarr++ = idx;
261 *idxarr++ = idx + vverts + 1;
262 *idxarr++ = idx + 1;
264 *idxarr++ = idx;
265 *idxarr++ = idx + vverts;
266 *idxarr++ = idx + vverts + 1;
267 }
269 v += dv;
270 }
271 u += du;
272 }
275 // now the bottom cap!
276 if(!capsub) {
277 return;
278 }
280 dv = 1.0 / (float)(capvverts - 1);
282 u = 0.0;
283 for(int i=0; i<uverts; i++) {
284 float theta = SURAD(u);
286 float v = 0.0;
287 for(int j=0; j<capvverts; j++) {
288 float r = v * rad;
290 Vector3 pos = conevec(theta, 0.0, height) * r;
291 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
293 *varr++ = pos;
294 *narr++ = Vector3(0, -1, 0);
295 *tarr++ = tang;
296 *uvarr++ = Vector2(u * urange, v);
298 if(i < usub && j < capsub) {
299 unsigned int idx = num_body_verts + i * capvverts + j;
301 unsigned int vidx[4] = {
302 idx,
303 idx + capvverts,
304 idx + (capvverts + 1),
305 idx + 1
306 };
308 *idxarr++ = vidx[0];
309 *idxarr++ = vidx[1];
310 *idxarr++ = vidx[2];
311 *idxarr++ = vidx[0];
312 *idxarr++ = vidx[2];
313 *idxarr++ = vidx[3];
314 }
316 v += dv;
317 }
318 u += du;
319 }
320 }
323 // -------- plane --------
325 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
326 {
327 gen_heightmap(mesh, width, height, usub, vsub, 0);
328 }
331 // ----- heightmap ------
333 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
334 {
335 if(usub < 1) usub = 1;
336 if(vsub < 1) vsub = 1;
338 mesh->clear();
340 int uverts = usub + 1;
341 int vverts = vsub + 1;
342 int num_verts = uverts * vverts;
344 int num_quads = usub * vsub;
345 int num_tri = num_quads * 2;
347 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
348 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
349 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
350 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
351 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
353 float du = 1.0 / (float)usub;
354 float dv = 1.0 / (float)vsub;
356 float u = 0.0;
357 for(int i=0; i<uverts; i++) {
358 float v = 0.0;
359 for(int j=0; j<vverts; j++) {
360 float x = (u - 0.5) * width;
361 float y = (v - 0.5) * height;
362 float z = hf ? hf(u, v, hfdata) : 0.0;
364 Vector3 normal = Vector3(0, 0, 1);
365 if(hf) {
366 float u1z = hf(u + du, v, hfdata);
367 float v1z = hf(u, v + dv, hfdata);
369 Vector3 tang = Vector3(du * width, 0, u1z - z);
370 Vector3 bitan = Vector3(0, dv * height, v1z - z);
371 normal = cross_product(tang, bitan).normalized();
372 }
374 *varr++ = Vector3(x, y, z);
375 *narr++ = normal;
376 *tarr++ = Vector3(1, 0, 0);
377 *uvarr++ = Vector2(u, v);
379 if(i < usub && j < vsub) {
380 int idx = i * vverts + j;
382 *idxarr++ = idx;
383 *idxarr++ = idx + vverts + 1;
384 *idxarr++ = idx + 1;
386 *idxarr++ = idx;
387 *idxarr++ = idx + vverts;
388 *idxarr++ = idx + vverts + 1;
389 }
391 v += dv;
392 }
393 u += du;
394 }
395 }
397 // ----- box ------
398 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
399 {
400 static const float face_angles[][2] = {
401 {0, 0},
402 {M_PI / 2.0, 0},
403 {M_PI, 0},
404 {3.0 * M_PI / 2.0, 0},
405 {0, M_PI / 2.0},
406 {0, -M_PI / 2.0}
407 };
409 if(usub < 1) usub = 1;
410 if(vsub < 1) vsub = 1;
412 mesh->clear();
414 for(int i=0; i<6; i++) {
415 Matrix4x4 xform, dir_xform;
416 Mesh m;
418 gen_plane(&m, 1, 1, usub, vsub);
419 xform.rotate(Vector3(face_angles[i][1], face_angles[i][0], 0));
420 dir_xform = xform;
421 xform.translate(Vector3(0, 0, 0.5));
422 m.apply_xform(xform, dir_xform);
424 mesh->append(m);
425 }
427 Matrix4x4 scale;
428 scale.set_scaling(Vector3(xsz, ysz, zsz));
429 mesh->apply_xform(scale, Matrix4x4::identity);
430 }
432 /*
433 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
434 {
435 mesh->clear();
437 const int num_faces = 6;
438 int num_verts = num_faces * 4;
439 int num_tri = num_faces * 2;
441 float x = xsz / 2.0;
442 float y = ysz / 2.0;
443 float z = zsz / 2.0;
445 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
446 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
447 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
448 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
449 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
451 static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) };
453 // front
454 for(int i=0; i<4; i++) {
455 *narr++ = Vector3(0, 0, 1);
456 *tarr++ = Vector3(1, 0, 0);
457 *uvarr++ = uv[i];
458 }
459 *varr++ = Vector3(-x, -y, z);
460 *varr++ = Vector3(x, -y, z);
461 *varr++ = Vector3(x, y, z);
462 *varr++ = Vector3(-x, y, z);
463 // right
464 for(int i=0; i<4; i++) {
465 *narr++ = Vector3(1, 0, 0);
466 *tarr++ = Vector3(0, 0, -1);
467 *uvarr++ = uv[i];
468 }
469 *varr++ = Vector3(x, -y, z);
470 *varr++ = Vector3(x, -y, -z);
471 *varr++ = Vector3(x, y, -z);
472 *varr++ = Vector3(x, y, z);
473 // back
474 for(int i=0; i<4; i++) {
475 *narr++ = Vector3(0, 0, -1);
476 *tarr++ = Vector3(-1, 0, 0);
477 *uvarr++ = uv[i];
478 }
479 *varr++ = Vector3(x, -y, -z);
480 *varr++ = Vector3(-x, -y, -z);
481 *varr++ = Vector3(-x, y, -z);
482 *varr++ = Vector3(x, y, -z);
483 // left
484 for(int i=0; i<4; i++) {
485 *narr++ = Vector3(-1, 0, 0);
486 *tarr++ = Vector3(0, 0, 1);
487 *uvarr++ = uv[i];
488 }
489 *varr++ = Vector3(-x, -y, -z);
490 *varr++ = Vector3(-x, -y, z);
491 *varr++ = Vector3(-x, y, z);
492 *varr++ = Vector3(-x, y, -z);
493 // top
494 for(int i=0; i<4; i++) {
495 *narr++ = Vector3(0, 1, 0);
496 *tarr++ = Vector3(1, 0, 0);
497 *uvarr++ = uv[i];
498 }
499 *varr++ = Vector3(-x, y, z);
500 *varr++ = Vector3(x, y, z);
501 *varr++ = Vector3(x, y, -z);
502 *varr++ = Vector3(-x, y, -z);
503 // bottom
504 for(int i=0; i<4; i++) {
505 *narr++ = Vector3(0, -1, 0);
506 *tarr++ = Vector3(1, 0, 0);
507 *uvarr++ = uv[i];
508 }
509 *varr++ = Vector3(-x, -y, -z);
510 *varr++ = Vector3(x, -y, -z);
511 *varr++ = Vector3(x, -y, z);
512 *varr++ = Vector3(-x, -y, z);
514 // index array
515 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
516 for(int i=0; i<num_faces; i++) {
517 for(int j=0; j<6; j++) {
518 *idxarr++ = faceidx[j] + i * 4;
519 }
520 }
521 }
522 */
524 static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls)
525 {
526 Vector2 pos = rf(u, v, cls);
528 float angle = u * 2.0 * M_PI;
529 float x = pos.x * cos(angle);
530 float y = pos.y;
531 float z = pos.x * sin(angle);
533 return Vector3(x, y, z);
534 }
536 // ------ surface of revolution -------
537 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls)
538 {
539 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
540 }
542 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*),
543 Vector2 (*nfunc)(float, float, void*), void *cls)
544 {
545 if(!rfunc) return;
546 if(usub < 3) usub = 3;
547 if(vsub < 1) vsub = 1;
549 mesh->clear();
551 int uverts = usub + 1;
552 int vverts = vsub + 1;
553 int num_verts = uverts * vverts;
555 int num_quads = usub * vsub;
556 int num_tri = num_quads * 2;
558 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
559 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
560 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
561 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
562 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
564 float du = 1.0 / (float)(uverts - 1);
565 float dv = 1.0 / (float)(vverts - 1);
567 float u = 0.0;
568 for(int i=0; i<uverts; i++) {
569 float v = 0.0;
570 for(int j=0; j<vverts; j++) {
571 Vector3 pos = rev_vert(u, v, rfunc, cls);
573 Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
574 Vector3 tang = nextu - pos;
575 if(tang.length_sq() < 1e-6) {
576 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
577 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
578 tang = nextu - pos;
579 }
581 Vector3 normal;
582 if(nfunc) {
583 normal = rev_vert(u, v, nfunc, cls);
584 } else {
585 Vector3 nextv = rev_vert(u, v + dv, rfunc, cls);
586 Vector3 bitan = nextv - pos;
587 if(bitan.length_sq() < 1e-6) {
588 nextv = rev_vert(u, v - dv, rfunc, cls);
589 bitan = pos - nextv;
590 }
592 normal = cross_product(tang, bitan);
593 }
595 *varr++ = pos;
596 *narr++ = normal.normalized();
597 *tarr++ = tang.normalized();
598 *uvarr++ = Vector2(u, v);
600 if(i < usub && j < vsub) {
601 int idx = i * vverts + j;
603 *idxarr++ = idx;
604 *idxarr++ = idx + vverts + 1;
605 *idxarr++ = idx + 1;
607 *idxarr++ = idx;
608 *idxarr++ = idx + vverts;
609 *idxarr++ = idx + vverts + 1;
610 }
612 v += dv;
613 }
614 u += du;
615 }
616 }