MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
mesh_io_off.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#include <fstream>
11#include <iostream>
12#include <iomanip>
13#include <stdexcept>
14#include <cstring>
15#include <cerrno>
16
17#include "math/vector.h"
18#include "util/exception.h"
19#include "mve/mesh_io_off.h"
20
23
24TriangleMesh::Ptr
25load_off_mesh (std::string const& filename)
26{
27 if (filename.empty())
28 throw std::invalid_argument("No filename given");
29
30 /* Open file. */
31 std::fstream input(filename.c_str());
32 if (input.fail())
33 throw util::FileException(filename, std::strerror(errno));
34
35 /* Start parsing. */
36 std::string buffer;
37 bool parse_normals = false;
38
39 /* Read "OFF" file signature. */
40 input >> buffer;
41 if (buffer == "NOFF")
42 {
43 parse_normals = true;
44 }
45 else if (buffer != "OFF")
46 {
47 input.close();
48 throw util::Exception("File not recognized as OFF model");
49 }
50
51 /* Create a new triangle mesh. */
52 TriangleMesh::Ptr mesh = TriangleMesh::create();
53 TriangleMesh::VertexList& vertices = mesh->get_vertices();
54 TriangleMesh::FaceList& faces = mesh->get_faces();
55 TriangleMesh::NormalList& vertex_normals = mesh->get_vertex_normals();
56
57 /* Clear the model data and init some values. */
58 std::size_t num_vertices = 0;
59 std::size_t num_faces = 0;
60 std::size_t num_edges = 0;
61
62 /* Read vertex, face and edge information. */
63 input >> num_vertices >> num_faces >> num_edges;
64
65 vertices.reserve(num_vertices);
66 faces.reserve(num_faces * 3);
67 vertex_normals.reserve(num_vertices);
68
69 /* Read vertices. */
70 for (std::size_t i = 0; i < num_vertices; ++i)
71 {
72 float x, y, z;
73 input >> x >> y >> z;
74 vertices.push_back(math::Vec3f(x, y, z));
75
76 /* Also read vertex normals if present. */
77 if (parse_normals)
78 {
79 input >> x >> y >> z;
80 vertex_normals.push_back(math::Vec3f(x, y, z));
81 }
82 }
83
84 /* Read faces. */
85 for (std::size_t i = 0; i < num_faces; ++i)
86 {
87 std::size_t n_vertices;
88 input >> n_vertices;
89
90 if (n_vertices == 3)
91 {
92 /* Polygon is a triangle. */
93 unsigned int vidx[3];
94 bool indices_good = true;
95 for (int j = 0; j < 3; ++j)
96 {
97 input >> vidx[j];
98 if (vidx[j] >= num_vertices)
99 {
100 std::cout << "OFF Loader: Warning: Face " << i
101 << " has invalid vertex " << vidx[j]
102 << ", skipping face." << std::endl;
103 indices_good = false;
104 }
105 }
106
107 if (indices_good)
108 for (int j = 0; j < 3; ++j)
109 faces.push_back(vidx[j]);
110 }
111 else if (n_vertices == 4)
112 {
113 /* Polygon is a quad and converted to 2 triangles. */
114 unsigned int vidx[4];
115 bool indices_good = true;
116 for (int j = 0; j < 4; ++j)
117 {
118 input >> vidx[j];
119 if (vidx[j] >= num_vertices)
120 {
121 std::cout << "OFF Loader: Warning: Face " << i
122 << " has invalid vertex " << vidx[j]
123 << ", skipping face." << std::endl;
124 indices_good = false;
125 }
126 }
127
128 if (indices_good)
129 {
130 for (int j = 0; j < 3; ++j)
131 faces.push_back(vidx[j]);
132 for (int j = 0; j < 3; ++j)
133 faces.push_back(vidx[(j + 2) % 4]);
134 }
135 }
136 else
137 {
138 std::cout << "Warning: Line " << (2 + num_vertices + i)
139 << ": Polygon with " << n_vertices << "vertices, "
140 << "Skipping face!" << std::endl;
141
142 for (std::size_t j = 0; j < n_vertices; ++j)
143 {
144 float tmp;
145 input >> tmp;
146 }
147 }
148 }
149
150 /* Close file stream. */
151 input.close();
152
153 return mesh;
154}
155
156/* ---------------------------------------------------------------- */
157
158void
159save_off_mesh (TriangleMesh::ConstPtr mesh, std::string const& filename)
160{
161 if (mesh == nullptr)
162 throw std::invalid_argument("Null mesh given");
163 if (filename.empty())
164 throw std::invalid_argument("No filename given");
165
166 /* Open file for writing. */
167 std::ofstream out(filename.c_str(), std::ios::binary);
168 if (out.fail())
169 throw util::FileException(filename, std::strerror(errno));
170
171 TriangleMesh::VertexList const& vertices = mesh->get_vertices();
172 TriangleMesh::FaceList const& faces = mesh->get_faces();
173 std::size_t num_verts = vertices.size();
174 std::size_t num_faces = faces.size() / 3;
175
176 /* Write the header. */
177 out << "OFF" << std::endl;
178
179 /* Write number of vertices and faces (and 0 for edges). */
180 out << num_verts << " " << num_faces << " 0" << std::endl;
181
182 /* Write at least 7 digits for float values. */
183 out << std::fixed << std::setprecision(7);
184
185 /* Write vertices. */
186 for (std::size_t i = 0; i < num_verts; ++i)
187 {
188 out << vertices[i][0] << " " << vertices[i][1]
189 << " " << vertices[i][2] << std::endl;
190 }
191
192 /* Write faces. */
193 for (std::size_t i = 0; i < num_faces * 3; i += 3)
194 {
195 out << "3 " << faces[i + 0] << " "
196 << faces[i + 1] << " " << faces[i + 2] << std::endl;
197 }
198
199 /* Close file stream. */
200 out.close();
201}
202
Vector class for arbitrary dimensions and types.
Definition vector.h:87
std::vector< math::Vec3f > VertexList
Definition mesh.h:33
std::vector< math::Vec3f > NormalList
Definition mesh.h:95
std::shared_ptr< TriangleMesh > Ptr
Definition mesh.h:92
std::vector< VertexID > FaceList
Definition mesh.h:97
std::shared_ptr< TriangleMesh const > ConstPtr
Definition mesh.h:93
Universal, simple exception class.
Definition exception.h:24
Exception class for file exceptions with additional filename.
Definition exception.h:53
#define MVE_NAMESPACE_BEGIN
Definition defines.h:13
#define MVE_NAMESPACE_END
Definition defines.h:14
#define MVE_GEOM_NAMESPACE_END
Definition defines.h:20
#define MVE_GEOM_NAMESPACE_BEGIN
Definition defines.h:19
TriangleMesh::Ptr load_off_mesh(std::string const &filename)
Loads a triangle mesh from an OFF model file.
void save_off_mesh(TriangleMesh::ConstPtr mesh, std::string const &filename)
Saves a triangle mesh to an OFF model file.