1 /**
2 * MOAB, a Mesh-Oriented datABase, is a software component for creating,
3 * storing and accessing finite element mesh data.
4 *
5 * Copyright 2004 Sandia Corporation. Under the terms of Contract
6 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
7 * retains certain rights in this software.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 */
15
16 //-----------------------------------------------------------------------------
17 // Filename : ReadOBJ.hpp
18 //
19 // Purpose : Wavefront obj file reader
20 //
21 // Creators : Chelsea D'Angelo, Paul Wilson, Andrew Davis
22 //
23 // Date : 02/16
24 //
25 // Owner : Chelsea D'Angelo
26 //-----------------------------------------------------------------------------
27
28 /**
29 * This class will read in an obj file and populate a MOAB instance with the
30 * vertex and connectivity information in the file. A specification for obj files
31 * can be found here: https://en.wikipedia.org/wiki/Wavefront_.obj_file
32 * This reader only supports a subset of the full file structure, namely,
33 * object names, group names, vertices, and faces.
34 *
35 * Overview of the supported structure:
36 *
37 * Heading
38 * Object line: o object_name
39 * Group line: g group_name1
40 * Vertex lines: v x y z
41 * Face lines (tri): f v1 v2 v3
42 * Face lines (quad): f v1 v2 v3 v4
43 *
44 * Lines that begin w/ anything other than 'o ', 'g ', 'v ', and 'f ' are not
45 * supported. If a valid, but unsupported line is found, it will be ignored.
46 * If an invalid line is found, an error will be produced.
47 * Face lines that contain 'vertex\texture\normal' are handled by ignoring the
48 * texture and normal
49 *
50 *
51 * A new meshset will be created for each object or group in the file.
52 * Each object and group must have a name, or the line will be ignored.
53 * Groups are thought to be collections of elements with no dimension or category and
54 * will therefore only be assigned name and id tags.
55 * Objects are thought to be closed surfaces. A surface meshset will be
56 * created for each object. A volume meshset that directly corresponds
57 * to the surface meshset will also be created. These will have name, id,
58 * categorty, and dimension tags. A parent-child relationship exists
59 * between the volume and surface meshsets.
60 * Vertices will be created and added to a global vertex meshset.
61 * Triangular faces will be created and added as members of the surface meshets.
62 */
63
64 #ifndef READ_OBJ_HPP
65 #define READ_OBJ_HPP
66
67 #ifndef IS_BUILDING_MB
68 #error "ReadOBJ.hpp isn't supposed to be included into an application"
69 #endif
70
71 #include <iostream>
72 #include <fstream>
73 #include <sstream>
74 #include <vector>
75 #include <map>
76
77 #include "moab/Interface.hpp"
78 #include "moab/ReaderIface.hpp"
79 #include "FileTokenizer.hpp"
80 #include "moab/RangeMap.hpp"
81 #include "MBTagConventions.hpp"
82
83 /* struct vertex is a structure that stores coordinates
84 of vertices. This is a convenience structure making
85 i/o easier.
86 */
87 struct vertex
88 {
89 int vertex_id;
90 double coord[3];
91 };
92
93 /* struct face is a structure that stores connectivity.
94 This is a convenience structure makin i/o easier.
95 */
96 struct face
97 {
98 int face_id;
99 moab::EntityHandle conn[3];
100 };
101 namespace moab
102 {
103
104 /* Supported obj file keywords
105 */
106 enum keyword_type
107 {
108 obj_undefined = 0,
109 object_start,
110 group_start,
111 face_start,
112 vertex_start,
113 valid_unsupported
114 };
115
116 class ReadUtilIface;
117 class GeomTopoTool;
118
119 class ReadOBJ : public ReaderIface
120 {
121
122 public:
123 //! factory method
124 static ReaderIface* factory( Interface* );
125
126 ErrorCode load_file( const char* file_name,
127 const EntityHandle* file_set,
128 const FileOptions& opts,
129 const SubsetList* subset_list = 0,
130 const Tag* file_id_tag = 0 );
131
132 ErrorCode read_tag_values( const char* file_name,
133 const char* tag_name,
134 const FileOptions& opts,
135 std::vector< int >& tag_values_out,
136 const SubsetList* subset_list = 0 );
137
138 //! Constructor
139 ReadOBJ( Interface* impl = NULL );
140
141 //! Destructor
142 virtual ~ReadOBJ();
143
144 private:
145 ReadUtilIface* readMeshIface;
146
147 //! interface instance
148 Interface* MBI;
149
150 GeomTopoTool* myGeomTool;
151
152 Tag geom_tag, id_tag, name_tag, category_tag, faceting_tol_tag, geometry_resabs_tag, obj_name_tag;
153
154 /* The keyword type function matches the first character extracted from each line to a type of
155 * line
156 */
157 keyword_type get_keyword( std::vector< std::string > tokens );
158
159 /* The match function searches a list of map keys for a match with the token
160 */
161 template < typename T >
162 std::string match( const std::string& token, std::map< std::string, T >& tokenList );
163
164 /* The tokenize function takes a string as input and splits it into
165 * a vector of strings based on the delimiter
166 */
167 static const char* delimiters;
168
169 void tokenize( const std::string& str, std::vector< std::string >& tokens, const char* delimiters );
170
171 /*
172 * The create_object funtion will create a new meshset for
173 * each object that contains all vertices and faces
174 */
175 ErrorCode create_new_object( std::string object_name, int object_id, EntityHandle& curr_obj_meshset );
176
177 ErrorCode create_new_group( std::string object_name, int curr_object, EntityHandle& object_meshset );
178
179 /* create_new_vertex converts tokenized string input to
180 vertex structure
181 */
182 ErrorCode create_new_vertex( std::vector< std::string > v_tokens, EntityHandle& vertex_eh );
183
184 /* create_new_face converts tokenized string input to
185 * face structure
186 */
187 ErrorCode create_new_face( std::vector< std::string > f_tokens,
188 const std::vector< EntityHandle >& vertex_list,
189 EntityHandle& face_eh );
190
191 /*
192 * The split_quad function creates 1 new vertex and 4 new tri faces
193 * from a quad face.
194 */
195
196 ErrorCode split_quad( std::vector< std::string > f_tokens,
197 std::vector< EntityHandle >& vertex_list,
198 Range& face_eh );
199
200 ErrorCode create_tri_faces( std::vector< EntityHandle > quad_vert_eh,
201 // EntityHandle center_vertex_eh,
202 Range& face_eh );
203 };
204
205 } // namespace moab
206
207 #endif