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