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