cubemapper
diff src/meshgen.cc @ 0:8fc9e1d3aad2
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 27 Jul 2017 20:36:12 +0300 |
parents | |
children | 2bfafdced01a |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/meshgen.cc Thu Jul 27 20:36:12 2017 +0300 1.3 @@ -0,0 +1,881 @@ 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 Vec3 sphvec(float theta, float phi) 1.14 +{ 1.15 + return Vec3(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 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.34 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.35 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.36 + Vec2 *uvarr = (Vec2*)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 + Vec3 pos = sphvec(theta, phi); 1.51 + 1.52 + *varr++ = pos * rad; 1.53 + *narr++ = pos; 1.54 + *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)); 1.55 + *uvarr++ = Vec2(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 +// ------ geosphere ------ 1.75 +#define PHI 1.618034 1.76 + 1.77 +static Vec3 icosa_pt[] = { 1.78 + Vec3(PHI, 1, 0), 1.79 + Vec3(-PHI, 1, 0), 1.80 + Vec3(PHI, -1, 0), 1.81 + Vec3(-PHI, -1, 0), 1.82 + Vec3(1, 0, PHI), 1.83 + Vec3(1, 0, -PHI), 1.84 + Vec3(-1, 0, PHI), 1.85 + Vec3(-1, 0, -PHI), 1.86 + Vec3(0, PHI, 1), 1.87 + Vec3(0, -PHI, 1), 1.88 + Vec3(0, PHI, -1), 1.89 + Vec3(0, -PHI, -1) 1.90 +}; 1.91 +enum { P11, P12, P13, P14, P21, P22, P23, P24, P31, P32, P33, P34 }; 1.92 +static int icosa_idx[] = { 1.93 + P11, P31, P21, 1.94 + P11, P22, P33, 1.95 + P13, P21, P32, 1.96 + P13, P34, P22, 1.97 + P12, P23, P31, 1.98 + P12, P33, P24, 1.99 + P14, P32, P23, 1.100 + P14, P24, P34, 1.101 + 1.102 + P11, P33, P31, 1.103 + P12, P31, P33, 1.104 + P13, P32, P34, 1.105 + P14, P34, P32, 1.106 + 1.107 + P21, P13, P11, 1.108 + P22, P11, P13, 1.109 + P23, P12, P14, 1.110 + P24, P14, P12, 1.111 + 1.112 + P31, P23, P21, 1.113 + P32, P21, P23, 1.114 + P33, P22, P24, 1.115 + P34, P24, P22 1.116 +}; 1.117 + 1.118 +static void geosphere(std::vector<Vec3> *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter) 1.119 +{ 1.120 + if(!iter) { 1.121 + verts->push_back(v1); 1.122 + verts->push_back(v2); 1.123 + verts->push_back(v3); 1.124 + return; 1.125 + } 1.126 + 1.127 + Vec3 v12 = normalize(v1 + v2); 1.128 + Vec3 v23 = normalize(v2 + v3); 1.129 + Vec3 v31 = normalize(v3 + v1); 1.130 + 1.131 + geosphere(verts, v1, v12, v31, iter - 1); 1.132 + geosphere(verts, v2, v23, v12, iter - 1); 1.133 + geosphere(verts, v3, v31, v23, iter - 1); 1.134 + geosphere(verts, v12, v23, v31, iter - 1); 1.135 +} 1.136 + 1.137 +void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi) 1.138 +{ 1.139 + int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3; 1.140 + 1.141 + std::vector<Vec3> verts; 1.142 + for(int i=0; i<num_tri; i++) { 1.143 + Vec3 v[3]; 1.144 + 1.145 + for(int j=0; j<3; j++) { 1.146 + int vidx = icosa_idx[i * 3 + j]; 1.147 + v[j] = normalize(icosa_pt[vidx]); 1.148 + } 1.149 + 1.150 + if(hemi && (v[0].y < 0.0 || v[1].y < 0.0 || v[2].y < 0.0)) { 1.151 + continue; 1.152 + } 1.153 + 1.154 + geosphere(&verts, v[0], v[1], v[2], subdiv); 1.155 + } 1.156 + 1.157 + int num_verts = (int)verts.size(); 1.158 + 1.159 + mesh->clear(); 1.160 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.161 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.162 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.163 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.164 + 1.165 + for(int i=0; i<num_verts; i++) { 1.166 + *varr++ = verts[i] * rad; 1.167 + *narr++ = verts[i]; 1.168 + 1.169 + float theta = atan2(verts[i].z, verts[i].x); 1.170 + float phi = acos(verts[i].y); 1.171 + 1.172 + *tarr++ = normalize(sphvec(theta + 0.1f, (float)M_PI / 2.0f) - sphvec(theta - 0.1f, (float)M_PI / 2.0f)); 1.173 + 1.174 + float u = 0.5 * theta / M_PI + 0.5; 1.175 + float v = phi / M_PI; 1.176 + *uvarr++ = Vec2(u, v); 1.177 + } 1.178 +} 1.179 + 1.180 +// -------- torus ----------- 1.181 +static Vec3 torusvec(float theta, float phi, float mr, float rr) 1.182 +{ 1.183 + theta = -theta; 1.184 + 1.185 + float rx = -cos(phi) * rr + mr; 1.186 + float ry = sin(phi) * rr; 1.187 + float rz = 0.0; 1.188 + 1.189 + float x = rx * sin(theta) + rz * cos(theta); 1.190 + float y = ry; 1.191 + float z = -rx * cos(theta) + rz * sin(theta); 1.192 + 1.193 + return Vec3(x, y, z); 1.194 +} 1.195 + 1.196 +void gen_torus(Mesh *mesh, float mainrad, float ringrad, int usub, int vsub, float urange, float vrange) 1.197 +{ 1.198 + if(usub < 4) usub = 4; 1.199 + if(vsub < 2) vsub = 2; 1.200 + 1.201 + int uverts = usub + 1; 1.202 + int vverts = vsub + 1; 1.203 + 1.204 + int num_verts = uverts * vverts; 1.205 + int num_quads = usub * vsub; 1.206 + int num_tri = num_quads * 2; 1.207 + 1.208 + mesh->clear(); 1.209 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.210 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.211 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.212 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.213 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.214 + 1.215 + float du = urange / (float)(uverts - 1); 1.216 + float dv = vrange / (float)(vverts - 1); 1.217 + 1.218 + float u = 0.0; 1.219 + for(int i=0; i<uverts; i++) { 1.220 + float theta = u * 2.0 * M_PI; 1.221 + 1.222 + float v = 0.0; 1.223 + for(int j=0; j<vverts; j++) { 1.224 + float phi = v * 2.0 * M_PI; 1.225 + 1.226 + Vec3 pos = torusvec(theta, phi, mainrad, ringrad); 1.227 + Vec3 cent = torusvec(theta, phi, mainrad, 0.0); 1.228 + 1.229 + *varr++ = pos; 1.230 + *narr++ = (pos - cent) / ringrad; 1.231 + 1.232 + Vec3 pprev = torusvec(theta - 0.1f, phi, mainrad, ringrad); 1.233 + Vec3 pnext = torusvec(theta + 0.1f, phi, mainrad, ringrad); 1.234 + 1.235 + *tarr++ = normalize(pnext - pprev); 1.236 + *uvarr++ = Vec2(u * urange, v * vrange); 1.237 + 1.238 + if(i < usub && j < vsub) { 1.239 + int idx = i * vverts + j; 1.240 + *idxarr++ = idx; 1.241 + *idxarr++ = idx + 1; 1.242 + *idxarr++ = idx + vverts + 1; 1.243 + 1.244 + *idxarr++ = idx; 1.245 + *idxarr++ = idx + vverts + 1; 1.246 + *idxarr++ = idx + vverts; 1.247 + } 1.248 + 1.249 + v += dv; 1.250 + } 1.251 + u += du; 1.252 + } 1.253 +} 1.254 + 1.255 + 1.256 +// -------- cylinder -------- 1.257 + 1.258 +static Vec3 cylvec(float theta, float height) 1.259 +{ 1.260 + return Vec3(sin(theta), height, cos(theta)); 1.261 +} 1.262 + 1.263 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.264 +{ 1.265 + if(usub < 4) usub = 4; 1.266 + if(vsub < 1) vsub = 1; 1.267 + 1.268 + int uverts = usub + 1; 1.269 + int vverts = vsub + 1; 1.270 + 1.271 + int num_body_verts = uverts * vverts; 1.272 + int num_body_quads = usub * vsub; 1.273 + int num_body_tri = num_body_quads * 2; 1.274 + 1.275 + int capvverts = capsub ? capsub + 1 : 0; 1.276 + int num_cap_verts = uverts * capvverts; 1.277 + int num_cap_quads = usub * capsub; 1.278 + int num_cap_tri = num_cap_quads * 2; 1.279 + 1.280 + int num_verts = num_body_verts + num_cap_verts * 2; 1.281 + int num_tri = num_body_tri + num_cap_tri * 2; 1.282 + 1.283 + mesh->clear(); 1.284 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.285 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.286 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.287 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.288 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.289 + 1.290 + float du = urange / (float)(uverts - 1); 1.291 + float dv = vrange / (float)(vverts - 1); 1.292 + 1.293 + float u = 0.0; 1.294 + for(int i=0; i<uverts; i++) { 1.295 + float theta = SURAD(u); 1.296 + 1.297 + float v = 0.0; 1.298 + for(int j=0; j<vverts; j++) { 1.299 + float y = (v - 0.5) * height; 1.300 + Vec3 pos = cylvec(theta, y); 1.301 + 1.302 + *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad); 1.303 + *narr++ = Vec3(pos.x, 0.0, pos.z); 1.304 + *tarr++ = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)); 1.305 + *uvarr++ = Vec2(u * urange, v * vrange); 1.306 + 1.307 + if(i < usub && j < vsub) { 1.308 + int idx = i * vverts + j; 1.309 + 1.310 + *idxarr++ = idx; 1.311 + *idxarr++ = idx + vverts + 1; 1.312 + *idxarr++ = idx + 1; 1.313 + 1.314 + *idxarr++ = idx; 1.315 + *idxarr++ = idx + vverts; 1.316 + *idxarr++ = idx + vverts + 1; 1.317 + } 1.318 + 1.319 + v += dv; 1.320 + } 1.321 + u += du; 1.322 + } 1.323 + 1.324 + 1.325 + // now the cap! 1.326 + if(!capsub) { 1.327 + return; 1.328 + } 1.329 + 1.330 + dv = 1.0 / (float)(capvverts - 1); 1.331 + 1.332 + u = 0.0; 1.333 + for(int i=0; i<uverts; i++) { 1.334 + float theta = SURAD(u); 1.335 + 1.336 + float v = 0.0; 1.337 + for(int j=0; j<capvverts; j++) { 1.338 + float r = v * rad; 1.339 + 1.340 + Vec3 pos = cylvec(theta, height / 2.0) * r; 1.341 + pos.y = height / 2.0; 1.342 + Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)); 1.343 + 1.344 + *varr++ = pos; 1.345 + *narr++ = Vec3(0, 1, 0); 1.346 + *tarr++ = tang; 1.347 + *uvarr++ = Vec2(u * urange, v); 1.348 + 1.349 + pos.y = -height / 2.0; 1.350 + *varr++ = pos; 1.351 + *narr++ = Vec3(0, -1, 0); 1.352 + *tarr++ = -tang; 1.353 + *uvarr++ = Vec2(u * urange, v); 1.354 + 1.355 + if(i < usub && j < capsub) { 1.356 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 1.357 + 1.358 + unsigned int vidx[4] = { 1.359 + idx, 1.360 + idx + capvverts * 2, 1.361 + idx + (capvverts + 1) * 2, 1.362 + idx + 2 1.363 + }; 1.364 + 1.365 + *idxarr++ = vidx[0]; 1.366 + *idxarr++ = vidx[2]; 1.367 + *idxarr++ = vidx[1]; 1.368 + *idxarr++ = vidx[0]; 1.369 + *idxarr++ = vidx[3]; 1.370 + *idxarr++ = vidx[2]; 1.371 + 1.372 + *idxarr++ = vidx[0] + 1; 1.373 + *idxarr++ = vidx[1] + 1; 1.374 + *idxarr++ = vidx[2] + 1; 1.375 + *idxarr++ = vidx[0] + 1; 1.376 + *idxarr++ = vidx[2] + 1; 1.377 + *idxarr++ = vidx[3] + 1; 1.378 + } 1.379 + 1.380 + v += dv; 1.381 + } 1.382 + u += du; 1.383 + } 1.384 +} 1.385 + 1.386 +// -------- cone -------- 1.387 + 1.388 +static Vec3 conevec(float theta, float y, float height) 1.389 +{ 1.390 + float scale = 1.0 - y / height; 1.391 + return Vec3(sin(theta) * scale, y, cos(theta) * scale); 1.392 +} 1.393 + 1.394 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.395 +{ 1.396 + if(usub < 4) usub = 4; 1.397 + if(vsub < 1) vsub = 1; 1.398 + 1.399 + int uverts = usub + 1; 1.400 + int vverts = vsub + 1; 1.401 + 1.402 + int num_body_verts = uverts * vverts; 1.403 + int num_body_quads = usub * vsub; 1.404 + int num_body_tri = num_body_quads * 2; 1.405 + 1.406 + int capvverts = capsub ? capsub + 1 : 0; 1.407 + int num_cap_verts = uverts * capvverts; 1.408 + int num_cap_quads = usub * capsub; 1.409 + int num_cap_tri = num_cap_quads * 2; 1.410 + 1.411 + int num_verts = num_body_verts + num_cap_verts; 1.412 + int num_tri = num_body_tri + num_cap_tri; 1.413 + 1.414 + mesh->clear(); 1.415 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.416 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.417 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.418 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.419 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.420 + 1.421 + float du = urange / (float)(uverts - 1); 1.422 + float dv = vrange / (float)(vverts - 1); 1.423 + 1.424 + float u = 0.0; 1.425 + for(int i=0; i<uverts; i++) { 1.426 + float theta = SURAD(u); 1.427 + 1.428 + float v = 0.0; 1.429 + for(int j=0; j<vverts; j++) { 1.430 + float y = v * height; 1.431 + Vec3 pos = conevec(theta, y, height); 1.432 + 1.433 + Vec3 tang = normalize(conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)); 1.434 + Vec3 bitang = normalize(conevec(theta, y + 0.1, height) - pos); 1.435 + 1.436 + *varr++ = Vec3(pos.x * rad, pos.y, pos.z * rad); 1.437 + *narr++ = cross(tang, bitang); 1.438 + *tarr++ = tang; 1.439 + *uvarr++ = Vec2(u * urange, v * vrange); 1.440 + 1.441 + if(i < usub && j < vsub) { 1.442 + int idx = i * vverts + j; 1.443 + 1.444 + *idxarr++ = idx; 1.445 + *idxarr++ = idx + vverts + 1; 1.446 + *idxarr++ = idx + 1; 1.447 + 1.448 + *idxarr++ = idx; 1.449 + *idxarr++ = idx + vverts; 1.450 + *idxarr++ = idx + vverts + 1; 1.451 + } 1.452 + 1.453 + v += dv; 1.454 + } 1.455 + u += du; 1.456 + } 1.457 + 1.458 + 1.459 + // now the bottom cap! 1.460 + if(!capsub) { 1.461 + return; 1.462 + } 1.463 + 1.464 + dv = 1.0 / (float)(capvverts - 1); 1.465 + 1.466 + u = 0.0; 1.467 + for(int i=0; i<uverts; i++) { 1.468 + float theta = SURAD(u); 1.469 + 1.470 + float v = 0.0; 1.471 + for(int j=0; j<capvverts; j++) { 1.472 + float r = v * rad; 1.473 + 1.474 + Vec3 pos = conevec(theta, 0.0, height) * r; 1.475 + Vec3 tang = normalize(cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)); 1.476 + 1.477 + *varr++ = pos; 1.478 + *narr++ = Vec3(0, -1, 0); 1.479 + *tarr++ = tang; 1.480 + *uvarr++ = Vec2(u * urange, v); 1.481 + 1.482 + if(i < usub && j < capsub) { 1.483 + unsigned int idx = num_body_verts + i * capvverts + j; 1.484 + 1.485 + unsigned int vidx[4] = { 1.486 + idx, 1.487 + idx + capvverts, 1.488 + idx + (capvverts + 1), 1.489 + idx + 1 1.490 + }; 1.491 + 1.492 + *idxarr++ = vidx[0]; 1.493 + *idxarr++ = vidx[1]; 1.494 + *idxarr++ = vidx[2]; 1.495 + *idxarr++ = vidx[0]; 1.496 + *idxarr++ = vidx[2]; 1.497 + *idxarr++ = vidx[3]; 1.498 + } 1.499 + 1.500 + v += dv; 1.501 + } 1.502 + u += du; 1.503 + } 1.504 +} 1.505 + 1.506 + 1.507 +// -------- plane -------- 1.508 + 1.509 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 1.510 +{ 1.511 + gen_heightmap(mesh, width, height, usub, vsub, 0); 1.512 +} 1.513 + 1.514 + 1.515 +// ----- heightmap ------ 1.516 + 1.517 +void gen_heightmap(Mesh *mesh, float width, float height, int usub, int vsub, float (*hf)(float, float, void*), void *hfdata) 1.518 +{ 1.519 + if(usub < 1) usub = 1; 1.520 + if(vsub < 1) vsub = 1; 1.521 + 1.522 + mesh->clear(); 1.523 + 1.524 + int uverts = usub + 1; 1.525 + int vverts = vsub + 1; 1.526 + int num_verts = uverts * vverts; 1.527 + 1.528 + int num_quads = usub * vsub; 1.529 + int num_tri = num_quads * 2; 1.530 + 1.531 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.532 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.533 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.534 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.535 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.536 + 1.537 + float du = 1.0 / (float)usub; 1.538 + float dv = 1.0 / (float)vsub; 1.539 + 1.540 + float u = 0.0; 1.541 + for(int i=0; i<uverts; i++) { 1.542 + float v = 0.0; 1.543 + for(int j=0; j<vverts; j++) { 1.544 + float x = (u - 0.5) * width; 1.545 + float y = (v - 0.5) * height; 1.546 + float z = hf ? hf(u, v, hfdata) : 0.0; 1.547 + 1.548 + Vec3 normal = Vec3(0, 0, 1); 1.549 + if(hf) { 1.550 + float u1z = hf(u + du, v, hfdata); 1.551 + float v1z = hf(u, v + dv, hfdata); 1.552 + 1.553 + Vec3 tang = Vec3(du * width, 0, u1z - z); 1.554 + Vec3 bitan = Vec3(0, dv * height, v1z - z); 1.555 + normal = normalize(cross(tang, bitan)); 1.556 + } 1.557 + 1.558 + *varr++ = Vec3(x, y, z); 1.559 + *narr++ = normal; 1.560 + *tarr++ = Vec3(1, 0, 0); 1.561 + *uvarr++ = Vec2(u, v); 1.562 + 1.563 + if(i < usub && j < vsub) { 1.564 + int idx = i * vverts + j; 1.565 + 1.566 + *idxarr++ = idx; 1.567 + *idxarr++ = idx + vverts + 1; 1.568 + *idxarr++ = idx + 1; 1.569 + 1.570 + *idxarr++ = idx; 1.571 + *idxarr++ = idx + vverts; 1.572 + *idxarr++ = idx + vverts + 1; 1.573 + } 1.574 + 1.575 + v += dv; 1.576 + } 1.577 + u += du; 1.578 + } 1.579 +} 1.580 + 1.581 +// ----- box ------ 1.582 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz, int usub, int vsub) 1.583 +{ 1.584 + static const float face_angles[][2] = { 1.585 + {0, 0}, 1.586 + {M_PI / 2.0, 0}, 1.587 + {M_PI, 0}, 1.588 + {3.0 * M_PI / 2.0, 0}, 1.589 + {0, M_PI / 2.0}, 1.590 + {0, -M_PI / 2.0} 1.591 + }; 1.592 + 1.593 + if(usub < 1) usub = 1; 1.594 + if(vsub < 1) vsub = 1; 1.595 + 1.596 + mesh->clear(); 1.597 + 1.598 + for(int i=0; i<6; i++) { 1.599 + Mat4 xform, dir_xform; 1.600 + Mesh m; 1.601 + 1.602 + gen_plane(&m, 1, 1, usub, vsub); 1.603 + xform.rotate(Vec3(face_angles[i][1], face_angles[i][0], 0)); 1.604 + dir_xform = xform; 1.605 + xform.translate(Vec3(0, 0, 0.5)); 1.606 + m.apply_xform(xform, dir_xform); 1.607 + 1.608 + mesh->append(m); 1.609 + } 1.610 + 1.611 + Mat4 scale; 1.612 + scale.scaling(xsz, ysz, zsz); 1.613 + mesh->apply_xform(scale, Mat4::identity); 1.614 +} 1.615 + 1.616 +/* 1.617 +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz) 1.618 +{ 1.619 + mesh->clear(); 1.620 + 1.621 + const int num_faces = 6; 1.622 + int num_verts = num_faces * 4; 1.623 + int num_tri = num_faces * 2; 1.624 + 1.625 + float x = xsz / 2.0; 1.626 + float y = ysz / 2.0; 1.627 + float z = zsz / 2.0; 1.628 + 1.629 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.630 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.631 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.632 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.633 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.634 + 1.635 + static const Vec2 uv[] = { Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1) }; 1.636 + 1.637 + // front 1.638 + for(int i=0; i<4; i++) { 1.639 + *narr++ = Vec3(0, 0, 1); 1.640 + *tarr++ = Vec3(1, 0, 0); 1.641 + *uvarr++ = uv[i]; 1.642 + } 1.643 + *varr++ = Vec3(-x, -y, z); 1.644 + *varr++ = Vec3(x, -y, z); 1.645 + *varr++ = Vec3(x, y, z); 1.646 + *varr++ = Vec3(-x, y, z); 1.647 + // right 1.648 + for(int i=0; i<4; i++) { 1.649 + *narr++ = Vec3(1, 0, 0); 1.650 + *tarr++ = Vec3(0, 0, -1); 1.651 + *uvarr++ = uv[i]; 1.652 + } 1.653 + *varr++ = Vec3(x, -y, z); 1.654 + *varr++ = Vec3(x, -y, -z); 1.655 + *varr++ = Vec3(x, y, -z); 1.656 + *varr++ = Vec3(x, y, z); 1.657 + // back 1.658 + for(int i=0; i<4; i++) { 1.659 + *narr++ = Vec3(0, 0, -1); 1.660 + *tarr++ = Vec3(-1, 0, 0); 1.661 + *uvarr++ = uv[i]; 1.662 + } 1.663 + *varr++ = Vec3(x, -y, -z); 1.664 + *varr++ = Vec3(-x, -y, -z); 1.665 + *varr++ = Vec3(-x, y, -z); 1.666 + *varr++ = Vec3(x, y, -z); 1.667 + // left 1.668 + for(int i=0; i<4; i++) { 1.669 + *narr++ = Vec3(-1, 0, 0); 1.670 + *tarr++ = Vec3(0, 0, 1); 1.671 + *uvarr++ = uv[i]; 1.672 + } 1.673 + *varr++ = Vec3(-x, -y, -z); 1.674 + *varr++ = Vec3(-x, -y, z); 1.675 + *varr++ = Vec3(-x, y, z); 1.676 + *varr++ = Vec3(-x, y, -z); 1.677 + // top 1.678 + for(int i=0; i<4; i++) { 1.679 + *narr++ = Vec3(0, 1, 0); 1.680 + *tarr++ = Vec3(1, 0, 0); 1.681 + *uvarr++ = uv[i]; 1.682 + } 1.683 + *varr++ = Vec3(-x, y, z); 1.684 + *varr++ = Vec3(x, y, z); 1.685 + *varr++ = Vec3(x, y, -z); 1.686 + *varr++ = Vec3(-x, y, -z); 1.687 + // bottom 1.688 + for(int i=0; i<4; i++) { 1.689 + *narr++ = Vec3(0, -1, 0); 1.690 + *tarr++ = Vec3(1, 0, 0); 1.691 + *uvarr++ = uv[i]; 1.692 + } 1.693 + *varr++ = Vec3(-x, -y, -z); 1.694 + *varr++ = Vec3(x, -y, -z); 1.695 + *varr++ = Vec3(x, -y, z); 1.696 + *varr++ = Vec3(-x, -y, z); 1.697 + 1.698 + // index array 1.699 + static const int faceidx[] = {0, 1, 2, 0, 2, 3}; 1.700 + for(int i=0; i<num_faces; i++) { 1.701 + for(int j=0; j<6; j++) { 1.702 + *idxarr++ = faceidx[j] + i * 4; 1.703 + } 1.704 + } 1.705 +} 1.706 +*/ 1.707 + 1.708 +static inline Vec3 rev_vert(float u, float v, Vec2 (*rf)(float, float, void*), void *cls) 1.709 +{ 1.710 + Vec2 pos = rf(u, v, cls); 1.711 + 1.712 + float angle = u * 2.0 * M_PI; 1.713 + float x = pos.x * cos(angle); 1.714 + float y = pos.y; 1.715 + float z = pos.x * sin(angle); 1.716 + 1.717 + return Vec3(x, y, z); 1.718 +} 1.719 + 1.720 +// ------ surface of revolution ------- 1.721 +void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*), void *cls) 1.722 +{ 1.723 + gen_revol(mesh, usub, vsub, rfunc, 0, cls); 1.724 +} 1.725 + 1.726 +void gen_revol(Mesh *mesh, int usub, int vsub, Vec2 (*rfunc)(float, float, void*), 1.727 + Vec2 (*nfunc)(float, float, void*), void *cls) 1.728 +{ 1.729 + if(!rfunc) return; 1.730 + if(usub < 3) usub = 3; 1.731 + if(vsub < 1) vsub = 1; 1.732 + 1.733 + mesh->clear(); 1.734 + 1.735 + int uverts = usub + 1; 1.736 + int vverts = vsub + 1; 1.737 + int num_verts = uverts * vverts; 1.738 + 1.739 + int num_quads = usub * vsub; 1.740 + int num_tri = num_quads * 2; 1.741 + 1.742 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.743 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.744 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.745 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.746 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.747 + 1.748 + float du = 1.0 / (float)(uverts - 1); 1.749 + float dv = 1.0 / (float)(vverts - 1); 1.750 + 1.751 + float u = 0.0; 1.752 + for(int i=0; i<uverts; i++) { 1.753 + float v = 0.0; 1.754 + for(int j=0; j<vverts; j++) { 1.755 + Vec3 pos = rev_vert(u, v, rfunc, cls); 1.756 + 1.757 + Vec3 nextu = rev_vert(fmod(u + du, 1.0), v, rfunc, cls); 1.758 + Vec3 tang = nextu - pos; 1.759 + if(length_sq(tang) < 1e-6) { 1.760 + float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25; 1.761 + nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls); 1.762 + tang = nextu - pos; 1.763 + } 1.764 + 1.765 + Vec3 normal; 1.766 + if(nfunc) { 1.767 + normal = rev_vert(u, v, nfunc, cls); 1.768 + } else { 1.769 + Vec3 nextv = rev_vert(u, v + dv, rfunc, cls); 1.770 + Vec3 bitan = nextv - pos; 1.771 + if(length_sq(bitan) < 1e-6) { 1.772 + nextv = rev_vert(u, v - dv, rfunc, cls); 1.773 + bitan = pos - nextv; 1.774 + } 1.775 + 1.776 + normal = cross(tang, bitan); 1.777 + } 1.778 + 1.779 + *varr++ = pos; 1.780 + *narr++ = normalize(normal); 1.781 + *tarr++ = normalize(tang); 1.782 + *uvarr++ = Vec2(u, v); 1.783 + 1.784 + if(i < usub && j < vsub) { 1.785 + int idx = i * vverts + j; 1.786 + 1.787 + *idxarr++ = idx; 1.788 + *idxarr++ = idx + vverts + 1; 1.789 + *idxarr++ = idx + 1; 1.790 + 1.791 + *idxarr++ = idx; 1.792 + *idxarr++ = idx + vverts; 1.793 + *idxarr++ = idx + vverts + 1; 1.794 + } 1.795 + 1.796 + v += dv; 1.797 + } 1.798 + u += du; 1.799 + } 1.800 +} 1.801 + 1.802 + 1.803 +static inline Vec3 sweep_vert(float u, float v, float height, Vec2 (*sf)(float, float, void*), void *cls) 1.804 +{ 1.805 + Vec2 pos = sf(u, v, cls); 1.806 + 1.807 + float x = pos.x; 1.808 + float y = v * height; 1.809 + float z = pos.y; 1.810 + 1.811 + return Vec3(x, y, z); 1.812 +} 1.813 + 1.814 +// ---- sweep shape along a path ---- 1.815 +void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vec2 (*sfunc)(float, float, void*), void *cls) 1.816 +{ 1.817 + if(!sfunc) return; 1.818 + if(usub < 3) usub = 3; 1.819 + if(vsub < 1) vsub = 1; 1.820 + 1.821 + mesh->clear(); 1.822 + 1.823 + int uverts = usub + 1; 1.824 + int vverts = vsub + 1; 1.825 + int num_verts = uverts * vverts; 1.826 + 1.827 + int num_quads = usub * vsub; 1.828 + int num_tri = num_quads * 2; 1.829 + 1.830 + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.831 + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.832 + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.833 + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.834 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.835 + 1.836 + float du = 1.0 / (float)(uverts - 1); 1.837 + float dv = 1.0 / (float)(vverts - 1); 1.838 + 1.839 + float u = 0.0; 1.840 + for(int i=0; i<uverts; i++) { 1.841 + float v = 0.0; 1.842 + for(int j=0; j<vverts; j++) { 1.843 + Vec3 pos = sweep_vert(u, v, height, sfunc, cls); 1.844 + 1.845 + Vec3 nextu = sweep_vert(fmod(u + du, 1.0), v, height, sfunc, cls); 1.846 + Vec3 tang = nextu - pos; 1.847 + if(length_sq(tang) < 1e-6) { 1.848 + float new_v = v > 0.5 ? v - dv * 0.25 : v + dv * 0.25; 1.849 + nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls); 1.850 + tang = nextu - pos; 1.851 + } 1.852 + 1.853 + Vec3 normal; 1.854 + Vec3 nextv = sweep_vert(u, v + dv, height, sfunc, cls); 1.855 + Vec3 bitan = nextv - pos; 1.856 + if(length_sq(bitan) < 1e-6) { 1.857 + nextv = sweep_vert(u, v - dv, height, sfunc, cls); 1.858 + bitan = pos - nextv; 1.859 + } 1.860 + 1.861 + normal = cross(tang, bitan); 1.862 + 1.863 + *varr++ = pos; 1.864 + *narr++ = normalize(normal); 1.865 + *tarr++ = normalize(tang); 1.866 + *uvarr++ = Vec2(u, v); 1.867 + 1.868 + if(i < usub && j < vsub) { 1.869 + int idx = i * vverts + j; 1.870 + 1.871 + *idxarr++ = idx; 1.872 + *idxarr++ = idx + vverts + 1; 1.873 + *idxarr++ = idx + 1; 1.874 + 1.875 + *idxarr++ = idx; 1.876 + *idxarr++ = idx + vverts; 1.877 + *idxarr++ = idx + vverts + 1; 1.878 + } 1.879 + 1.880 + v += dv; 1.881 + } 1.882 + u += du; 1.883 + } 1.884 +}