X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=ld42_outofspace;a=blobdiff_plain;f=src%2Fmeshgen.cc;fp=src%2Fmeshgen.cc;h=7664aea4562374e6c417a34d4acf8c231297a47a;hp=0000000000000000000000000000000000000000;hb=066942396f5fbac07e608bc5b23bb6d3cdccc42a;hpb=89df915930177f3bc5f71095562c6e15074be220 diff --git a/src/meshgen.cc b/src/meshgen.cc new file mode 100644 index 0000000..7664aea --- /dev/null +++ b/src/meshgen.cc @@ -0,0 +1,883 @@ +#include +#include "meshgen.h" +#include "mesh.h" + +// -------- sphere -------- + +#define SURAD(u) ((u) * 2.0 * M_PI) +#define SVRAD(v) ((v) * M_PI) + +static Vec3 sphvec(float theta, float phi) +{ + return Vec3(sin(theta) * sin(phi), + cos(phi), + cos(theta) * sin(phi)); +} + +void gen_sphere(Mesh *mesh, float rad, int usub, int vsub, float urange, float vrange) +{ + if(urange == 0.0 || vrange == 0.0) return; + + if(usub < 4) usub = 4; + if(vsub < 2) vsub = 2; + + int uverts = usub + 1; + int vverts = vsub + 1; + + int num_verts = uverts * vverts; + int num_quads = usub * vsub; + int num_tri = num_quads * 2; + + mesh->clear(); + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = urange / (float)(uverts - 1); + float dv = vrange / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; i *verts, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, int iter) +{ + if(!iter) { + verts->push_back(v1); + verts->push_back(v2); + verts->push_back(v3); + return; + } + + Vec3 v12 = normalize(v1 + v2); + Vec3 v23 = normalize(v2 + v3); + Vec3 v31 = normalize(v3 + v1); + + geosphere(verts, v1, v12, v31, iter - 1); + geosphere(verts, v2, v23, v12, iter - 1); + geosphere(verts, v3, v31, v23, iter - 1); + geosphere(verts, v12, v23, v31, iter - 1); +} + +void gen_geosphere(Mesh *mesh, float rad, int subdiv, bool hemi) +{ + int num_tri = (sizeof icosa_idx / sizeof *icosa_idx) / 3; + + std::vector verts; + for(int i=0; iclear(); + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + + for(int i=0; iclear(); + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = urange / (float)(uverts - 1); + float dv = vrange / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; iclear(); + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = urange / (float)(uverts - 1); + float dv = vrange / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; iclear(); + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = urange / (float)(uverts - 1); + float dv = vrange / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; iclear(); + + int uverts = usub + 1; + int vverts = vsub + 1; + int num_verts = uverts * vverts; + + int num_quads = usub * vsub; + int num_tri = num_quads * 2; + + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = 1.0 / (float)usub; + float dv = 1.0 / (float)vsub; + + float u = 0.0; + for(int i=0; iclear(); + + for(int i=0; i<6; i++) { + Mat4 xform, dir_xform; + Mesh m; + + gen_plane(&m, 1, 1, usub, vsub); + xform.translate(Vec3(0, 0, 0.5)); + xform.rotate(Vec3(face_angles[i][1], face_angles[i][0], 0)); + dir_xform = xform; + m.apply_xform(xform, dir_xform); + + mesh->append(m); + } + + Mat4 scale; + scale.scaling(xsz, ysz, zsz); + mesh->apply_xform(scale, Mat4::identity); +} + +/* +void gen_box(Mesh *mesh, float xsz, float ysz, float zsz) +{ + mesh->clear(); + + const int num_faces = 6; + int num_verts = num_faces * 4; + int num_tri = num_faces * 2; + + float x = xsz / 2.0; + float y = ysz / 2.0; + float z = zsz / 2.0; + + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + static const Vec2 uv[] = { Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1) }; + + // front + for(int i=0; i<4; i++) { + *narr++ = Vec3(0, 0, 1); + *tarr++ = Vec3(1, 0, 0); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(-x, -y, z); + *varr++ = Vec3(x, -y, z); + *varr++ = Vec3(x, y, z); + *varr++ = Vec3(-x, y, z); + // right + for(int i=0; i<4; i++) { + *narr++ = Vec3(1, 0, 0); + *tarr++ = Vec3(0, 0, -1); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(x, -y, z); + *varr++ = Vec3(x, -y, -z); + *varr++ = Vec3(x, y, -z); + *varr++ = Vec3(x, y, z); + // back + for(int i=0; i<4; i++) { + *narr++ = Vec3(0, 0, -1); + *tarr++ = Vec3(-1, 0, 0); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(x, -y, -z); + *varr++ = Vec3(-x, -y, -z); + *varr++ = Vec3(-x, y, -z); + *varr++ = Vec3(x, y, -z); + // left + for(int i=0; i<4; i++) { + *narr++ = Vec3(-1, 0, 0); + *tarr++ = Vec3(0, 0, 1); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(-x, -y, -z); + *varr++ = Vec3(-x, -y, z); + *varr++ = Vec3(-x, y, z); + *varr++ = Vec3(-x, y, -z); + // top + for(int i=0; i<4; i++) { + *narr++ = Vec3(0, 1, 0); + *tarr++ = Vec3(1, 0, 0); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(-x, y, z); + *varr++ = Vec3(x, y, z); + *varr++ = Vec3(x, y, -z); + *varr++ = Vec3(-x, y, -z); + // bottom + for(int i=0; i<4; i++) { + *narr++ = Vec3(0, -1, 0); + *tarr++ = Vec3(1, 0, 0); + *uvarr++ = uv[i]; + } + *varr++ = Vec3(-x, -y, -z); + *varr++ = Vec3(x, -y, -z); + *varr++ = Vec3(x, -y, z); + *varr++ = Vec3(-x, -y, z); + + // index array + static const int faceidx[] = {0, 1, 2, 0, 2, 3}; + for(int i=0; iclear(); + + int uverts = usub + 1; + int vverts = vsub + 1; + int num_verts = uverts * vverts; + + int num_quads = usub * vsub; + int num_tri = num_quads * 2; + + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = 1.0 / (float)(uverts - 1); + float dv = 1.0 / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; i 0.5 ? v - dv * 0.25 : v + dv * 0.25; + nextu = rev_vert(fmod(u + du, 1.0), new_v, rfunc, cls); + tang = nextu - pos; + } + + Vec3 normal; + if(nfunc) { + normal = rev_vert(u, v, nfunc, cls); + } else { + Vec3 nextv = rev_vert(u, v + dv, rfunc, cls); + Vec3 bitan = nextv - pos; + if(length_sq(bitan) < 1e-6) { + nextv = rev_vert(u, v - dv, rfunc, cls); + bitan = pos - nextv; + } + + normal = cross(tang, bitan); + } + + *varr++ = pos; + *narr++ = normalize(normal); + *tarr++ = normalize(tang); + *uvarr++ = Vec2(u, v); + + if(i < usub && j < vsub) { + int idx = i * vverts + j; + + *idxarr++ = idx; + *idxarr++ = idx + vverts + 1; + *idxarr++ = idx + 1; + + *idxarr++ = idx; + *idxarr++ = idx + vverts; + *idxarr++ = idx + vverts + 1; + } + + v += dv; + } + u += du; + } +} + + +static inline Vec3 sweep_vert(float u, float v, float height, Vec2 (*sf)(float, float, void*), void *cls) +{ + Vec2 pos = sf(u, v, cls); + + float x = pos.x; + float y = v * height; + float z = pos.y; + + return Vec3(x, y, z); +} + +// ---- sweep shape along a path ---- +void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vec2 (*sfunc)(float, float, void*), void *cls) +{ + if(!sfunc) return; + if(usub < 3) usub = 3; + if(vsub < 1) vsub = 1; + + mesh->clear(); + + int uverts = usub + 1; + int vverts = vsub + 1; + int num_verts = uverts * vverts; + + int num_quads = usub * vsub; + int num_tri = num_quads * 2; + + Vec3 *varr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vec3 *narr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vec3 *tarr = (Vec3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vec2 *uvarr = (Vec2*)mesh->set_attrib_data(MESH_ATTR_TEXCOORD, 2, num_verts, 0); + unsigned int *idxarr = mesh->set_index_data(num_tri * 3, 0); + + float du = 1.0 / (float)(uverts - 1); + float dv = 1.0 / (float)(vverts - 1); + + float u = 0.0; + for(int i=0; i 0.5 ? v - dv * 0.25 : v + dv * 0.25; + nextu = sweep_vert(fmod(u + du, 1.0), new_v, height, sfunc, cls); + tang = nextu - pos; + } + + Vec3 normal; + Vec3 nextv = sweep_vert(u, v + dv, height, sfunc, cls); + Vec3 bitan = nextv - pos; + if(length_sq(bitan) < 1e-6) { + nextv = sweep_vert(u, v - dv, height, sfunc, cls); + bitan = pos - nextv; + } + + normal = cross(tang, bitan); + + *varr++ = pos; + *narr++ = normalize(normal); + *tarr++ = normalize(tang); + *uvarr++ = Vec2(u, v); + + if(i < usub && j < vsub) { + int idx = i * vverts + j; + + *idxarr++ = idx; + *idxarr++ = idx + vverts + 1; + *idxarr++ = idx + 1; + + *idxarr++ = idx; + *idxarr++ = idx + vverts; + *idxarr++ = idx + vverts + 1; + } + + v += dv; + } + u += du; + } +}