1 | /* |
2 | * ObjReader.hpp |
3 | * |
4 | * Created on: Oct 31, 2018 |
5 | * Author: i-bird |
6 | */ |
7 | |
8 | #ifndef OBJREADER_HPP_ |
9 | #define OBJREADER_HPP_ |
10 | |
11 | #include "config.h" |
12 | #include "Space/Shape/Point.hpp" |
13 | |
14 | #ifdef HAVE_TINYOBJLOADER |
15 | #include "tiny_obj_loader.h" |
16 | |
17 | /*! \brief Wavefront obj File reader |
18 | * |
19 | * \tparam T precision of the 3D space |
20 | * |
21 | */ |
22 | template<typename T> |
23 | class ObjReader |
24 | { |
25 | size_t shape_counter; |
26 | size_t face_counter; |
27 | size_t index_offset; |
28 | |
29 | tinyobj::attrib_t attrib; |
30 | std::vector<tinyobj::shape_t> shapes; |
31 | std::vector<tinyobj::material_t> materials; |
32 | |
33 | size_t end_shape; |
34 | |
35 | public: |
36 | |
37 | /*! \brief Constructor |
38 | * |
39 | * |
40 | */ |
41 | ObjReader() |
42 | {} |
43 | |
44 | /*! \brief Read an Wavefront obj file |
45 | * |
46 | * \param file to open |
47 | * |
48 | * \return true if the read succeed |
49 | */ |
50 | bool read(std::string file) |
51 | { |
52 | shape_counter = 0; |
53 | face_counter = 0; |
54 | index_offset = 0; |
55 | |
56 | shapes.clear(); |
57 | materials.clear(); |
58 | |
59 | std::string err; |
60 | bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, file.c_str()); |
61 | |
62 | if (!err.empty()) |
63 | {std::cerr << err << std::endl;} |
64 | |
65 | if (!ret) |
66 | {return false;} |
67 | |
68 | end_shape = shapes.size(); |
69 | |
70 | return true; |
71 | } |
72 | |
73 | |
74 | /*! \brief Next triangle |
75 | * |
76 | * \return itself |
77 | * |
78 | */ |
79 | ObjReader & operator++() |
80 | { |
81 | index_offset += getFaceNVertex(); |
82 | ++face_counter; |
83 | |
84 | if (face_counter >= shapes[shape_counter].mesh.num_face_vertices.size()) |
85 | { |
86 | face_counter = 0; |
87 | index_offset = 0; |
88 | ++shape_counter; |
89 | } |
90 | |
91 | return *this; |
92 | } |
93 | |
94 | /*! \brief Return true if we have another face |
95 | * |
96 | * \return true if we have next face |
97 | */ |
98 | inline bool isNext() |
99 | { |
100 | return shape_counter < end_shape; |
101 | } |
102 | |
103 | /*! \brief Iterate only on a partucular object faces |
104 | * |
105 | * \param i object to iterate |
106 | * |
107 | * \return |
108 | */ |
109 | inline void setObject(int i) |
110 | { |
111 | if (i >= shapes.size()) |
112 | { |
113 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " you selected object " << i << " but the file contain " << shapes.size() << " objects" << std::endl; |
114 | } |
115 | |
116 | shape_counter = i; |
117 | end_shape = i+1; |
118 | } |
119 | |
120 | |
121 | /*! \brief Get the number of vertices in the face |
122 | * |
123 | * \return number of vertices a face has |
124 | */ |
125 | unsigned int getFaceNVertex() |
126 | { |
127 | return shapes[shape_counter].mesh.num_face_vertices[face_counter]; |
128 | } |
129 | |
130 | /*! \brief return the vertex v of the actual face |
131 | * |
132 | * \param v vertex |
133 | * \return the position of such vertex |
134 | */ |
135 | inline Point<3,T> getVertex(unsigned int v) |
136 | { |
137 | Point<3,T> p; |
138 | |
139 | tinyobj::index_t idx = shapes[shape_counter].mesh.indices[index_offset + v]; |
140 | |
141 | p.get(0) = attrib.vertices[3*idx.vertex_index+0]; |
142 | p.get(1) = attrib.vertices[3*idx.vertex_index+1]; |
143 | p.get(2) = attrib.vertices[3*idx.vertex_index+2]; |
144 | |
145 | return p; |
146 | } |
147 | |
148 | /*! \brief return the vertex v of the actual face |
149 | * |
150 | * \param v vertex |
151 | * \return the position of such vertex |
152 | */ |
153 | inline Point<3,T> getNormal(unsigned int v) |
154 | { |
155 | Point<3,T> p; |
156 | |
157 | tinyobj::index_t idx = shapes[shape_counter].mesh.indices[index_offset + v]; |
158 | |
159 | p.get(0) = attrib.normals[3*idx.normal_index+0]; |
160 | p.get(1) = attrib.normals[3*idx.normal_index+1]; |
161 | p.get(2) = attrib.normals[3*idx.normal_index+2]; |
162 | |
163 | return p; |
164 | } |
165 | |
166 | /*! \brief Get the texture coordinates |
167 | * |
168 | * \param v vertex |
169 | * |
170 | * \return The texture coordinates of the vertex v |
171 | * |
172 | */ |
173 | inline Point<2,T> getTexCoord(unsigned int v) |
174 | { |
175 | Point<2,T> p; |
176 | |
177 | tinyobj::index_t idx = shapes[shape_counter].mesh.indices[index_offset + v]; |
178 | |
179 | p.get(0) = attrib.texcoords[2*idx.texcoord_index+0]; |
180 | p.get(1) = attrib.texcoords[2*idx.texcoord_index+1]; |
181 | |
182 | return p; |
183 | } |
184 | }; |
185 | |
186 | #endif |
187 | |
188 | #endif /* OBJREADER_HPP_ */ |
189 | |