dbf-halloween2015

annotate src/meshgen.cc @ 0:50683c78264e

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 01 Nov 2015 00:09:12 +0200
parents
children
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include "meshgen.h"
nuclear@0 3 #include "mesh.h"
nuclear@0 4
nuclear@0 5 // -------- sphere --------
nuclear@0 6
nuclear@0 7 #define SURAD(u) ((u) * 2.0 * M_PI)
nuclear@0 8 #define SVRAD(v) ((v) * M_PI)
nuclear@0 9
nuclear@0 10 static Vector3 sphvec(float theta, float phi)
nuclear@0 11 {
nuclear@0 12 return Vector3(sin(theta) * sin(phi),
nuclear@0 13 cos(phi),
nuclear@0 14 cos(theta) * sin(phi));
nuclear@0 15 }
nuclear@0 16
nuclear@0 17 void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange)
nuclear@0 18 {
nuclear@0 19 if(usub < 4) usub = 4;
nuclear@0 20 if(vsub < 2) vsub = 2;
nuclear@0 21
nuclear@0 22 int uverts = usub + 1;
nuclear@0 23 int vverts = vsub + 1;
nuclear@0 24
nuclear@0 25 int num_verts = uverts * vverts;
nuclear@0 26 int num_quads = usub * vsub;
nuclear@0 27 int num_tri = num_quads * 2;
nuclear@0 28
nuclear@0 29 mesh->clear();
nuclear@0 30 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 31 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 32 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 33 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 34 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 35
nuclear@0 36 float du = urange / (float)(uverts - 1);
nuclear@0 37 float dv = vrange / (float)(vverts - 1);
nuclear@0 38
nuclear@0 39 float u = 0.0;
nuclear@0 40 for(int i=0; i<uverts; i++) {
nuclear@0 41 float theta = u * 2.0 * M_PI;
nuclear@0 42
nuclear@0 43 float v = 0.0;
nuclear@0 44 for(int j=0; j<vverts; j++) {
nuclear@0 45 float phi = v * M_PI;
nuclear@0 46
nuclear@0 47 Vector3 pos = sphvec(theta, phi);
nuclear@0 48
nuclear@0 49 *varr++ = pos * rad;
nuclear@0 50 *narr++ = pos;
nuclear@0 51 *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized();
nuclear@0 52 *uvarr++ = Vector2(u * urange, v * vrange);
nuclear@0 53
nuclear@0 54 if(i < usub && j < vsub) {
nuclear@0 55 int idx = i * vverts + j;
nuclear@0 56 *idxarr++ = idx;
nuclear@0 57 *idxarr++ = idx + 1;
nuclear@0 58 *idxarr++ = idx + vverts + 1;
nuclear@0 59
nuclear@0 60 *idxarr++ = idx;
nuclear@0 61 *idxarr++ = idx + vverts + 1;
nuclear@0 62 *idxarr++ = idx + vverts;
nuclear@0 63 }
nuclear@0 64
nuclear@0 65 v += dv;
nuclear@0 66 }
nuclear@0 67 u += du;
nuclear@0 68 }
nuclear@0 69 }
nuclear@0 70
nuclear@0 71 // -------- torus -----------
nuclear@0 72 static Vector3 torusvec(float theta, float phi, float mr, float rr)
nuclear@0 73 {
nuclear@0 74 theta = -theta;
nuclear@0 75
nuclear@0 76 float rx = -cos(phi) * rr + mr;
nuclear@0 77 float ry = sin(phi) * rr;
nuclear@0 78 float rz = 0.0;
nuclear@0 79
nuclear@0 80 float x = rx * sin(theta) + rz * cos(theta);
nuclear@0 81 float y = ry;
nuclear@0 82 float z = -rx * cos(theta) + rz * sin(theta);
nuclear@0 83
nuclear@0 84 return Vector3(x, y, z);
nuclear@0 85 }
nuclear@0 86
nuclear@0 87 void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange)
nuclear@0 88 {
nuclear@0 89 if(usub < 4) usub = 4;
nuclear@0 90 if(vsub < 2) vsub = 2;
nuclear@0 91
nuclear@0 92 int uverts = usub + 1;
nuclear@0 93 int vverts = vsub + 1;
nuclear@0 94
nuclear@0 95 int num_verts = uverts * vverts;
nuclear@0 96 int num_quads = usub * vsub;
nuclear@0 97 int num_tri = num_quads * 2;
nuclear@0 98
nuclear@0 99 mesh->clear();
nuclear@0 100 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 101 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 102 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 103 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 104 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 105
nuclear@0 106 float du = urange / (float)(uverts - 1);
nuclear@0 107 float dv = vrange / (float)(vverts - 1);
nuclear@0 108
nuclear@0 109 float u = 0.0;
nuclear@0 110 for(int i=0; i<uverts; i++) {
nuclear@0 111 float theta = u * 2.0 * M_PI;
nuclear@0 112
nuclear@0 113 float v = 0.0;
nuclear@0 114 for(int j=0; j<vverts; j++) {
nuclear@0 115 float phi = v * 2.0 * M_PI;
nuclear@0 116
nuclear@0 117 Vector3 pos = torusvec(theta, phi, mainrad, ringrad);
nuclear@0 118 Vector3 cent = torusvec(theta, phi, mainrad, 0.0);
nuclear@0 119
nuclear@0 120 *varr++ = pos;
nuclear@0 121 *narr++ = (pos - cent) / ringrad;
nuclear@0 122
nuclear@0 123 Vector3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad);
nuclear@0 124 Vector3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad);
nuclear@0 125
nuclear@0 126 *tarr++ = (pnext - pprev).normalized();
nuclear@0 127 *uvarr++ = Vector2(u * urange, v * vrange);
nuclear@0 128
nuclear@0 129 if(i < usub && j < vsub) {
nuclear@0 130 int idx = i * vverts + j;
nuclear@0 131 *idxarr++ = idx;
nuclear@0 132 *idxarr++ = idx + 1;
nuclear@0 133 *idxarr++ = idx + vverts + 1;
nuclear@0 134
nuclear@0 135 *idxarr++ = idx;
nuclear@0 136 *idxarr++ = idx + vverts + 1;
nuclear@0 137 *idxarr++ = idx + vverts;
nuclear@0 138 }
nuclear@0 139
nuclear@0 140 v += dv;
nuclear@0 141 }
nuclear@0 142 u += du;
nuclear@0 143 }
nuclear@0 144 }
nuclear@0 145
nuclear@0 146
nuclear@0 147 // -------- cylinder --------
nuclear@0 148
nuclear@0 149 static Vector3 cylvec(float theta, float height)
nuclear@0 150 {
nuclear@0 151 return Vector3(sin(theta), height, cos(theta));
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
nuclear@0 155 {
nuclear@0 156 if(usub < 4) usub = 4;
nuclear@0 157 if(vsub < 1) vsub = 1;
nuclear@0 158
nuclear@0 159 int uverts = usub + 1;
nuclear@0 160 int vverts = vsub + 1;
nuclear@0 161
nuclear@0 162 int num_body_verts = uverts * vverts;
nuclear@0 163 int num_body_quads = usub * vsub;
nuclear@0 164 int num_body_tri = num_body_quads * 2;
nuclear@0 165
nuclear@0 166 int capvverts = capsub ? capsub + 1 : 0;
nuclear@0 167 int num_cap_verts = uverts * capvverts;
nuclear@0 168 int num_cap_quads = usub * capsub;
nuclear@0 169 int num_cap_tri = num_cap_quads * 2;
nuclear@0 170
nuclear@0 171 int num_verts = num_body_verts + num_cap_verts * 2;
nuclear@0 172 int num_tri = num_body_tri + num_cap_tri * 2;
nuclear@0 173
nuclear@0 174 mesh->clear();
nuclear@0 175 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 176 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 177 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 178 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 179 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 180
nuclear@0 181 float du = urange / (float)(uverts - 1);
nuclear@0 182 float dv = vrange / (float)(vverts - 1);
nuclear@0 183
nuclear@0 184 float u = 0.0;
nuclear@0 185 for(int i=0; i<uverts; i++) {
nuclear@0 186 float theta = SURAD(u);
nuclear@0 187
nuclear@0 188 float v = 0.0;
nuclear@0 189 for(int j=0; j<vverts; j++) {
nuclear@0 190 float y = (v - 0.5) * height;
nuclear@0 191 Vector3 pos = cylvec(theta, y);
nuclear@0 192
nuclear@0 193 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
nuclear@0 194 *narr++ = Vector3(pos.x, 0.0, pos.z);
nuclear@0 195 *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
nuclear@0 196 *uvarr++ = Vector2(u * urange, v * vrange);
nuclear@0 197
nuclear@0 198 if(i < usub && j < vsub) {
nuclear@0 199 int idx = i * vverts + j;
nuclear@0 200
nuclear@0 201 *idxarr++ = idx;
nuclear@0 202 *idxarr++ = idx + vverts + 1;
nuclear@0 203 *idxarr++ = idx + 1;
nuclear@0 204
nuclear@0 205 *idxarr++ = idx;
nuclear@0 206 *idxarr++ = idx + vverts;
nuclear@0 207 *idxarr++ = idx + vverts + 1;
nuclear@0 208 }
nuclear@0 209
nuclear@0 210 v += dv;
nuclear@0 211 }
nuclear@0 212 u += du;
nuclear@0 213 }
nuclear@0 214
nuclear@0 215
nuclear@0 216 // now the cap!
nuclear@0 217 if(!capsub) {
nuclear@0 218 return;
nuclear@0 219 }
nuclear@0 220
nuclear@0 221 dv = 1.0 / (float)(capvverts - 1);
nuclear@0 222
nuclear@0 223 u = 0.0;
nuclear@0 224 for(int i=0; i<uverts; i++) {
nuclear@0 225 float theta = SURAD(u);
nuclear@0 226
nuclear@0 227 float v = 0.0;
nuclear@0 228 for(int j=0; j<capvverts; j++) {
nuclear@0 229 float r = v * rad;
nuclear@0 230
nuclear@0 231 Vector3 pos = cylvec(theta, height / 2.0) * r;
nuclear@0 232 pos.y = height / 2.0;
nuclear@0 233 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
nuclear@0 234
nuclear@0 235 *varr++ = pos;
nuclear@0 236 *narr++ = Vector3(0, 1, 0);
nuclear@0 237 *tarr++ = tang;
nuclear@0 238 *uvarr++ = Vector2(u * urange, v);
nuclear@0 239
nuclear@0 240 pos.y = -height / 2.0;
nuclear@0 241 *varr++ = pos;
nuclear@0 242 *narr++ = Vector3(0, -1, 0);
nuclear@0 243 *tarr++ = -tang;
nuclear@0 244 *uvarr++ = Vector2(u * urange, v);
nuclear@0 245
nuclear@0 246 if(i < usub && j < capsub) {
nuclear@0 247 unsigned int idx = num_body_verts + (i * capvverts + j) * 2;
nuclear@0 248
nuclear@0 249 unsigned int vidx[4] = {
nuclear@0 250 idx,
nuclear@0 251 idx + capvverts * 2,
nuclear@0 252 idx + (capvverts + 1) * 2,
nuclear@0 253 idx + 2
nuclear@0 254 };
nuclear@0 255
nuclear@0 256 *idxarr++ = vidx[0];
nuclear@0 257 *idxarr++ = vidx[2];
nuclear@0 258 *idxarr++ = vidx[1];
nuclear@0 259 *idxarr++ = vidx[0];
nuclear@0 260 *idxarr++ = vidx[3];
nuclear@0 261 *idxarr++ = vidx[2];
nuclear@0 262
nuclear@0 263 *idxarr++ = vidx[0] + 1;
nuclear@0 264 *idxarr++ = vidx[1] + 1;
nuclear@0 265 *idxarr++ = vidx[2] + 1;
nuclear@0 266 *idxarr++ = vidx[0] + 1;
nuclear@0 267 *idxarr++ = vidx[2] + 1;
nuclear@0 268 *idxarr++ = vidx[3] + 1;
nuclear@0 269 }
nuclear@0 270
nuclear@0 271 v += dv;
nuclear@0 272 }
nuclear@0 273 u += du;
nuclear@0 274 }
nuclear@0 275 }
nuclear@0 276
nuclear@0 277 // -------- cone --------
nuclear@0 278
nuclear@0 279 static Vector3 conevec(float theta, float y, float height)
nuclear@0 280 {
nuclear@0 281 float scale = 1.0 - y / height;
nuclear@0 282 return Vector3(sin(theta) * scale, y, cos(theta) * scale);
nuclear@0 283 }
nuclear@0 284
nuclear@0 285 void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange)
nuclear@0 286 {
nuclear@0 287 if(usub < 4) usub = 4;
nuclear@0 288 if(vsub < 1) vsub = 1;
nuclear@0 289
nuclear@0 290 int uverts = usub + 1;
nuclear@0 291 int vverts = vsub + 1;
nuclear@0 292
nuclear@0 293 int num_body_verts = uverts * vverts;
nuclear@0 294 int num_body_quads = usub * vsub;
nuclear@0 295 int num_body_tri = num_body_quads * 2;
nuclear@0 296
nuclear@0 297 int capvverts = capsub ? capsub + 1 : 0;
nuclear@0 298 int num_cap_verts = uverts * capvverts;
nuclear@0 299 int num_cap_quads = usub * capsub;
nuclear@0 300 int num_cap_tri = num_cap_quads * 2;
nuclear@0 301
nuclear@0 302 int num_verts = num_body_verts + num_cap_verts;
nuclear@0 303 int num_tri = num_body_tri + num_cap_tri;
nuclear@0 304
nuclear@0 305 mesh->clear();
nuclear@0 306 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 307 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 308 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 309 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 310 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 311
nuclear@0 312 float du = urange / (float)(uverts - 1);
nuclear@0 313 float dv = vrange / (float)(vverts - 1);
nuclear@0 314
nuclear@0 315 float u = 0.0;
nuclear@0 316 for(int i=0; i<uverts; i++) {
nuclear@0 317 float theta = SURAD(u);
nuclear@0 318
nuclear@0 319 float v = 0.0;
nuclear@0 320 for(int j=0; j<vverts; j++) {
nuclear@0 321 float y = v * height;
nuclear@0 322 Vector3 pos = conevec(theta, y, height);
nuclear@0 323
nuclear@0 324 Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized();
nuclear@0 325 Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized();
nuclear@0 326
nuclear@0 327 *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad);
nuclear@0 328 *narr++ = cross_product(tang, bitang);
nuclear@0 329 *tarr++ = tang;
nuclear@0 330 *uvarr++ = Vector2(u * urange, v * vrange);
nuclear@0 331
nuclear@0 332 if(i < usub && j < vsub) {
nuclear@0 333 int idx = i * vverts + j;
nuclear@0 334
nuclear@0 335 *idxarr++ = idx;
nuclear@0 336 *idxarr++ = idx + vverts + 1;
nuclear@0 337 *idxarr++ = idx + 1;
nuclear@0 338
nuclear@0 339 *idxarr++ = idx;
nuclear@0 340 *idxarr++ = idx + vverts;
nuclear@0 341 *idxarr++ = idx + vverts + 1;
nuclear@0 342 }
nuclear@0 343
nuclear@0 344 v += dv;
nuclear@0 345 }
nuclear@0 346 u += du;
nuclear@0 347 }
nuclear@0 348
nuclear@0 349
nuclear@0 350 // now the bottom cap!
nuclear@0 351 if(!capsub) {
nuclear@0 352 return;
nuclear@0 353 }
nuclear@0 354
nuclear@0 355 dv = 1.0 / (float)(capvverts - 1);
nuclear@0 356
nuclear@0 357 u = 0.0;
nuclear@0 358 for(int i=0; i<uverts; i++) {
nuclear@0 359 float theta = SURAD(u);
nuclear@0 360
nuclear@0 361 float v = 0.0;
nuclear@0 362 for(int j=0; j<capvverts; j++) {
nuclear@0 363 float r = v * rad;
nuclear@0 364
nuclear@0 365 Vector3 pos = conevec(theta, 0.0, height) * r;
nuclear@0 366 Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized();
nuclear@0 367
nuclear@0 368 *varr++ = pos;
nuclear@0 369 *narr++ = Vector3(0, -1, 0);
nuclear@0 370 *tarr++ = tang;
nuclear@0 371 *uvarr++ = Vector2(u * urange, v);
nuclear@0 372
nuclear@0 373 if(i < usub && j < capsub) {
nuclear@0 374 unsigned int idx = num_body_verts + i * capvverts + j;
nuclear@0 375
nuclear@0 376 unsigned int vidx[4] = {
nuclear@0 377 idx,
nuclear@0 378 idx + capvverts,
nuclear@0 379 idx + (capvverts + 1),
nuclear@0 380 idx + 1
nuclear@0 381 };
nuclear@0 382
nuclear@0 383 *idxarr++ = vidx[0];
nuclear@0 384 *idxarr++ = vidx[1];
nuclear@0 385 *idxarr++ = vidx[2];
nuclear@0 386 *idxarr++ = vidx[0];
nuclear@0 387 *idxarr++ = vidx[2];
nuclear@0 388 *idxarr++ = vidx[3];
nuclear@0 389 }
nuclear@0 390
nuclear@0 391 v += dv;
nuclear@0 392 }
nuclear@0 393 u += du;
nuclear@0 394 }
nuclear@0 395 }
nuclear@0 396
nuclear@0 397
nuclear@0 398 // -------- plane --------
nuclear@0 399
nuclear@0 400 void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub)
nuclear@0 401 {
nuclear@0 402 gen_heightmap(mesh, width, height, usub, vsub, 0);
nuclear@0 403 }
nuclear@0 404
nuclear@0 405
nuclear@0 406 // ----- heightmap ------
nuclear@0 407
nuclear@0 408 void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata)
nuclear@0 409 {
nuclear@0 410 if(usub < 1) usub = 1;
nuclear@0 411 if(vsub < 1) vsub = 1;
nuclear@0 412
nuclear@0 413 mesh->clear();
nuclear@0 414
nuclear@0 415 int uverts = usub + 1;
nuclear@0 416 int vverts = vsub + 1;
nuclear@0 417 int num_verts = uverts * vverts;
nuclear@0 418
nuclear@0 419 int num_quads = usub * vsub;
nuclear@0 420 int num_tri = num_quads * 2;
nuclear@0 421
nuclear@0 422 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 423 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 424 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 425 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 426 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 427
nuclear@0 428 float du = 1.0 / (float)usub;
nuclear@0 429 float dv = 1.0 / (float)vsub;
nuclear@0 430
nuclear@0 431 float u = 0.0;
nuclear@0 432 for(int i=0; i<uverts; i++) {
nuclear@0 433 float v = 0.0;
nuclear@0 434 for(int j=0; j<vverts; j++) {
nuclear@0 435 float x = (u - 0.5) * width;
nuclear@0 436 float y = (v - 0.5) * height;
nuclear@0 437 float z = hf ? hf(u, v, hfdata) : 0.0;
nuclear@0 438
nuclear@0 439 Vector3 normal = Vector3(0, 0, 1);
nuclear@0 440 if(hf) {
nuclear@0 441 float u1z = hf(u + du, v, hfdata);
nuclear@0 442 float v1z = hf(u, v + dv, hfdata);
nuclear@0 443
nuclear@0 444 Vector3 tang = Vector3(du * width, 0, u1z - z);
nuclear@0 445 Vector3 bitan = Vector3(0, dv * height, v1z - z);
nuclear@0 446 normal = cross_product(tang, bitan).normalized();
nuclear@0 447 }
nuclear@0 448
nuclear@0 449 *varr++ = Vector3(x, y, z);
nuclear@0 450 *narr++ = normal;
nuclear@0 451 *tarr++ = Vector3(1, 0, 0);
nuclear@0 452 *uvarr++ = Vector2(u, v);
nuclear@0 453
nuclear@0 454 if(i < usub && j < vsub) {
nuclear@0 455 int idx = i * vverts + j;
nuclear@0 456
nuclear@0 457 *idxarr++ = idx;
nuclear@0 458 *idxarr++ = idx + vverts + 1;
nuclear@0 459 *idxarr++ = idx + 1;
nuclear@0 460
nuclear@0 461 *idxarr++ = idx;
nuclear@0 462 *idxarr++ = idx + vverts;
nuclear@0 463 *idxarr++ = idx + vverts + 1;
nuclear@0 464 }
nuclear@0 465
nuclear@0 466 v += dv;
nuclear@0 467 }
nuclear@0 468 u += du;
nuclear@0 469 }
nuclear@0 470 }
nuclear@0 471
nuclear@0 472 // ----- box ------
nuclear@0 473 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub)
nuclear@0 474 {
nuclear@0 475 static const float face_angles[][2] = {
nuclear@0 476 {0, 0},
nuclear@0 477 {M_PI / 2.0, 0},
nuclear@0 478 {M_PI, 0},
nuclear@0 479 {3.0 * M_PI / 2.0, 0},
nuclear@0 480 {0, M_PI / 2.0},
nuclear@0 481 {0, -M_PI / 2.0}
nuclear@0 482 };
nuclear@0 483
nuclear@0 484 if(usub < 1) usub = 1;
nuclear@0 485 if(vsub < 1) vsub = 1;
nuclear@0 486
nuclear@0 487 mesh->clear();
nuclear@0 488
nuclear@0 489 for(int i=0; i<6; i++) {
nuclear@0 490 Matrix4x4 xform, dir_xform;
nuclear@0 491 Mesh m;
nuclear@0 492
nuclear@0 493 gen_plane(&m, 1, 1, usub, vsub);
nuclear@0 494 xform.rotate(Vector3(face_angles[i][1], face_angles[i][0], 0));
nuclear@0 495 dir_xform = xform;
nuclear@0 496 xform.translate(Vector3(0, 0, 0.5));
nuclear@0 497 m.apply_xform(xform, dir_xform);
nuclear@0 498
nuclear@0 499 mesh->append(m);
nuclear@0 500 }
nuclear@0 501
nuclear@0 502 Matrix4x4 scale;
nuclear@0 503 scale.set_scaling(Vector3(xsz, ysz, zsz));
nuclear@0 504 mesh->apply_xform(scale, Matrix4x4::identity);
nuclear@0 505 }
nuclear@0 506
nuclear@0 507 /*
nuclear@0 508 void gen_box(Mesh *mesh, float xsz, float ysz, float zsz)
nuclear@0 509 {
nuclear@0 510 mesh->clear();
nuclear@0 511
nuclear@0 512 const int num_faces = 6;
nuclear@0 513 int num_verts = num_faces * 4;
nuclear@0 514 int num_tri = num_faces * 2;
nuclear@0 515
nuclear@0 516 float x = xsz / 2.0;
nuclear@0 517 float y = ysz / 2.0;
nuclear@0 518 float z = zsz / 2.0;
nuclear@0 519
nuclear@0 520 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 521 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 522 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 523 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 524 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 525
nuclear@0 526 static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) };
nuclear@0 527
nuclear@0 528 // front
nuclear@0 529 for(int i=0; i<4; i++) {
nuclear@0 530 *narr++ = Vector3(0, 0, 1);
nuclear@0 531 *tarr++ = Vector3(1, 0, 0);
nuclear@0 532 *uvarr++ = uv[i];
nuclear@0 533 }
nuclear@0 534 *varr++ = Vector3(-x, -y, z);
nuclear@0 535 *varr++ = Vector3(x, -y, z);
nuclear@0 536 *varr++ = Vector3(x, y, z);
nuclear@0 537 *varr++ = Vector3(-x, y, z);
nuclear@0 538 // right
nuclear@0 539 for(int i=0; i<4; i++) {
nuclear@0 540 *narr++ = Vector3(1, 0, 0);
nuclear@0 541 *tarr++ = Vector3(0, 0, -1);
nuclear@0 542 *uvarr++ = uv[i];
nuclear@0 543 }
nuclear@0 544 *varr++ = Vector3(x, -y, z);
nuclear@0 545 *varr++ = Vector3(x, -y, -z);
nuclear@0 546 *varr++ = Vector3(x, y, -z);
nuclear@0 547 *varr++ = Vector3(x, y, z);
nuclear@0 548 // back
nuclear@0 549 for(int i=0; i<4; i++) {
nuclear@0 550 *narr++ = Vector3(0, 0, -1);
nuclear@0 551 *tarr++ = Vector3(-1, 0, 0);
nuclear@0 552 *uvarr++ = uv[i];
nuclear@0 553 }
nuclear@0 554 *varr++ = Vector3(x, -y, -z);
nuclear@0 555 *varr++ = Vector3(-x, -y, -z);
nuclear@0 556 *varr++ = Vector3(-x, y, -z);
nuclear@0 557 *varr++ = Vector3(x, y, -z);
nuclear@0 558 // left
nuclear@0 559 for(int i=0; i<4; i++) {
nuclear@0 560 *narr++ = Vector3(-1, 0, 0);
nuclear@0 561 *tarr++ = Vector3(0, 0, 1);
nuclear@0 562 *uvarr++ = uv[i];
nuclear@0 563 }
nuclear@0 564 *varr++ = Vector3(-x, -y, -z);
nuclear@0 565 *varr++ = Vector3(-x, -y, z);
nuclear@0 566 *varr++ = Vector3(-x, y, z);
nuclear@0 567 *varr++ = Vector3(-x, y, -z);
nuclear@0 568 // top
nuclear@0 569 for(int i=0; i<4; i++) {
nuclear@0 570 *narr++ = Vector3(0, 1, 0);
nuclear@0 571 *tarr++ = Vector3(1, 0, 0);
nuclear@0 572 *uvarr++ = uv[i];
nuclear@0 573 }
nuclear@0 574 *varr++ = Vector3(-x, y, z);
nuclear@0 575 *varr++ = Vector3(x, y, z);
nuclear@0 576 *varr++ = Vector3(x, y, -z);
nuclear@0 577 *varr++ = Vector3(-x, y, -z);
nuclear@0 578 // bottom
nuclear@0 579 for(int i=0; i<4; i++) {
nuclear@0 580 *narr++ = Vector3(0, -1, 0);
nuclear@0 581 *tarr++ = Vector3(1, 0, 0);
nuclear@0 582 *uvarr++ = uv[i];
nuclear@0 583 }
nuclear@0 584 *varr++ = Vector3(-x, -y, -z);
nuclear@0 585 *varr++ = Vector3(x, -y, -z);
nuclear@0 586 *varr++ = Vector3(x, -y, z);
nuclear@0 587 *varr++ = Vector3(-x, -y, z);
nuclear@0 588
nuclear@0 589 // index array
nuclear@0 590 static const int faceidx[] = {0, 1, 2, 0, 2, 3};
nuclear@0 591 for(int i=0; i<num_faces; i++) {
nuclear@0 592 for(int j=0; j<6; j++) {
nuclear@0 593 *idxarr++ = faceidx[j] + i * 4;
nuclear@0 594 }
nuclear@0 595 }
nuclear@0 596 }
nuclear@0 597 */
nuclear@0 598
nuclear@0 599 static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls)
nuclear@0 600 {
nuclear@0 601 Vector2 pos = rf(u, v, cls);
nuclear@0 602
nuclear@0 603 float angle = u * 2.0 * M_PI;
nuclear@0 604 float x = pos.x * cos(angle);
nuclear@0 605 float y = pos.y;
nuclear@0 606 float z = pos.x * sin(angle);
nuclear@0 607
nuclear@0 608 return Vector3(x, y, z);
nuclear@0 609 }
nuclear@0 610
nuclear@0 611 // ------ surface of revolution -------
nuclear@0 612 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls)
nuclear@0 613 {
nuclear@0 614 gen_revol(mesh, usub, vsub, rfunc, 0, cls);
nuclear@0 615 }
nuclear@0 616
nuclear@0 617 void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*),
nuclear@0 618 Vector2 (*nfunc)(float, float, void*), void *cls)
nuclear@0 619 {
nuclear@0 620 if(!rfunc) return;
nuclear@0 621 if(usub < 3) usub = 3;
nuclear@0 622 if(vsub < 1) vsub = 1;
nuclear@0 623
nuclear@0 624 mesh->clear();
nuclear@0 625
nuclear@0 626 int uverts = usub + 1;
nuclear@0 627 int vverts = vsub + 1;
nuclear@0 628 int num_verts = uverts * vverts;
nuclear@0 629
nuclear@0 630 int num_quads = usub * vsub;
nuclear@0 631 int num_tri = num_quads * 2;
nuclear@0 632
nuclear@0 633 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 634 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 635 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 636 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 637 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 638
nuclear@0 639 float du = 1.0 / (float)(uverts - 1);
nuclear@0 640 float dv = 1.0 / (float)(vverts - 1);
nuclear@0 641
nuclear@0 642 float u = 0.0;
nuclear@0 643 for(int i=0; i<uverts; i++) {
nuclear@0 644 float v = 0.0;
nuclear@0 645 for(int j=0; j<vverts; j++) {
nuclear@0 646 Vector3 pos = rev_vert(u, v, rfunc, cls);
nuclear@0 647
nuclear@0 648 Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls);
nuclear@0 649 Vector3 tang = nextu - pos;
nuclear@0 650 if(tang.length_sq() < 1e-6) {
nuclear@0 651 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
nuclear@0 652 nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls);
nuclear@0 653 tang = nextu - pos;
nuclear@0 654 }
nuclear@0 655
nuclear@0 656 Vector3 normal;
nuclear@0 657 if(nfunc) {
nuclear@0 658 normal = rev_vert(u, v, nfunc, cls);
nuclear@0 659 } else {
nuclear@0 660 Vector3 nextv = rev_vert(u, v + dv, rfunc, cls);
nuclear@0 661 Vector3 bitan = nextv - pos;
nuclear@0 662 if(bitan.length_sq() < 1e-6) {
nuclear@0 663 nextv = rev_vert(u, v - dv, rfunc, cls);
nuclear@0 664 bitan = pos - nextv;
nuclear@0 665 }
nuclear@0 666
nuclear@0 667 normal = cross_product(tang, bitan);
nuclear@0 668 }
nuclear@0 669
nuclear@0 670 *varr++ = pos;
nuclear@0 671 *narr++ = normal.normalized();
nuclear@0 672 *tarr++ = tang.normalized();
nuclear@0 673 *uvarr++ = Vector2(u, v);
nuclear@0 674
nuclear@0 675 if(i < usub && j < vsub) {
nuclear@0 676 int idx = i * vverts + j;
nuclear@0 677
nuclear@0 678 *idxarr++ = idx;
nuclear@0 679 *idxarr++ = idx + vverts + 1;
nuclear@0 680 *idxarr++ = idx + 1;
nuclear@0 681
nuclear@0 682 *idxarr++ = idx;
nuclear@0 683 *idxarr++ = idx + vverts;
nuclear@0 684 *idxarr++ = idx + vverts + 1;
nuclear@0 685 }
nuclear@0 686
nuclear@0 687 v += dv;
nuclear@0 688 }
nuclear@0 689 u += du;
nuclear@0 690 }
nuclear@0 691 }
nuclear@0 692
nuclear@0 693
nuclear@0 694 static inline Vector3 sweep_vert(float u, float v, float height, Vector2 (*sf)(float, float, void*), void *cls)
nuclear@0 695 {
nuclear@0 696 Vector2 pos = sf(u, v, cls);
nuclear@0 697
nuclear@0 698 float x = pos.x;
nuclear@0 699 float y = v * height;
nuclear@0 700 float z = pos.y;
nuclear@0 701
nuclear@0 702 return Vector3(x, y, z);
nuclear@0 703 }
nuclear@0 704
nuclear@0 705 // ---- sweep shape along a path ----
nuclear@0 706 void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vector2 (*sfunc)(float, float, void*), void *cls)
nuclear@0 707 {
nuclear@0 708 if(!sfunc) return;
nuclear@0 709 if(usub < 3) usub = 3;
nuclear@0 710 if(vsub < 1) vsub = 1;
nuclear@0 711
nuclear@0 712 mesh->clear();
nuclear@0 713
nuclear@0 714 int uverts = usub + 1;
nuclear@0 715 int vverts = vsub + 1;
nuclear@0 716 int num_verts = uverts * vverts;
nuclear@0 717
nuclear@0 718 int num_quads = usub * vsub;
nuclear@0 719 int num_tri = num_quads * 2;
nuclear@0 720
nuclear@0 721 Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0);
nuclear@0 722 Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0);
nuclear@0 723 Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0);
nuclear@0 724 Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0);
nuclear@0 725 unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0);
nuclear@0 726
nuclear@0 727 float du = 1.0 / (float)(uverts - 1);
nuclear@0 728 float dv = 1.0 / (float)(vverts - 1);
nuclear@0 729
nuclear@0 730 float u = 0.0;
nuclear@0 731 for(int i=0; i<uverts; i++) {
nuclear@0 732 float v = 0.0;
nuclear@0 733 for(int j=0; j<vverts; j++) {
nuclear@0 734 Vector3 pos = sweep_vert(u, v, height, sfunc, cls);
nuclear@0 735
nuclear@0 736 Vector3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls);
nuclear@0 737 Vector3 tang = nextu - pos;
nuclear@0 738 if(tang.length_sq() < 1e-6) {
nuclear@0 739 float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25;
nuclear@0 740 nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls);
nuclear@0 741 tang = nextu - pos;
nuclear@0 742 }
nuclear@0 743
nuclear@0 744 Vector3 normal;
nuclear@0 745 Vector3 nextv = sweep_vert(u, v + dv, height, sfunc, cls);
nuclear@0 746 Vector3 bitan = nextv - pos;
nuclear@0 747 if(bitan.length_sq() < 1e-6) {
nuclear@0 748 nextv = sweep_vert(u, v - dv, height, sfunc, cls);
nuclear@0 749 bitan = pos - nextv;
nuclear@0 750 }
nuclear@0 751
nuclear@0 752 normal = cross_product(tang, bitan);
nuclear@0 753
nuclear@0 754 *varr++ = pos;
nuclear@0 755 *narr++ = normal.normalized();
nuclear@0 756 *tarr++ = tang.normalized();
nuclear@0 757 *uvarr++ = Vector2(u, v);
nuclear@0 758
nuclear@0 759 if(i < usub && j < vsub) {
nuclear@0 760 int idx = i * vverts + j;
nuclear@0 761
nuclear@0 762 *idxarr++ = idx;
nuclear@0 763 *idxarr++ = idx + vverts + 1;
nuclear@0 764 *idxarr++ = idx + 1;
nuclear@0 765
nuclear@0 766 *idxarr++ = idx;
nuclear@0 767 *idxarr++ = idx + vverts;
nuclear@0 768 *idxarr++ = idx + vverts + 1;
nuclear@0 769 }
nuclear@0 770
nuclear@0 771 v += dv;
nuclear@0 772 }
nuclear@0 773 u += du;
nuclear@0 774 }
nuclear@0 775 }