# HG changeset patch # User John Tsiombikas # Date 1440642304 -10800 # Node ID 1b30bd38166717bf14d132bc00153b6e86adddde # Parent 4f6168f3ca82f0a07e5a97740490315db51ce6d8 sweep curve mesh gen and dragon horns diff -r 4f6168f3ca82 -r 1b30bd381667 src/dragon.cc --- a/src/dragon.cc Thu Aug 27 01:58:26 2015 +0300 +++ b/src/dragon.cc Thu Aug 27 05:25:04 2015 +0300 @@ -4,7 +4,9 @@ #include "metasurf.h" #include "geom.h" #include "game.h" +#include "object.h" #include "shadow.h" +#include "meshgen.h" #define VOXEL_PAD 1.0f #define DYN_FCOUNT 64 @@ -19,6 +21,9 @@ static Vector3 bezier(const Vector3 &a, const Vector3 &b, const Vector3 &c, const Vector3 &d, float t); static float mseval(struct metasurface *ms, float x, float y, float z); static void msvertex(struct metasurface *ms, float x, float y, float z); +static void gen_detail_meshes(); + +static std::vector detail_obj; Dragon::Dragon() @@ -48,6 +53,10 @@ msurf_set_threshold(msurf, 1.0); msurf_eval_func(msurf, mseval); msurf_vertex_func(msurf, msvertex); + + if(detail_obj.empty()) { + gen_detail_meshes(); + } } Dragon::~Dragon() @@ -214,6 +223,17 @@ glPopAttrib(); if(cur_sdr) glUseProgram(cur_sdr); } + + // draw detail objects + for(size_t i=0; ixform().set_translation(head_pos); + + if(dbg_wireframe) { + detail_obj[i]->draw_wire(); + } else { + detail_obj[i]->draw(); + } + } } void Dragon::flush_dynvbo() const @@ -290,3 +310,40 @@ dragon->flush_dynvbo(); } } + + +#define HORN_RAD 0.15f +static Vector2 horn_sweep(float u, float v, void *cls) +{ + float t = 1.0f - v; + float angle = u * 2.0 * M_PI; + float x = sin(angle) * t * HORN_RAD; + float y = cos(angle) * t * HORN_RAD; + return Vector2(x, y + smoothstep(0.3, 1.0, v) * 0.5); +} + +static void gen_detail_meshes() +{ + Mesh *mesh; + Object *obj; + Matrix4x4 xform; + + for(int i=0; i<2; i++) { + float sign = i ? 1.0f : -1.0f; + + mesh = new Mesh; + gen_sweep(mesh, 2, 6, 6, horn_sweep, 0); + xform.set_translation(Vector3(0.5 * sign, 1.5, 3)); + xform.rotate(Vector3(DEG_TO_RAD(25), 0, 0)); + xform.rotate(Vector3(0, 0, DEG_TO_RAD(15) * -sign)); + mesh->apply_xform(xform, Matrix4x4::identity); + + obj = new Object; + obj->set_mesh(mesh); + obj->mtl.diffuse = Vector3(1.0, 0.85, 0.8); + obj->mtl.specular = Vector3(1, 1, 1); + obj->mtl.shininess = 60.0; + + detail_obj.push_back(obj); + } +} diff -r 4f6168f3ca82 -r 1b30bd381667 src/meshgen.cc --- a/src/meshgen.cc Thu Aug 27 01:58:26 2015 +0300 +++ b/src/meshgen.cc Thu Aug 27 05:25:04 2015 +0300 @@ -689,3 +689,87 @@ u += du; } } + + +static inline Vector3 sweep_vert(float u, float v, float height, Vector2 (*sf)(float, float, void*), void *cls) +{ + Vector2 pos = sf(u, v, cls); + + float x = pos.x; + float y = v * height; + float z = pos.y; + + return Vector3(x, y, z); +} + +// ---- sweep shape along a path ---- +void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vector2 (*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; + + Vector3 *varr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_VERTEX, 3, num_verts, 0); + Vector3 *narr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_NORMAL, 3, num_verts, 0); + Vector3 *tarr = (Vector3*)mesh->set_attrib_data(MESH_ATTR_TANGENT, 3, num_verts, 0); + Vector2 *uvarr = (Vector2*)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; + } + + Vector3 normal; + Vector3 nextv = sweep_vert(u, v + dv, height, sfunc, cls); + Vector3 bitan = nextv - pos; + if(bitan.length_sq() < 1e-6) { + nextv = sweep_vert(u, v - dv, height, sfunc, cls); + bitan = pos - nextv; + } + + normal = cross_product(tang, bitan); + + *varr++ = pos; + *narr++ = normal.normalized(); + *tarr++ = tang.normalized(); + *uvarr++ = Vector2(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; + } +} diff -r 4f6168f3ca82 -r 1b30bd381667 src/meshgen.h --- a/src/meshgen.h Thu Aug 27 01:58:26 2015 +0300 +++ b/src/meshgen.h Thu Aug 27 05:25:04 2015 +0300 @@ -16,4 +16,7 @@ void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), void *cls = 0); void gen_revol(Mesh *mesh, int usub, int vsub, Vector2 (*rfunc)(float, float, void*), Vector2 (*nfunc)(float, float, void*), void *cls); +/* callback args: (float u, float v, void *cls) -> Vector2 XZ offset u,v in [0, 1] */ +void gen_sweep(Mesh *mesh, float height, int usub, int vsub, Vector2 (*sfunc)(float, float, void*), void *cls = 0); + #endif // MESHGEN_H_