//-*-c++-*- #ifndef SIMPLEMESH_H #define SIMPLEMESH_H /* James R. Diebel Stanford University Started: 7 August 2005 Simple Triangular mesh class - simple mesh, with limited connectivity information. See mesh.hh for more advanced mesh with greater connectivity information - used in bmtk. Everything is inlined and contained in this header file. The reason for this is because the code should be fairly brief and we'd like this to be easy to include in other projects. It is also templated so that the user can decide whether space (use floats) or precision (use doubles) is more important. */ #include #include #include #include #include #define SM_CHECK_BOUNDS 1 #define SM_PO 2 // Forward Declarations template class SimpleMeshVertex; template class SimpleMeshFace; template class SimpleMesh; ////////////////////// // SimpleMesh Class // ////////////////////// template class SimpleMesh { public: // Constructors/Destructor and Related SimpleMesh(); SimpleMesh(const SimpleMesh& m); SimpleMesh(int nv_, int nf_); ~SimpleMesh(); // Memory Allocation and Deallocation void startUp(int nv_, int nf_); // allocate memory void cleanUp(); // deallocate memory // References SimpleMeshVertex& v(const int i); SimpleMeshFace& f(const int i); SimpleMeshVertex& v(const int i) const; SimpleMeshFace& f(const int i) const; int numv() const; int numf() const; sla::Vec3 getFace(const int i) const; // Assignments void setVertex(const int i, bool boundary_,sla::Vec3 x_, sla::Vec3 c_); void setFace(const int i, const sla::Vec3& ind); // File I/O int readBSM(char* filename); // read Binary Simple Mesh int writeBSM(char* filename); // write Binary Simple Mesh void writeTo(std::ostream& os); void readFrom(std::istream& is); void print(std::ostream& os) const; void print(); // Find Derived Data void findFaceNormals(); void findVertexNormals(); void findNormals(); protected: // Protected Data int nv, nf; // numbers of vertices, faces SimpleMeshVertex* vd; // global vertex list SimpleMeshFace* fd; // global face list }; // Instantiate a few instances template class SimpleMesh; template class SimpleMesh; // Declare a few common typdefs typedef SimpleMesh SimpleMeshf; typedef SimpleMesh SimpleMeshd; //////////////////////////// // SimpleMeshVertex Class // //////////////////////////// template class SimpleMeshVertex { public: // Public Data sla::Vec3 x; // position of the vertex sla::Vec3 n; // normal of vertex (mean of normals of touching faces) sla::Vec3 c; // 24-bit color bool boundary; // flag to indicate if vertex is on boundary of mesh // Public Methods void writeTo(std::ostream& os); void readFrom(std::istream& is); void print(std::ostream& os) const; }; // Instantiate a few instances template class SimpleMeshVertex; template class SimpleMeshVertex; ////////////////////////// // SimpleMeshFace Class // ////////////////////////// template class SimpleMeshFace { public: // Public Data sla::Vec3 n; // normal vector of face // Public Methods SimpleMeshVertex& v(const int i); void writeTo(std::ostream& os, SimpleMeshVertex* v0); void readFrom(std::istream& is, SimpleMeshVertex* v0); void print(std::ostream& os, SimpleMeshVertex* v0) const; protected: // Protected Data SimpleMeshVertex* vd[3]; // pointers to vertices that make up this face // Protected members void setVertexIndices(const sla::Vec3& ind, SimpleMeshVertex* v0); sla::Vec3 getVertexIndices(SimpleMeshVertex* v0) const; friend class SimpleMesh; }; // Instantiate a few instances template class SimpleMeshFace; template class SimpleMeshFace; //////////////////////// // SimpleMesh Methods // //////////////////////// // Constructor: default template inline SimpleMesh::SimpleMesh() { nv = nf = 0; vd = NULL; fd = NULL; } // Constructor: copy template inline SimpleMesh::SimpleMesh(const SimpleMesh& m) { nv = nf = 0; vd = NULL; fd = NULL; startUp(m.nv,m.nf); for (int i=0;i inline SimpleMesh::SimpleMesh(int nv_, int nf_) { nv = nf = 0; vd = NULL; fd = NULL; startUp(nv_,nf_); } // Destructor: cleans up allocated memory template inline SimpleMesh::~SimpleMesh() { cleanUp(); } // Memory allocation template inline void SimpleMesh::startUp(int nv_, int nf_) { cleanUp(); // always clean up first, in case of old data nv = nv_; nf = nf_; if (SM_PO>1) printf("Allocating memory for %i vertices and %i faces...", nv,nf); vd = new SimpleMeshVertex[nv]; fd = new SimpleMeshFace[nf]; if (SM_PO>1) printf("Done.\n"); } // Memory deallocation template inline void SimpleMesh::cleanUp() { if (nv != 0) { if (SM_PO>1) printf("Deleting vertex list (%i)...",nv); delete [] vd; if (SM_PO>1) printf("Done.\n"); } if (nf != 0) { if (SM_PO>1) printf("Deleting face list (%i)...", nf); delete [] fd; if (SM_PO>1) printf("Done.\n"); } nv = nf = 0; vd = NULL; fd = NULL; } // Returns reference to vertex i in the global vertex list template inline SimpleMeshVertex& SimpleMesh::v(const int i) { #if SM_CHECK_BOUNDS if (i < 0 || i >= nv) { printf("Vertex index %i out of range [0,%i], exiting.\n", i, nv); std::exit(1); } #endif return vd[i]; } // Returns reference to face i in the global face list template inline SimpleMeshFace& SimpleMesh::f(const int i) { #if SM_CHECK_BOUNDS if (i < 0 || i >= nf) { printf("Face index %i out of range [0,%i], exiting.\n", i, nf); std::exit(1); } #endif return fd[i]; } // Returns vertex i in the global vertex list template inline SimpleMeshVertex& SimpleMesh::v(const int i) const { #if SM_CHECK_BOUNDS if (i < 0 || i >= nv) { printf("Vertex index %i out of range [0,%i], exiting.\n", i, nv); std::exit(1); } #endif return vd[i]; } // Returns face i in the global face list template inline SimpleMeshFace& SimpleMesh::f(const int i) const { #if SM_CHECK_BOUNDS if (i < 0 || i >= nf) { printf("Face index %i out of range [0,%i], exiting.\n", i, nf); std::exit(1); } #endif return fd[i]; } // Returns the total number of vertices template inline int SimpleMesh::numv() const { return nv; } // Returns the total number of faces template inline int SimpleMesh::numf() const { return nf; } // Get face-vertex indices to passed values template inline sla::Vec3 SimpleMesh::getFace(const int i) const { return f(i).getVertexIndices(vd); } // Set vertex position and color to passed values template inline void SimpleMesh::setVertex(const int i, bool boundary_, sla::Vec3 x_, sla::Vec3 c_) { v(i).boundary = boundary_; v(i).x = x_; v(i).c = c_; } // Set face-vertex indices to passed values template inline void SimpleMesh::setFace(const int i, const sla::Vec3& ind) { #if SM_CHECK_BOUNDS for (int j=0;j<3;j++) if (ind(j) < 0 || ind(j) >= nv) { printf("Vertex index %i out of range [0,%i], exiting.\n", ind(j), nf); std::exit(1); } #endif f(i).setVertexIndices(ind,vd); } // I/O: Writes state to stream (binary) template inline void SimpleMesh::writeTo(std::ostream& os) { //write number of vertices and faces to file os.write(reinterpret_cast(&nv),sizeof(int)); os.write(reinterpret_cast(&nf),sizeof(int)); //write all vertices to file for (int i=0;i inline void SimpleMesh::readFrom(std::istream& is) { //read number of vertices and faces from stream int nv_, nf_; is.read(reinterpret_cast(&nv_),sizeof(int)); is.read(reinterpret_cast(&nf_),sizeof(int)); //allocate memory startUp(nv_, nf_); //read all vertices from stream for (int i=0;i inline void SimpleMesh::print(std::ostream& os) const { os << "Not implemented yet!" << std::endl; } // I/O: Reads binary file of mesh template inline int SimpleMesh::readBSM(char* filename) { if (SM_PO>0) printf("Reading BSM from %s ...\n", filename); std::fstream fin; fin.open(filename,std::ios::in|std::ios::binary); if (fin.is_open()) { readFrom(fin); } else { printf("Couldn't open file, exiting...\n"); std::exit(1); } fin.close(); if (SM_PO>0) printf("Done.\n"); return 0; } // I/O: Writes binary file format template inline int SimpleMesh::writeBSM(char* filename) { if (SM_PO>0) printf("Writing BSM to %s ...\n", filename); std::fstream fout; fout.open(filename,std::ios::out|std::ios::binary); if (fout.is_open()) { writeTo(fout); } else { printf("Couldn't open file, exiting...\n"); std::exit(1); } fout.close(); if (SM_PO>0) printf("Done.\n"); return 0; } // Displays ascii mesh to screen template inline void SimpleMesh::print() { if (SM_PO>0) printf("Printing ASM to screen...\n"); // write header printf("%i %i\n", nv, nf); // write all vertices for (int i=0;i0) printf("Done.\n"); } // Find face normals template inline void SimpleMesh::findFaceNormals() { if (SM_PO>0) printf("Finding face normals..."); for (int i=0;i(f(i).v(1).x - f(i).v(0).x).cross (sla::Vec3(f(i).v(2).x - f(i).v(0).x)); f(i).n.normalize(); } if (SM_PO>0) printf("Done.\n"); } // Find vertex normals template inline void SimpleMesh::findVertexNormals() { if (SM_PO>0) printf("Finding vertex normals..."); for (int i=0;i0) printf("Done.\n"); } // Find face and vertex normals template inline void SimpleMesh::findNormals() { findFaceNormals(); findVertexNormals(); } ////////////////////////////// // SimpleMeshVertex Methods // ////////////////////////////// // Writes state to stream (binary) template inline void SimpleMeshVertex::writeTo(std::ostream& os) { x.writeTo(os); n.writeTo(os); c.writeTo(os); os.write(reinterpret_cast(&boundary),sizeof(bool)); } // Restores state from stream (binary) template inline void SimpleMeshVertex::readFrom(std::istream& is) { x.readFrom(is); n.readFrom(is); c.readFrom(is); is.read(reinterpret_cast(&boundary),sizeof(bool)); } // Writes state as formated ascii to given stream template inline void SimpleMeshVertex::print(std::ostream& os) const { os << "pos: " << x; os << "normal: " << n; os << "color: " << c; os << std::endl; } //////////////////////////// // SimpleMeshFace Methods // //////////////////////////// // Returns reference to vertex i of this face template inline SimpleMeshVertex& SimpleMeshFace::v(const int i) { #if SM_CHECK_BOUNDS if (i < 0 || i >= 3) { printf("Vertex index %i out of range [0,%i], exiting.\n", i, 3); std::exit(1); } #endif return *(vd[i]); } // Sets vertex i of this face to point to the given vertex template inline void SimpleMeshFace::setVertexIndices(const sla::Vec3& ind, SimpleMeshVertex* v) { for (int i=0;i<3;i++) vd[i] = &(v[ind(i)]); } // Returns the indices of the vertices of this face relative to given ref template inline sla::Vec3 SimpleMeshFace::getVertexIndices(SimpleMeshVertex* v0) const { return sla::Vec3(int(vd[0] - v0),int(vd[1] - v0),int(vd[2] - v0)); } // Writes state to stream (binary) template inline void SimpleMeshFace::writeTo(std::ostream& os, SimpleMeshVertex* v0) { sla::Vec3i ind(getVertexIndices(v0)); ind.writeTo(os); n.writeTo(os); } // Restores state from stream (binary) template inline void SimpleMeshFace::readFrom(std::istream& is, SimpleMeshVertex* v0) { sla::Vec3i ind; ind.readFrom(is); setVertexIndices(ind, v0); n.readFrom(is); } // Writes state as formated ascii to given stream template inline void SimpleMeshFace::print(std::ostream& os, SimpleMeshVertex* v0) const { sla::Vec3i ind(getVertexIndices(v0)); os << "indices: " << ind; os << "normal: " << n; } #endif