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