X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=ld42_outofspace;a=blobdiff_plain;f=src%2Fmesh.h;fp=src%2Fmesh.h;h=8291aa712d805fa3cb4f28e2c91258cedd69b92c;hp=0000000000000000000000000000000000000000;hb=066942396f5fbac07e608bc5b23bb6d3cdccc42a;hpb=89df915930177f3bc5f71095562c6e15074be220 diff --git a/src/mesh.h b/src/mesh.h new file mode 100644 index 0000000..8291aa7 --- /dev/null +++ b/src/mesh.h @@ -0,0 +1,249 @@ +#ifndef MESH_H_ +#define MESH_H_ + +#include +#include +#include +#include "gmath/gmath.h" +#include "geom.h" + +enum { + MESH_ATTR_VERTEX, + MESH_ATTR_NORMAL, + MESH_ATTR_TANGENT, + MESH_ATTR_TEXCOORD, + MESH_ATTR_COLOR, + MESH_ATTR_BONEWEIGHTS, + MESH_ATTR_BONEIDX, + MESH_ATTR_TEXCOORD2, + + NUM_MESH_ATTR +}; + +// intersection mode flags +enum { + ISECT_DEFAULT = 0, // default (whole mesh, all intersections) + ISECT_FRONT = 1, // front-faces only + ISECT_FACE = 2, // return intersected face pointer instead of mesh + ISECT_VERTICES = 4 // return (?) TODO +}; + +//class XFormNode; + + +class Triangle { +public: + Vec3 v[3]; + Vec3 normal; + bool normal_valid; + int id; + + Triangle(); + Triangle(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2); + Triangle(int n, const Vec3 *varr, const unsigned int *idxarr = 0); + + /// calculate normal (quite expensive) + void calc_normal(); + const Vec3 &get_normal() const; + + void transform(const Mat4 &xform); + + void draw() const; + void draw_wire() const; + + /// calculate barycentric coordinates of a point + Vec3 calc_barycentric(const Vec3 &pos) const; + + bool intersect(const Ray &ray, HitPoint *hit = 0) const; +}; + + +class Mesh { +private: + std::string name; + unsigned int nverts, nfaces; + + // current value for each attribute for the immedate mode + // interface. + Vec4 cur_val[NUM_MESH_ATTR]; + + unsigned int buffer_objects[NUM_MESH_ATTR + 1]; + + // vertex attribute data and buffer objects + struct VertexAttrib { + int nelem; // number of elements per attribute range: [1, 4] + std::vector data; + unsigned int vbo; + mutable bool vbo_valid; // if this is false, the vbo needs updating from the data + mutable bool data_valid; // if this is false, the data needs to be pulled from the vbo + //int sdr_loc; + } vattr[NUM_MESH_ATTR]; + + static int global_sdr_loc[NUM_MESH_ATTR]; + + //std::vector bones; // bones affecting this mesh + + // index data and buffer object + std::vector idata; + unsigned int ibo; + mutable bool ibo_valid; + mutable bool idata_valid; + + // index buffer object for wireframe rendering (constructed on demand) + unsigned int wire_ibo; + mutable bool wire_ibo_valid; + + // axis-aligned bounding box + mutable AABox aabb; + mutable bool aabb_valid; + + // bounding sphere + mutable Sphere bsph; + mutable bool bsph_valid; + + // keeps the last intersected face + mutable Triangle hitface; + // keeps the last intersected vertex position + mutable Vec3 hitvert; + + void calc_aabb(); + void calc_bsph(); + + static unsigned int intersect_mode; + static float vertex_sel_dist; + + static float vis_vecsize; + + /// update the VBOs after data has changed (invalid vbo/ibo) + void update_buffers(); + /// construct/update the wireframe index buffer (called from draw_wire). + void update_wire_ibo(); + + mutable int cur_sdr; + bool pre_draw() const; + void post_draw() const; + + +public: + static bool use_custom_sdr_attr; + + Mesh(); + ~Mesh(); + + Mesh(const Mesh &rhs); + Mesh &operator =(const Mesh &rhs); + bool clone(const Mesh &m); + + void set_name(const char *name); + const char *get_name() const; + + bool has_attrib(int attr) const; + bool is_indexed() const; + + // clears everything about this mesh, and returns to the newly constructed state + void clear(); + + // access the vertex attribute data + // if vdata == 0, space is just allocated + float *set_attrib_data(int attrib, int nelem, unsigned int num, const float *vdata = 0); // invalidates vbo + float *get_attrib_data(int attrib); // invalidates vbo + const float *get_attrib_data(int attrib) const; + + // simple access to any particular attribute + void set_attrib(int attrib, int idx, const Vec4 &v); // invalidates vbo + Vec4 get_attrib(int attrib, int idx) const; + + int get_attrib_count(int attrib) const; + + // ... same for index data + unsigned int *set_index_data(int num, const unsigned int *indices = 0); // invalidates ibo + unsigned int *get_index_data(); // invalidates ibo + const unsigned int *get_index_data() const; + + int get_index_count() const; + + void append(const Mesh &mesh); + + // immediate-mode style mesh construction interface + void vertex(float x, float y, float z); + void normal(float nx, float ny, float nz); + void tangent(float tx, float ty, float tz); + void texcoord(float u, float v, float w); + void boneweights(float w1, float w2, float w3, float w4); + void boneidx(int idx1, int idx2, int idx3, int idx4); + + int get_poly_count() const; + + /* apply a transformation to the vertices and its inverse-transpose + * to the normals and tangents. + */ + void apply_xform(const Mat4 &xform); + void apply_xform(const Mat4 &xform, const Mat4 &dir_xform); + + void flip(); // both faces and normals + void flip_faces(); + void flip_normals(); + + void explode(); // undo all vertex sharing + + void calc_face_normals(); // this is only guaranteed to work on an exploded mesh + + // adds a bone and returns its index + /*int add_bone(XFormNode *bone); + const XFormNode *get_bone(int idx) const; + int get_bones_count() const;*/ + + // access the shader attribute locations + static void set_attrib_location(int attr, int loc); + static int get_attrib_location(int attr); + static void clear_attrib_locations(); + + static void set_vis_vecsize(float sz); + static float get_vis_vecsize(); + + void draw() const; + void draw_wire() const; + void draw_vertices() const; + void draw_normals() const; + void draw_tangents() const; + + /** get the bounding box in local space. The result will be cached, and subsequent + * calls will return the same box. The cache gets invalidated by any functions that can affect + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). + * @{ */ + void get_aabbox(Vec3 *vmin, Vec3 *vmax) const; + const AABox &get_aabbox() const; + /// @} + + /** get the bounding sphere in local space. The result will be cached, and subsequent + * calls will return the same box. The cache gets invalidated by any functions that can affect + * the vertex data (non-const variant of get_attrib_data(MESH_ATTR_VERTEX, ...) included). + * @{ */ + float get_bsphere(Vec3 *center, float *rad) const; + const Sphere &get_bsphere() const; + /// @} + + static void set_intersect_mode(unsigned int mode); + static unsigned int get_intersect_mode(); + static void set_vertex_select_distance(float dist); + static float get_vertex_select_distance(); + + /** Find the intersection between the mesh and a ray. + * XXX Brute force at the moment, not intended to be used for anything other than picking in tools. + * If you intend to use it in a speed-critical part of the code, you'll *have* to optimize it! + */ + bool intersect(const Ray &ray, HitPoint *hit = 0) const; + + // texture coordinate manipulation + void texcoord_apply_xform(const Mat4 &xform); + void texcoord_gen_plane(const Vec3 &norm, const Vec3 &tang); + void texcoord_gen_box(); + void texcoord_gen_cylinder(); + + bool dump(const char *fname) const; + bool dump(FILE *fp) const; + bool dump_obj(const char *fname) const; + bool dump_obj(FILE *fp, int voffs = 0) const; +}; + +#endif // MESH_H_