// ---------------------------------------------------------
// Mesh Class
// Author : Tamy Boubekeur (boubek@gmail.com).
// Copyright (C) 2008 Tamy Boubekeur.
// All rights reserved.
// ---------------------------------------------------------

#ifndef MESH_H
#define MESH_H

#include <vector>
#include <string>

#include "Vertex.h"
#include "Triangle.h"
#include "BoundingBox.h"
#include "Edge.h"
#include "KdTree.h"

class Mesh {
public:
    inline Mesh () : tree(*this) {}
    inline Mesh (const std::vector<Vertex> & v)
        : vertices (v), tree(*this) {}
    inline Mesh (const std::vector<Vertex> & v,
                 const std::vector<Triangle> & t)
        : vertices (v), triangles (t), tree(*this) { rebuildTree(); }
    inline Mesh (const Mesh & mesh) :
          vertices (mesh.vertices),
          triangles (mesh.triangles),
          tree(*this)
    { rebuildTree(); }

    inline virtual ~Mesh () {}
    std::vector<Vertex> & getVertices () { return vertices; }
    const std::vector<Vertex> & getVertices () const { return vertices; }
    std::vector<Triangle> & getTriangles () { return triangles; }
    const std::vector<Triangle> & getTriangles () const { return triangles; }
    const KdTree& getTree() const { return tree; }
    void clear ();
    void clearGeometry ();
    void clearTopology ();
    void unmarkAllVertices ();
    void recomputeSmoothVertexNormals (unsigned int weight);
    void computeTriangleNormals (std::vector<Vec3Df> & triangleNormals);
    void collectOneRing (std::vector<std::vector<unsigned int> > & oneRing) const;
    void collectOrderedOneRing (std::vector<std::vector<unsigned int> > & oneRing) const;
    void computeDualEdgeMap (EdgeMapIndex & dualVMap1, EdgeMapIndex & dualVMap2);
    void markBorderEdges (EdgeMapIndex & edgeMap);
    void updateBoundingBox();

    void addVertex(const Vertex& v);
    void addTriangle(const Triangle& t);

    void rebuildTree();
    void rebuildAmbientOcclusion(unsigned int nbRays, float d);

    const BoundingBox& getBoundingBox() const { return bbox; }

    void renderGL (bool flat) const;

    void loadOFF (const std::string & filename);

    class Exception {
    private:
        std::string msg;
    public:
        Exception (const std::string & msg) : msg ("[Mesh Exception]" + msg) {}
        virtual ~Exception () {}
        inline const std::string & getMessage () const { return msg; }
    };

private:
    std::vector<Vertex> vertices;
    std::vector<Triangle> triangles;
    std::vector<std::vector<unsigned int> > neighbours;
    KdTree tree;
    BoundingBox bbox;
};

#endif // MESH_H

// Some Emacs-Hints -- please don't remove:
//
//  Local Variables:
//  mode:C++
//  tab-width:4
//  End:
