1 /****************************************************************************
2 * VCGLib o o *
3 * Visual and Computer Graphics Library o o *
4 * _ O _ *
5 * Copyright(C) 2004-2016 \/)\/ *
6 * Visual Computing Lab /\/| *
7 * ISTI - Italian National Research Council | *
8 * \ *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
20 * for more details. *
21 * *
22 ****************************************************************************/
23 #ifndef __VCGLIB_IMPORTERPLY
24 #define __VCGLIB_IMPORTERPLY
25
26 #include <stddef.h>
27 #include<wrap/callback.h>
28 #include<wrap/ply/plylib.h>
29 #include<wrap/io_trimesh/io_mask.h>
30 #include<wrap/io_trimesh/io_ply.h>
31 #include<vcg/complex/algorithms/create/platonic.h>
32
33 namespace vcg {
34 namespace tri {
35 namespace io {
36
37 template <class TYPE>
PlyType()38 int PlyType () { return 0;}
39
40
41 // 10/6/05 Cignoni this specialization must be inlined becouse otherwise if we include this
42 // .h in two different cpp we should get a double definition error during linking
43
44 template <> inline int PlyType <float >() { return ply::T_FLOAT; }
45 template <> inline int PlyType <double>() { return ply::T_DOUBLE; }
46 template <> inline int PlyType <int >() { return ply::T_INT; }
47 template <> inline int PlyType <short >() { return ply::T_SHORT; }
48 template <> inline int PlyType <unsigned char >() { return ply::T_UCHAR; }
49
50 /**
51 This class encapsulate a filter for opening ply meshes.
52 The ply file format is quite extensible...
53 */
54 template <class OpenMeshType>
55 class ImporterPLY
56 {
57 public:
58
59 typedef ::vcg::ply::PropDescriptor PropDescriptor ;
60 typedef typename OpenMeshType::VertexPointer VertexPointer;
61 typedef typename OpenMeshType::ScalarType ScalarType;
62 typedef typename OpenMeshType::VertexType VertexType;
63 typedef typename VertexType::QualityType VertQualityType;
64 typedef typename OpenMeshType::FaceType FaceType;
65 typedef typename FaceType::QualityType FaceQualityType;
66
67 typedef typename OpenMeshType::VertexIterator VertexIterator;
68 typedef typename OpenMeshType::FaceIterator FaceIterator;
69 typedef typename OpenMeshType::EdgeIterator EdgeIterator;
70
71 #define MAX_USER_DATA 256
72 // Auxiliary structure for reading ply files
73 template<class S>
74 struct LoadPly_FaceAux
75 {
76 unsigned char size;
77 int v[512];
78 int flags;
79 S n[3];
80 S q;
81 float texcoord[32];
82 unsigned char ntexcoord;
83 int texcoordind;
84 float colors[32];
85 unsigned char ncolors;
86
87 unsigned char r;
88 unsigned char g;
89 unsigned char b;
90 unsigned char a;
91
92 unsigned char data[MAX_USER_DATA];
93 };
94
95 struct LoadPly_TristripAux
96 {
97 int size;
98 int *v;
99 unsigned char data[MAX_USER_DATA];
100 };
101
102 struct LoadPly_EdgeAux
103 {
104 int v1,v2;
105 unsigned char data[MAX_USER_DATA];
106 };
107
108 // Yet another auxiliary data structure for loading some strange ply files
109 // the original stanford range data...
110 struct LoadPly_RangeGridAux {
111 unsigned char num_pts;
112 int pts[5];
113 };
114
115
116 // Auxiliary structure to load vertex data
117 template<class S>
118 struct LoadPly_VertAux
119 {
120 S p[3];
121 S n[3];
122 int flags;
123 S q; // the confidence
124 float intensity;
125 unsigned char r;
126 unsigned char g;
127 unsigned char b;
128 unsigned char a;
129 unsigned char data[MAX_USER_DATA];
130 float radius;
131 float u,v,w;
132 };
133
134 // Auxiliary structure to load the camera
135 struct LoadPly_Camera
136 {
137 float view_px;
138 float view_py;
139 float view_pz;
140 float x_axisx;
141 float x_axisy;
142 float x_axisz;
143 float y_axisx;
144 float y_axisy;
145 float y_axisz;
146 float z_axisx;
147 float z_axisy;
148 float z_axisz;
149 float focal;
150 float scalex;
151 float scaley;
152 float centerx;
153 float centery;
154 int viewportx;
155 int viewporty;
156 float k1;
157 float k2;
158 float k3;
159 float k4;
160 };
161
162 #define _VERTDESC_LAST_ 32
VertDesc(int i)163 static const PropDescriptor &VertDesc(int i)
164 {
165 static const PropDescriptor pv[_VERTDESC_LAST_]={
166 /**** { elename, propname, storedtype1, memtype1, memoffset, */
167 /*00*/ {"vertex", "x", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p),0,0,0,0,0 ,0},
168 /*01*/ {"vertex", "y", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p) + sizeof(ScalarType),0,0,0,0,0 ,0},
169 /*02*/ {"vertex", "z", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p) + 2*sizeof(ScalarType),0,0,0,0,0 ,0},
170 /*03*/ {"vertex", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_VertAux<ScalarType>,flags),0,0,0,0,0 ,0},
171 /*04*/ {"vertex", "quality", ply::T_FLOAT, PlyType<ScalarType>(), offsetof(LoadPly_VertAux<ScalarType>,q),0,0,0,0,0 ,0},
172 /*05*/ {"vertex", "red", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,r),0,0,0,0,0 ,0},
173 /*06*/ {"vertex", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,g),0,0,0,0,0 ,0},
174 /*07*/ { "vertex", "blue", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,b),0,0,0,0,0 ,0},
175 /*08*/ { "vertex", "alpha", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,a),0,0,0,0,0 ,0},
176 /*09*/ {"vertex", "diffuse_red", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,r),0,0,0,0,0 ,0},
177 /*10*/ {"vertex", "diffuse_green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,g),0,0,0,0,0 ,0},
178 /*11*/ {"vertex", "diffuse_blue", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,b),0,0,0,0,0 ,0},
179 /*12*/ {"vertex", "diffuse_alpha", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,a),0,0,0,0,0 ,0},
180 /*13*/ {"vertex", "confidence", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,q),0,0,0,0,0 ,0},
181 /*14*/ {"vertex", "nx", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) ,0,0,0,0,0 ,0},
182 /*15*/ {"vertex", "ny", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) + 1*sizeof(ScalarType),0,0,0,0,0 ,0},
183 /*16*/ {"vertex", "nz", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0},
184 /*17*/ {"vertex", "radius", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,radius),0,0,0,0,0 ,0},
185 /*18*/ {"vertex", "texture_u", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,u),0,0,0,0,0 ,0},
186 /*19*/ {"vertex", "texture_v", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,v),0,0,0,0,0 ,0},
187 /*20*/ {"vertex", "texture_w", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,w),0,0,0,0,0 ,0},
188 /*21*/ {"vertex", "intensity", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,intensity),0,0,0,0,0 ,0},
189 /*22*/ {"vertex", "s", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,u),0,0,0,0,0 ,0},
190 /*23*/ {"vertex", "t", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,v),0,0,0,0,0 ,0},
191 // DOUBLE
192 /*24*/ {"vertex", "x", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p),0,0,0,0,0 ,0},
193 /*25*/ {"vertex", "y", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p) + sizeof(ScalarType) ,0,0,0,0,0 ,0},
194 /*26*/ {"vertex", "z", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p) + 2*sizeof(ScalarType),0,0,0,0,0 ,0},
195 /*27*/ {"vertex", "nx", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) ,0,0,0,0,0 ,0},
196 /*28*/ {"vertex", "ny", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) + 1*sizeof(ScalarType),0,0,0,0,0 ,0},
197 /*29*/ {"vertex", "nz", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0},
198 /*30*/ {"vertex", "radius", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,radius),0,0,0,0,0 ,0},
199 /*31*/ {"vertex", "quality", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,q),0,0,0,0,0 ,0}
200 };
201 return pv[i];
202 }
203
204 #define _FACEDESC_FIRST_ 13 // the first descriptor with possible vertex indices
205 #define _FACEDESC_LAST_ 29
FaceDesc(int i)206 static const PropDescriptor &FaceDesc(int i)
207 {
208 static const PropDescriptor qf[_FACEDESC_LAST_]=
209 {
210 /* on file on memory on file on memory */
211 /* 0 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_UCHAR, ply::T_UCHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
212 /* 1 */ {"face", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,flags), 0,0,0,0,0 ,0},
213 /* 2 */ {"face", "quality", ply::T_FLOAT, PlyType<ScalarType>(), offsetof(LoadPly_FaceAux<ScalarType>,q), 0,0,0,0,0 ,0},
214 /* 3 */ {"face", "texcoord", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux<ScalarType>,texcoord), 1,0,ply::T_UCHAR, ply::T_UCHAR,offsetof(LoadPly_FaceAux<ScalarType>,ntexcoord) ,0},
215 /* 4 */ {"face", "color", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux<ScalarType>,colors), 1,0,ply::T_UCHAR, ply::T_UCHAR,offsetof(LoadPly_FaceAux<ScalarType>,ncolors) ,0},
216 /* 5 */ {"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,texcoordind), 0,0,0,0,0 ,0},
217 /* 6 */ {"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux<ScalarType>,r), 0,0,0,0,0 ,0},
218 /* 7 */ {"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux<ScalarType>,g), 0,0,0,0,0 ,0},
219 /* 8 */ {"face", "blue", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux<ScalarType>,b), 0,0,0,0,0 ,0},
220 /* 9 */ {"face", "alpha", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux<ScalarType>,a), 0,0,0,0,0 ,0},
221 /* 10 */ {"face", "nx", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) ,0,0,0,0,0 ,0},
222 /* 11 */ {"face", "ny", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) + 1*sizeof(ScalarType),0,0,0,0,0 ,0},
223 /* 12 */ {"face", "nz", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0},
224 /* 13 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
225 /* 14 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
226 /* 15 */ {"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
227
228 /* 16 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
229 /* 17 */ {"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
230 /* 18 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
231 /* 19 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
232 /* 20 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
233 /* 21 */ {"face", "vertex_indices", ply::T_UINT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_USHORT,ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
234 /* 22 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_CHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
235 /* 23 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_UCHAR, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
236 /* 24 */ {"face", "vertex_indices", ply::T_SHORT, ply::T_INT, offsetof(LoadPly_FaceAux<ScalarType>,v), 1,0,ply::T_INT, ply::T_CHAR,offsetof(LoadPly_FaceAux<ScalarType>,size) ,0},
237 // DOUBLE
238 /* 25 */ {"face", "quality", ply::T_DOUBLE, PlyType<ScalarType>(), offsetof(LoadPly_FaceAux<ScalarType>,q), 0,0,0,0,0 ,0},
239 /* 26 */ {"face", "nx", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) ,0,0,0,0,0 ,0},
240 /* 27 */ {"face", "ny", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) + 1*sizeof(ScalarType),0,0,0,0,0 ,0},
241 /* 28 */ {"face", "nz", ply::T_DOUBLE, PlyType<ScalarType>(),offsetof(LoadPly_FaceAux<ScalarType>,n) + 2*sizeof(ScalarType),0,0,0,0,0 ,0}
242
243 };
244 return qf[i];
245 }
TristripDesc(int i)246 static const PropDescriptor &TristripDesc(int i)
247 {
248 static const PropDescriptor qf[1]=
249 {
250 {"tristrips","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TristripAux,v), 1,1,ply::T_INT,ply::T_INT,offsetof(LoadPly_TristripAux,size) ,0},
251 };
252 return qf[i];
253 }
254
EdgeDesc(int i)255 static const PropDescriptor &EdgeDesc(int i)
256 {
257 static const PropDescriptor qf[2]=
258 {
259 {"edge","vertex1", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v1), 0,0,0,0,0 ,0},
260 {"edge","vertex2", ply::T_INT, ply::T_INT, offsetof(LoadPly_EdgeAux,v2), 0,0,0,0,0 ,0},
261 };
262 return qf[i];
263 }
264
265 // Descriptor for the Stanford Data Repository Range Maps.
266 // In practice a grid with some invalid elements. Coords are saved only for good elements
RangeDesc(int i)267 static const PropDescriptor &RangeDesc(int i)
268 {
269 static const PropDescriptor range_props[1] = {
270 {"range_grid","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_RangeGridAux,pts), 1, 0, ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_RangeGridAux,num_pts),0},
271 };
272 return range_props[i];
273 }
274
275
CameraDesc(int i)276 static const PropDescriptor &CameraDesc(int i)
277 {
278 static const PropDescriptor cad[23] =
279 {
280 {"camera","view_px",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_px),0,0,0,0,0 ,0},
281 {"camera","view_py",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_py),0,0,0,0,0 ,0},
282 {"camera","view_pz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_pz),0,0,0,0,0 ,0},
283 {"camera","x_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisx),0,0,0,0,0 ,0},
284 {"camera","x_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisy),0,0,0,0,0 ,0},
285 {"camera","x_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisz),0,0,0,0,0 ,0},
286 {"camera","y_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisx),0,0,0,0,0 ,0},
287 {"camera","y_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisy),0,0,0,0,0 ,0},
288 {"camera","y_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisz),0,0,0,0,0 ,0},
289 {"camera","z_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisx),0,0,0,0,0 ,0},
290 {"camera","z_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisy),0,0,0,0,0 ,0},
291 {"camera","z_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisz),0,0,0,0,0 ,0},
292 {"camera","focal" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,focal ),0,0,0,0,0 ,0},
293 {"camera","scalex" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scalex ),0,0,0,0,0 ,0},
294 {"camera","scaley" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scaley ),0,0,0,0,0 ,0},
295 {"camera","centerx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centerx),0,0,0,0,0 ,0},
296 {"camera","centery",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centery),0,0,0,0,0 ,0},
297 {"camera","viewportx",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewportx),0,0,0,0,0 ,0},
298 {"camera","viewporty",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewporty),0,0,0,0,0 ,0},
299 {"camera","k1" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k1 ),0,0,0,0,0 ,0},
300 {"camera","k2" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k2 ),0,0,0,0,0 ,0},
301 {"camera","k3" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k3 ),0,0,0,0,0 ,0},
302 {"camera","k4" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k4 ),0,0,0,0,0 ,0}
303 };
304 return cad[i];
305 }
306 /// Standard call for knowing the meaning of an error code
ErrorMsg(int error)307 static const char *ErrorMsg(int error)
308 {
309 static std::vector<std::string> ply_error_msg;
310 if(ply_error_msg.empty())
311 {
312 ply_error_msg.resize(PlyInfo::E_MAXPLYINFOERRORS );
313 ply_error_msg[ply::E_NOERROR ]="No errors";
314 ply_error_msg[ply::E_CANTOPEN ]="Can't open file";
315 ply_error_msg[ply::E_NOTHEADER ]="Header not found";
316 ply_error_msg[ply::E_UNESPECTEDEOF ]="Eof in header";
317 ply_error_msg[ply::E_NOFORMAT ]="Format not found";
318 ply_error_msg[ply::E_SYNTAX ]="Syntax error on header";
319 ply_error_msg[ply::E_PROPOUTOFELEMENT]="Property without element";
320 ply_error_msg[ply::E_BADTYPENAME ]="Bad type name";
321 ply_error_msg[ply::E_ELEMNOTFOUND ]="Element not found";
322 ply_error_msg[ply::E_PROPNOTFOUND ]="Property not found";
323 ply_error_msg[ply::E_BADTYPE ]="Bad type on addtoread";
324 ply_error_msg[ply::E_INCOMPATIBLETYPE]="Incompatible type";
325 ply_error_msg[ply::E_BADCAST ]="Bad cast";
326
327 ply_error_msg[PlyInfo::E_NO_VERTEX ]="No vertex field found";
328 ply_error_msg[PlyInfo::E_NO_FACE ]="No face field found";
329 ply_error_msg[PlyInfo::E_SHORTFILE ]="Unespected eof";
330 ply_error_msg[PlyInfo::E_NO_3VERTINFACE ]="Face with more than 3 vertices";
331 ply_error_msg[PlyInfo::E_BAD_VERT_INDEX ]="Bad vertex index in face";
332 ply_error_msg[PlyInfo::E_BAD_VERT_INDEX_EDGE ]="Bad vertex index in edge";
333 ply_error_msg[PlyInfo::E_NO_6TCOORD ]="Face with no 6 texture coordinates";
334 ply_error_msg[PlyInfo::E_DIFFER_COLORS ]="Number of color differ from vertices";
335 }
336
337 if(error>PlyInfo::E_MAXPLYINFOERRORS || error<0) return "Unknown error";
338 else return ply_error_msg[error].c_str();
339 };
340
341 // to check if a given error is critical or not.
ErrorCritical(int err)342 static bool ErrorCritical(int err)
343 {
344 if ((err == ply::E_NOERROR) || (err == PlyInfo::E_NO_FACE)) return false;
345 return true;
346 }
347
348
349 /// Standard call for reading a mesh, returns 0 on success.
350 static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
351 {
352 PlyInfo pi;
353 pi.cb=cb;
354 return Open(m, filename, pi);
355 }
356
357 /// Read a mesh and store in loadmask the loaded field
358 /// Note that loadmask is not read! just modified. You cannot specify what fields
359 /// have to be read. ALL the data for which your mesh HasSomething and are present
360 /// in the file are read in.
361 static int Open( OpenMeshType &m, const char * filename, int & loadmask, CallBackPos *cb =0)
362 {
363 PlyInfo pi;
364 pi.cb=cb;
365 int r = Open(m, filename,pi);
366 loadmask=pi.mask;
367 return r;
368 }
369
370
371 /// read a mesh with all the possible option specified in the PlyInfo obj, returns 0 on success.
Open(OpenMeshType & m,const char * filename,PlyInfo & pi)372 static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
373 {
374 assert(filename!=0);
375 std::vector<VertexPointer> index;
376 LoadPly_FaceAux<ScalarType> fa;
377 LoadPly_EdgeAux ea;
378 LoadPly_TristripAux tsa;
379 LoadPly_VertAux<ScalarType> va;
380
381 LoadPly_RangeGridAux rga;
382 std::vector<int> RangeGridAuxVec;
383 int RangeGridCols=0;
384 int RangeGridRows=0;
385
386
387 pi.mask = 0;
388 bool hasIntensity = false; // the intensity is a strange way to code single channel color used sometimes in rangemap. it is a kind of color. so it do not need another entry in the IOM mask.
389 bool multit = false; // true if texture has a per face int spec the texture index
390
391 va.flags = 42;
392
393 pi.status = ::vcg::ply::E_NOERROR;
394
395 /*
396 // TO BE REMOVED: tv not used AND "spurious" vertex declaration causes error if ocf
397
398 // init defaults
399 VertexType tv;
400 //tv.ClearFlags();
401
402 if (vcg::tri::HasPerVertexQuality(m)) tv.Q() = (typename OpenMeshType::VertexType::QualityType)1.0;
403 if (vcg::tri::HasPerVertexColor (m)) tv.C() = Color4b(Color4b::White);
404 */
405
406 // Descrittori delle strutture
407
408 //bool isvflags = false; // Il file contiene i flags
409
410
411 // The main descriptor of the ply file
412 vcg::ply::PlyFile pf;
413
414 // Open the file and parse the header
415 if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 )
416 {
417 pi.status = pf.GetError();
418 return pi.status;
419 }
420 pi.header = pf.GetHeader();
421
422 // Descrittori della camera
423 { // Check that all the camera properties are present.
424 bool found = true;
425 for(int i=0;i<23;++i)
426 {
427 if( pf.AddToRead(CameraDesc(i))==-1 ) {
428 found = false;
429 break;
430 }
431 }
432 if(found) pi.mask |= Mask::IOM_CAMERA;
433 }
434
435 // Standard data desciptors (vertex coord and faces)
436 if( pf.AddToRead(VertDesc(0))==-1 && pf.AddToRead(VertDesc(24)) ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; }
437 if( pf.AddToRead(VertDesc(1))==-1 && pf.AddToRead(VertDesc(25)) ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; }
438 if( pf.AddToRead(VertDesc(2))==-1 && pf.AddToRead(VertDesc(26)) ) { pi.status = PlyInfo::E_NO_VERTEX; return pi.status; }
439 if( pf.AddToRead(FaceDesc(0))==-1 ) // Se fallisce si prova anche la sintassi di rapidform con index al posto di indices
440 {
441 int ii;
442 for (ii=_FACEDESC_FIRST_;ii< _FACEDESC_LAST_;++ii)
443 if( pf.AddToRead(FaceDesc(ii))!=-1 ) break;
444
445 if (ii==_FACEDESC_LAST_)
446 if(pf.AddToRead(TristripDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono tristrip alla levoy.
447 if(pf.AddToRead(RangeDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono rangemap alla levoy.
448 {
449 pi.status = PlyInfo::E_NO_FACE;
450 //return pi.status; no face is not a critical error. let's continue.
451 }
452
453 }
454 // Optional flag descriptors
455 if(pf.AddToRead(EdgeDesc(0) )!= -1 && pf.AddToRead(EdgeDesc(1)) != -1 )
456 pi.mask |= Mask::IOM_EDGEINDEX;
457
458 if(vcg::tri::HasPerVertexFlags(m) && pf.AddToRead(VertDesc(3))!=-1 )
459 pi.mask |= Mask::IOM_VERTFLAGS;
460
461 if( vcg::tri::HasPerVertexNormal(m) )
462 {
463 if( pf.AddToRead(VertDesc(14))!=-1 && pf.AddToRead(VertDesc(15))!=-1 && pf.AddToRead(VertDesc(16))!=-1 )
464 pi.mask |= Mask::IOM_VERTNORMAL;
465 else // try also for Normals stored with doubles
466 if( pf.AddToRead(VertDesc(27))!=-1 && pf.AddToRead(VertDesc(28))!=-1 && pf.AddToRead(VertDesc(29))!=-1 )
467 pi.mask |= Mask::IOM_VERTNORMAL;
468
469 }
470
471 if( vcg::tri::HasPerVertexQuality(m) )
472 {
473 if( pf.AddToRead(VertDesc(4))!=-1 ||
474 pf.AddToRead(VertDesc(13))!=-1 )
475 pi.mask |= Mask::IOM_VERTQUALITY;
476 else
477 if (pf.AddToRead(VertDesc(31))!=-1)
478 pi.mask |= Mask::IOM_VERTQUALITY;
479 }
480
481 if(vcg::tri::HasPerVertexColor(m) )
482 {
483 if( pf.AddToRead(VertDesc(5))!=-1 )
484 {
485 pf.AddToRead(VertDesc(6));
486 pf.AddToRead(VertDesc(7));
487 pf.AddToRead(VertDesc(8));
488 pi.mask |= Mask::IOM_VERTCOLOR;
489 }
490 if( pf.AddToRead(VertDesc(9))!=-1 )
491 {
492 pf.AddToRead(VertDesc(10));
493 pf.AddToRead(VertDesc(11));
494 pf.AddToRead(VertDesc(12));
495 pi.mask |= Mask::IOM_VERTCOLOR;
496 }
497 if( pf.AddToRead(VertDesc(21))!=-1 )
498 {
499 hasIntensity = true;
500 pi.mask |= Mask::IOM_VERTCOLOR;
501 }
502
503 }
504 if( tri::HasPerVertexTexCoord(m) )
505 {
506 if(( pf.AddToRead(VertDesc(22))!=-1 )&& (pf.AddToRead(VertDesc(23))!=-1))
507 {
508 pi.mask |= Mask::IOM_VERTTEXCOORD;
509 }
510 if(( pf.AddToRead(VertDesc(18))!=-1 )&& (pf.AddToRead(VertDesc(19))!=-1))
511 {
512 pi.mask |= Mask::IOM_VERTTEXCOORD;
513 }
514 }
515 if(tri::HasPerVertexRadius(m))
516 {
517 if( pf.AddToRead(VertDesc(17))!=-1 )
518 pi.mask |= Mask::IOM_VERTRADIUS;
519 else if( pf.AddToRead(VertDesc(30))!=-1 )
520 pi.mask |= Mask::IOM_VERTRADIUS;
521 }
522 // se ci sono i flag per vertice ci devono essere anche i flag per faccia
523 if( pf.AddToRead(FaceDesc(1))!=-1 )
524 pi.mask |= Mask::IOM_FACEFLAGS;
525
526 if (vcg::tri::HasPerFaceNormal(m))
527 {
528 if (pf.AddToRead(FaceDesc(10)) != -1 && pf.AddToRead(FaceDesc(11)) != -1 && pf.AddToRead(FaceDesc(12)) != -1)
529 pi.mask |= Mask::IOM_FACENORMAL;
530 else if (pf.AddToRead(FaceDesc(26)) != -1 && pf.AddToRead(FaceDesc(27)) != -1 && pf.AddToRead(FaceDesc(28)) != -1)
531 pi.mask |= Mask::IOM_FACENORMAL;
532 }
533
534 if( vcg::tri::HasPerFaceQuality(m) )
535 {
536 if( pf.AddToRead(FaceDesc(2))!=-1 )
537 pi.mask |= Mask::IOM_FACEQUALITY;
538 else if (pf.AddToRead(FaceDesc(25)) != -1)
539 pi.mask |= Mask::IOM_FACEQUALITY;
540 }
541
542 if( vcg::tri::HasPerFaceColor(m) )
543 {
544 if( pf.AddToRead(FaceDesc(6))!=-1 )
545 {
546 pf.AddToRead(FaceDesc(7));
547 pf.AddToRead(FaceDesc(8));
548 pf.AddToRead(FaceDesc(9));
549 pi.mask |= Mask::IOM_FACECOLOR;
550 }
551 }
552
553
554 if( vcg::tri::HasPerWedgeTexCoord(m) )
555 {
556 if( pf.AddToRead(FaceDesc(3))!=-1 )
557 {
558 if(pf.AddToRead(FaceDesc(5))==0) {
559 multit=true; // try to read also the multi texture indicies
560 pi.mask |= Mask::IOM_WEDGTEXMULTI;
561 }
562 pi.mask |= Mask::IOM_WEDGTEXCOORD;
563 }
564 }
565
566 if( vcg::tri::HasPerFaceColor(m) || vcg::tri::HasPerVertexColor(m) || vcg::tri::HasPerWedgeColor(m) )
567 {
568 if( pf.AddToRead(FaceDesc(4))!=-1 )
569 {
570 pi.mask |= Mask::IOM_WEDGCOLOR;
571 }
572 }
573
574 // User defined descriptors
575 std::vector<PropDescriptor> VPV(pi.VertDescriptorVec.size()); // property descriptor relative al tipo LoadPly_VertexAux
576 std::vector<PropDescriptor> FPV(pi.FaceDescriptorVec.size()); // property descriptor relative al tipo LoadPly_FaceAux
577 if(pi.VertDescriptorVec.size()>0){
578 // Compute the total size needed to load additional per vertex data.
579 size_t totsz=0;
580 for(size_t i=0;i<pi.VertDescriptorVec.size();i++){
581 VPV[i] = pi.VertDescriptorVec[i];
582 VPV[i].offset1=offsetof(LoadPly_VertAux<ScalarType>,data)+totsz;
583 totsz+=pi.VertDescriptorVec[i].memtypesize();
584 if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
585 }
586 if(totsz > MAX_USER_DATA)
587 {
588 pi.status = vcg::ply::E_BADTYPE;
589 return pi.status;
590 }
591 }
592 if(pi.FaceDescriptorVec.size()>0){
593 size_t totsz=0;
594 for(size_t i=0;i<pi.FaceDescriptorVec.size();i++){
595 FPV[i] = pi.FaceDescriptorVec[i];
596 FPV[i].offset1=offsetof(LoadPly_FaceAux<ScalarType>,data)+totsz;
597 totsz+=pi.FaceDescriptorVec[i].memtypesize();
598 if( pf.AddToRead(FPV[i])==-1 ) { pi.status = pf.GetError(); return pi.status; }
599 }
600 if(totsz > MAX_USER_DATA)
601 {
602 pi.status = vcg::ply::E_BADTYPE;
603 return pi.status;
604 }
605 }
606
607 /**************************************************************/
608 /* Main Reading Loop */
609 /**************************************************************/
610 m.Clear();
611 for(size_t i=0;i<pf.elements.size();i++)
612 {
613 int n = pf.ElemNumber(i);
614
615 if( !strcmp( pf.ElemName(i),"camera" ) )
616 {
617 pf.SetCurElement(i);
618
619 LoadPly_Camera ca;
620
621 for(int j=0;j<n;++j)
622 {
623 if( pf.Read( (void *)&(ca) )==-1 )
624 {
625 pi.status = PlyInfo::E_SHORTFILE;
626 return pi.status;
627 }
628 //camera.valid = true;
629
630 // extrinsic
631 m.shot.Extrinsics.SetIdentity();
632 // view point
633 m.shot.Extrinsics.SetTra(Point3<ScalarType>( ca.view_px,ca.view_py,ca.view_pz));
634
635 // axis (i.e. rotation).
636 Matrix44<ScalarType> rm;
637 rm.SetIdentity();
638 rm[0][0] = ca.x_axisx;
639 rm[0][1] = ca.x_axisy;
640 rm[0][2] = ca.x_axisz;
641
642 rm[1][0] = ca.y_axisx;
643 rm[1][1] = ca.y_axisy;
644 rm[1][2] = ca.y_axisz;
645
646 rm[2][0] = ca.z_axisx;
647 rm[2][1] = ca.z_axisy;
648 rm[2][2] = ca.z_axisz;
649
650 m.shot.Extrinsics.SetRot(rm);
651
652 //intrinsic
653 m.shot.Intrinsics.FocalMm = ca.focal;
654 m.shot.Intrinsics.PixelSizeMm[0] = ca.scalex;
655 m.shot.Intrinsics.PixelSizeMm[1] = ca.scaley;
656 m.shot.Intrinsics.CenterPx[0] = ca.centerx;
657 m.shot.Intrinsics.CenterPx[1] = ca.centery;
658 m.shot.Intrinsics.ViewportPx[0] = ca.viewportx;
659 m.shot.Intrinsics.ViewportPx[1] = ca.viewporty;
660 m.shot.Intrinsics.k[0] = ca.k1;
661 m.shot.Intrinsics.k[1] = ca.k2;
662 m.shot.Intrinsics.k[2] = ca.k3;
663 m.shot.Intrinsics.k[3] = ca.k4;
664
665 }
666 }
667 else if( !strcmp( pf.ElemName(i),"vertex" ) )
668 {
669 int j;
670
671 pf.SetCurElement(i);
672 VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,n);
673
674 for(j=0;j<n;++j)
675 {
676 if(pi.cb && (j%1000)==0) pi.cb(j*50/n,"Vertex Loading");
677 va.a = 255;
678 if( pf.Read( (void *)&(va) )==-1 )
679 {
680 pi.status = PlyInfo::E_SHORTFILE;
681 return pi.status;
682 }
683
684 (*vi).P()[0] = va.p[0];
685 (*vi).P()[1] = va.p[1];
686 (*vi).P()[2] = va.p[2];
687
688 if( HasPerVertexFlags(m) && (pi.mask & Mask::IOM_VERTFLAGS) )
689 (*vi).Flags() = va.flags;
690
691 if( pi.mask & Mask::IOM_VERTQUALITY )
692 (*vi).Q() = (VertQualityType)va.q;
693
694 if( pi.mask & Mask::IOM_VERTNORMAL )
695 {
696 (*vi).N()[0]=va.n[0];
697 (*vi).N()[1]=va.n[1];
698 (*vi).N()[2]=va.n[2];
699 }
700
701 if( pi.mask & Mask::IOM_VERTTEXCOORD )
702 {
703 (*vi).T().P().X() = va.u;
704 (*vi).T().P().Y() = va.v;
705 }
706
707 if( pi.mask & Mask::IOM_VERTCOLOR )
708 {
709 if(hasIntensity)
710 (*vi).C().SetGrayShade(va.intensity);
711 else
712 {
713 (*vi).C()[0] = va.r;
714 (*vi).C()[1] = va.g;
715 (*vi).C()[2] = va.b;
716 (*vi).C()[3] = va.a;
717 }
718 }
719 if( pi.mask & Mask::IOM_VERTRADIUS )
720 (*vi).R() = va.radius;
721
722
723 for(size_t k=0;k<pi.VertDescriptorVec.size();k++)
724 memcpy((char *)(&*vi) + pi.VertDescriptorVec[k].offset1,
725 (char *)(&va) + VPV[k].offset1,
726 VPV[k].memtypesize());
727 ++vi;
728 }
729
730 index.resize(n);
731 for(j=0,vi=m.vert.begin();j<n;++j,++vi)
732 index[j] = &*vi;
733 }
734 else if( !strcmp( pf.ElemName(i),"edge") && (n>0) )/******************** EDGE READING *******************************/
735 {
736 assert( pi.mask & Mask::IOM_EDGEINDEX );
737 EdgeIterator ei=Allocator<OpenMeshType>::AddEdges(m,n);
738 pf.SetCurElement(i);
739 for(int j=0;j<n;++j)
740 {
741 if(pi.cb && (j%1000)==0) pi.cb(50+j*50/n,"Edge Loading");
742 if( pf.Read(&ea)==-1 )
743 {
744 pi.status = PlyInfo::E_SHORTFILE;
745 return pi.status;
746 }
747 if( ea.v1<0 || ea.v2<0 || ea.v1>=m.vn || ea.v2>=m.vn)
748 {
749 pi.status = PlyInfo::E_BAD_VERT_INDEX_EDGE;
750 return pi.status;
751 }
752 (*ei).V(0) = index[ ea.v1 ];
753 (*ei).V(1) = index[ ea.v2 ];
754 ++ei;
755 }
756 }
757 else if( !strcmp( pf.ElemName(i),"face") && (n>0) )/******************** FACE READING ****************************************/
758 {
759 int j;
760
761 FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,n);
762 pf.SetCurElement(i);
763
764 for(j=0;j<n;++j)
765 {
766 int k;
767
768 if(pi.cb && (j%1000)==0) pi.cb(50+j*50/n,"Face Loading");
769 fa.a = 255;
770 if( pf.Read(&fa)==-1 )
771 {
772 pi.status = PlyInfo::E_SHORTFILE;
773 return pi.status;
774 }
775 if(fa.size!=3)
776 { // Non triangular face are manageable ONLY if there are no Per Wedge attributes
777 if( ( pi.mask & Mask::IOM_WEDGCOLOR ) || ( pi.mask & Mask::IOM_WEDGTEXCOORD ) )
778 {
779 pi.status = PlyInfo::E_NO_3VERTINFACE;
780 return pi.status;
781 }
782 }
783
784 if(HasPolyInfo(m)) (*fi).Alloc(fa.size);
785
786 if(HasPerFaceFlags(m) &&( pi.mask & Mask::IOM_FACEFLAGS) )
787 {
788 (*fi).Flags() = fa.flags;
789 }
790
791 if (pi.mask & Mask::IOM_FACENORMAL)
792 {
793 (*fi).N()[0] = fa.n[0];
794 (*fi).N()[1] = fa.n[1];
795 (*fi).N()[2] = fa.n[2];
796 }
797
798 if( pi.mask & Mask::IOM_FACEQUALITY )
799 {
800 (*fi).Q() = (typename OpenMeshType::FaceType::QualityType) fa.q;
801 }
802
803 if( pi.mask & Mask::IOM_FACECOLOR )
804 {
805 (*fi).C()[0] = fa.r;
806 (*fi).C()[1] = fa.g;
807 (*fi).C()[2] = fa.b;
808 (*fi).C()[3] = fa.a;
809 }
810
811 if( pi.mask & Mask::IOM_WEDGTEXCOORD )
812 {
813 for(int k=0;k<3;++k)
814 {
815 (*fi).WT(k).u() = fa.texcoord[k*2+0];
816 (*fi).WT(k).v() = fa.texcoord[k*2+1];
817 if(multit) (*fi).WT(k).n() = fa.texcoordind;
818 else (*fi).WT(k).n()=0; // safely intialize texture index
819 }
820 }
821
822 if( pi.mask & Mask::IOM_WEDGCOLOR )
823 {
824 if(FaceType::HasWedgeColor()){
825 for(int k=0;k<3;++k)
826 {
827 (*fi).WC(k)[0] = (unsigned char)(fa.colors[k*3+0]*255);
828 (*fi).WC(k)[1] = (unsigned char)(fa.colors[k*3+1]*255);
829 (*fi).WC(k)[2] = (unsigned char)(fa.colors[k*3+2]*255);
830 }
831 }
832 //if(FaceType::HasFaceColor()){
833 //if(pi.mask & Mask::IOM_FACECOLOR){
834 if(HasPerFaceColor(m)) {
835 (*fi).C()[0] = (unsigned char)((fa.colors[0*3+0]*255+fa.colors[1*3+0]*255+fa.colors[2*3+0]*255)/3.0f);
836 (*fi).C()[1] = (unsigned char)((fa.colors[0*3+1]*255+fa.colors[1*3+1]*255+fa.colors[2*3+1]*255)/3.0f);
837 (*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f);
838 }
839 }
840
841 if (HasPolyInfo(m))
842 {
843 for(k=0; k<fa.size; ++k)
844 {
845 if( fa.v[k]<0 || fa.v[k]>=m.vn )
846 {
847 pi.status = PlyInfo::E_BAD_VERT_INDEX;
848 return pi.status;
849 }
850 (*fi).V(k) = index[ fa.v[k] ];
851 }
852 fi++;
853 continue;
854 }
855
856 /// Now the temporary struct 'fa' is ready to be copied into the real face '*fi'
857 /// This loop
858 for(k=0;k<3;++k)
859 {
860 if( fa.v[k]<0 || fa.v[k]>=m.vn )
861 {
862 pi.status = PlyInfo::E_BAD_VERT_INDEX;
863 return pi.status;
864 }
865 (*fi).V(k) = index[ fa.v[k] ];
866 }
867
868 // tag faux vertices of first face
869 if (fa.size>3) fi->SetF(2);
870
871 for(size_t k=0;k<pi.FaceDescriptorVec.size();k++)
872 memcpy((char *)(&(*fi)) + pi.FaceDescriptorVec[k].offset1,
873 (char *)(&fa) + FPV[k].offset1,
874 FPV[k].memtypesize());
875
876
877 ++fi;
878
879 // Non Triangular Faces Loop
880 // It performs a simple fan triangulation.
881 if(fa.size>3)
882 {
883 int curpos=int(fi-m.face.begin());
884 Allocator<OpenMeshType>::AddFaces(m,fa.size-3);
885 fi=m.face.begin()+curpos;
886 pi.mask |= Mask::IOM_BITPOLYGONAL;
887 }
888 for(int qq=0;qq<fa.size-3;++qq)
889 {
890 if(HasPolyInfo(m)) (*fi).Alloc(3);
891
892 (*fi).V(0) = index[ fa.v[0] ];
893 for(k=1;k<3;++k)
894 {
895 if( fa.v[2+qq]<0 || fa.v[2+qq]>=m.vn )
896 {
897 pi.status = PlyInfo::E_BAD_VERT_INDEX;
898 return pi.status;
899 }
900 (*fi).V(k) = index[ fa.v[1+qq+k] ];
901
902 }
903 if( pi.mask & Mask::IOM_FACEQUALITY )
904 (*fi).Q() = (typename OpenMeshType::FaceType::QualityType)
905 fa.q;
906 if( pi.mask & Mask::IOM_FACECOLOR )
907 (*fi).C() = Color4b(fa.r,fa.g,fa.b,255);
908 // tag faux vertices of extra faces
909 fi->SetF(0);
910 if(qq<(fa.size-4)) fi->SetF(2);
911
912 for(size_t k=0;k<pi.FaceDescriptorVec.size();k++)
913 memcpy((char *)(&(*fi)) + pi.FaceDescriptorVec[k].offset1,
914 (char *)(&fa) + FPV[k].offset1, FPV[k].memtypesize());
915 ++fi;
916 }
917
918 }
919 }else if( !strcmp( pf.ElemName(i),"tristrips") )//////////////////// LETTURA TRISTRIP DI STANFORD
920 {
921 int j;
922 pf.SetCurElement(i);
923 int numvert_tmp = (int)m.vert.size();
924 for(j=0;j<n;++j)
925 {
926 int k;
927 if(pi.cb && (j%1000)==0) pi.cb(50+j*50/n,"Tristrip Face Loading");
928 if( pf.Read(&tsa)==-1 )
929 {
930 pi.status = PlyInfo::E_SHORTFILE;
931 return pi.status;
932 }
933 int remainder=0;
934 for(k=0;k<tsa.size-2;++k)
935 {
936 if(pi.cb && (k%1000)==0) pi.cb(50+k*50/tsa.size,"Tristrip Face Loading");
937 if(tsa.v[k]<0 || tsa.v[k]>=numvert_tmp ) {
938 pi.status = PlyInfo::E_BAD_VERT_INDEX;
939 return pi.status;
940 }
941 if(tsa.v[k+2]==-1)
942 {
943 k+=2;
944 if(k%2) remainder=0;
945 else remainder=1;
946 continue;
947 }
948 Allocator<OpenMeshType>::AddFaces(m,1);
949 FaceType &tf =m.face.back();
950 tf.V(0) = index[ tsa.v[k+0] ];
951 tf.V(1) = index[ tsa.v[k+1] ];
952 tf.V(2) = index[ tsa.v[k+2] ];
953 if((k+remainder)%2) std::swap (tf.V(0), tf.V(1) );
954 }
955 }
956 }
957 else if( !strcmp( pf.ElemName(i),"range_grid") )//////////////////// LETTURA RANGEMAP DI STANFORD
958 {
959 //qDebug("Starting Reading of Range Grid");
960 if(RangeGridCols==0) // not initialized.
961 {
962 for(size_t co=0;co< pf.comments.size();++co)
963 {
964 std::string num_cols = "num_cols";
965 std::string num_rows = "num_rows";
966 std::string &c = pf.comments[co];
967 std::string bufstr,bufclean;
968 if( num_cols == c.substr(0,num_cols.length()) )
969 {
970 bufstr = c.substr(num_cols.length()+1);
971 RangeGridCols = atoi(bufstr.c_str());
972 }
973 if( num_rows == c.substr(0,num_rows.length()) )
974 {
975 bufstr = c.substr(num_rows.length()+1);
976 RangeGridRows = atoi(bufstr.c_str());
977 }
978 }
979 //qDebug("Rows %i Cols %i",RangeGridRows,RangeGridCols);
980 }
981 int totPnt = RangeGridCols*RangeGridRows;
982 // standard reading;
983 pf.SetCurElement(i);
984 for(int j=0;j<totPnt;++j)
985 {
986 if(pi.cb && (j%1000)==0) pi.cb(50+j*50/totPnt,"RangeMap Face Loading");
987 if( pf.Read(&rga)==-1 )
988 {
989 //qDebug("Error after loading %i elements",j);
990 pi.status = PlyInfo::E_SHORTFILE;
991 return pi.status;
992 }
993 else
994 {
995 if(rga.num_pts == 0)
996 RangeGridAuxVec.push_back(-1);
997 else
998 RangeGridAuxVec.push_back(rga.pts[0]);
999 }
1000 }
1001 //qDebug("Completed the reading of %i indexes",RangeGridAuxVec.size());
1002 tri::SparseFaceGrid(m, RangeGridAuxVec, RangeGridCols,RangeGridRows);
1003 }
1004 else
1005 {
1006 // Skippaggio elementi non gestiti
1007 int n = pf.ElemNumber(i);
1008 pf.SetCurElement(i);
1009
1010 for(int j=0;j<n;j++)
1011 {
1012 if( pf.Read(0)==-1)
1013 {
1014 pi.status = PlyInfo::E_SHORTFILE;
1015 return pi.status;
1016 }
1017 }
1018 }
1019 }
1020
1021 // Parsing texture names
1022 m.textures.clear();
1023 m.normalmaps.clear();
1024
1025 for(size_t co=0;co<pf.comments.size();++co)
1026 {
1027 std::string TFILE = "TextureFile";
1028 std::string NFILE = "TextureNormalFile";
1029 std::string &c = pf.comments[co];
1030 // char buf[256];
1031 std::string bufstr,bufclean;
1032 int n;
1033
1034 if( TFILE == c.substr(0,TFILE.length()) )
1035 {
1036 bufstr = c.substr(TFILE.length()+1);
1037 n = static_cast<int>(bufstr.length());
1038 for(int i=0;i<n;i++)
1039 if( bufstr[i]!=' ' && bufstr[i]!='\t' && bufstr[i]>32 && bufstr[i]<125 ) bufclean.push_back(bufstr[i]);
1040
1041 char buf2[255];
1042 ply::interpret_texture_name( bufclean.c_str(),filename,buf2 );
1043 m.textures.push_back( std::string(buf2) );
1044 }
1045 /*if( !strncmp(c,NFILE,strlen(NFILE)) )
1046 {
1047 strcpy(buf,c+strlen(NFILE)+1);
1048 n = strlen(buf);
1049 for(i=j=0;i<n;i++)
1050 if( buf[i]!=' ' && buf[i]!='\t' && buf[i]>32 && buf[i]<125 ) buf[j++] = buf[i];
1051
1052 buf[j] = 0;
1053 char buf2[255];
1054 __interpret_texture_name( buf,filename,buf2 );
1055 m.normalmaps.push_back( string(buf2) );
1056 }*/
1057 }
1058
1059 // vn and fn should be correct but if someone wrongly saved some deleted elements they can be wrong.
1060 m.vn = 0;
1061 for(VertexIterator vi=m.vert.begin();vi!=m.vert.end();++vi)
1062 if( ! (*vi).IsD() )
1063 ++m.vn;
1064
1065 m.fn = 0;
1066 for(FaceIterator fi=m.face.begin();fi!=m.face.end();++fi)
1067 if( ! (*fi).IsD() )
1068 ++m.fn;
1069
1070 tri::UpdateBounding<OpenMeshType>::Box(m);
1071 return 0;
1072 }
1073
1074
1075 // Caricamento camera da un ply
LoadCamera(const char * filename)1076 int LoadCamera(const char * filename)
1077 {
1078 vcg::ply::PlyFile pf;
1079 if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 )
1080 {
1081 this->pi.status = pf.GetError();
1082 return this->pi.status;
1083 }
1084
1085
1086 bool found = true;
1087 for(int i=0;i<23;++i)
1088 {
1089 if( pf.AddToRead(CameraDesc(i))==-1 )
1090 {
1091 found = false;
1092 break;
1093 }
1094 }
1095
1096 if(!found)
1097 return this->pi.status;
1098
1099 for(size_t i=0;i<pf.elements.size();i++)
1100 {
1101 int n = pf.ElemNumber(i);
1102
1103 if( !strcmp( pf.ElemName(i),"camera" ) )
1104 {
1105 pf.SetCurElement(i);
1106
1107 LoadPly_Camera ca;
1108
1109 for(int j=0;j<n;++j)
1110 {
1111 if( pf.Read( (void *)&(ca) )==-1 )
1112 {
1113 this->pi.status = PlyInfo::E_SHORTFILE;
1114 return this->pi.status;
1115 }
1116 this->camera.valid = true;
1117 this->camera.view_p[0] = ca.view_px;
1118 this->camera.view_p[1] = ca.view_py;
1119 this->camera.view_p[2] = ca.view_pz;
1120 this->camera.x_axis[0] = ca.x_axisx;
1121 this->camera.x_axis[1] = ca.x_axisy;
1122 this->camera.x_axis[2] = ca.x_axisz;
1123 this->camera.y_axis[0] = ca.y_axisx;
1124 this->camera.y_axis[1] = ca.y_axisy;
1125 this->camera.y_axis[2] = ca.y_axisz;
1126 this->camera.z_axis[0] = ca.z_axisx;
1127 this->camera.z_axis[1] = ca.z_axisy;
1128 this->camera.z_axis[2] = ca.z_axisz;
1129 this->camera.f = ca.focal;
1130 this->camera.s[0] = ca.scalex;
1131 this->camera.s[1] = ca.scaley;
1132 this->camera.c[0] = ca.centerx;
1133 this->camera.c[1] = ca.centery;
1134 this->camera.viewport[0] = ca.viewportx;
1135 this->camera.viewport[1] = ca.viewporty;
1136 this->camera.k[0] = ca.k1;
1137 this->camera.k[1] = ca.k2;
1138 this->camera.k[2] = ca.k3;
1139 this->camera.k[3] = ca.k4;
1140 }
1141 break;
1142 }
1143 }
1144
1145 return 0;
1146 }
1147
1148
LoadMask(const char * filename,int & mask)1149 static bool LoadMask(const char * filename, int &mask)
1150 {
1151 PlyInfo pi;
1152 return LoadMask(filename, mask,pi);
1153 }
LoadMask(const char * filename,int & mask,PlyInfo & pi)1154 static bool LoadMask(const char * filename, int &mask, PlyInfo &pi)
1155 {
1156 mask=0;
1157 vcg::ply::PlyFile pf;
1158 if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 )
1159 {
1160 pi.status = pf.GetError();
1161 return false;
1162 }
1163
1164 if( pf.AddToRead(VertDesc( 0))!=-1 &&
1165 pf.AddToRead(VertDesc( 1))!=-1 &&
1166 pf.AddToRead(VertDesc( 2))!=-1 ) mask |= Mask::IOM_VERTCOORD;
1167 if( pf.AddToRead(VertDesc(24))!=-1 &&
1168 pf.AddToRead(VertDesc(25))!=-1 &&
1169 pf.AddToRead(VertDesc(26))!=-1 ) mask |= Mask::IOM_VERTCOORD;
1170
1171 if( pf.AddToRead(VertDesc(14))!=-1 &&
1172 pf.AddToRead(VertDesc(15))!=-1 &&
1173 pf.AddToRead(VertDesc(16))!=-1 ) mask |= Mask::IOM_VERTNORMAL;
1174 if( pf.AddToRead(VertDesc(27))!=-1 &&
1175 pf.AddToRead(VertDesc(28))!=-1 &&
1176 pf.AddToRead(VertDesc(29))!=-1 ) mask |= Mask::IOM_VERTNORMAL;
1177
1178 if( pf.AddToRead(VertDesc( 3))!=-1 ) mask |= Mask::IOM_VERTFLAGS;
1179 if( pf.AddToRead(VertDesc( 4))!=-1 ) mask |= Mask::IOM_VERTQUALITY;
1180 if( pf.AddToRead(VertDesc(13))!=-1 ) mask |= Mask::IOM_VERTQUALITY;
1181 if( pf.AddToRead(VertDesc(17))!=-1 ) mask |= Mask::IOM_VERTRADIUS;
1182 if( pf.AddToRead(VertDesc(30))!=-1 ) mask |= Mask::IOM_VERTRADIUS;
1183 if( pf.AddToRead(VertDesc(31))!=-1 ) mask |= Mask::IOM_VERTQUALITY;
1184 if( pf.AddToRead(VertDesc( 5))!=-1 &&
1185 pf.AddToRead(VertDesc( 6))!=-1 &&
1186 pf.AddToRead(VertDesc( 7))!=-1 ) mask |= Mask::IOM_VERTCOLOR;
1187 if( pf.AddToRead(VertDesc( 9))!=-1 &&
1188 pf.AddToRead(VertDesc(10))!=-1 &&
1189 pf.AddToRead(VertDesc(11))!=-1 ) mask |= Mask::IOM_VERTCOLOR;
1190 if( pf.AddToRead(VertDesc(21))!=-1 ) mask |= Mask::IOM_VERTCOLOR;
1191
1192 if( pf.AddToRead(VertDesc(22))!=-1 &&
1193 pf.AddToRead(VertDesc(23))!=-1) mask |= Mask::IOM_VERTTEXCOORD;
1194
1195 if( pf.AddToRead(VertDesc(18))!=-1 &&
1196 pf.AddToRead(VertDesc(19))!=-1) mask |= Mask::IOM_VERTTEXCOORD;
1197
1198 if( pf.AddToRead(FaceDesc(0))!=-1 ) mask |= Mask::IOM_FACEINDEX;
1199 if( pf.AddToRead(FaceDesc(1))!=-1 ) mask |= Mask::IOM_FACEFLAGS;
1200 if( pf.AddToRead(FaceDesc(10))!=-1 &&
1201 pf.AddToRead(FaceDesc(11))!=-1 &&
1202 pf.AddToRead(FaceDesc(12))!=-1 ) mask |= Mask::IOM_FACENORMAL;
1203 if( pf.AddToRead(FaceDesc(26))!=-1 &&
1204 pf.AddToRead(FaceDesc(27))!=-1 &&
1205 pf.AddToRead(FaceDesc(28))!=-1 ) mask |= Mask::IOM_FACENORMAL;
1206 if( pf.AddToRead(FaceDesc(2))!=-1 ) mask |= Mask::IOM_FACEQUALITY;
1207 if( pf.AddToRead(FaceDesc(25))!=-1 ) mask |= Mask::IOM_FACEQUALITY;
1208 if( pf.AddToRead(FaceDesc(3))!=-1 ) mask |= Mask::IOM_WEDGTEXCOORD;
1209 if( pf.AddToRead(FaceDesc(5))!=-1 ) mask |= Mask::IOM_WEDGTEXMULTI;
1210 if( pf.AddToRead(FaceDesc(4))!=-1 ) mask |= Mask::IOM_WEDGCOLOR;
1211 if( pf.AddToRead(FaceDesc(6))!=-1 &&
1212 pf.AddToRead(FaceDesc(7))!=-1 &&
1213 pf.AddToRead(FaceDesc(8))!=-1 ) mask |= Mask::IOM_FACECOLOR;
1214
1215 return true;
1216 }
1217
1218
1219 }; // end class
1220
1221
1222 } // end namespace tri
1223 } // end namespace io
1224 } // end namespace vcg
1225
1226 #endif
1227
1228