dbf-halloween2015
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/meshgen.cc Sun Nov 01 00:09:12 2015 +0200 1.3 @@ -0,0 +1,775 @@ 1.4 +#include <stdio.h> 1.5 +#include "meshgen.h" 1.6 +#include "mesh.h" 1.7 + 1.8 +// -------- sphere -------- 1.9 + 1.10 +#define SURAD(u) ((u) * 2.0 * M_PI) 1.11 +#define SVRAD(v) ((v) * M_PI) 1.12 + 1.13 +static Vector3 sphvec(float theta, float phi) 1.14 +{ 1.15 + return Vector3(sin(theta) * sin(phi), 1.16 + cos(phi), 1.17 + cos(theta) * sin(phi)); 1.18 +} 1.19 + 1.20 +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange) 1.21 +{ 1.22 + if(usub < 4) usub = 4; 1.23 + if(vsub < 2) vsub = 2; 1.24 + 1.25 + int uverts = usub + 1; 1.26 + int vverts = vsub + 1; 1.27 + 1.28 + int num_verts = uverts * vverts; 1.29 + int num_quads = usub * vsub; 1.30 + int num_tri = num_quads * 2; 1.31 + 1.32 + mesh->clear(); 1.33 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.34 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.35 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.36 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.37 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.38 + 1.39 + float du = urange / (float)(uverts - 1); 1.40 + float dv = vrange / (float)(vverts - 1); 1.41 + 1.42 + float u = 0.0; 1.43 + for(int i=0; i<uverts; i++) { 1.44 + float theta = u * 2.0 * M_PI; 1.45 + 1.46 + float v = 0.0; 1.47 + for(int j=0; j<vverts; j++) { 1.48 + float phi = v * M_PI; 1.49 + 1.50 + Vector3 pos = sphvec(theta, phi); 1.51 + 1.52 + *varr++ = pos * rad; 1.53 + *narr++ = pos; 1.54 + *tarr++ = (sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)).normalized(); 1.55 + *uvarr++ = Vector2(u * urange, v * vrange); 1.56 + 1.57 + if(i < usub && j < vsub) { 1.58 + int idx = i * vverts + j; 1.59 + *idxarr++ = idx; 1.60 + *idxarr++ = idx + 1; 1.61 + *idxarr++ = idx + vverts + 1; 1.62 + 1.63 + *idxarr++ = idx; 1.64 + *idxarr++ = idx + vverts + 1; 1.65 + *idxarr++ = idx + vverts; 1.66 + } 1.67 + 1.68 + v += dv; 1.69 + } 1.70 + u += du; 1.71 + } 1.72 +} 1.73 + 1.74 +// -------- torus ----------- 1.75 +static Vector3 torusvec(float theta, float phi, float mr, float rr) 1.76 +{ 1.77 + theta = -theta; 1.78 + 1.79 + float rx = -cos(phi) * rr + mr; 1.80 + float ry = sin(phi) * rr; 1.81 + float rz = 0.0; 1.82 + 1.83 + float x = rx * sin(theta) + rz * cos(theta); 1.84 + float y = ry; 1.85 + float z = -rx * cos(theta) + rz * sin(theta); 1.86 + 1.87 + return Vector3(x, y, z); 1.88 +} 1.89 + 1.90 +void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange) 1.91 +{ 1.92 + if(usub < 4) usub = 4; 1.93 + if(vsub < 2) vsub = 2; 1.94 + 1.95 + int uverts = usub + 1; 1.96 + int vverts = vsub + 1; 1.97 + 1.98 + int num_verts = uverts * vverts; 1.99 + int num_quads = usub * vsub; 1.100 + int num_tri = num_quads * 2; 1.101 + 1.102 + mesh->clear(); 1.103 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.104 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.105 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.106 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.107 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.108 + 1.109 + float du = urange / (float)(uverts - 1); 1.110 + float dv = vrange / (float)(vverts - 1); 1.111 + 1.112 + float u = 0.0; 1.113 + for(int i=0; i<uverts; i++) { 1.114 + float theta = u * 2.0 * M_PI; 1.115 + 1.116 + float v = 0.0; 1.117 + for(int j=0; j<vverts; j++) { 1.118 + float phi = v * 2.0 * M_PI; 1.119 + 1.120 + Vector3 pos = torusvec(theta, phi, mainrad, ringrad); 1.121 + Vector3 cent = torusvec(theta, phi, mainrad, 0.0); 1.122 + 1.123 + *varr++ = pos; 1.124 + *narr++ = (pos - cent) / ringrad; 1.125 + 1.126 + Vector3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad); 1.127 + Vector3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad); 1.128 + 1.129 + *tarr++ = (pnext - pprev).normalized(); 1.130 + *uvarr++ = Vector2(u * urange, v * vrange); 1.131 + 1.132 + if(i < usub && j < vsub) { 1.133 + int idx = i * vverts + j; 1.134 + *idxarr++ = idx; 1.135 + *idxarr++ = idx + 1; 1.136 + *idxarr++ = idx + vverts + 1; 1.137 + 1.138 + *idxarr++ = idx; 1.139 + *idxarr++ = idx + vverts + 1; 1.140 + *idxarr++ = idx + vverts; 1.141 + } 1.142 + 1.143 + v += dv; 1.144 + } 1.145 + u += du; 1.146 + } 1.147 +} 1.148 + 1.149 + 1.150 +// -------- cylinder -------- 1.151 + 1.152 +static Vector3 cylvec(float theta, float height) 1.153 +{ 1.154 + return Vector3(sin(theta), height, cos(theta)); 1.155 +} 1.156 + 1.157 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.158 +{ 1.159 + if(usub < 4) usub = 4; 1.160 + if(vsub < 1) vsub = 1; 1.161 + 1.162 + int uverts = usub + 1; 1.163 + int vverts = vsub + 1; 1.164 + 1.165 + int num_body_verts = uverts * vverts; 1.166 + int num_body_quads = usub * vsub; 1.167 + int num_body_tri = num_body_quads * 2; 1.168 + 1.169 + int capvverts = capsub ? capsub + 1 : 0; 1.170 + int num_cap_verts = uverts * capvverts; 1.171 + int num_cap_quads = usub * capsub; 1.172 + int num_cap_tri = num_cap_quads * 2; 1.173 + 1.174 + int num_verts = num_body_verts + num_cap_verts * 2; 1.175 + int num_tri = num_body_tri + num_cap_tri * 2; 1.176 + 1.177 + mesh->clear(); 1.178 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.179 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.180 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.181 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.182 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.183 + 1.184 + float du = urange / (float)(uverts - 1); 1.185 + float dv = vrange / (float)(vverts - 1); 1.186 + 1.187 + float u = 0.0; 1.188 + for(int i=0; i<uverts; i++) { 1.189 + float theta = SURAD(u); 1.190 + 1.191 + float v = 0.0; 1.192 + for(int j=0; j<vverts; j++) { 1.193 + float y = (v - 0.5) * height; 1.194 + Vector3 pos = cylvec(theta, y); 1.195 + 1.196 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 1.197 + *narr++ = Vector3(pos.x, 0.0, pos.z); 1.198 + *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.199 + *uvarr++ = Vector2(u * urange, v * vrange); 1.200 + 1.201 + if(i < usub && j < vsub) { 1.202 + int idx = i * vverts + j; 1.203 + 1.204 + *idxarr++ = idx; 1.205 + *idxarr++ = idx + vverts + 1; 1.206 + *idxarr++ = idx + 1; 1.207 + 1.208 + *idxarr++ = idx; 1.209 + *idxarr++ = idx + vverts; 1.210 + *idxarr++ = idx + vverts + 1; 1.211 + } 1.212 + 1.213 + v += dv; 1.214 + } 1.215 + u += du; 1.216 + } 1.217 + 1.218 + 1.219 + // now the cap! 1.220 + if(!capsub) { 1.221 + return; 1.222 + } 1.223 + 1.224 + dv = 1.0 / (float)(capvverts - 1); 1.225 + 1.226 + u = 0.0; 1.227 + for(int i=0; i<uverts; i++) { 1.228 + float theta = SURAD(u); 1.229 + 1.230 + float v = 0.0; 1.231 + for(int j=0; j<capvverts; j++) { 1.232 + float r = v * rad; 1.233 + 1.234 + Vector3 pos = cylvec(theta, height / 2.0) * r; 1.235 + pos.y = height / 2.0; 1.236 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.237 + 1.238 + *varr++ = pos; 1.239 + *narr++ = Vector3(0, 1, 0); 1.240 + *tarr++ = tang; 1.241 + *uvarr++ = Vector2(u * urange, v); 1.242 + 1.243 + pos.y = -height / 2.0; 1.244 + *varr++ = pos; 1.245 + *narr++ = Vector3(0, -1, 0); 1.246 + *tarr++ = -tang; 1.247 + *uvarr++ = Vector2(u * urange, v); 1.248 + 1.249 + if(i < usub && j < capsub) { 1.250 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 1.251 + 1.252 + unsigned int vidx[4] = { 1.253 + idx, 1.254 + idx + capvverts * 2, 1.255 + idx + (capvverts + 1) * 2, 1.256 + idx + 2 1.257 + }; 1.258 + 1.259 + *idxarr++ = vidx[0]; 1.260 + *idxarr++ = vidx[2]; 1.261 + *idxarr++ = vidx[1]; 1.262 + *idxarr++ = vidx[0]; 1.263 + *idxarr++ = vidx[3]; 1.264 + *idxarr++ = vidx[2]; 1.265 + 1.266 + *idxarr++ = vidx[0] + 1; 1.267 + *idxarr++ = vidx[1] + 1; 1.268 + *idxarr++ = vidx[2] + 1; 1.269 + *idxarr++ = vidx[0] + 1; 1.270 + *idxarr++ = vidx[2] + 1; 1.271 + *idxarr++ = vidx[3] + 1; 1.272 + } 1.273 + 1.274 + v += dv; 1.275 + } 1.276 + u += du; 1.277 + } 1.278 +} 1.279 + 1.280 +// -------- cone -------- 1.281 + 1.282 +static Vector3 conevec(float theta, float y, float height) 1.283 +{ 1.284 + float scale = 1.0 - y / height; 1.285 + return Vector3(sin(theta) * scale, y, cos(theta) * scale); 1.286 +} 1.287 + 1.288 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.289 +{ 1.290 + if(usub < 4) usub = 4; 1.291 + if(vsub < 1) vsub = 1; 1.292 + 1.293 + int uverts = usub + 1; 1.294 + int vverts = vsub + 1; 1.295 + 1.296 + int num_body_verts = uverts * vverts; 1.297 + int num_body_quads = usub * vsub; 1.298 + int num_body_tri = num_body_quads * 2; 1.299 + 1.300 + int capvverts = capsub ? capsub + 1 : 0; 1.301 + int num_cap_verts = uverts * capvverts; 1.302 + int num_cap_quads = usub * capsub; 1.303 + int num_cap_tri = num_cap_quads * 2; 1.304 + 1.305 + int num_verts = num_body_verts + num_cap_verts; 1.306 + int num_tri = num_body_tri + num_cap_tri; 1.307 + 1.308 + mesh->clear(); 1.309 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.310 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.311 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.312 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.313 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.314 + 1.315 + float du = urange / (float)(uverts - 1); 1.316 + float dv = vrange / (float)(vverts - 1); 1.317 + 1.318 + float u = 0.0; 1.319 + for(int i=0; i<uverts; i++) { 1.320 + float theta = SURAD(u); 1.321 + 1.322 + float v = 0.0; 1.323 + for(int j=0; j<vverts; j++) { 1.324 + float y = v * height; 1.325 + Vector3 pos = conevec(theta, y, height); 1.326 + 1.327 + Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized(); 1.328 + Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized(); 1.329 + 1.330 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 1.331 + *narr++ = cross_product(tang, bitang); 1.332 + *tarr++ = tang; 1.333 + *uvarr++ = Vector2(u * urange, v * vrange); 1.334 + 1.335 + if(i < usub && j < vsub) { 1.336 + int idx = i * vverts + j; 1.337 + 1.338 + *idxarr++ = idx; 1.339 + *idxarr++ = idx + vverts + 1; 1.340 + *idxarr++ = idx + 1; 1.341 + 1.342 + *idxarr++ = idx; 1.343 + *idxarr++ = idx + vverts; 1.344 + *idxarr++ = idx + vverts + 1; 1.345 + } 1.346 + 1.347 + v += dv; 1.348 + } 1.349 + u += du; 1.350 + } 1.351 + 1.352 + 1.353 + // now the bottom cap! 1.354 + if(!capsub) { 1.355 + return; 1.356 + } 1.357 + 1.358 + dv = 1.0 / (float)(capvverts - 1); 1.359 + 1.360 + u = 0.0; 1.361 + for(int i=0; i<uverts; i++) { 1.362 + float theta = SURAD(u); 1.363 + 1.364 + float v = 0.0; 1.365 + for(int j=0; j<capvverts; j++) { 1.366 + float r = v * rad; 1.367 + 1.368 + Vector3 pos = conevec(theta, 0.0, height) * r; 1.369 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.370 + 1.371 + *varr++ = pos; 1.372 + *narr++ = Vector3(0, -1, 0); 1.373 + *tarr++ = tang; 1.374 + *uvarr++ = Vector2(u * urange, v); 1.375 + 1.376 + if(i < usub && j < capsub) { 1.377 + unsigned int idx = num_body_verts + i * capvverts + j; 1.378 + 1.379 + unsigned int vidx[4] = { 1.380 + idx, 1.381 + idx + capvverts, 1.382 + idx + (capvverts + 1), 1.383 + idx + 1 1.384 + }; 1.385 + 1.386 + *idxarr++ = vidx[0]; 1.387 + *idxarr++ = vidx[1]; 1.388 + *idxarr++ = vidx[2]; 1.389 + *idxarr++ = vidx[0]; 1.390 + *idxarr++ = vidx[2]; 1.391 + *idxarr++ = vidx[3]; 1.392 + } 1.393 + 1.394 + v += dv; 1.395 + } 1.396 + u += du; 1.397 + } 1.398 +} 1.399 + 1.400 + 1.401 +// -------- plane -------- 1.402 + 1.403 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 1.404 +{ 1.405 + gen_heightmap(mesh, width, height, usub, vsub, 0); 1.406 +} 1.407 + 1.408 + 1.409 +// ----- heightmap ------ 1.410 + 1.411 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata) 1.412 +{ 1.413 + if(usub < 1) usub = 1; 1.414 + if(vsub < 1) vsub = 1; 1.415 + 1.416 + mesh->clear(); 1.417 + 1.418 + int uverts = usub + 1; 1.419 + int vverts = vsub + 1; 1.420 + int num_verts = uverts * vverts; 1.421 + 1.422 + int num_quads = usub * vsub; 1.423 + int num_tri = num_quads * 2; 1.424 + 1.425 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.426 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.427 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.428 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.429 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.430 + 1.431 + float du = 1.0 / (float)usub; 1.432 + float dv = 1.0 / (float)vsub; 1.433 + 1.434 + float u = 0.0; 1.435 + for(int i=0; i<uverts; i++) { 1.436 + float v = 0.0; 1.437 + for(int j=0; j<vverts; j++) { 1.438 + float x = (u - 0.5) * width; 1.439 + float y = (v - 0.5) * height; 1.440 + float z = hf ? hf(u, v, hfdata) : 0.0; 1.441 + 1.442 + Vector3 normal = Vector3(0, 0, 1); 1.443 + if(hf) { 1.444 + float u1z = hf(u + du, v, hfdata); 1.445 + float v1z = hf(u, v + dv, hfdata); 1.446 + 1.447 + Vector3 tang = Vector3(du * width, 0, u1z - z); 1.448 + Vector3 bitan = Vector3(0, dv * height, v1z - z); 1.449 + normal = cross_product(tang, bitan).normalized(); 1.450 + } 1.451 + 1.452 + *varr++ = Vector3(x, y, z); 1.453 + *narr++ = normal; 1.454 + *tarr++ = Vector3(1, 0, 0); 1.455 + *uvarr++ = Vector2(u, v); 1.456 + 1.457 + if(i < usub && j < vsub) { 1.458 + int idx = i * vverts + j; 1.459 + 1.460 + *idxarr++ = idx; 1.461 + *idxarr++ = idx + vverts + 1; 1.462 + *idxarr++ = idx + 1; 1.463 + 1.464 + *idxarr++ = idx; 1.465 + *idxarr++ = idx + vverts; 1.466 + *idxarr++ = idx + vverts + 1; 1.467 + } 1.468 + 1.469 + v += dv; 1.470 + } 1.471 + u += du; 1.472 + } 1.473 +} 1.474 + 1.475 +// ----- box ------ 1.476 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub) 1.477 +{ 1.478 + static const float face_angles[][2] = { 1.479 + {0, 0}, 1.480 + {M_PI / 2.0, 0}, 1.481 + {M_PI, 0}, 1.482 + {3.0 * M_PI / 2.0, 0}, 1.483 + {0, M_PI / 2.0}, 1.484 + {0, -M_PI / 2.0} 1.485 + }; 1.486 + 1.487 + if(usub < 1) usub = 1; 1.488 + if(vsub < 1) vsub = 1; 1.489 + 1.490 + mesh->clear(); 1.491 + 1.492 + for(int i=0; i<6; i++) { 1.493 + Matrix4x4 xform, dir_xform; 1.494 + Mesh m; 1.495 + 1.496 + gen_plane(&m, 1, 1, usub, vsub); 1.497 + xform.rotate(Vector3(face_angles[i][1], face_angles[i][0], 0)); 1.498 + dir_xform = xform; 1.499 + xform.translate(Vector3(0, 0, 0.5)); 1.500 + m.apply_xform(xform, dir_xform); 1.501 + 1.502 + mesh->append(m); 1.503 + } 1.504 + 1.505 + Matrix4x4 scale; 1.506 + scale.set_scaling(Vector3(xsz, ysz, zsz)); 1.507 + mesh->apply_xform(scale, Matrix4x4::identity); 1.508 +} 1.509 + 1.510 +/* 1.511 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz) 1.512 +{ 1.513 + mesh->clear(); 1.514 + 1.515 + const int num_faces = 6; 1.516 + int num_verts = num_faces * 4; 1.517 + int num_tri = num_faces * 2; 1.518 + 1.519 + float x = xsz / 2.0; 1.520 + float y = ysz / 2.0; 1.521 + float z = zsz / 2.0; 1.522 + 1.523 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.524 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.525 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.526 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.527 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.528 + 1.529 + static const Vector2 uv[] = { Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(0, 1) }; 1.530 + 1.531 + // front 1.532 + for(int i=0; i<4; i++) { 1.533 + *narr++ = Vector3(0, 0, 1); 1.534 + *tarr++ = Vector3(1, 0, 0); 1.535 + *uvarr++ = uv[i]; 1.536 + } 1.537 + *varr++ = Vector3(-x, -y, z); 1.538 + *varr++ = Vector3(x, -y, z); 1.539 + *varr++ = Vector3(x, y, z); 1.540 + *varr++ = Vector3(-x, y, z); 1.541 + // right 1.542 + for(int i=0; i<4; i++) { 1.543 + *narr++ = Vector3(1, 0, 0); 1.544 + *tarr++ = Vector3(0, 0, -1); 1.545 + *uvarr++ = uv[i]; 1.546 + } 1.547 + *varr++ = Vector3(x, -y, z); 1.548 + *varr++ = Vector3(x, -y, -z); 1.549 + *varr++ = Vector3(x, y, -z); 1.550 + *varr++ = Vector3(x, y, z); 1.551 + // back 1.552 + for(int i=0; i<4; i++) { 1.553 + *narr++ = Vector3(0, 0, -1); 1.554 + *tarr++ = Vector3(-1, 0, 0); 1.555 + *uvarr++ = uv[i]; 1.556 + } 1.557 + *varr++ = Vector3(x, -y, -z); 1.558 + *varr++ = Vector3(-x, -y, -z); 1.559 + *varr++ = Vector3(-x, y, -z); 1.560 + *varr++ = Vector3(x, y, -z); 1.561 + // left 1.562 + for(int i=0; i<4; i++) { 1.563 + *narr++ = Vector3(-1, 0, 0); 1.564 + *tarr++ = Vector3(0, 0, 1); 1.565 + *uvarr++ = uv[i]; 1.566 + } 1.567 + *varr++ = Vector3(-x, -y, -z); 1.568 + *varr++ = Vector3(-x, -y, z); 1.569 + *varr++ = Vector3(-x, y, z); 1.570 + *varr++ = Vector3(-x, y, -z); 1.571 + // top 1.572 + for(int i=0; i<4; i++) { 1.573 + *narr++ = Vector3(0, 1, 0); 1.574 + *tarr++ = Vector3(1, 0, 0); 1.575 + *uvarr++ = uv[i]; 1.576 + } 1.577 + *varr++ = Vector3(-x, y, z); 1.578 + *varr++ = Vector3(x, y, z); 1.579 + *varr++ = Vector3(x, y, -z); 1.580 + *varr++ = Vector3(-x, y, -z); 1.581 + // bottom 1.582 + for(int i=0; i<4; i++) { 1.583 + *narr++ = Vector3(0, -1, 0); 1.584 + *tarr++ = Vector3(1, 0, 0); 1.585 + *uvarr++ = uv[i]; 1.586 + } 1.587 + *varr++ = Vector3(-x, -y, -z); 1.588 + *varr++ = Vector3(x, -y, -z); 1.589 + *varr++ = Vector3(x, -y, z); 1.590 + *varr++ = Vector3(-x, -y, z); 1.591 + 1.592 + // index array 1.593 + static const int faceidx[] = {0, 1, 2, 0, 2, 3}; 1.594 + for(int i=0; i<num_faces; i++) { 1.595 + for(int j=0; j<6; j++) { 1.596 + *idxarr++ = faceidx[j] + i * 4; 1.597 + } 1.598 + } 1.599 +} 1.600 +*/ 1.601 + 1.602 +static inline Vector3 rev_vert(float u, float v, Vector2 (*rf)(float, float, void*), void *cls) 1.603 +{ 1.604 + Vector2 pos = rf(u, v, cls); 1.605 + 1.606 + float angle = u * 2.0 * M_PI; 1.607 + float x = pos.x * cos(angle); 1.608 + float y = pos.y; 1.609 + float z = pos.x * sin(angle); 1.610 + 1.611 + return Vector3(x, y, z); 1.612 +} 1.613 + 1.614 +// ------ surface of revolution ------- 1.615 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls) 1.616 +{ 1.617 + gen_revol(mesh, usub, vsub, rfunc, 0, cls); 1.618 +} 1.619 + 1.620 +void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), 1.621 + Vector2 (*nfunc)(float, float, void*), void *cls) 1.622 +{ 1.623 + if(!rfunc) return; 1.624 + if(usub < 3) usub = 3; 1.625 + if(vsub < 1) vsub = 1; 1.626 + 1.627 + mesh->clear(); 1.628 + 1.629 + int uverts = usub + 1; 1.630 + int vverts = vsub + 1; 1.631 + int num_verts = uverts * vverts; 1.632 + 1.633 + int num_quads = usub * vsub; 1.634 + int num_tri = num_quads * 2; 1.635 + 1.636 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.637 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.638 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.639 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.640 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.641 + 1.642 + float du = 1.0 / (float)(uverts - 1); 1.643 + float dv = 1.0 / (float)(vverts - 1); 1.644 + 1.645 + float u = 0.0; 1.646 + for(int i=0; i<uverts; i++) { 1.647 + float v = 0.0; 1.648 + for(int j=0; j<vverts; j++) { 1.649 + Vector3 pos = rev_vert(u, v, rfunc, cls); 1.650 + 1.651 + Vector3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls); 1.652 + Vector3 tang = nextu - pos; 1.653 + if(tang.length_sq() < 1e-6) { 1.654 + float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25; 1.655 + nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls); 1.656 + tang = nextu - pos; 1.657 + } 1.658 + 1.659 + Vector3 normal; 1.660 + if(nfunc) { 1.661 + normal = rev_vert(u, v, nfunc, cls); 1.662 + } else { 1.663 + Vector3 nextv = rev_vert(u, v + dv, rfunc, cls); 1.664 + Vector3 bitan = nextv - pos; 1.665 + if(bitan.length_sq() < 1e-6) { 1.666 + nextv = rev_vert(u, v - dv, rfunc, cls); 1.667 + bitan = pos - nextv; 1.668 + } 1.669 + 1.670 + normal = cross_product(tang, bitan); 1.671 + } 1.672 + 1.673 + *varr++ = pos; 1.674 + *narr++ = normal.normalized(); 1.675 + *tarr++ = tang.normalized(); 1.676 + *uvarr++ = Vector2(u, v); 1.677 + 1.678 + if(i < usub && j < vsub) { 1.679 + int idx = i * vverts + j; 1.680 + 1.681 + *idxarr++ = idx; 1.682 + *idxarr++ = idx + vverts + 1; 1.683 + *idxarr++ = idx + 1; 1.684 + 1.685 + *idxarr++ = idx; 1.686 + *idxarr++ = idx + vverts; 1.687 + *idxarr++ = idx + vverts + 1; 1.688 + } 1.689 + 1.690 + v += dv; 1.691 + } 1.692 + u += du; 1.693 + } 1.694 +} 1.695 + 1.696 + 1.697 +static inline Vector3 sweep_vert(float u, float v, float height, Vector2 (*sf)(float, float, void*), void *cls) 1.698 +{ 1.699 + Vector2 pos = sf(u, v, cls); 1.700 + 1.701 + float x = pos.x; 1.702 + float y = v * height; 1.703 + float z = pos.y; 1.704 + 1.705 + return Vector3(x, y, z); 1.706 +} 1.707 + 1.708 +// ---- sweep shape along a path ---- 1.709 +void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vector2 (*sfunc)(float, float, void*), void *cls) 1.710 +{ 1.711 + if(!sfunc) return; 1.712 + if(usub < 3) usub = 3; 1.713 + if(vsub < 1) vsub = 1; 1.714 + 1.715 + mesh->clear(); 1.716 + 1.717 + int uverts = usub + 1; 1.718 + int vverts = vsub + 1; 1.719 + int num_verts = uverts * vverts; 1.720 + 1.721 + int num_quads = usub * vsub; 1.722 + int num_tri = num_quads * 2; 1.723 + 1.724 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.725 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.726 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.727 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.728 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.729 + 1.730 + float du = 1.0 / (float)(uverts - 1); 1.731 + float dv = 1.0 / (float)(vverts - 1); 1.732 + 1.733 + float u = 0.0; 1.734 + for(int i=0; i<uverts; i++) { 1.735 + float v = 0.0; 1.736 + for(int j=0; j<vverts; j++) { 1.737 + Vector3 pos = sweep_vert(u, v, height, sfunc, cls); 1.738 + 1.739 + Vector3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls); 1.740 + Vector3 tang = nextu - pos; 1.741 + if(tang.length_sq() < 1e-6) { 1.742 + float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25; 1.743 + nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls); 1.744 + tang = nextu - pos; 1.745 + } 1.746 + 1.747 + Vector3 normal; 1.748 + Vector3 nextv = sweep_vert(u, v + dv, height, sfunc, cls); 1.749 + Vector3 bitan = nextv - pos; 1.750 + if(bitan.length_sq() < 1e-6) { 1.751 + nextv = sweep_vert(u, v - dv, height, sfunc, cls); 1.752 + bitan = pos - nextv; 1.753 + } 1.754 + 1.755 + normal = cross_product(tang, bitan); 1.756 + 1.757 + *varr++ = pos; 1.758 + *narr++ = normal.normalized(); 1.759 + *tarr++ = tang.normalized(); 1.760 + *uvarr++ = Vector2(u, v); 1.761 + 1.762 + if(i < usub && j < vsub) { 1.763 + int idx = i * vverts + j; 1.764 + 1.765 + *idxarr++ = idx; 1.766 + *idxarr++ = idx + vverts + 1; 1.767 + *idxarr++ = idx + 1; 1.768 + 1.769 + *idxarr++ = idx; 1.770 + *idxarr++ = idx + vverts; 1.771 + *idxarr++ = idx + vverts + 1; 1.772 + } 1.773 + 1.774 + v += dv; 1.775 + } 1.776 + u += du; 1.777 + } 1.778 +}