Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

PLYFile.cc

Go to the documentation of this file.
00001 /*
00002     File:       PLYFile.cc
00003  
00004     Function:   
00005  
00006     Authors:    Greg Turk, Andrew Willmott
00007  
00008     Notes:      
00009 */
00010 
00011 #include "ply.h"
00012 #include "gcl/SceneLang.h"
00013 #include "gcl/VecUtil.h"
00014 
00015 /*
00016  
00017     Based on example programs by:
00018  
00019     Greg Turk
00020  
00021     -----------------------------------------------------------------------
00022  
00023     Copyright (c) 1998 Georgia Institute of Technology.  All rights reserved.   
00024       
00025     Permission to use, copy, modify and distribute this software and its   
00026     documentation for any purpose is hereby granted without fee, provided   
00027     that the above copyright notice and this permission notice appear in   
00028     all copies of this software and that you do not sell the software.   
00029       
00030     THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,   
00031     EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY   
00032     WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
00033  
00034 */
00035 
00036 /* user's vertex and face definitions for a polygonal object */
00037 
00038 struct Vertex
00039 {
00040     float x, y, z;
00041     float nx, ny, nz;
00042     unsigned char r, g, b;
00043     void *other_props;         /* other properties */
00044 };
00045 
00046 struct Face
00047 {
00048     unsigned char nverts;      /* number of vertex indices in list */
00049     int *verts;                /* vertex index list */
00050     void *other_props;         /* other properties */
00051 };
00052 
00053 struct TriStrips
00054 {
00055     int nverts;      /* number of vertex indices in list */
00056     int *verts;                /* vertex index list */
00057     void *other_props;         /* other properties */
00058 };
00059 
00060 char *elem_names[] = { /* list of the kinds of elements in the user's object */
00061     "vertex", "face", "tristrips"
00062 };
00063 
00064 PlyProperty vert_props[] = { /* list of property information for a vertex */
00065     {"x", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, x), 0, 0, 0, 0},
00066     {"y", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, y), 0, 0, 0, 0},
00067     {"z", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, z), 0, 0, 0, 0},
00068     {"nx", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, nx), 0, 0, 0, 0},
00069     {"ny", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, ny), 0, 0, 0, 0},
00070     {"nz", PLY_FLOAT, PLY_FLOAT, offsetof(Vertex, nz), 0, 0, 0, 0},
00071     {"red", PLY_UCHAR, PLY_UCHAR, offsetof(Vertex, r), 0, 0, 0, 0},
00072     {"green", PLY_UCHAR, PLY_UCHAR, offsetof(Vertex, g), 0, 0, 0, 0},
00073     {"blue", PLY_UCHAR, PLY_UCHAR, offsetof(Vertex, b), 0, 0, 0, 0},
00074 };
00075 
00076 PlyProperty face_props[] = { /* list of property information for a vertex */
00077     {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face, verts),
00078      1, PLY_UCHAR, PLY_UCHAR, offsetof(Face, nverts)},
00079 };
00080 
00081 PlyProperty tristrip_props[] = { /* list of property information for a vertex */
00082     {"vertex_indices", PLY_INT, PLY_INT, offsetof(TriStrips, verts),
00083      1, PLY_INT, PLY_INT, offsetof(TriStrips, nverts)},
00084 };
00085 
00086 /*** the PLY object ***/
00087 
00088 static int nverts, nfaces, ntristrips;
00089 static Vertex *vlist;
00090 static Face *flist;
00091 static TriStrips *tslist;
00092 static PlyOtherElems *other_elements = NULL;
00093 static PlyOtherProp *vert_other, *face_other, *tristrip_other;
00094 static int nelems;
00095 static char **elist;
00096 static int num_comments;
00097 static char **comments;
00098 static int num_obj_info;
00099 static char **obj_info;
00100 static int file_type;
00101 
00102 static int has_normals, has_rgb;   /* are normals in PLY file? */
00103 
00104 
00105 /******************************************************************************
00106 Read in the PLY file from standard in.
00107 ******************************************************************************/
00108 
00109 void read_file(FILE *file)
00110 {
00111     int         i, j, k;
00112     PlyFile     *ply;
00113     int         nprops;
00114     int         num_elems;
00115     PlyProperty **plist;
00116     char        *elem_name;
00117     float       version;
00118 
00119 
00120     /*** Read in the original PLY object ***/
00121 
00122 
00123     ply = ply_read (file, &nelems, &elist);
00124     ply_get_info (ply, &version, &file_type);
00125 
00126     for (i = 0; i < nelems; i++)
00127     {
00128 
00129         /* get the description of the first element */
00130         elem_name = elist[i];
00131         plist = ply_get_element_description (ply, elem_name, &num_elems, &nprops);
00132 
00133         if (equal_strings ("vertex", elem_name))
00134         {
00135 
00136             /* see if vertex holds any normal information */
00137             has_normals = has_rgb = 0;
00138             for (j = 0; j < nprops; j++)
00139             {
00140                 if (equal_strings ("nx", plist[j]->name)) has_normals = 1;
00141                 if (equal_strings ("red", plist[j]->name)) has_rgb = 1;
00142             }
00143 
00144             /* create a vertex list to hold all the vertices */
00145             vlist = (Vertex *) malloc (sizeof (Vertex) * num_elems);
00146             nverts = num_elems;
00147 
00148             /* set up for getting vertex elements */
00149 
00150             ply_get_property (ply, elem_name, &vert_props[0]);
00151             ply_get_property (ply, elem_name, &vert_props[1]);
00152             ply_get_property (ply, elem_name, &vert_props[2]);
00153             if (has_normals)
00154             {
00155                 ply_get_property (ply, elem_name, &vert_props[3]);
00156                 ply_get_property (ply, elem_name, &vert_props[4]);
00157                 ply_get_property (ply, elem_name, &vert_props[5]);
00158             }
00159             if (has_rgb)
00160             {
00161                 ply_get_property (ply, elem_name, &vert_props[6]);
00162                 ply_get_property (ply, elem_name, &vert_props[7]);
00163                 ply_get_property (ply, elem_name, &vert_props[8]);
00164             }
00165             vert_other = ply_get_other_properties (ply, elem_name,
00166                                                    offsetof(Vertex, other_props));
00167 
00168             /* grab all the vertex elements */
00169             for (j = 0; j < num_elems; j++)
00170                 ply_get_element (ply, (void *) (vlist + j));
00171         }
00172         else if (equal_strings ("face", elem_name))
00173         {
00174 
00175             /* create a list to hold all the face elements */
00176             flist = (Face *) malloc (sizeof(Face) * num_elems);
00177             nfaces = num_elems;
00178 
00179             /* set up for getting face elements */
00180 
00181             ply_get_property (ply, elem_name, &face_props[0]);
00182             face_other = ply_get_other_properties (ply, elem_name,
00183                                                    offsetof(Face, other_props));
00184 
00185             /* grab all the face elements */
00186             for (j = 0; j < num_elems; j++)
00187                 ply_get_element (ply, (void *) (flist + j));
00188         }
00189         else if (equal_strings ("tristrips", elem_name))
00190         {
00191 
00192             /* create a list to hold all the tristrip elements */
00193             tslist = (TriStrips *) malloc (sizeof(TriStrips) * num_elems);
00194             ntristrips = num_elems;
00195 
00196             /* set up for getting tristrip elements */
00197 
00198             ply_get_property (ply, elem_name, &tristrip_props[0]);
00199             tristrip_other = ply_get_other_properties (ply, elem_name,
00200                              offsetof(TriStrips, other_props));
00201 
00202             /* grab all the tristrip elements */
00203             for (j = 0; j < num_elems; j++)
00204                 ply_get_element (ply, (void *) (tslist + j));
00205         }
00206         else
00207             other_elements = ply_get_other_element (ply, elem_name, num_elems);
00208     }
00209 
00210     comments = ply_get_comments (ply, &num_comments);
00211     obj_info = ply_get_obj_info (ply, &num_obj_info);
00212 
00213     ply_close (ply);
00214 }
00215 
00216 
00217 /******************************************************************************
00218 Write out the PLY file to standard out.
00219 ******************************************************************************/
00220 
00221 write_file()
00222 {
00223     int i, j, k;
00224     PlyFile *ply;
00225     int num_elems;
00226     char *elem_name;
00227 
00228     /*** Write out the final PLY object ***/
00229 
00230 
00231     ply = ply_write (stdout, 3, elem_names, file_type);
00232 
00233 
00234     /* describe what properties go into the vertex and face elements */
00235 
00236     ply_element_count (ply, "vertex", nverts);
00237     ply_describe_property (ply, "vertex", &vert_props[0]);
00238     ply_describe_property (ply, "vertex", &vert_props[1]);
00239     ply_describe_property (ply, "vertex", &vert_props[2]);
00240     if (has_normals)
00241     {
00242         ply_describe_property (ply, "vertex", &vert_props[3]);
00243         ply_describe_property (ply, "vertex", &vert_props[4]);
00244         ply_describe_property (ply, "vertex", &vert_props[5]);
00245     }
00246     ply_describe_other_properties (ply, vert_other, offsetof(Vertex, other_props));
00247 
00248     ply_element_count (ply, "face", nfaces);
00249     ply_describe_property (ply, "face", &face_props[0]);
00250     ply_describe_other_properties (ply, face_other, offsetof(Face, other_props));
00251 
00252     ply_describe_other_elements (ply, other_elements);
00253 
00254     for (i = 0; i < num_comments; i++)
00255         ply_put_comment (ply, comments[i]);
00256 
00257     for (i = 0; i < num_obj_info; i++)
00258         ply_put_obj_info (ply, obj_info[i]);
00259 
00260     ply_header_complete (ply);
00261 
00262     /* set up and write the vertex elements */
00263     ply_put_element_setup (ply, "vertex");
00264     for (i = 0; i < nverts; i++)
00265         ply_put_element (ply, (void *) (vlist + i));
00266 
00267     /* set up and write the face elements */
00268     ply_put_element_setup (ply, "face");
00269     for (i = 0; i < nfaces; i++)
00270         ply_put_element (ply, (void *) (flist + i));
00271 
00272     ply_put_other_elements (ply);
00273 
00274     /* close the PLY file */
00275     ply_close (ply);
00276 }
00277 
00278 
00279 
00280 // --- GCL stuff -------------------------------
00281 
00282 Void AccumNormals(
00283     Int tri[3],
00284     PointList   &points,
00285     NormalList  &normals,
00286     ScalarList  &areas
00287 )
00288 {
00289     Vector  normal;
00290     GCLReal normalLen;
00291 
00292     CalcTriAreaNormal(
00293         points[tri[0]],
00294         points[tri[1]],
00295         points[tri[2]],
00296         normal
00297     );
00298 
00299     normal *= 0.5;
00300     normalLen = len(normal);
00301 
00302     normals[tri[0]] += normal;
00303     normals[tri[1]] += normal;
00304     normals[tri[2]] += normal;
00305     areas[tri[0]] += normalLen;
00306     areas[tri[1]] += normalLen;
00307     areas[tri[2]] += normalLen;
00308 }
00309 
00310 Void MakeNormals()
00311 {
00312     scPoints    *sp = SL_GET(Points);
00313     scNormals   *sn = new scNormals;
00314     NormalList  &normals = *sn;
00315     PointList   &points = *sp;
00316     ScalarList  areas(nverts);
00317     Int         i, j;
00318     Int         tri[3], triStripLen;
00319 
00320     normals.SetSize(nverts);
00321     normals.ClearTo(vl_0);
00322     areas.ClearTo(0.0);
00323 
00324     if (nfaces > 0)
00325         for (i = 0; i < nfaces; i++)
00326         {
00327             Face    *face = flist + i;
00328 
00329             tri[0] = face->verts[face->nverts - 2];
00330             tri[1] = face->verts[face->nverts - 1];
00331             for (j = 0; j < face->nverts; j++)
00332             {
00333                 tri[2] = face->verts[j];
00334                 AccumNormals(tri, points, normals, areas);
00335                 tri[0] = tri[1];
00336                 tri[1] = tri[2];
00337             }
00338         }
00339 
00340     if (ntristrips > 0)
00341     {
00342         for (i = 0; i < ntristrips; i++)
00343         {
00344             TriStrips   *tristrip = tslist + i;
00345 
00346             triStripLen = 0;
00347 
00348             for (j = 0; j < tristrip->nverts; j++)
00349                 if (tristrip->verts[j] == -1)
00350                     triStripLen = 0;
00351                 else
00352                 {
00353                     triStripLen++;
00354                     if (triStripLen < 3)
00355                         continue;
00356                     else if (triStripLen % 2)
00357                     {
00358                         tri[0] = tristrip->verts[j - 2];
00359                         tri[1] = tristrip->verts[j - 1];
00360                     }
00361                     else
00362                     {
00363                         tri[0] = tristrip->verts[j - 1];
00364                         tri[1] = tristrip->verts[j - 2];
00365                     }
00366                     tri[2] = tristrip->verts[j];
00367 
00368                     AccumNormals(tri, points, normals, areas);
00369                 }
00370         }
00371     }
00372 
00373     for (i = 0; i < normals.NumItems(); i++)
00374     {
00375         if (areas[i] > 0.0)
00376             normals[i] /= areas[i];
00377     }
00378 
00379     slAttribute(sn);
00380 }
00381 
00382 scScenePtr ParsePLYFile(const Char *filename)
00383 {
00384     FILE *plyFile;
00385     scScenePtr  result;
00386     Int i, j;
00387 
00388     plyFile = fopen(filename, "r");
00389     read_file(plyFile);
00390     // ply does the close??? hard to tell
00391 
00392     cerr << nfaces << " faces" << endl;
00393     cerr << ntristrips << " triangle strips" << endl;
00394     cerr << nverts << " vertices" << endl;
00395     cerr << "converting..." << endl;
00396 
00397     result = slBeginObject(filename);
00398 
00399     cerr << "making point list" << endl;
00400     slPointList();
00401     SL_GET(Points)->PreAllocate(nverts);
00402     for (i = 0; i < nverts; i++)
00403     {
00404         Vertex *v = vlist + i;
00405         slPoint(Point(v->x, v->y, v->z));
00406     }
00407 
00408     if (has_normals)
00409     {
00410         cerr << "making normals list" << endl;
00411         slNormalList();
00412         SL_GET(Normals)->PreAllocate(nverts);
00413 
00414         for (i = 0; i < nverts; i++)
00415         {
00416             Vertex *v = vlist + i;
00417             slNormal(Vector(v->nx, v->ny, v->nz));
00418         }
00419     }
00420     else
00421     {
00422         cerr << "creating a normals list" << endl;
00423         MakeNormals();
00424     }
00425     
00426     if (has_rgb)
00427     {
00428         cerr << "making colours list" << endl;
00429         slColourList();
00430         SL_GET(Colours)->PreAllocate(nverts);
00431 
00432         for (i = 0; i < nverts; i++)
00433         {
00434             Vertex *v = vlist + i;
00435             slColour(Colour(v->r, v->g, v->b) / 255.0);
00436         }
00437     }
00438 
00439     free(vlist);
00440 
00441     if (nfaces > 0)
00442     {
00443         cerr << "making faces list" << endl;
00444         slBeginFaces();
00445         for (i = 0; i < nfaces; i++)
00446         {
00447             Face    *face = flist + i;
00448 
00449             for (j = 0; j < face->nverts; j++)
00450                 slPointIndex(face->verts[j]);
00451 
00452             slFace();
00453             free(face->verts);
00454         }
00455         slEndFaces();
00456     }
00457     free(flist);
00458 
00459     if (ntristrips > 0)
00460     {
00461         Int strips = 0;
00462 
00463         cerr << "making tristrips list" << endl;
00464 
00465         slMeshType(renTriStrip);
00466         slBeginFaces();
00467 
00468         for (i = 0; i < ntristrips; i++)
00469         {
00470             TriStrips   *tristrip = tslist + i;
00471 
00472             for (j = 0; j < tristrip->nverts; j++)
00473                 if (tristrip->verts[j] == -1)
00474                 {
00475                     strips++;
00476                     slFace();
00477                 }
00478                 else
00479                     slPointIndex(tristrip->verts[j]);
00480 
00481             strips++;
00482             free(tristrip->verts);
00483         }
00484 
00485         slEndFaces();
00486         slEndAttribute(aMeshType);
00487     }
00488     free(tslist);
00489 
00490     slEndObject();
00491 
00492     cerr << "done." << endl;
00493 
00494     return (result);
00495 }
00496 
00497 #include "plyfile.c"
00498 

Generated at Sat Aug 5 00:17:02 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000