goat3dgfx
diff src/meshgen.cc @ 0:1873dfd13f2d
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 14 Nov 2013 05:27:09 +0200 |
parents | |
children | 7d6b667821cf |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/meshgen.cc Thu Nov 14 05:27:09 2013 +0200 1.3 @@ -0,0 +1,373 @@ 1.4 +#include "meshgen.h" 1.5 +#include "mesh.h" 1.6 +#include "logger.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 = SURAD(u * urange); 1.45 + 1.46 + float v = 0.0; 1.47 + for(int j=0; j<vverts; j++) { 1.48 + float phi = SVRAD(v * vrange); 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.1, M_PI / 2.0) - sphvec(theta - 0.1, M_PI / 2.0)).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 + 1.75 +// -------- cylinder -------- 1.76 + 1.77 +static Vector3 cylvec(float theta, float height) 1.78 +{ 1.79 + return Vector3(sin(theta), height, cos(theta)); 1.80 +} 1.81 + 1.82 +void gen_cylinder(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.83 +{ 1.84 + if(usub < 4) usub = 4; 1.85 + if(vsub < 1) vsub = 1; 1.86 + 1.87 + int uverts = usub + 1; 1.88 + int vverts = vsub + 1; 1.89 + 1.90 + int num_body_verts = uverts * vverts; 1.91 + int num_body_quads = usub * vsub; 1.92 + int num_body_tri = num_body_quads * 2; 1.93 + 1.94 + int capvverts = capsub ? capsub + 1 : 0; 1.95 + int num_cap_verts = uverts * capvverts; 1.96 + int num_cap_quads = usub * capsub; 1.97 + int num_cap_tri = num_cap_quads * 2; 1.98 + 1.99 + int num_verts = num_body_verts + num_cap_verts * 2; 1.100 + int num_tri = num_body_tri + num_cap_tri * 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 = SURAD(u); 1.115 + 1.116 + float v = 0.0; 1.117 + for(int j=0; j<vverts; j++) { 1.118 + float y = (v - 0.5) * height; 1.119 + Vector3 pos = cylvec(theta, y); 1.120 + 1.121 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 1.122 + *narr++ = Vector3(pos.x, 0.0, pos.z); 1.123 + *tarr++ = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.124 + *uvarr++ = Vector2(u * urange, v * vrange); 1.125 + 1.126 + if(i < usub && j < vsub) { 1.127 + int idx = i * vverts + j; 1.128 + 1.129 + *idxarr++ = idx; 1.130 + *idxarr++ = idx + vverts + 1; 1.131 + *idxarr++ = idx + 1; 1.132 + 1.133 + *idxarr++ = idx; 1.134 + *idxarr++ = idx + vverts; 1.135 + *idxarr++ = idx + vverts + 1; 1.136 + } 1.137 + 1.138 + v += dv; 1.139 + } 1.140 + u += du; 1.141 + } 1.142 + 1.143 + 1.144 + // now the cap! 1.145 + if(!capsub) { 1.146 + return; 1.147 + } 1.148 + 1.149 + dv = 1.0 / (float)(capvverts - 1); 1.150 + 1.151 + u = 0.0; 1.152 + for(int i=0; i<uverts; i++) { 1.153 + float theta = SURAD(u); 1.154 + 1.155 + float v = 0.0; 1.156 + for(int j=0; j<capvverts; j++) { 1.157 + float r = v * rad; 1.158 + 1.159 + Vector3 pos = cylvec(theta, height / 2.0) * r; 1.160 + pos.y = height / 2.0; 1.161 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.162 + 1.163 + *varr++ = pos; 1.164 + *narr++ = Vector3(0, 1, 0); 1.165 + *tarr++ = tang; 1.166 + *uvarr++ = Vector2(u * urange, v); 1.167 + 1.168 + pos.y = -height / 2.0; 1.169 + *varr++ = pos; 1.170 + *narr++ = Vector3(0, -1, 0); 1.171 + *tarr++ = -tang; 1.172 + *uvarr++ = Vector2(u * urange, v); 1.173 + 1.174 + if(i < usub && j < capsub) { 1.175 + unsigned int idx = num_body_verts + (i * capvverts + j) * 2; 1.176 + 1.177 + unsigned int vidx[4] = { 1.178 + idx, 1.179 + idx + capvverts * 2, 1.180 + idx + (capvverts + 1) * 2, 1.181 + idx + 2 1.182 + }; 1.183 + 1.184 + *idxarr++ = vidx[0]; 1.185 + *idxarr++ = vidx[2]; 1.186 + *idxarr++ = vidx[1]; 1.187 + *idxarr++ = vidx[0]; 1.188 + *idxarr++ = vidx[3]; 1.189 + *idxarr++ = vidx[2]; 1.190 + 1.191 + *idxarr++ = vidx[0] + 1; 1.192 + *idxarr++ = vidx[1] + 1; 1.193 + *idxarr++ = vidx[2] + 1; 1.194 + *idxarr++ = vidx[0] + 1; 1.195 + *idxarr++ = vidx[2] + 1; 1.196 + *idxarr++ = vidx[3] + 1; 1.197 + } 1.198 + 1.199 + v += dv; 1.200 + } 1.201 + u += du; 1.202 + } 1.203 +} 1.204 + 1.205 +// -------- cone -------- 1.206 + 1.207 +static Vector3 conevec(float theta, float y, float height) 1.208 +{ 1.209 + float scale = 1.0 - y / height; 1.210 + return Vector3(sin(theta) * scale, y, cos(theta) * scale); 1.211 +} 1.212 + 1.213 +void gen_cone(Mesh *mesh, float rad, float height, int usub, int vsub, int capsub, float urange, float vrange) 1.214 +{ 1.215 + if(usub < 4) usub = 4; 1.216 + if(vsub < 1) vsub = 1; 1.217 + 1.218 + int uverts = usub + 1; 1.219 + int vverts = vsub + 1; 1.220 + 1.221 + int num_body_verts = uverts * vverts; 1.222 + int num_body_quads = usub * vsub; 1.223 + int num_body_tri = num_body_quads * 2; 1.224 + 1.225 + int capvverts = capsub ? capsub + 1 : 0; 1.226 + int num_cap_verts = uverts * capvverts; 1.227 + int num_cap_quads = usub * capsub; 1.228 + int num_cap_tri = num_cap_quads * 2; 1.229 + 1.230 + int num_verts = num_body_verts + num_cap_verts; 1.231 + int num_tri = num_body_tri + num_cap_tri; 1.232 + 1.233 + mesh->clear(); 1.234 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.235 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.236 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.237 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.238 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.239 + 1.240 + float du = urange / (float)(uverts - 1); 1.241 + float dv = vrange / (float)(vverts - 1); 1.242 + 1.243 + float u = 0.0; 1.244 + for(int i=0; i<uverts; i++) { 1.245 + float theta = SURAD(u); 1.246 + 1.247 + float v = 0.0; 1.248 + for(int j=0; j<vverts; j++) { 1.249 + float y = v * height; 1.250 + Vector3 pos = conevec(theta, y, height); 1.251 + 1.252 + Vector3 tang = (conevec(theta + 0.1, 0.0, height) - conevec(theta - 0.1, 0.0, height)).normalized(); 1.253 + Vector3 bitang = (conevec(theta, y + 0.1, height) - pos).normalized(); 1.254 + 1.255 + *varr++ = Vector3(pos.x * rad, pos.y, pos.z * rad); 1.256 + *narr++ = cross_product(tang, bitang); 1.257 + *tarr++ = tang; 1.258 + *uvarr++ = Vector2(u * urange, v * vrange); 1.259 + 1.260 + if(i < usub && j < vsub) { 1.261 + int idx = i * vverts + j; 1.262 + 1.263 + *idxarr++ = idx; 1.264 + *idxarr++ = idx + vverts + 1; 1.265 + *idxarr++ = idx + 1; 1.266 + 1.267 + *idxarr++ = idx; 1.268 + *idxarr++ = idx + vverts; 1.269 + *idxarr++ = idx + vverts + 1; 1.270 + } 1.271 + 1.272 + v += dv; 1.273 + } 1.274 + u += du; 1.275 + } 1.276 + 1.277 + 1.278 + // now the bottom cap! 1.279 + if(!capsub) { 1.280 + return; 1.281 + } 1.282 + 1.283 + dv = 1.0 / (float)(capvverts - 1); 1.284 + 1.285 + u = 0.0; 1.286 + for(int i=0; i<uverts; i++) { 1.287 + float theta = SURAD(u); 1.288 + 1.289 + float v = 0.0; 1.290 + for(int j=0; j<capvverts; j++) { 1.291 + float r = v * rad; 1.292 + 1.293 + Vector3 pos = conevec(theta, 0.0, height) * r; 1.294 + Vector3 tang = (cylvec(theta + 0.1, 0.0) - cylvec(theta - 0.1, 0.0)).normalized(); 1.295 + 1.296 + *varr++ = pos; 1.297 + *narr++ = Vector3(0, -1, 0); 1.298 + *tarr++ = tang; 1.299 + *uvarr++ = Vector2(u * urange, v); 1.300 + 1.301 + if(i < usub && j < capsub) { 1.302 + unsigned int idx = num_body_verts + i * capvverts + j; 1.303 + 1.304 + unsigned int vidx[4] = { 1.305 + idx, 1.306 + idx + capvverts, 1.307 + idx + (capvverts + 1), 1.308 + idx + 1 1.309 + }; 1.310 + 1.311 + *idxarr++ = vidx[0]; 1.312 + *idxarr++ = vidx[1]; 1.313 + *idxarr++ = vidx[2]; 1.314 + *idxarr++ = vidx[0]; 1.315 + *idxarr++ = vidx[2]; 1.316 + *idxarr++ = vidx[3]; 1.317 + } 1.318 + 1.319 + v += dv; 1.320 + } 1.321 + u += du; 1.322 + } 1.323 +} 1.324 + 1.325 + 1.326 +// -------- plane -------- 1.327 + 1.328 +void gen_plane(Mesh *mesh, float width, float height, int usub, int vsub) 1.329 +{ 1.330 + if(usub < 1) usub = 1; 1.331 + if(vsub < 1) vsub = 1; 1.332 + 1.333 + mesh->clear(); 1.334 + 1.335 + int uverts = usub + 1; 1.336 + int vverts = vsub + 1; 1.337 + int num_verts = uverts * vverts; 1.338 + 1.339 + int num_quads = usub * vsub; 1.340 + int num_tri = num_quads * 2; 1.341 + 1.342 + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); 1.343 + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); 1.344 + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); 1.345 + Vector2 *uvarr = (Vector2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); 1.346 + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); 1.347 + 1.348 + float du = 1.0 / (float)usub; 1.349 + float dv = 1.0 / (float)vsub; 1.350 + 1.351 + float u = 0.0; 1.352 + for(int i=0; i<uverts; i++) { 1.353 + float v = 0.0; 1.354 + for(int j=0; j<vverts; j++) { 1.355 + *varr++ = Vector3((u - 0.5) * width, (v - 0.5) * height, 0.0); 1.356 + *narr++ = Vector3(0, 0, 1); 1.357 + *tarr++ = Vector3(1, 0, 0); 1.358 + *uvarr++ = Vector2(u, v); 1.359 + 1.360 + if(i < usub && j < vsub) { 1.361 + int idx = i * vverts + j; 1.362 + 1.363 + *idxarr++ = idx; 1.364 + *idxarr++ = idx + vverts + 1; 1.365 + *idxarr++ = idx + 1; 1.366 + 1.367 + *idxarr++ = idx; 1.368 + *idxarr++ = idx + vverts; 1.369 + *idxarr++ = idx + vverts + 1; 1.370 + } 1.371 + 1.372 + v += dv; 1.373 + } 1.374 + u += du; 1.375 + } 1.376 +}