#ifndef _Mesh_H__ #define _Mesh_H__ #include // #include "Intersectable.h" #include "Plane3.h" #include "Matrix4x4.h" #include "AxisAlignedBox3.h" #include "Material.h" #include "Containers.h" namespace GtpVisibilityPreprocessor { extern bool MeshDebug; struct Triangle3; class MeshInstance; class MeshKdTree; /** Patch used as an element of the mesh */ struct Face { public: Face(): mVertexIndices() {} Face(const int a, const int b, const int c):mVertexIndices(3) { mVertexIndices[0] = a; mVertexIndices[1] = b; mVertexIndices[2] = c; } Face(const int a, const int b, const int c, const int d): mVertexIndices(4) { mVertexIndices[0] = a; mVertexIndices[1] = b; mVertexIndices[2] = c; mVertexIndices[3] = d; } Face(const VertexIndexContainer &vertices):mVertexIndices(vertices.size()) { for (int i=0; i < vertices.size(); i++) mVertexIndices[i] = vertices[i]; } //////////////////////////// /// list of vertex pointers VertexIndexContainer mVertexIndices; }; /// default vertex container for Mesh typedef std::vector VertexContainer; /// default patch container for Mesh typedef std::vector FaceContainer; /** Mesh containing polygonal patches */ class Mesh { public: /// Default constructor Mesh():mVertices(), mFaces(), mMaterial(NULL), mKdTree(NULL), mId(0) {} /// Constructor with container preallocation Mesh(const int vertices, const int faces): mFaces(), mMaterial(NULL), mKdTree(NULL), mVertices(), mIsConvex(false), mIsWatertight(false), mId(0) { mVertices.reserve(vertices); mFaces.reserve(faces); } /** Constructor setting a unqiue mesh id. */ Mesh(const int id); /** Setting unique mesh id and using preallocation. */ Mesh(const int id, const int vertices, const int faces); /** Copy constructor making a deep copy of the faces. */ Mesh(const Mesh &rhs); /** Assignement operator. @note does not copy id @note preprocess may be necessary */ Mesh& operator=(const Mesh& m); ~Mesh(); void Clear(); void IndexVertices(); void AssignRandomMaterial(); void AddTriangle(const Triangle3 &triangle); void AddRectangle(const Rectangle3 &triangle); void Cleanup(); bool ValidateFace(const int face); void AddFace(Face *face) { mFaces.push_back(face); } void ComputeBoundingBox(); /** This function must be called after creating the mesh because it creates the local kd tree and the bounding box. */ void Preprocess(const bool cleanup = true); /** Applies transformation to the mesh. @note: meshkdtree will most likely be outdated after transformation, thus another preprocess might be necessary. */ void ApplyTransformation(const Matrix4x4 &m); /** Axis aligned bounding box of the mesh in local mesh coordinates. */ AxisAlignedBox3 mBox; /** Vertices forming the mesh. */ VertexContainer mVertices; /** Patches forming the mesh. */ FaceContainer mFaces; /** Global mesh material. */ Material *mMaterial; /** true if the mesh is a convex mesh. */ bool mIsConvex; /** true if the mesh is a convex mesh. */ bool mIsWatertight; MeshKdTree *mKdTree; int CastRay(Ray &ray, MeshInstance *instance); int CastRayToSelectedFaces( Ray &ray, const std::vector &faces, Intersectable *instance ); int CastRayToFace( const int faceIndex, Ray &ray, float &nearestT, Vector3 &nearestNormal, int &nearestFace, Intersectable *instance ); int RayFaceIntersection(const int faceIndex, const Ray &ray, float &t, Vector3 &normal, const float nearestT ); Plane3 GetFacePlane(const int faceIndex) const; AxisAlignedBox3 GetFaceBox(const int faceIndex); int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); int GetRandomVisibleSurfacePoint(Vector3 &point, Vector3 &normal, const Vector3 &viewpoint, const int maxTries ); /** Returns unique mesh id. */ int GetId() const { return mId; } Vector3 GetNormal(const int idx) const; // $$ matt temp bool CheckMesh() const; void Print(std::ostream &app) const; virtual std::ostream &Describe(std::ostream &s) const { return s<<"Mesh #vertices="<<(int)mVertices.size()<<" #faces="<<(int)mFaces.size(); } /** Creates a mesh from a axis aligned bounding box. The mesh is handled from the resource manager. */ friend Mesh *CreateMeshFromBox(const AxisAlignedBox3 &box); friend std::ostream& operator<< (std::ostream &s, const Vector3 &A); protected: /// Unique id of this mesh. int mId; }; // Overload << operator for C++-style output inline std::ostream& operator<< (std::ostream &s, const Mesh &A) { A.Print(s); return s; } class MeshInstance : public Intersectable { public: MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh), mMaterial(NULL) { } int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); int GetRandomVisibleSurfacePoint(Vector3 &point, Vector3 &normal, const Vector3 &viewpoint, const int maxTries ); virtual int GetRandomEdgePoint(Vector3 &point, Vector3 &normal); Mesh *GetMesh() { return mMesh; } virtual AxisAlignedBox3 GetBox() const { return mMesh->mBox; } virtual int CastRay(Ray &ray); virtual bool IsConvex() const { return mMesh->mIsConvex; } virtual bool IsWatertight() const { return mMesh->mIsWatertight; } virtual float IntersectionComplexity() { return (float)mMesh->mFaces.size(); } virtual int NumberOfFaces() const { return (int)mMesh->mFaces.size(); } virtual int Type() const { return MESH_INSTANCE; } virtual int CastRay( Ray &ray, const std::vector &faces ); virtual std::ostream &Describe(std::ostream &s) { s<<"MeshInstance Id="<Describe(s); } /** Sets the material. this overrides the material from the mesh itself. */ void SetMaterial(Material *mat); /** Returns the material of this mesh instance. if not defined, returns the material of the mesh itself. */ Material *GetMaterial() const; virtual Vector3 GetNormal(const int idx) const; protected: Mesh *mMesh; /** This material overrides the mesh material; */ Material *mMaterial; }; /** This mesh instance includes a world transform. Use this class if the same mesh should be instantiated on different places. */ class TransformedMeshInstance: public MeshInstance { public: TransformedMeshInstance(Mesh *mesh); virtual AxisAlignedBox3 GetBox() const; virtual int CastRay(Ray &ray); virtual int CastRay(Ray &ray, const std::vector &faces); virtual int Type() const { return TRANSFORMED_MESH_INSTANCE; } int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); /** Transforms this mesh instance by m. */ void ApplyWorldTransform(const Matrix4x4 &m); /** Loads the transformation matrix into this mesh instance. */ void LoadWorldTransform(const Matrix4x4 &m); /** The transformation is returned in m. */ void GetWorldTransform(Matrix4x4 &m) const; /** Transforms a mesh according to the stored world transform. @param transformedMesh returns the tranformed mesh. */ void GetTransformedMesh(Mesh &transformedMesh) const; Vector3 GetNormal(const int idx) const; protected: /// the transformation matrix Matrix4x4 mWorldTransform; }; } #endif