From dad4ad9ba334b657eaf76cb5405a7ce9bc175862 Mon Sep 17 00:00:00 2001 From: "T.Alderighi" Date: Mon, 28 May 2018 19:06:35 +0200 Subject: [PATCH] added first basic version of msh importer --- wrap/io_tetramesh/import_msh.h | 308 +++++++++++++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 wrap/io_tetramesh/import_msh.h diff --git a/wrap/io_tetramesh/import_msh.h b/wrap/io_tetramesh/import_msh.h new file mode 100644 index 00000000..53a58977 --- /dev/null +++ b/wrap/io_tetramesh/import_msh.h @@ -0,0 +1,308 @@ +#ifndef __VCGLIB_IMPORTTETMSH_H +#define __VCGLIB_IMPORTTETMSH_H + +#include + +namespace vcg +{ +namespace tetra +{ +namespace io +{ +template +class ImporterMSH +{ + typedef typename MeshType::ScalarType ScalarType; + typedef typename MeshType::CoordType CoordType; + typedef typename MeshType::VertexType VertexType; + typedef typename MeshType::TetraType TetraType; + typedef typename MeshType::VertexIterator VertexIterator; + typedef typename MeshType::TetraIterator TetraIterator; + + enum ErrorCodes + { + INVALID_FORMAT = 1, + INVALID_VERSION, + NOT_IMPLEMENTED, + IO_ERROR + }; + + static inline void parseWhiteSpace(std::ifstream &fin) + { + //we don't want to consume non whitespace bytes, just peek it.. + char next = fin.peek(); + + while (next == '\n' || next == ' ' || next == '\t' || next == '\r') + { + fin.get(); + next = fin.peek(); + } + } + + static int parseNodes(MeshType &m, std::ifstream &fin, bool binary) + { + int numOfNodes; + fin >> numOfNodes; + if (numOfNodes < 0) + return INVALID_FORMAT; + + VertexIterator vi = vcg::tri::Allocator::AddVertices(m, numOfNodes); + + if (binary) + { + size_t lineBytes = (4 + 3 * 8); //int index + 3 * double coords + size_t bytes = numOfNodes * lineBytes; + char *data = new char[bytes]; + parseWhiteSpace(fin); + fin.read(data, bytes); + + for (int i = 0; i < numOfNodes; ++i) + { + int index = *reinterpret_cast(&data[i * lineBytes]) - 1; + if (index < 0) + return INVALID_FORMAT; + + m.vert[index].P().X() = *reinterpret_cast(&data[i * lineBytes + 4]); + m.vert[index].P().Y() = *reinterpret_cast(&data[i * lineBytes + 4 + 8]); + m.vert[index].P().Z() = *reinterpret_cast(&data[i * lineBytes + 4 + 2 * 8]); + } + delete[] data; + } + else + { + for (int i = 0; i < numOfNodes; ++i) + { + int index; + fin >> index; + --index; + + if (index < 0) + return INVALID_FORMAT; + + fin >> m.vert[index].P().X(); + fin >> m.vert[index].P().Y(); + fin >> m.vert[index].P().Z(); + } + } + return 0; + } + + static int parseElements(MeshType &m, std::ifstream &fin, bool binary) + { + int numOfElements; + fin >> numOfElements; + if (numOfElements < 0) + return INVALID_FORMAT; + + TetraIterator ti = vcg::tri::Allocator::AddTetras(m, numOfElements); + + if (binary) + { + parseWhiteSpace(fin); + size_t parsedElems = 0; + + while (parsedElems < numOfElements) + { + int index, type, tags; + fin.read((char *)&index, sizeof(int)); + fin.read((char *)&type, sizeof(int)); + fin.read((char *)&tags, sizeof(int)); + --index; + + //check for tetra type + if (type != 4) + return NOT_IMPLEMENTED; + //check index validity + if (index < 0) + return INVALID_FORMAT; + + //read tags and throw them + for (size_t j = 0; j < tags; ++j) + { + int tag; + fin.read((char *)&tag, sizeof(int)); + } + + //read element nodes + TetraType t = m.tetra[index]; + for (int i = 0; i < 4; ++i) + { + int nodeIndex; + fin.read((char *)&nodeIndex, sizeof(int)); + --nodeIndex; + + if (nodeIndex < 0 || nodeIndex >= m.VN()) + return INVALID_FORMAT; + + t.V(i) = &m.vert[nodeIndex]; + } + ++parsedElems; + } + } + else + { + for (int i = 0; i < numOfElements; ++i) + { + int index, type, tags; + fin >> index >> type >> tags; + --index; + + // std::cerr << index << std::endl; + + //check for tetra type + if (type != 4) + return NOT_IMPLEMENTED; + //check index validity + if (index < 0) + return INVALID_FORMAT; + //read tags and throw them + for (size_t j = 0; j < tags; ++j) + { + int tag; + fin >> tag; + } + + TetraType * t = &m.tetra[index]; + for (int i = 0; i < 4; ++i) + { + int nodeIndex; + fin >> nodeIndex; + --nodeIndex; + + if (nodeIndex < 0 || nodeIndex > m.VN()) + return INVALID_FORMAT; + // std::cerr << nodeIndex << std::endl; + + t->V(i) = &m.vert[nodeIndex]; + } + } + } + + return 0; + } + + static int parseMshMesh(MeshType &m, std::string &filename) + { + std::ifstream fin(filename.c_str(), std::ios::in | std::ios::binary); + + if (!fin.is_open()) + return IO_ERROR; + + std::string lookAhead; + + fin >> lookAhead; + if (lookAhead != "$MeshFormat") + return INVALID_FORMAT; + + + double version; + int type, dataSize; + + fin >> version >> type >> dataSize; + + if (version != 2.2) + return INVALID_VERSION; + + bool binary = (type == 1); + + if (dataSize != 8) + return INVALID_FORMAT; + + // Read in extra info from binary header. + if (binary) + { + int one; + parseWhiteSpace(fin); + fin.read(reinterpret_cast(&one), sizeof(int)); + if (one != 1) + { + std::cerr << "Warning: binary msh file " << filename + << " is saved with different endianness than this machine." + << std::endl; + throw NOT_IMPLEMENTED; + } + } + + lookAhead.clear(); + fin >> lookAhead; + if (lookAhead != "$EndMeshFormat") + return INVALID_FORMAT; + + std::cerr << "reading nodes and elements" << std::endl; + + while (!fin.eof()) + { + lookAhead.clear(); + fin >> lookAhead; + + if (lookAhead == "$Nodes") + { + int res = parseNodes(m, fin, binary); + + std::cerr << "reading nodes: " << res << std::endl; + + + if (res != 0) + return res; + std::cerr << "reading nodes" << std::endl; + + fin >> lookAhead; + if (lookAhead != "$EndNodes") + return INVALID_FORMAT; + } + else if (lookAhead == "$Elements") + { + int res = parseElements(m, fin, binary); + + if (res != 0) + return res; + + std::cerr << "elements" << std::endl; + + + fin >> lookAhead; + if (lookAhead != "$EndElements") + return INVALID_FORMAT; + } + else if (lookAhead == "$NodeData") + { + return NOT_IMPLEMENTED; + // parse_node_field(fin); + // fin >> lookAhead; + // if (lookAhead != "$EndNodeData") + // return INVALID_FORMAT; + } + else if (lookAhead == "$ElementData") + { + return NOT_IMPLEMENTED; + // parse_element_field(fin); + // fin >> lookAhead; + // if (lookAhead != "$EndElementData") + // return INVALID_FORMAT; + } + else if (fin.eof()) + { + break; + } + else + { + return INVALID_FORMAT; + // parse_unknown_field(fin, lookAhead); + } + } + fin.close(); + return 0; + } + + public: + static int Open(MeshType &m, const char *filename, CallBackPos *cb = 0) + { + std::string name(filename); + return parseMshMesh(m, name); + } +}; +} // namespace io +} // namespace tetra +} // namespace vcg + +#endif