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