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