00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 #include <assert.h>
00046 #include <math.h>
00047 #include <stdio.h>
00048 
00049 #include "VRender.h"
00050 #include "ParserGL.h"
00051 
00052 using namespace vrender ;
00053 using namespace std;
00054 
00055 class ParserUtils
00056 {
00057         public:
00058                 static void NormalizeBufferCoordinates(GLint size, GLfloat * buffer, GLfloat MaxSize, GLfloat& zmin, GLfloat& zmax) ;
00059 
00060                 static PtrPrimitive checkPoint(Point *& P);
00061                 static PtrPrimitive checkSegment(Segment *& P);
00062                 static PtrPrimitive checkPolygon(Polygone *& P);
00063 
00064                 static void ComputeBufferBB(GLint size, GLfloat * buffer,
00065                                 GLfloat & xmin, GLfloat & xmax,
00066                                 GLfloat & ymin, GLfloat & ymax,
00067                                 GLfloat & zmin, GLfloat & zmax) ;
00068 
00069         private:
00070                 static void print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer) ;
00071                 static void debug_printBuffer(GLint size, GLfloat *buffer) ;
00072 
00073                 static void NormalizePrimitiveCoordinates(GLfloat * & loc,GLfloat MaxSize,GLfloat zmin,GLfloat zmax) ;
00074                 static void ComputePrimitiveBB( GLfloat * & loc,
00075                                 GLfloat & xmin,GLfloat & xmax,
00076                                 GLfloat & ymin,GLfloat & ymax,
00077                                 GLfloat & zmin,GLfloat & zmax);
00078 
00079                 static const char *nameOfToken(int token);
00080 
00081                 static const double EGALITY_EPS ;
00082 };
00083 
00084 const double ParserUtils::EGALITY_EPS = 0.00001 ;
00085 
00086 void ParserGL::parseFeedbackBuffer(     GLfloat *buffer,int size,
00087                                                                                                 std::vector<PtrPrimitive>& primitive_tab,
00088                                                                                                 VRenderParams& vparams)
00089 {
00090         int token;
00091         int nvertices = 0 ;
00092         nb_lines = 0 ;
00093         nb_polys = 0 ;
00094         nb_points = 0 ;
00095         nb_degenerated_lines = 0 ;
00096         nb_degenerated_polys = 0 ;
00097         nb_degenerated_points = 0 ;
00098 
00099         
00100 
00101         _xmin = FLT_MAX ;
00102         _ymin = FLT_MAX ;
00103         _zmin = FLT_MAX ;
00104         _xmax = -FLT_MAX ;
00105         _ymax = -FLT_MAX ;
00106         _zmax = -FLT_MAX ;
00107 
00108         ParserUtils::ComputeBufferBB(size, buffer, _xmin,_xmax,_ymin,_ymax,_zmin,_zmax) ;
00109 
00110 #ifdef DEBUGEPSRENDER
00111         printf("Buffer bounding box: %f %f %f %f %f %f\n",xmin,xmax,ymin,ymax,zmin,zmax) ;
00112 #endif
00113         float Zdepth = max(_ymax-_ymin,_xmax-_xmin) ;
00114         ParserUtils::NormalizeBufferCoordinates(size,buffer,Zdepth,_zmin,_zmax) ;
00115 
00116         
00117         GLfloat *end = buffer + size;
00118 
00119         GLfloat *loc = buffer ;
00120         int next_step = 0 ;
00121         int N = size/200 + 1 ;
00122 
00123         while (loc < end)
00124         {
00125                 token = int(0.5f + *loc) ;
00126                 loc++;
00127 
00128                 if((end-loc)/N >= next_step)
00129                         vparams.progress((end-loc)/(float)size, QGLViewer::tr("Parsing feedback buffer.")), ++next_step ;
00130 
00131                 switch (token)
00132                 {
00133                         case GL_LINE_TOKEN:
00134                         case GL_LINE_RESET_TOKEN:
00135                                 {
00136                                         Segment *S = new Segment(Feedback3DColor(loc),Feedback3DColor(loc+Feedback3DColor::sizeInBuffer())) ;
00137 
00138                                         primitive_tab.push_back(ParserUtils::checkSegment(S)) ;
00139 
00140                                         if(S == NULL)
00141                                                 nb_degenerated_lines++ ;
00142 
00143                                         nb_lines++ ;
00144                                         loc += 2*Feedback3DColor::sizeInBuffer();
00145                                 }
00146                                 break;
00147 
00148                         case GL_POLYGON_TOKEN:
00149                                 {
00150                                         nvertices = int(0.5f + *loc) ;
00151                                         loc++;
00152 
00153                                         std::vector<Feedback3DColor> verts ;
00154 
00155                                         for(int i=0;i<nvertices;++i)
00156                                                 verts.push_back(Feedback3DColor(loc)),loc+=Feedback3DColor::sizeInBuffer() ;
00157 
00158                                         Polygone *P = new Polygone(verts) ;
00159 
00160                                         primitive_tab.push_back(ParserUtils::checkPolygon(P)) ;
00161 
00162                                         if(P == NULL)
00163                                                 nb_degenerated_polys++ ;
00164 
00165                                         nb_polys++ ;
00166                                 }
00167                                 break ;
00168 
00169                         case GL_POINT_TOKEN:
00170                                 {
00171                                         Point *Pt = new Point(Feedback3DColor(loc)) ;
00172 
00173                                         primitive_tab.push_back(Pt);
00174 
00175                                         if(Pt == NULL)
00176                                                 nb_degenerated_points++ ;
00177 
00178                                         nb_points++ ;
00179                                         loc += Feedback3DColor::sizeInBuffer();
00180                                 }
00181                                 break;
00182                         default:
00183                                 break;
00184                 }
00185         }
00186 
00187 }
00188 
00189 
00190 
00191 
00192 PtrPrimitive ParserUtils::checkPoint(Point *& P)
00193 {
00194         return P ;
00195 }
00196 
00197 PtrPrimitive ParserUtils::checkSegment(Segment *& P)
00198 {
00199         if((P->vertex(0) - P->vertex(1)).infNorm() < EGALITY_EPS)
00200         {
00201                 Point *pp = new Point(P->sommet3DColor(0)) ;
00202                 delete P ;
00203                 P = NULL ;
00204 
00205                 return checkPoint(pp) ;
00206         }
00207 
00208         return P ;
00209 }
00210 
00211 PtrPrimitive ParserUtils::checkPolygon(Polygone *& P)
00212 {
00213         if(P->nbVertices() != 3)
00214         {
00215                 cout << "unexpected case: Polygon with " << P->nbVertices() << " vertices !" << endl ;
00216                 delete P ;
00217                 return NULL ;
00218         }
00219 
00220         if(P->FlatFactor() < FLAT_POLYGON_EPS)
00221         {
00222                 
00223 
00224                 int n = P->nbVertices() ;
00225 
00226                 for(int i=0;i<n;++i)
00227                         if( (P->vertex(i) - P->vertex((i+1)%n)).norm() > EGALITY_EPS)
00228                         {
00229                                 Segment *pp = new Segment(P->sommet3DColor((i+1)%n),P->sommet3DColor((i+2)%n)) ;
00230                                 delete P ;
00231                                 P = NULL ;
00232 
00233                                 return checkSegment(pp) ;
00234                         }
00235 
00236                 Point *pp = new Point(P->sommet3DColor(0)) ;
00237                 delete P ;
00238                 P = NULL ;
00239 
00240                 return checkPoint(pp) ;
00241         }
00242 
00243         
00244 
00245         return P ;
00246 }
00247 
00248 
00249 
00250 
00251 void ParserUtils::print3DcolorVertex(GLint size, GLint * count, GLfloat * buffer)
00252 {
00253         int i;
00254 
00255         printf("  ");
00256         for (i = 0; i < Feedback3DColor::sizeInBuffer(); i++)
00257         {
00258                 printf("%4.2f ", buffer[size - (*count)]);
00259                 *count = *count - 1;
00260         }
00261         printf("\n");
00262 }
00263 
00264 void ParserUtils::debug_printBuffer(GLint size, GLfloat * buffer)
00265 {
00266         GLint count;
00267         int token, nvertices;
00268 
00269         count = size;
00270         while (count) {
00271                 token = int(buffer[size - count]);
00272                 count--;
00273                 switch (token)
00274                 {
00275                         case GL_PASS_THROUGH_TOKEN:
00276                                 printf("GL_PASS_THROUGH_TOKEN\n");
00277                                 printf("  %4.2f\n", buffer[size - count]);
00278                                 count--;
00279                                 break;
00280                         case GL_POINT_TOKEN:
00281                                 printf("GL_POINT_TOKEN\n");
00282                                 print3DcolorVertex(size, &count, buffer);
00283                                 break;
00284                         case GL_LINE_TOKEN:
00285                                 printf("GL_LINE_TOKEN\n");
00286                                 print3DcolorVertex(size, &count, buffer);
00287                                 print3DcolorVertex(size, &count, buffer);
00288                                 break;
00289                         case GL_LINE_RESET_TOKEN:
00290                                 printf("GL_LINE_RESET_TOKEN\n");
00291                                 print3DcolorVertex(size, &count, buffer);
00292                                 print3DcolorVertex(size, &count, buffer);
00293                                 break;
00294                         case GL_POLYGON_TOKEN:
00295                                 printf("GL_POLYGON_TOKEN\n");
00296                                 nvertices = int(buffer[size - count]) ;
00297                                 count--;
00298                                 for (; nvertices > 0; nvertices--)
00299                                         print3DcolorVertex(size, &count, buffer);
00300                 }
00301         }
00302 }
00303 
00304 void ParserUtils::NormalizePrimitiveCoordinates(GLfloat * & loc,GLfloat MaxSize,GLfloat zmin,GLfloat zmax)
00305 {
00306         int token;
00307         int nvertices, i;
00308 
00309         token = int(*loc) ;
00310         loc++;
00311         int size = Feedback3DColor::sizeInBuffer() ;
00312 
00313         switch (token)
00314         {
00315                 case GL_LINE_RESET_TOKEN:
00316                 case GL_LINE_TOKEN:
00317                         {
00318                                 for (i = 0; i < 2; i++)
00319                                         (loc+size*i)[2] = ((loc+size*i)[2] - zmin)/(zmax-zmin)*MaxSize ;
00320 
00321                                 loc += 2*size;          
00322                                 break;
00323                         }
00324                 case GL_POLYGON_TOKEN:
00325                         {
00326                                 nvertices = int(*loc) ;
00327                                 loc++;
00328 
00329                                 for (i = 0; i < nvertices; i++)
00330                                         (loc+size*i)[2] = ((loc+size*i)[2] - zmin)/(zmax-zmin)*MaxSize ;
00331 
00332                                 loc += nvertices * size;  
00333                                 break;
00334                         }
00335                 case GL_POINT_TOKEN:
00336                         {
00337                                 loc[2] = (loc[2] - zmin)/(zmax-zmin)*MaxSize ;
00338 
00339                                 loc += size;           
00340                                 break;
00341                         }
00342                 default:
00343                         
00344 #ifdef DEBUGEPSRENDER
00345                         printf("%s (%d) not handled yet. Sorry.\n", ParserUtils::nameOfToken(token), token);
00346 #endif
00347                         ;
00348         }
00349 }
00350 
00351 void ParserUtils::ComputePrimitiveBB(GLfloat * & loc,GLfloat & xmin,GLfloat & xmax,GLfloat & ymin,GLfloat & ymax, GLfloat & zmin,GLfloat & zmax)
00352 {
00353         int token;
00354         int nvertices, i;
00355 
00356         token = int(*loc) ;
00357         loc++;
00358         int size = Feedback3DColor::sizeInBuffer() ;
00359 
00360         switch (token)
00361         {
00362                 case GL_LINE_RESET_TOKEN:
00363                 case GL_LINE_TOKEN:
00364                         {
00365                                 for (i = 0; i < 2; i++)
00366                                 {
00367                                         Feedback3DColor f(loc+size*i) ;
00368 
00369                                         if(f.x() < xmin) xmin = GLfloat(f.x()) ;
00370                                         if(f.y() < ymin) ymin = GLfloat(f.y()) ;
00371                                         if(f.z() < zmin) zmin = GLfloat(f.z()) ;
00372                                         if(f.x() > xmax) xmax = GLfloat(f.x()) ;
00373                                         if(f.y() > ymax) ymax = GLfloat(f.y()) ;
00374                                         if(f.z() > zmax) zmax = GLfloat(f.z()) ;
00375                                 }
00376 
00377                                 loc += 2*size;          
00378 
00379                                 break;
00380                         }
00381                 case GL_POLYGON_TOKEN:
00382                         {
00383                                 nvertices = int(*loc) ;
00384                                 loc++;
00385 
00386                                 for (i = 0; i < nvertices; i++)
00387                                 {
00388                                         Feedback3DColor f(loc+size*i) ;
00389 
00390                                         if(f.x() < xmin) xmin = GLfloat(f.x()) ;
00391                                         if(f.y() < ymin) ymin = GLfloat(f.y()) ;
00392                                         if(f.z() < zmin) zmin = GLfloat(f.z()) ;
00393                                         if(f.x() > xmax) xmax = GLfloat(f.x()) ;
00394                                         if(f.y() > ymax) ymax = GLfloat(f.y()) ;
00395                                         if(f.z() > zmax) zmax = GLfloat(f.z()) ;
00396                                 }
00397 
00398                                 loc += nvertices * size;  
00399 
00400                                 break;
00401                         }
00402                 case GL_POINT_TOKEN:
00403                         {
00404                                 Feedback3DColor f(loc) ;
00405 
00406                                 if(f.x() < xmin) xmin = GLfloat(f.x()) ;
00407                                 if(f.y() < ymin) ymin = GLfloat(f.y()) ;
00408                                 if(f.z() < zmin) zmin = GLfloat(f.z()) ;
00409                                 if(f.x() > xmax) xmax = GLfloat(f.x()) ;
00410                                 if(f.y() > ymax) ymax = GLfloat(f.y()) ;
00411                                 if(f.z() > zmax) zmax = GLfloat(f.z()) ;
00412 
00413                                 loc += size;           
00414 
00415                                 break;
00416                         }
00417                 default:
00418                         
00419 #ifdef DEBUGEPSRENDER
00420                         printf("Incomplete implementation.  Unexpected token (%d).\n", token);
00421 #endif
00422                         ;
00423         }
00424 }
00425 
00426 void ParserUtils::NormalizeBufferCoordinates(GLint size, GLfloat * buffer, GLfloat MaxSize, GLfloat& zmin,GLfloat& zmax)
00427 {
00428         GLfloat *loc, *end;
00429 
00430         if(zmax == zmin)
00431         {
00432 #ifdef DEBUGEPSRENDER
00433                 printf("Warning: zmin = zmax in NormalizePrimitiveCoordinates\n") ;
00434 #endif
00435                 return ;
00436         }
00437 
00438         loc = buffer;
00439         end = buffer + size;
00440 
00441         while (loc < end)
00442                 NormalizePrimitiveCoordinates(loc,MaxSize,zmin,zmax);
00443 
00444         zmin = 0.0 ;
00445         zmax = MaxSize ;
00446 }
00447 
00448 void ParserUtils::ComputeBufferBB(GLint size, GLfloat * buffer,
00449                      GLfloat & xmin, GLfloat & xmax,
00450                      GLfloat & ymin, GLfloat & ymax,
00451                      GLfloat & zmin, GLfloat & zmax)
00452 {
00453         GLfloat *loc, *end;
00454 
00455         loc = buffer;
00456         end = buffer + size;
00457 
00458         while (loc < end)
00459                 ComputePrimitiveBB(loc,xmin,xmax,ymin,ymax,zmin,zmax);
00460 }
00461 
00462 typedef struct _DepthIndex {
00463   GLfloat *ptr;
00464   GLfloat depth;
00465 } DepthIndex;
00466 
00467 const char *ParserUtils::nameOfToken(int token)
00468 {
00469         switch(token)
00470         {
00471                 case GL_PASS_THROUGH_TOKEN:     return "GL_PASS_THROUGH_TOKEN" ;
00472                 case GL_POINT_TOKEN:                    return "GL_POINT_TOKEN" ;
00473                 case GL_LINE_TOKEN:                             return "GL_LINE_TOKEN" ;
00474                 case GL_POLYGON_TOKEN:                  return "GL_POLYGON_TOKEN" ;
00475                 case GL_BITMAP_TOKEN:                   return "GL_BITMAP_TOKEN" ;
00476                 case GL_DRAW_PIXEL_TOKEN:               return "GL_DRAW_PIXEL_TOKEN" ;
00477                 case GL_COPY_PIXEL_TOKEN:               return "GL_COPY_PIXEL_TOKEN" ;
00478                 case GL_LINE_RESET_TOKEN:               return "GL_LINE_RESET_TOKEN" ;
00479                 default:
00480                                                                                                 return "(Unidentified token)" ;
00481         }
00482 }
00483