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