Pipeline graphique
 Tout Structures de données Espaces de nommage Fichiers Fonctions Variables Définitions de type Ã‰numérations Valeurs énumérées Macros
PlyLoader.cpp
Aller à la documentation de ce fichier.
1 #define _CRT_SECURE_NO_WARNINGS
2 #include <math.h>
3 #include <memory.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "PlyLoader.h"
7 #include "defTypes.h"
8 #include "defUtil.h"
9 using namespace Ply;
10 
11 // structure et enum local
12 const int invlimit = 3;
13 typedef enum {
15 } Format;
16 
18 typedef struct { /* for coherence check only */
19  unsigned int a,b; // couple d'indice de face ayant une ar�te commune
20  int s; // 1 if unchanged, -1 if inversed.
21 } EDGE;
22 
24 typedef enum {
25  FieldXYZ = 0,
27  FieldToler = 2,
28  FieldCond = 3,
30 } Field;
31 
32 #ifdef _DEBUG
33 #define LOG(format,...) fprintf (stderr,"LOG %s:%s:%s - " format, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
34 #define WARN(format,...) fprintf (stderr,"Warning %s:%s:%s - " format, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
35 #define ERR(format,...) fprintf (stderr,"Error %s:%s:%s - " format, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
36 #else
37 #define LOG(format, ...)
38 #define WARN(format, ...)
39 #define ERR(format,...) fprintf (stderr,"Error %s:%s:%s - " format, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
40 #endif
41 
42 /*Test if the local int encoding is big or little endian
43 * return 0 if little,
44 * 1 if big,
45 * Note:
46 * big endian: x1234 is stored 12 in memory a+1,and 34 in memory a
47 * little endian: x1234 is stored 34 in memory a+1,and 12 in memory a
48 * endian means: what is the end (little or big) of
49 * the 16bits number which is stored at the starting address
50 * big endian: IBM Power PC, Hp PARisc, Sun Sparc
51 * little endian: Intel i386, DEC alpha
52 * network encoding is big endian
53 */
55  union {
56  unsigned short int s;
57  char c[2];
58  } un;
59  un.s = 0x0102;
60  if ((un.c[0] == 1) && (un.c[1] == 2))
61  return BigEndian; /* big endian */
62  else return LittleEndian; /* little endian */
63 }
64 
65 const char *PlyLoader::GetMask(dword m, int b0, int b1) {
66  static char str[33];
67  int n=b1-b0+1;
68  if (b0 > 0) m = m >> b0;
69  str[n+1]='0';
70  for(int i=0;i<=n;i++) {
71  str[n-i] = (m & 0x00000001 ? '1':'0');
72  m = m >> 1;
73  }
74  return str;
75 }
76 
77 const char *PlyLoader::GetMask(dword m) {
78  return GetMask(m,0,31);
79 }
80 
81 int EdgeSort(const void *x, const void *y) {
82  if (((EDGE *) x)->a > ((EDGE *) y)->a) return 1;
83  else if (((EDGE *) x)->a < ((EDGE *) y)->a) return -1;
84  else
85  {
86  if (((EDGE *) x)->b > ((EDGE *) y)->b) return 1;
87  else if (((EDGE *) x)->b < ((EDGE *) y)->b) return -1;
88  else return 0;
89  }
90 }
91 
92 /* bornes maximales */
93 float PlyLoader::MaxBound(void) {
94  float dM = 0.0;
95  for(int i=0;i<npoints;i++) {
96  if (fabs(points[i].x) > dM) dM=fabs(points[i].x);
97  if (fabs(points[i].y) > dM) dM=fabs(points[i].y);
98  if (fabs(points[i].z) > dM) dM=fabs(points[i].z);
99  }
100  return dM;
101 }
102 
103 /* test si l'orientation des normales est correcte
104 amelioration possible de la robustesse : comment avant (le plus loin dans
105 une direction donnee) mais en centrant autour de barycentre.
106 */
107 bool PlyLoader::PerformNormalCheck (float dM, float *P) {
108  int j, j0;
109  float d, dm,bx,by,bz;
110 
111  /* renormalisation du point externe */
112  d = sqrt(P[0]*P[0] + P[1]*P[1] + P[2]*P[2]);
113  P[0] *= dM/d;
114  P[1] *= dM/d;
115  P[2] *= dM/d;
116 
117  /* calcul du barycentre */
118  bx = by = bz = 0.0;
119  for(j=0;j<npoints;j++) {
120  bx += points[j].x;
121  by += points[j].y;
122  bz += points[j].z;
123  }
124  bx /= npoints;
125  by /= npoints;
126  bz /= npoints;
127 
128  /* recherche du point le plus loin du barycentre */
129  j0=0;
130  dm = 0.f;
131  for(j=0;j<npoints;j++) {
132  d = (bx - points[j].x) * (bx - points[j].x)
133  + (by - points[j].y) * (by - points[j].y)
134  + (bz - points[j].z) * (bz - points[j].z);
135  if (d > dm) {
136  dm = d;
137  j0 = j;
138  }
139  }
140 
141  /* on l'a : regarde le produit scalaire */
142  d = (points[j0].x - bx) * points[j0].nx
143  + (points[j0].y - by) * points[j0].ny
144  + (points[j0].z - bz) * points[j0].nz;
145 
146  /* retour */
147  if (d>0) return true; // succ�s
148  else return false; // �chec
149 }
150 
151 /* Main coherence check function */
153  check = CheckNotChecked;
154  /* allocation */
155  unsigned char *cor = new unsigned char[npoints];
156  memset(cor,0,npoints*sizeof(unsigned char));
157  //LOG0("Coherence check:\n");
158  /* Level 1: vertex indice is out of bounds */
159  for(int i=0;i<nfaces;i++) {
160  for (int j=0; j<faces[i].npts; j++) {
161  if (faces[i].ind[j] >= (unsigned int)npoints) {
162  check |= CheckInvalidIndices;
163  return;
164  } else cor[ faces[i].ind[j] ]++;
165  }
166  }
167 
168  /* Level 2: if a defined point doesn't belong to a face */
169  {
170  int p=0;
171  for (int i = 0; i < npoints; i++)
172  if (cor[i] == 0) p++;
173  //LOG1("\tUnconnected points: %d (vertex belonging to no face)\n", p);
174  if (p!=0) check |= CheckUnconnectedPts;
175  }
176 
177  /* Level 3&4: holes in the surface (brute force method) */
178  /* number of edges */
179  int nedges=0;
180  for (int i=0;i<npoints;i++) nedges += cor[i];
181  EDGE *edge = new EDGE[nedges];
182 
183  /* filling edge array */
184  {
185  int p = 0, j = 0;
186  for (int i = 0; i < nfaces; i++) {
187  for (j = 0; j < faces[i].npts - 1; j++) {
188  edge[p].a = faces[i].ind[j];
189  edge[p].b = faces[i].ind[j + 1];
190  edge[p].s = 1;
191  p++;
192  }
193  edge[p].a = faces[i].ind[j];
194  edge[p].b = faces[i].ind[0];
195  edge[p].s = 1;
196  p++;
197  }
198  }
199 
200  /* first indice point always smaller */
201  {
202  int p=0;
203  for (int i = 0; i < nedges; i++) {
204  if (edge[i].a > edge[i].b) {
205  p = edge[i].a;
206  edge[i].a = edge[i].b;
207  edge[i].b = p;
208  edge[i].s = -1;
209  }
210  }
211  }
212 
213  /* sorting */
214  qsort (edge, nedges, sizeof (EDGE), EdgeSort);
215 
216  /* finding holes */
217  {
218  int p = 0; // number of unshared edges
219  int q = 0; // number of inverted facets
220  int i = 0;
221  while (i + 1 < nedges) {
222  if ((edge[i].a != edge[i + 1].a) || (edge[i].b != edge[i + 1].b)) {
223  i++;
224  p++;
225  } else {
226  if (edge[i].s == edge[i + 1].s)
227  q++;
228  i += 2;
229  }
230  }
231  if (i + 1 == nedges) p++;
232 
233  //LOG1("\tUnshared edges : %d (imply holes)\n", p);
234  if (p!=0) check |= CheckUnsharedEdges;
235  //LOG1("\tInverted facets : %d (imply wrong facets orientations)\n", q);
236  if (q!=0) check |= CheckRevFacets;
237  }
238 
239  /* level 5 : orientation des normales */
240  {
241 #define NTEST 1
242  float PTEST[14][3]={
243  {+1,-1,-1},{+1,-1,+1},{+1,+1,+1},{+1,+1,-1},
244  {-1,-1,-1},{-1,-1,+1},{-1,+1,+1},{-1,+1,-1},
245  {0,0,1},{0,0,-1},{0,1,0},{0,-1,0},{1,0,0},{-1,0,0}
246  };
247  int ngood = 0, nbad = 0;
248  /* distance plus loin que le plus loin des points */
249  float dM = 1.5f * MaxBound();
250  /* renormalisation des points externes */
251  for(int i=0;i<NTEST;i++) {
252  /* renormalisation du point et mise a distance */
253  if (PerformNormalCheck(10*dM,PTEST[i])) ngood++;
254  else nbad++;
255  }
256 
257  //LOG3("\tNormal tests : %s (Good=%d, Bad=%d)\n",(nbad==0 ? "Success" : "Failed"),ngood,nbad);
258  if (nbad != 0) {
259  if (ngood <= nbad / invlimit) check |= CheckInvNormals;
260  else if (check!=0) check |= CheckBadNormals;
261  }
262  }
263 
264  /* desallocation */
265  delete [] cor;
266  delete [] edge;
267  check |= CheckCoherence;
268 }
269 
271  // quelques points lus avec leurs coordonnees
272  printf("TRACE : 10 first vertex\n");
273  for (int i=0; i<min(10,npoints); i++) {
274  printf ("%5d: ", i);
275  if (HavePos) printf("\tcoord:<%f,%f,%f>\n", points[i].x, points[i].y, points[i].z);
276  if (HaveNrm) printf("\tnorm :<%f,%f,%f>\n", points[i].nx, points[i].ny, points[i].nz);
277  if (HaveCol) printf("\tcolor:<%f %f %f>\n", points[i].r, points[i].g, points[i].b);
278  if (HaveUV) printf ("\tcolor:<%f %f>\n", points[i].u, points[i].v);
279  if (HaveTol) printf ("\tconf :%e\n", points[i].c);
280  }
281  // quelques facettes lues avec leurs coordonnees
282  printf("TRACE : 10 first polygons\n");
283  for (int i=0; i<min(10,nfaces); i++) {
284  printf ("%5d : ", i);
285  for (int j=0; j<faces[i].npts; j++)
286  printf ("%u ", faces[i].ind[j]);
287  printf ("\n");
288  }
289 }
290 
291 void PlyLoader::Dump(void) {
292  int i,j;
293  /* quelques points lus avec leurs coordonnees */
294  printf("TRACE : all vertex\n");
295  for (i = 0; i < npoints; i++) {
296  printf ("%5d: ", i);
297  printf ("\tcoord:<%f,%f,%f>\n", points[i].x, points[i].y, points[i].z);
298  }
299  /* quelques facettes lues avec leurs coordonnees */
300  printf("TRACE : all polygons\n");
301  for (i = 0; i < nfaces; i++) {
302  printf ("%5d : ", i);
303  for (j = 0; j < faces[i].npts; j++)
304  printf ("%u ", faces[i].ind[j]);
305  printf ("\n");
306  }
307 }
308 
309 /*********************************
310 Scan Ply file header
311 **********************************/
312 const float iMaxInt1 = 1.f/255, iMaxInt2 = 1.f/32768, iMaxInt4 = 1.f/2147483647UL;
313 const float iMaxUInt1 = 1.f/128, iMaxUInt2 = 1.f/65535, iMaxUInt4 = 1.f/4294967295UL;
314 bool ReadTextFloat(FILE *ptf, float &sto) { float v; int lu=fscanf(ptf,"%f",&v); sto = v; return lu==1; };
315 bool ReadTextInt1(FILE *ptf, float &sto) { int v; int lu=fscanf(ptf,"%d",&v); sto = float(v)*iMaxInt1; return lu==1; };
316 bool ReadTextInt2(FILE *ptf, float &sto) { int v; int lu=fscanf(ptf,"%d",&v); sto = float(v)*iMaxInt2; return lu==1; };
317 bool ReadTextInt4(FILE *ptf, float &sto) { int v; int lu=fscanf(ptf,"%d",&v); sto = float(v)*iMaxInt4; return lu==1; };
318 bool ReadTextUInt1(FILE *ptf, float &sto) { unsigned int v; int lu=fscanf(ptf,"%u",&v); sto = float(v)*iMaxUInt1; return lu==1; };
319 bool ReadTextUInt2(FILE *ptf, float &sto) { unsigned int v; int lu=fscanf(ptf,"%u",&v); sto = float(v)*iMaxUInt2; return lu==1; };
320 bool ReadTextUInt4(FILE *ptf, float &sto) { unsigned int v; int lu=fscanf(ptf,"%u",&v); sto = float(v)*iMaxUInt4; return lu==1; };
321 
322 bool ReadBinFloat4(FILE *ptf, float &sto) {
323  float v;
324  int lu=fread(&v,sizeof(float ),1,ptf);
325  sto = v;
326  return lu==1;
327 };
328 bool ReadBinFloat8(FILE *ptf, float &sto) { double v; int lu=fread(&v,sizeof(double),1,ptf); sto = float(v); return lu==1; };
329 bool ReadBinUInt1(FILE *ptf, float &sto) { unsigned char v; int lu=fread(&v,sizeof(unsigned char ),1,ptf); sto = float(v)*iMaxUInt1; return lu==1; };
330 bool ReadBinUInt2(FILE *ptf, float &sto) { unsigned short v; int lu=fread(&v,sizeof(unsigned short),1,ptf); sto = float(v)*iMaxUInt2; return lu==1; };
331 bool ReadBinUInt4(FILE *ptf, float &sto) { unsigned int v; int lu=fread(&v,sizeof(unsigned int ),1,ptf); sto = float(v)*iMaxUInt4; return lu==1; };
332 bool ReadBinInt1(FILE *ptf, float &sto) { char v; int lu=fread(&v,sizeof(char ),1,ptf); sto = float(v)*iMaxInt1; return lu==1; };
333 bool ReadBinInt2(FILE *ptf, float &sto) { short v; int lu=fread(&v,sizeof(short),1,ptf); sto = float(v)*iMaxInt2; return lu==1; };
334 bool ReadBinInt4(FILE *ptf, float &sto) { int v; int lu=fread(&v,sizeof(int ),1,ptf); sto = float(v)*iMaxInt4; return lu==1; };
335 
336 bool ReadSwapBinFloat4(FILE *ptf, float &sto) {
337  float v;
338  int lu=fread(&v,sizeof(float ),1,ptf);
339  unsigned int *w = (unsigned int *)&v;
340  *w = SwapByte32(*w);
341  // Swap<float>(v);
342  sto = v;
343  return lu==1;
344 };
345 bool ReadSwapBinFloat8(FILE *ptf, float &sto) { double v; int lu=fread(&v,sizeof(double),1,ptf); Swap<double>(v); sto = float(v); return lu==1; };
346 bool ReadSwapBinUInt2(FILE *ptf, float &sto) { unsigned short v; int lu=fread(&v,sizeof(unsigned short),1,ptf); Swap<unsigned short>(v); sto = float(v)*iMaxUInt2; return lu==1; };
347 bool ReadSwapBinUInt4(FILE *ptf, float &sto) { unsigned int v; int lu=fread(&v,sizeof(unsigned int ),1,ptf); Swap<unsigned int>(v); sto = float(v)*iMaxUInt4; return lu==1; };
348 bool ReadSwapBinInt2(FILE *ptf, float &sto) { short v; int lu=fread(&v,sizeof(short),1,ptf); Swap<short>(v); sto = float(v)*iMaxInt2; return lu==1; };
349 bool ReadSwapBinInt4(FILE *ptf, float &sto) { int v; int lu=fread(&v,sizeof(int ),1,ptf); Swap<int>(v); sto = float(v)*iMaxInt4; return lu==1; };
350 
351 bool PlyLoader::BuildReader(int id, int FunType, int dec, uchar &SemCount, char *type) {
352  const int nbTypes = 12;
353  char TypeStr[nbTypes][8] = { "char", "uchar", "uint8", "uint16", "uint32", "int8", "int16", "int32", "int", "float", "float32", "float64" };
354  ReadFun Fun[3][nbTypes] = {
358  };
359  // fonction de lecture
360  int FunId=0;
361  for(FunId=0;FunId<nbTypes;FunId++)
362  if (! strcmp(TypeStr[FunId],type)) break;
363  if (FunId==nbTypes) return false;
364  // remplissage de la structure
365  field[id].dec = dec;
366  field[id].readfun = Fun[FunType][FunId];
367  // s�mantique courante
368  SemCount++;
369  return true;
370 }
371 
372 /*********************************
373 Scan Ply file header
374 **********************************/
376  int mode;
377  char line[512], lineaux[512];
378  // main
379  fscanf (ptf, "%s", line);
380  if (strcmp (line, "ply")) return false;
381  fscanf (ptf, "%s", line);
382  if (strcmp (line, "format")) return false;
383  // format de fichier
384  fscanf (ptf, "%s", line);
385  if (strcmp (line, "binary_big_endian") == 0) mode = (machFMT == BigEndian ? 1 : 2);
386  else if (strcmp (line, "binary_little_endian") == 0) mode = (machFMT == LittleEndian ? 1 : 2);
387  else if (strcmp (line, "ascii") == 0) mode = 0;
388  else return false;
389  fileFMT = (mode == 0 ? TextFile : BinaryFile );
390  doswap = (mode == 2 ? true : false);
391  // nombre de points
392  do fscanf (ptf, "%s", line); while (strcmp(line, "vertex"));
393  fscanf(ptf, "%d", &npoints);
394  /* nombre de champs */
395  memset(field,0,sizeof(ReadFmt)*maxfields);
396  do fscanf (ptf, "%s", line); while (strcmp (line, "property"));
397  nfields = 0;
398  POINT_PLY P;
399  do {
400  fscanf (ptf, "%s", lineaux); /* lecture du type */
401  fscanf (ptf, "%s", line); /* lecture de la semantique */
402  if (!strcmp(line,"x")) BuildReader(nfields,mode,&(P.x)-&(P.x),HavePos, lineaux);
403  else if (!strcmp(line,"y")) BuildReader(nfields,mode,&(P.y)-&(P.x),HavePos, lineaux);
404  else if (!strcmp(line,"z")) BuildReader(nfields,mode,&(P.z)-&(P.x),HavePos, lineaux);
405  else if (!strcmp(line,"nx")) BuildReader(nfields,mode,&(P.nx)-&(P.x),HaveNrm, lineaux);
406  else if (!strcmp(line,"ny")) BuildReader(nfields,mode,&(P.ny)-&(P.x),HaveNrm, lineaux);
407  else if (!strcmp(line,"nz")) BuildReader(nfields,mode,&(P.nz)-&(P.x),HaveNrm, lineaux);
408  else if (!strcmp(line,"r") || !strcmp (line, "red" )) BuildReader(nfields,mode,&(P.r)-&(P.x),HaveCol, lineaux);
409  else if (!strcmp(line,"g") || !strcmp (line, "green")) BuildReader(nfields,mode,&(P.g)-&(P.x),HaveCol, lineaux);
410  else if (!strcmp(line,"b") || !strcmp (line, "blue" )) BuildReader(nfields,mode,&(P.b)-&(P.x),HaveCol, lineaux);
411  else if (!strcmp(line,"u")) BuildReader(nfields,mode,&(P.u)-&(P.x), HaveUV, lineaux);
412  else if (!strcmp(line,"s")) BuildReader(nfields,mode,&(P.u)-&(P.x), HaveUV, lineaux);
413  else if (!strcmp(line,"v")) BuildReader(nfields,mode,&(P.v)-&(P.y), HaveUV, lineaux);
414  else if (!strcmp(line,"t")) BuildReader(nfields,mode,&(P.v)-&(P.y), HaveUV, lineaux);
415  else if (!strcmp(line,"confidence")) BuildReader(nfields,mode,&(P.c)-&(P.x), HaveTol, lineaux);
416  else return false;
417  nfields++;
418  fscanf (ptf, "%s", line);
419  } while (! strcmp (line, "property"));
420  // skipping ...
421  while (strcmp (line, "element")) fscanf (ptf, "%s", line);
422  fscanf (ptf, "%s", line);
423  // nombre de facettes
424  fscanf (ptf, "%d", &nfaces);
425  // skipping to the end ...
426  do fscanf (ptf, "%s", line);
427  while (strcmp (line, "end_header"));
428  fread(line,1,1,ptf); // lecture du caract�re de fin de ligne (n�cessaire en binaire)
429  // success
430  return true;
431 }
432 
433 /*********************************
434 read PLY data
435 **********************************/
437  // lecture des points
438  for(int i=0;i<npoints;i++)
439  for(int j=0;j<nfields;j++)
440  if (! (*field[j].readfun)(ptf,*(&(points[i].x) + field[j].dec)))
441  return false;
442  return true;
443 }
444 
446  for (int i=0;i<nfaces;i++) {
447  if (fscanf(ptf,"%d",(int*)&(faces[i].npts)) != 1) return false;
448  if (faces[i].npts != 3) return false;
449  for (int j=0;j<faces[i].npts;j++)
450  if (fscanf(ptf,"%d",&(faces[i].ind[j])) != 1) return false;
451  }
452  return true;
453 }
454 
456  for (int i=0;i<nfaces;i++) {
457  fread( &(faces[i].npts), sizeof(unsigned char), 1, ptf);
458  if (faces[i].npts != 3) return false;
459  for (int j=0;j<faces[i].npts;j++) {
460  fread( &(faces[i].ind[j]), sizeof(int), 1, ptf);
461  if (doswap) Swap<unsigned int>(faces[i].ind[j]);
462  }
463  }
464  return true;
465 }
466 
467 /* inverse des normales aux faces et du sens de parcours */
469  int i,j;
470  int n,sw;
471  for (i=0; i<nfaces; i++) {
472  faces[i].nx = -faces[i].nx;
473  faces[i].ny = -faces[i].ny;
474  faces[i].nz = -faces[i].nz;
475  /* les normales aux faces etant calcules par produit vectoriel, le sens de
476  parcours des faces etait donc faux: on inverse aussi le sens de parcours */
477  n = faces[i].npts;
478  for(j=0;j<n/2;j++) {
479  sw = faces[i].ind[j];
480  faces[i].ind[j] = faces[i].ind[n-1-j];
481  faces[i].ind[n-1-j] = sw;
482  }
483  }
484 }
485 
486 /* test et inverse les normales aux faces si elles sont incorrectes */
488  int i,j;
489  float v;
490  unsigned char s=0;
491  /* regarde si pour la premiere face, le nombre de sommets pour lequel la normale
492  est inversee par rapport a la normale de la face */
493  for(j=0;j<faces[0].npts;j++) {
494  i = faces[0].ind[j];
495  v = faces[0].nx * points[i].nx + faces[0].ny * points[i].ny + faces[0].nz * points[i].nz;
496  if (v>0) s++;
497  }
498  if (s==0) { /* normales point-face incoherentes, on inverse */
499  InvertFaceNormalsAndIndex();
500  //LOG0("Normal processing : [vertex normal in PLY] face normals inverted.\n");
501  } else {
502  //LOG0("Normal processing : [vertex normal in PLY] face normals already correct.\n");
503  }
504 }
505 
506 /*
507 Le test d'inversion des normales a ete evalue sur les sommets.
508 */
510  //LOG0("Normal processing : vertex normals inverted.\n");
511  /* inverse les normales aux faces si besoin */
512  if (! HaveNrm) {
513  /* dans ce cas, normales et sommets sont necessairement dans le meme sens
514  puisque calculees ensembles */
515  InvertFaceNormalsAndIndex();
516  //LOG0("Normal processing : face normals inverted.\n");
517  } else {
518  /* cas particulier: les normales n'ont peut-etre pas besoin d'etre inversees */
519  InvertFaceNormalsIfNeeded();
520  }
521 }
522 
523 /* inversion inconditionnelle */
525  int i;
526  /* les normales aux sommets sont toujours inverses dans cette fonction */
527  for(i=0;i<npoints;i++) {
528  points[i].nx = -points[i].nx;
529  points[i].ny = -points[i].ny;
530  points[i].nz = -points[i].nz;
531  }
532 }
533 
534 /*********************************
535 calcul des normales
536 (faces et sommets)
537 **********************************/
539  int i, j;
540  float lg;
541  float vec1[3], vec2[3];
542 
543  /* Normales aux faces */
544  for (i=0; i<nfaces; i++) {
545  vec1[0] = points[ faces[i].ind[0] ].x - points[ faces[i].ind[1] ].x;
546  vec1[1] = points[ faces[i].ind[0] ].y - points[ faces[i].ind[1] ].y;
547  vec1[2] = points[ faces[i].ind[0] ].z - points[ faces[i].ind[1] ].z;
548 
549  vec2[0] = points[ faces[i].ind[2] ].x - points[ faces[i].ind[1] ].x;
550  vec2[1] = points[ faces[i].ind[2] ].y - points[ faces[i].ind[1] ].y;
551  vec2[2] = points[ faces[i].ind[2] ].z - points[ faces[i].ind[1] ].z;
552 
553  faces[i].nx = vec2[1] * vec1[2] - vec2[2] * vec1[1];
554  faces[i].ny = vec2[2] * vec1[0] - vec2[0] * vec1[2];
555  faces[i].nz = vec2[0] * vec1[1] - vec2[1] * vec1[0];
556 
557  lg = sqrt( faces[i].nx * faces[i].nx +
558  faces[i].ny * faces[i].ny +
559  faces[i].nz * faces[i].nz);
560  if (lg>0) {
561  faces[i].nx /= lg;
562  faces[i].ny /= lg;
563  faces[i].nz /= lg;
564  }
565  }
566 
567  /* Normales aux sommets */
568  if (! HaveNrm) { /* pas de normales associ�es aux sommets */
569  /* initialisation des normales aux points */
570  for (i = 0; i < npoints; i++) {
571  points[i].nx = 0.0f;
572  points[i].ny = 0.0f;
573  points[i].nz = 0.0f;
574  }
575 
576  /* normales aux points */
577  for (i=0; i<nfaces; i++)
578  for (j=0; j<faces[i].npts; j++) {
579  points[ faces[i].ind[j] ].nx += faces[i].nx;
580  points[ faces[i].ind[j] ].ny += faces[i].ny;
581  points[ faces[i].ind[j] ].nz += faces[i].nz;
582  }
583 
584  /* normalisation des normales aux points */
585  for (i=0; i<npoints; i++) {
586  lg = sqrt( points[i].nx * points[i].nx +
587  points[i].ny * points[i].ny +
588  points[i].nz * points[i].nz );
589  if (lg > 0.0) {
590  points[i].nx /= lg;
591  points[i].ny /= lg;
592  points[i].nz /= lg;
593  }
594  }
595  }
596 }
597 
599  faces = NULL;
600  points = NULL;
601  Init();
602 }
603 
605  Delete();
606 }
607 
608 void PlyLoader::Delete(void) {
609  SAFE_DELETE_ARRAY(points);
610  SAFE_DELETE_ARRAY(faces[0].ind);
611  SAFE_DELETE_ARRAY(faces);
612 }
613 
614 void PlyLoader::Init(void) {
615  check = CheckNotChecked;
616  npoints = nfaces = nfields = 0;
617  machFMT = WhichEndian();
618  HavePos = HaveNrm = HaveCol = HaveTol = HaveUV = 0;
619 }
620 
622  NormalCheck();
623  CoherenceCheck();
624  if (check & CheckInvNormals) InvertNormals();
625  else if (HaveNrm == 3) InvertFaceNormalsIfNeeded();
626  // voir condition pour affecter la flag FullCoherence
627 }
628 
630  float P[3]={1,1,1};
631  float dM = 10 * MaxBound();
632  if (HaveNrm) {
633  bool result = PerformNormalCheck(dM,P);
634  if (!result) InvertNormals();
635  InvertFaceNormalsIfNeeded();
636  }
637  check |= CheckNormal;
638 }
639 
640 /*********************************
641 Read a Ply file.
642 Input :
643 name : filename of the PLY file
644 npoints: (pointer) number of points
645 points : (pointer) array of points (return allocated points)
646 
647 nfaces : (pointer) number of faces
648 faces : (pointer) array of faces (return allocated faces)
649 **********************************/
650 bool PlyLoader::Load(const char *name) {
651  // opening file
652  ptf = fopen(name, "rb");
653  if (!ptf) return false;
654  // scan du l'entete du fichier PLY
655  bool s;
656  s = ReadHeader();
657  if (!s) { printf("Scan Header Failed\n"); return false; }
658  // lecture des points
659  points = new POINT_PLY[npoints];
660  memset(points,0,npoints*sizeof(POINT_PLY));
661  s = ReadPoints();
662  if (!s) { printf("Read points Failed\n"); return false; }
663  // lecture des faces
664  faces = new FACE_PLY[nfaces];
665  faces[0].ind = new unsigned int[3*nfaces];
666  for(int i=1;i<nfaces;i++) faces[i].ind = faces[i-1].ind + 3;
667  if (fileFMT == BinaryFile) s = ReadBinaryFaces();
668  else s = ReadTextFaces();
669  if (!s) { printf("Read faces Failed\n"); return false; }
670  // fin de lecture du fichier
671  fclose (ptf);
672  ptf = NULL;
673  return true;
674 }
675 
676 /*********************************
677 Normalize an object.
678 Input :
679 npoints: number of points
680 points : array of points (return allocated points)
681 **********************************/
682 inline float NormalizePoint(const float Val, const float Min, const float Max) {
683  return 2.f * (Val - Min)/(Max - Min) - 1.f;
684 }
685 
686 #define MaxMin(v,m,M) { if (v<m) m=v; if (v>M) M=v; }
687 #define NormalizePoint(v,m,M) ( 2.f*(v-m)/(M-m) - 1.f )
689  float Xmax, Ymax, Zmax, Xmin, Ymin, Zmin, Cx, Cy, Cz;
690  Cx = Xmax = Xmin = points[0].x;
691  Cy = Ymax = Ymin = points[0].y;
692  Cz = Zmax = Zmin = points[0].z;
693  for(int i=1;i<npoints;i++) {
694  MaxMin(points[i].x, Xmin, Xmax);
695  MaxMin(points[i].y, Ymin, Ymax);
696  MaxMin(points[i].z, Zmin, Zmax);
697  Cx += points[i].x;
698  Cy += points[i].y;
699  Cz += points[i].z;
700  }
701  Cx /= float(npoints);
702  Cy /= float(npoints);
703  Cz /= float(npoints);
704  float norm = max( max(Xmax-Xmin,Ymax-Ymin),Zmax-Zmin);
705  for(int i=0;i<npoints;i++) {
706  points[i].x = (points[i].x - Cx) / norm;
707  points[i].y = (points[i].y - Cy) / norm;
708  points[i].z = (points[i].z - Cz) / norm;
709  }
710 }
const dword CheckNormal
si SimpleCheck (A = v�rification des normales) a �t� effectu�
Definition: PlyLoader.h:84
unsigned int b
Definition: PlyLoader.cpp:19
void Init(void)
m�thode interne
Definition: PlyLoader.cpp:614
void ProcessNormals(void)
Recalcul des normales sur un objet.
Definition: PlyLoader.cpp:538
bool BuildReader(int, int, int, uchar &, char *)
m�thode interne
Definition: PlyLoader.cpp:351
const float iMaxUInt2
Definition: PlyLoader.cpp:313
~PlyLoader()
destructeur
Definition: PlyLoader.cpp:604
bool ReadBinFloat8(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:328
#define MaxMin(v, m, M)
Definition: PlyLoader.cpp:686
bool ReadTextFaces(void)
m�thode interne
Definition: PlyLoader.cpp:445
const dword CheckCoherence
si CoherenceCheck (B) a �t� effectu�
Definition: PlyLoader.h:85
float MaxBound(void)
m�thode interne
Definition: PlyLoader.cpp:93
#define max(a, b)
Definition: defUtil.h:30
Format
Definition: PlyLoader.cpp:13
bool ReadBinUInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:330
PlyLoader()
constructeur
Definition: PlyLoader.cpp:598
void CheckAndRepair(void)
= NormalCheck + CoherenceCheck
Definition: PlyLoader.cpp:621
incertitude
Definition: PlyLoader.cpp:28
bool ReadBinInt1(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:332
const float iMaxUInt4
Definition: PlyLoader.cpp:313
bool ReadSwapBinUInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:347
const dword CheckBadNormals
si les normales semblent invers�es (heuristique) (B)
Definition: PlyLoader.h:83
void InvertFaceNormalsIfNeeded(void)
m�thode interne
Definition: PlyLoader.cpp:487
Ply::Endian WhichEndian(void)
m�thode interne
Definition: PlyLoader.cpp:54
bool ReadPoints(void)
m�thode interne
Definition: PlyLoader.cpp:436
tolerance
Definition: PlyLoader.cpp:27
#define NormalizePoint(v, m, M)
Definition: PlyLoader.cpp:687
const float iMaxInt2
Definition: PlyLoader.cpp:312
bool ReadSwapBinInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:349
#define NTEST
bool Load(const char *name)
charge le fichier PLY et construit les structures de donn�es.
Definition: PlyLoader.cpp:650
binaire en big endian
Definition: PlyLoader.h:54
void SmartInvertNormals(void)
inverse les normales si n�cessaire: si les normales sont lues, inverse simplement les normales...
Definition: PlyLoader.cpp:509
bool ReadSwapBinFloat4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:336
#define SwapByte32(u)
Swap par décalage et masque sur 4 octets.
Definition: defTypes.h:46
position
Definition: PlyLoader.cpp:25
Namespace utilis� pour stocker les structures, �num�rations, ... du PlyLoader. ...
Definition: PlyLoader.h:7
unsigned int * ind
Definition: PlyLoader.h:40
bool ReadSwapBinUInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:346
bool ReadBinFloat4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:322
bool ReadSwapBinFloat8(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:345
void DumpSample(void)
affiche les 10 premiers sommets lus dans le fichier
Definition: PlyLoader.cpp:270
void InvertNormals(void)
m�thode interne
Definition: PlyLoader.cpp:524
bool ReadTextInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:317
const dword CheckRevFacets
si des polygones adjacents ne sont pas orient�s dans le m�me sens (B)
Definition: PlyLoader.h:81
bool ReadTextUInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:320
#define SAFE_DELETE_ARRAY(x)
Definition: defUtil.h:9
le stockage est en texte
Definition: PlyLoader.h:50
bool ReadBinUInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:331
void CoherenceCheck(void)
test de la coh�rence g�om�trique d'un objet
Definition: PlyLoader.cpp:152
const dword CheckNotChecked
constante pour les v�rifications d'une g�om�trie
Definition: PlyLoader.h:77
structure interne pour le stockage des fonctions internes de lecture
Definition: PlyLoader.h:70
Structure interne utilis�e pour les tests de coh�rence sur les faces.
Definition: PlyLoader.cpp:18
bool ReadTextFloat(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:314
int s
Definition: PlyLoader.cpp:20
bool ReadBinaryFaces(void)
m�thode interne
Definition: PlyLoader.cpp:455
bool PerformNormalCheck(float, float *)
m�thode interne
Definition: PlyLoader.cpp:107
const dword CheckInvalidIndices
si un indice utilis� n'a pas de sommet associ� (B)
Definition: PlyLoader.h:78
bool(* ReadFun)(FILE *, float &)
pointeur interne sur une fonction de lecture
Definition: PlyLoader.h:68
binaire en little endian
Definition: PlyLoader.h:55
Structure utilis�e pour lire les caract�ristiques des sommets.
Definition: PlyLoader.h:38
bool ReadTextInt1(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:315
int EdgeSort(const void *x, const void *y)
Definition: PlyLoader.cpp:81
void InvertFaceNormalsAndIndex(void)
m�thode interne
Definition: PlyLoader.cpp:468
void NormalizeObject(void)
renormalise l'objet pour qu'il soit centr� � l'origine du rep�re (local) et de largeur 1...
Definition: PlyLoader.cpp:688
unsigned int dword
Definition: defTypes.h:4
Field
pour enum�ration des champs pr�sents dans le fichier PLY lu
Definition: PlyLoader.cpp:24
const float iMaxInt4
Definition: PlyLoader.cpp:312
bool ReadBinUInt1(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:329
const int invlimit
Definition: PlyLoader.cpp:12
const int maxfields
nombre maximum de champs lus dans un fichier PLY
Definition: PlyLoader.h:65
const dword CheckInvNormals
si le sens des normales a �t� test� (B)
Definition: PlyLoader.h:82
void Delete(void)
m�thode interne
Definition: PlyLoader.cpp:608
const dword CheckUnsharedEdges
si chaque ar�te n'est pas partag�e par 2 polygones (B)
Definition: PlyLoader.h:80
bool ReadTextInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:316
unsigned char uchar
Definition: defTypes.h:5
normale
Definition: PlyLoader.cpp:26
couleur
Definition: PlyLoader.cpp:29
void NormalCheck(void)
test des normales (si elles existent)
Definition: PlyLoader.cpp:629
bool ReadBinInt4(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:334
const float iMaxUInt1
Definition: PlyLoader.cpp:313
bool ReadTextUInt1(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:318
void Dump(void)
Affiche les valeurs de tous les sommets et faces lus dans la structure. Ne change pas le r�sultat de...
Definition: PlyLoader.cpp:291
structure utilis�e pour lire un fichier au format PLY
Definition: PlyLoader.h:13
bool ReadTextUInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:319
unsigned int a
Definition: PlyLoader.cpp:19
const float iMaxInt1
Definition: PlyLoader.cpp:312
const dword CheckUnconnectedPts
si un sommet n'appartient � aucun polygone (B)
Definition: PlyLoader.h:79
bool ReadSwapBinInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:348
bool ReadBinInt2(FILE *ptf, float &sto)
Definition: PlyLoader.cpp:333
bool ReadHeader(void)
m�thode interne
Definition: PlyLoader.cpp:375
#define min(a, b)
Definition: defUtil.h:29
const char * GetMask(dword, int, int)
m�thode interne
Definition: PlyLoader.cpp:65
le stockage est en binaire
Definition: PlyLoader.h:49
Endian
Enum pour le type de stockage des donn�es en binaire.
Definition: PlyLoader.h:53