MEPP2 Project
OffFileReader.h
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 #pragma once
12 
13 #include <iostream>
14 #include <sstream>
15 #include <vector>
16 #include <cassert>
17 #include <cstdio>
18 #include <string>
19 #include <stdexcept> // for runtime_error
20 
23 
24 namespace FEVV {
25 namespace IO {
26 
27 using namespace StrUtils;
28 using namespace FileUtils;
29 
30 
34 template< typename CoordType,
35  typename CoordNType,
36  typename CoordTType,
37  typename CoordCType,
38  typename IndexType >
39 void
40 read_off_file(std::string file_path,
41  std::vector< std::vector< CoordType > > &points_coords,
42  std::vector< std::vector< CoordNType > > &normals_coords,
43  std::vector< std::vector< CoordTType > > &texture_coords,
44  std::vector< std::vector< CoordCType > > &vertex_color_coords,
45  std::vector< std::vector< IndexType > > &face_indices,
46  std::vector< std::vector< CoordCType > > &face_color_coords)
47 {
48  points_coords.clear();
49  normals_coords.clear();
50  texture_coords.clear();
51  face_indices.clear();
52  vertex_color_coords.clear();
53  face_color_coords.clear();
54 
55  std::ifstream file(file_path);
56 
57  if(! file.is_open())
58  {
59  throw std::runtime_error(
60  "Reader::read_off_file -> failed to open input file.");
61  }
62 
63  std::string line_str, word;
64  std::istringstream line_ss;
65 
66  bool vertices_have_color = false;
67  bool vertices_have_normals = false;
68  bool vertices_have_texture = false;
69 
70  unsigned int vertex_dim = 3u,
71  normal_dim = 3u,
72  texture_dim = 2u,
73  color_dim = 3u;
74  unsigned int face_degree;
75  unsigned long nb_read_vertices = 0ul,
76  nb_total_vertices = 0ul;
77  unsigned long nb_total_edges = 0ul;
78  unsigned long nb_read_faces = 0ul,
79  nb_total_faces = 0ul;
80 
81  CoordType coord;
82  CoordNType n_coord;
83  CoordTType t_coord;
84  CoordCType c_coord;
85  IndexType f_ind;
86 
87  // Find the OFF flag
88  getline_skip_comment(file, line_str, line_ss);
89  line_ss >> word;
90  if((word.size() < 3) || (word.substr(word.size() - 3) != "OFF"))
91  {
92  throw std::runtime_error("Reader::read_off_file -> file format is "
93  "unknown (no [ST][C][N]OFF header). Other "
94  "OFF formats are not implemented yet.");
95  }
96 
97  vertices_have_normals = (word.size() >= 4) &&
98  (word.substr(word.size() - 4) == "NOFF");
99  // end with NOFF
100  vertices_have_color = (word == "COFF") || (word == "CNOFF") ||
101  (word == "STCOFF") || (word == "STCNOFF");
102  vertices_have_texture = (word.substr(0, 2) == "ST"); // begin with ST
103 
104  // Find the element numbers
105  getline_skip_comment(file, line_str, line_ss);
106  line_ss >> nb_total_vertices >> nb_total_faces >> nb_total_edges;
107 
108  points_coords.reserve(nb_total_vertices);
109  face_indices.reserve(nb_total_faces);
110  if(vertices_have_normals)
111  normals_coords.reserve(nb_total_vertices);
112  if(vertices_have_color)
113  vertex_color_coords.reserve(nb_total_vertices);
114  if(vertices_have_texture)
115  texture_coords.reserve(nb_total_vertices);
116 
117  // read vertices
118  std::vector< CoordType > point;
119  std::vector< CoordNType > normal;
120  std::vector< CoordCType > color;
121  std::vector< CoordTType > tex_coord;
122  while(nb_read_vertices < nb_total_vertices)
123  {
124  if(getline_skip_comment(file, line_str, line_ss))
125  {
126  // get vertex coordinates
127  point.clear();
128  for(unsigned int i = 0; i < vertex_dim; ++i)
129  {
130  line_ss >> coord;
131  point.push_back(coord);
132  }
133  points_coords.push_back(point);
134 
135  // get vertex normal
136  if(vertices_have_normals)
137  {
138  normal.clear();
139  for(unsigned int i = 0; i < normal_dim; ++i)
140  {
141  line_ss >> n_coord;
142  normal.push_back(n_coord);
143  }
144  normals_coords.push_back(normal);
145  }
146 
147  // get vertex color
148  if(vertices_have_color)
149  {
150  color.clear();
151  for(unsigned int i = 0; i < color_dim; ++i)
152  {
153  line_ss >> c_coord;
154  color.push_back(c_coord);
155  }
156  vertex_color_coords.push_back(color);
157  }
158 
159  // get vertex texture coordinates
160  if(vertices_have_texture)
161  {
162  tex_coord.clear();
163  for(unsigned int i = 0; i < texture_dim; ++i)
164  {
165  line_ss >> t_coord;
166  tex_coord.push_back(t_coord);
167  }
168  texture_coords.push_back(tex_coord);
169  }
170 
171  nb_read_vertices++;
172  }
173  else
174  {
175  throw std::runtime_error(
176  "Reader::read_off_file -> failed to read vertex line.");
177  }
178  }
179 
180  // read faces
181  std::vector< IndexType > face;
182  while(nb_read_faces < nb_total_faces)
183  {
184  if(getline_skip_comment(file, line_str, line_ss))
185  {
186  // read face vertices
187  face.clear();
188  line_ss >> face_degree;
189  for(unsigned int i = 0; i < face_degree; ++i)
190  {
191  line_ss >> f_ind;
192  face.push_back(f_ind);
193  }
194  face_indices.push_back(face);
195 
196  // read face color if present
197  if(line_ss.good())
198  {
199  // note: .good() is true if previous read was ok and
200  // end of line is not yet reached, so it means
201  // that extra data are available ;
202  // beware : some files have lines that end with
203  // a whitespace, so .good() is not enough to be
204  // sure that a color is provided for this face
205 
206  color.clear();
207  for(unsigned int i = 0; i < color_dim; ++i)
208  {
209  line_ss >> c_coord;
210  color.push_back(c_coord);
211  }
212 
213  // for the case where the line ends with a whitespace,
214  // or the color information is ill-formed
215  if(! line_ss.fail())
216  face_color_coords.push_back(color);
217  }
218 
219  nb_read_faces++;
220  }
221  else
222  {
223  throw std::runtime_error(
224  "Reader::read_off_file -> failed to read face line.");
225  }
226  }
227 
228  file.close();
229 }
230 
231 } // namespace IO
232 } // namespace FEVV
233 
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
FEVV::IO::read_off_file
void read_off_file(std::string file_path, std::vector< std::vector< CoordType > > &points_coords, std::vector< std::vector< CoordNType > > &normals_coords, std::vector< std::vector< CoordTType > > &texture_coords, std::vector< std::vector< CoordCType > > &vertex_color_coords, std::vector< std::vector< IndexType > > &face_indices, std::vector< std::vector< CoordCType > > &face_color_coords)
Definition: OffFileReader.h:40
StringUtilities.hpp
FEVV::DataStructures::AIF::face
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::face_descriptor face(typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::halfedge_descriptor h, const FEVV::DataStructures::AIF::AIFMesh &)
Returns the face incident to halfedge h.
Definition: Graph_traits_aif.h:664
FileUtilities.hpp
FEVV::FileUtils::getline_skip_comment
bool getline_skip_comment(std::istream &input, std::string &line)
Definition: FileUtilities.hpp:230