#ifndef _Mesh_H__ #define _Mesh_H__ #include using namespace std; #include "Intersectable.h" #include "Plane3.h" #include "Matrix4x4.h" #include "AxisAlignedBox3.h" #include "Material.h" struct Triangle3; class MeshInstance; class MeshKdTree; /// default vertex container for Mesh typedef std::vector VertexContainer; /// vertex index container typedef std::vector VertexIndexContainer; /** 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 patch container for Mesh typedef std::vector FaceContainer; /** Mesh containing polygonal patches */ class Mesh { public: /// Default constructor Mesh():mVertices(), mFaces(), mMaterial(NULL), mKdTree(NULL) {} /// Constructor with container preallocation Mesh(const int vertices, const int faces): mFaces(), mMaterial(NULL), mKdTree(NULL), mVertices(), mIsConvex(false), mIsWatertight(false) { mVertices.reserve(vertices); mFaces.reserve(faces); } ~Mesh() { for (int i=0; i < mFaces.size(); i++) delete mFaces[i]; } void Clear() { mVertices.clear(); mFaces.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 Preprocess(); /** 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 vector &faces, Intersectable *instance ); int CastRayToFace( const int faceIndex, Ray &ray, float &nearestT, int &nearestFace, Intersectable *instance ); int RayFaceIntersection(const int faceIndex, const Ray &ray, float &t, const float nearestT ); Plane3 GetFacePlane(const int faceIndex); AxisAlignedBox3 GetFaceBox(const int faceIndex); int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); int GetRandomVisibleSurfacePoint(Vector3 &point, Vector3 &normal, const Vector3 &viewpoint, const int maxTries ); virtual ostream &Describe(ostream &s) { return s<<"Mesh #vertices="<<(int)mVertices.size()<<" #faces="<<(int)mFaces.size(); } friend Mesh *CreateBox(const AxisAlignedBox3 &box); }; class MeshInstance : public Intersectable { protected: Mesh *mMesh; public: MeshInstance(Mesh *mesh):Intersectable(), mMesh(mesh) { } int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); int GetRandomVisibleSurfacePoint(Vector3 &point, Vector3 &normal, const Vector3 &viewpoint, const int maxTries ); Mesh *GetMesh() { return mMesh; } virtual AxisAlignedBox3 GetBox() { return mMesh->mBox; } virtual int CastRay( Ray &ray ); virtual bool IsConvex() { return mMesh->mIsConvex; } virtual bool IsWatertight() { 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 vector &faces ); virtual ostream &Describe(ostream &s) { s<<"MeshInstance Id="<Describe(s); } }; class TransformedMeshInstance : public MeshInstance { public: TransformedMeshInstance(Mesh *mesh):MeshInstance(mesh) { mWorldTransform = IdentityMatrix(); } virtual AxisAlignedBox3 GetBox() { return Transform(mMesh->mBox, mWorldTransform); } virtual int CastRay( Ray &ray ); virtual int Type() const { return TRANSFORMED_MESH_INSTANCE; } int GetRandomSurfacePoint(Vector3 &point, Vector3 &normal); private: Matrix4x4 mWorldTransform; }; #endif