Equalizer  1.2.1
eqPly/plyfile.cpp
00001 /* Copyright (c) 2005-2011, Stefan Eilemann <eile@equalizergraphics.com> 
00002    All rights reserved.
00003    - Cleaned up code for 64 bit, little and big endian support
00004    - Added new ply data types (uint8, float32, int32)
00005  */
00006 
00007 /*
00008 
00009 The interface routines for reading and writing PLY polygon files.
00010 
00011 Greg Turk, February 1994
00012 
00013 ---------------------------------------------------------------
00014 
00015 A PLY file contains a single polygonal _object_.
00016 
00017 An object is composed of lists of _elements_.  Typical elements are
00018 vertices, faces, edges and materials.
00019 
00020 Each type of element for a given object has one or more _properties_
00021 associated with the element type.  For instance, a vertex element may
00022 have as properties the floating-point values x,y,z and the three unsigned
00023 chars representing red, green and blue.
00024 
00025 ---------------------------------------------------------------
00026 
00027 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
00028 Junior University.  All rights reserved.   
00029   
00030 Permission to use, copy, modify and distribute this software and its   
00031 documentation for any purpose is hereby granted without fee, provided   
00032 that the above copyright notice and this permission notice appear in   
00033 all copies of this software and that you do not sell the software.   
00034   
00035 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,   
00036 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY   
00037 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.   
00038 
00039 */
00040 
00041 #include "ply.h"
00042 #include <stdio.h>
00043 #include <stdlib.h>
00044 #include <math.h>
00045 #include <string.h>
00046 
00047 #ifdef _WIN32
00048 # define strdup _strdup
00049 #endif
00050 
00051 const char *type_names[] = {
00052     "invalid",
00053     "char", "short", "int",
00054     "uchar", "ushort", "uint",
00055     "float", "double", "float32", "uint8", "int32"
00056 };
00057 
00058 int ply_type_size[] = {
00059     0, 1, 2, 4, 1, 2, 4, 4, 8, 4, 1, 4
00060 };
00061 
00062 #define NO_OTHER_PROPS  -1
00063 
00064 #define DONT_STORE_PROP  0
00065 #define STORE_PROP       1
00066 
00067 #define OTHER_PROP       0
00068 #define NAMED_PROP       1
00069 
00070 /* Byte-swapping macros */
00071 void swap2Bytes( void* ptr );
00072 void swap4Bytes( void* ptr );
00073 void swap8Bytes( void* ptr );
00074 
00075 #ifdef LITTLE_ENDIAN
00076 void swap2LE( void* );
00077 void swap2LE( short* );
00078 void swap2LE( unsigned short* );
00079 void swap4LE( void* );
00080 void swap4LE( int* );
00081 void swap4LE( unsigned int* );
00082 void swap4LE( float* );
00083 void swap8LE( void* );
00084 void swap8LE( long long* );
00085 void swap8LE( unsigned long long* );
00086 void swap8LE( double* );
00087 
00088 void swap2BE( void* ptr );
00089 void swap2BE( short* ptr );
00090 void swap2BE( unsigned short* ptr );
00091 void swap4BE( void* ptr );
00092 void swap4BE( int* ptr );
00093 void swap4BE( unsigned int* ptr );
00094 void swap4BE( float* ptr );
00095 void swap8BE( long long* ptr );
00096 void swap8BE( void* ptr );
00097 void swap8BE( unsigned long long* ptr );
00098 void swap8BE( double* ptr );
00099 #else // LITTLE_ENDIAN
00100 
00101 void swap2LE( void* ptr );
00102 void swap2LE( short* ptr );
00103 void swap2LE( unsigned short* ptr );
00104 void swap4LE( void* ptr );
00105 void swap4LE( int* ptr );
00106 void swap4LE( unsigned int* ptr );
00107 void swap4LE( float* ptr );
00108 void swap8LE( long long* ptr );
00109 void swap8LE( void* ptr );
00110 void swap8LE( unsigned long long* ptr );
00111 void swap8LE( double* ptr );
00112 
00113 void swap2BE( void* );
00114 void swap2BE( short* );
00115 void swap2BE( unsigned short* );
00116 void swap4BE( void* );
00117 void swap4BE( int* );
00118 void swap4BE( unsigned int* );
00119 void swap4BE( float* );
00120 void swap8BE( void* );
00121 void swap8BE( long long* );
00122 void swap8BE( unsigned long long* );
00123 void swap8BE( double* );
00124 
00125 #endif // LITTLE_ENDIAN
00126 
00127 /* returns 1 if strings are equal, 0 if not */
00128 int equal_strings(const char *, const char *);
00129 
00130 /* find an element in a plyfile's list */
00131 PlyElement *find_element(PlyFile *, const char *);
00132 
00133 /* find a property in an element's list */
00134 PlyProperty *find_property(PlyElement *, const char *, int *);
00135 
00136 /* write to a file the word describing a PLY file data type */
00137 void write_scalar_type (FILE *, int);
00138 
00139 /* read a line from a file and break it up into separate words */
00140 char **get_words(FILE *, int *, char **);
00141 
00142 /* write an item to a file */
00143 void write_binary_item(PlyFile *, int, unsigned int, double, int);
00144 void write_ascii_item(FILE *, int, unsigned int, double, int);
00145 
00146 /* add information to a PLY file descriptor */
00147 void add_element(PlyFile *, char **, int);
00148 void add_property(PlyFile *, char **, int);
00149 void add_comment(PlyFile *, char *);
00150 void add_obj_info(PlyFile *, char *);
00151 
00152 /* copy a property */
00153 void copy_property(PlyProperty *, PlyProperty *);
00154 
00155 /* store a value into where a pointer and a type specify */
00156 void store_item(char *, int, int, unsigned int, double);
00157 
00158 /* return the value of a stored item */
00159 void get_stored_item( void *, int, int *, unsigned int *, double *);
00160 
00161 /* return the value stored in an item, given ptr to it and its type */
00162 double get_item_value(char *, int);
00163 
00164 /* get binary or ascii item and store it according to ptr and type */
00165 void get_ascii_item(char *, int, int *, unsigned int *, double *);
00166 void get_binary_item(PlyFile *, int, int *, unsigned int *, double *);
00167 
00168 /* get a bunch of elements from a file */
00169 void ascii_get_element(PlyFile *, char *);
00170 void binary_get_element(PlyFile *, char *);
00171 
00172 /* memory allocation */
00173 char *my_alloc(int, int, const char *);
00174 
00175 
00176 PlyFile *ply_write(
00177                    FILE *fp,
00178                    int nelems,
00179                    const char **elem_names,
00180                    int file_type
00181                    );
00182 
00183 
00184 PlyFile *ply_open_for_writing(
00185                               char *filename,
00186                               int nelems,
00187                               const char **elem_names,
00188                               int file_type,
00189                               float *version
00190                              );
00191                    
00192 void ply_describe_element(
00193                           PlyFile *plyfile,
00194                           const char *elem_name,
00195                           int nelems,
00196                           int nprops,
00197                           PlyProperty *prop_list
00198                           );
00199 
00200 void ply_describe_other_properties(
00201                           PlyFile *plyfile,
00202                           PlyOtherProp *other,
00203                           int offset
00204                           );
00205 void setup_other_props(PlyFile *, PlyElement *elem);
00206 
00207 int get_prop_type(char *type_name);
00208 
00209 void ply_describe_property(
00210                            PlyFile *plyfile,
00211                            const char *elem_name,
00212                            PlyProperty *prop
00213                            );
00214 
00215 /************************/
00216 /* Byte-swapping macros */
00217 /************************/
00218 
00219 void swap2Bytes( void* ptr )
00220 {
00221     unsigned char* bytes = (unsigned char*)ptr;
00222     unsigned short* result = (unsigned short*)ptr;
00223     
00224     *result = (bytes[0]<<8) | bytes[1];
00225 }
00226 
00227 void swap4Bytes( void* ptr )
00228 {
00229     unsigned char* bytes = (unsigned char*)ptr;
00230     unsigned int* result = (unsigned int*)ptr;
00231 
00232     *result = (bytes[0]<<24) | (bytes[1]<<16) | (bytes[2]<<8) | bytes[3];
00233 }    
00234 
00235 void swap8Bytes( void* ptr )
00236 {
00237     unsigned char* bytes = (unsigned char*)ptr;
00238     unsigned long long* result = (unsigned long long*)ptr;
00239     
00240     *result = ((unsigned long long)(bytes[0])) << 56 |
00241         ((unsigned long long)(bytes[1])) << 48 |
00242         ((unsigned long long)(bytes[2])) << 40 |
00243         ((unsigned long long)(bytes[3])) << 32 |
00244         ((unsigned long long)(bytes[4])) << 24 |
00245         ((unsigned long long)(bytes[5])) << 16 |
00246         ((unsigned long long)(bytes[6])) << 8  |
00247         bytes[7];
00248 
00249 
00250 }
00251 
00252 #ifdef LITTLE_ENDIAN
00253 void swap2LE( void* ) {}
00254 void swap2LE( short* ) {}
00255 void swap2LE( unsigned short* ) {}
00256 void swap4LE( void* ) {}
00257 void swap4LE( int* ) {}
00258 void swap4LE( unsigned int* ) {}
00259 void swap4LE( float* ) {}
00260 void swap8LE( void* ) {}
00261 void swap8LE( long long* ) {}
00262 void swap8LE( unsigned long long* ) {}
00263 void swap8LE( double* ) {}
00264 
00265 void swap2BE( void* ptr ) { swap2Bytes(ptr); }
00266 void swap2BE( short* ptr ) { swap2Bytes(ptr); }
00267 void swap2BE( unsigned short* ptr ) { swap2Bytes(ptr); }
00268 void swap4BE( void* ptr ) { swap4Bytes(ptr); }
00269 void swap4BE( int* ptr ) { swap4Bytes(ptr); }
00270 void swap4BE( unsigned int* ptr ) { swap4Bytes(ptr); }
00271 void swap4BE( float* ptr ) { swap4Bytes(ptr); }
00272 void swap8BE( long long* ptr ) { swap8Bytes(ptr); }
00273 void swap8BE( void* ptr ) { swap8Bytes(ptr); }
00274 void swap8BE( unsigned long long* ptr ) { swap8Bytes(ptr); }
00275 void swap8BE( double* ptr ) { swap8Bytes(ptr); }
00276 
00277 #else // LITTLE_ENDIAN
00278 
00279 void swap2LE( void* ptr ) { swap2Bytes(ptr); }
00280 void swap2LE( short* ptr ) { swap2Bytes(ptr); }
00281 void swap2LE( unsigned short* ptr ) { swap2Bytes(ptr); }
00282 void swap4LE( void* ptr ) { swap4Bytes(ptr); }
00283 void swap4LE( int* ptr ) { swap4Bytes(ptr); }
00284 void swap4LE( unsigned int* ptr ) { swap4Bytes(ptr); }
00285 void swap4LE( float* ptr ) { swap4Bytes(ptr); }
00286 void swap8LE( long long* ptr ) { swap8Bytes(ptr); }
00287 void swap8LE( void* ptr ) { swap8Bytes(ptr); }
00288 void swap8LE( unsigned long long* ptr ) { swap8Bytes(ptr); }
00289 void swap8LE( double* ptr ) { swap8Bytes(ptr); }
00290 
00291 void swap2BE( void* ) {}
00292 void swap2BE( short* ) {}
00293 void swap2BE( unsigned short* ) {}
00294 void swap4BE( void* ) {}
00295 void swap4BE( int* ) {}
00296 void swap4BE( unsigned int* ) {}
00297 void swap4BE( float* ) {}
00298 void swap8BE( void* ) {}
00299 void swap8BE( long long* ) {}
00300 void swap8BE( unsigned long long* ) {}
00301 void swap8BE( double* ) {}
00302 
00303 #endif // LITTLE_ENDIAN
00304 
00305 
00306 /*************/
00307 /*  Writing  */
00308 /*************/
00309 
00310 
00311 /******************************************************************************
00312 Given a file pointer, get ready to write PLY data to the file.
00313 
00314 Entry:
00315   fp         - the given file pointer
00316   nelems     - number of elements in object
00317   elem_names - list of element names
00318   file_type  - file type, either ascii or binary
00319 
00320 Exit:
00321   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
00322 ******************************************************************************/
00323 
00324 PlyFile *ply_write(
00325   FILE *fp,
00326   int nelems,
00327   const char **elem_names,
00328   int file_type
00329 )
00330 {
00331   int i;
00332   PlyFile *plyfile;
00333   PlyElement *elem;
00334 
00335   /* check for NULL file pointer */
00336   if (fp == NULL)
00337     return (NULL);
00338 
00339   /* create a record for this object */
00340 
00341   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
00342   plyfile->file_type = file_type;
00343   plyfile->num_comments = 0;
00344   plyfile->num_obj_info = 0;
00345   plyfile->nelems = nelems;
00346   plyfile->version = 1.0;
00347   plyfile->fp = fp;
00348   plyfile->other_elems = NULL;
00349 
00350   /* tuck aside the names of the elements */
00351 
00352   plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
00353   for (i = 0; i < nelems; i++) {
00354     elem = (PlyElement *) myalloc (sizeof (PlyElement));
00355     plyfile->elems[i] = elem;
00356     elem->name = strdup (elem_names[i]);
00357     elem->num = 0;
00358     elem->nprops = 0;
00359   }
00360 
00361   /* return pointer to the file descriptor */
00362   return (plyfile);
00363 }
00364 
00365 
00366 /******************************************************************************
00367 Open a polygon file for writing.
00368 
00369 Entry:
00370   filename   - name of file to read from
00371   nelems     - number of elements in object
00372   elem_names - list of element names
00373   file_type  - file type, either ascii or binary
00374 
00375 Exit:
00376   version - version number of PLY file
00377   returns a file identifier, used to refer to this file, or NULL if error
00378 ******************************************************************************/
00379 
00380 PlyFile *ply_open_for_writing(
00381   char *filename,
00382   int nelems,
00383   const char **elem_names,
00384   int file_type,
00385   float *version
00386 )
00387 {
00388   PlyFile *plyfile;
00389   char *name;
00390   FILE *fp;
00391 
00392 
00393   /* tack on the extension .ply, if necessary */
00394   name = (char *) myalloc (sizeof (char) * 
00395                            (static_cast<int>(strlen (filename)) + 5));
00396   strcpy (name, filename);
00397   if (strlen (name) < 4 ||
00398       strcmp (name + strlen (name) - 4, ".ply") != 0)
00399       strcat (name, ".ply");
00400 
00401   /* open the file for writing */
00402 
00403   fp = fopen (name, "wb");
00404   free (name); //wjs remove memory leak//
00405   if (fp == NULL) {
00406     return (NULL);
00407   }
00408 
00409   /* create the actual PlyFile structure */
00410 
00411   plyfile = ply_write (fp, nelems, elem_names, file_type);
00412   if (plyfile == NULL)
00413     return (NULL);
00414 
00415   /* say what PLY file version number we're writing */
00416   *version = plyfile->version;
00417 
00418   /* return pointer to the file descriptor */
00419   return (plyfile);
00420 }
00421 
00422 
00423 /******************************************************************************
00424 Describe an element, including its properties and how many will be written
00425 to the file.
00426 
00427 Entry:
00428   plyfile   - file identifier
00429   elem_name - name of element that information is being specified about
00430   nelems    - number of elements of this type to be written
00431   nprops    - number of properties contained in the element
00432   prop_list - list of properties
00433 ******************************************************************************/
00434 
00435 void ply_describe_element(
00436   PlyFile *plyfile,
00437   const char *elem_name,
00438   int nelems,
00439   int nprops,
00440   PlyProperty *prop_list
00441 )
00442 {
00443   int i;
00444   PlyElement *elem;
00445   PlyProperty *prop;
00446 
00447   /* look for appropriate element */
00448   elem = find_element (plyfile, elem_name);
00449   if (elem == NULL) {
00450     fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
00451     exit (-1);
00452   }
00453 
00454   elem->num = nelems;
00455 
00456   /* copy the list of properties */
00457 
00458   elem->nprops = nprops;
00459   elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
00460   elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
00461 
00462   for (i = 0; i < nprops; i++) {
00463     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00464     elem->props[i] = prop;
00465     elem->store_prop[i] = NAMED_PROP;
00466     copy_property (prop, &prop_list[i]);
00467   }
00468 }
00469 
00470 
00471 /******************************************************************************
00472 Describe a property of an element.
00473 
00474 Entry:
00475   plyfile   - file identifier
00476   elem_name - name of element that information is being specified about
00477   prop      - the new property
00478 ******************************************************************************/
00479 
00480 void ply_describe_property(
00481   PlyFile *plyfile,
00482   const char *elem_name,
00483   PlyProperty *prop
00484 )
00485 {
00486   PlyElement *elem;
00487   PlyProperty *elem_prop;
00488 
00489   /* look for appropriate element */
00490   elem = find_element (plyfile, elem_name);
00491   if (elem == NULL) {
00492     fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
00493             elem_name);
00494     return;
00495   }
00496 
00497   /* create room for new property */
00498 
00499   if (elem->nprops == 0) {
00500     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
00501     elem->store_prop = (char *) myalloc (sizeof (char));
00502     elem->nprops = 1;
00503   }
00504   else {
00505     elem->nprops++;
00506     elem->props = (PlyProperty **)
00507                   realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
00508     elem->store_prop = (char *)
00509                   realloc (elem->store_prop, sizeof (char) * elem->nprops);
00510   }
00511 
00512   /* copy the new property */
00513   elem->other_offset = 0; //added by wjs Purify UMR
00514   elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00515   elem->props[elem->nprops - 1] = elem_prop;
00516   elem->store_prop[elem->nprops - 1] = NAMED_PROP;
00517   copy_property (elem_prop, prop);
00518 }
00519 
00520 
00521 /******************************************************************************
00522 Describe what the "other" properties are that are to be stored, and where
00523 they are in an element.
00524 ******************************************************************************/
00525 
00526 void ply_describe_other_properties(
00527   PlyFile *plyfile,
00528   PlyOtherProp *other,
00529   int offset
00530 )
00531 {
00532   int i;
00533   PlyElement *elem;
00534   PlyProperty *prop;
00535 
00536   /* look for appropriate element */
00537   elem = find_element (plyfile, other->name);
00538   if (elem == NULL) {
00539     fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
00540             other->name);
00541     return;
00542   }
00543 
00544   /* create room for other properties */
00545 
00546   if (elem->nprops == 0) {
00547     elem->props = (PlyProperty **)
00548                   myalloc (sizeof (PlyProperty *) * other->nprops);
00549     elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
00550     elem->nprops = 0;
00551   }
00552   else {
00553     int newsize;
00554     newsize = elem->nprops + other->nprops;
00555     elem->props = (PlyProperty **)
00556                   realloc (elem->props, sizeof (PlyProperty *) * newsize);
00557     elem->store_prop = (char *)
00558                   realloc (elem->store_prop, sizeof (char) * newsize);
00559   }
00560 
00561   /* copy the other properties */
00562 
00563   for (i = 0; i < other->nprops; i++) {
00564     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
00565     copy_property (prop, other->props[i]);
00566     elem->props[elem->nprops] = prop;
00567     elem->store_prop[elem->nprops] = OTHER_PROP;
00568     elem->nprops++;
00569   }
00570 
00571   /* save other info about other properties */
00572   elem->other_size = other->size;
00573   elem->other_offset = offset;
00574 }
00575 
00576 
00577 /******************************************************************************
00578 State how many of a given element will be written.
00579 
00580 Entry:
00581   plyfile   - file identifier
00582   elem_name - name of element that information is being specified about
00583   nelems    - number of elements of this type to be written
00584 ******************************************************************************/
00585 
00586 void ply_element_count(
00587   PlyFile *plyfile,
00588   const char *elem_name,
00589   int nelems
00590 )
00591 {
00592   PlyElement *elem;
00593 
00594   /* look for appropriate element */
00595   elem = find_element (plyfile, elem_name);
00596   if (elem == NULL) {
00597     fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
00598     exit (-1);
00599   }
00600 
00601   elem->num = nelems;
00602 }
00603 
00604 
00605 /******************************************************************************
00606 Signal that we've described everything a PLY file's header and that the
00607 header should be written to the file.
00608 
00609 Entry:
00610   plyfile - file identifier
00611 ******************************************************************************/
00612 
00613 void ply_header_complete(PlyFile *plyfile)
00614 {
00615   int i,j;
00616   FILE *fp = plyfile->fp;
00617   PlyElement *elem;
00618   PlyProperty *prop;
00619 
00620   fprintf (fp, "ply\n");
00621 
00622   switch (plyfile->file_type) {
00623     case PLY_ASCII:
00624       fprintf (fp, "format ascii 1.0\n");
00625       break;
00626     case PLY_BINARY_BE:
00627       fprintf (fp, "format binary_big_endian 1.0\n");
00628       break;
00629     case PLY_BINARY_LE:
00630       fprintf (fp, "format binary_little_endian 1.0\n");
00631       break;
00632     default:
00633       fprintf (stderr, "ply_header_complete: bad file type = %d\n",
00634                plyfile->file_type);
00635       exit (-1);
00636   }
00637 
00638   /* write out the comments */
00639 
00640   for (i = 0; i < plyfile->num_comments; i++)
00641     fprintf (fp, "comment %s\n", plyfile->comments[i]);
00642 
00643   /* write out object information */
00644 
00645   for (i = 0; i < plyfile->num_obj_info; i++)
00646     fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
00647 
00648   /* write out information about each element */
00649 
00650   for (i = 0; i < plyfile->nelems; i++) {
00651 
00652     elem = plyfile->elems[i];
00653     fprintf (fp, "element %s %d\n", elem->name, elem->num);
00654 
00655     /* write out each property */
00656     for (j = 0; j < elem->nprops; j++) {
00657       prop = elem->props[j];
00658       if (prop->is_list) {
00659         fprintf (fp, "property list ");
00660         write_scalar_type (fp, prop->count_external);
00661         fprintf (fp, " ");
00662         write_scalar_type (fp, prop->external_type);
00663         fprintf (fp, " %s\n", prop->name);
00664       }
00665       else {
00666         fprintf (fp, "property ");
00667         write_scalar_type (fp, prop->external_type);
00668         fprintf (fp, " %s\n", prop->name);
00669       }
00670     }
00671   }
00672 
00673   fprintf (fp, "end_header\n");
00674 }
00675 
00676 
00677 /******************************************************************************
00678 Specify which elements are going to be written.  This should be called
00679 before a call to the routine ply_put_element().
00680 
00681 Entry:
00682   plyfile   - file identifier
00683   elem_name - name of element we're talking about
00684 ******************************************************************************/
00685 
00686 void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
00687 {
00688   PlyElement *elem;
00689 
00690   elem = find_element (plyfile, elem_name);
00691   if (elem == NULL) {
00692     fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
00693     exit (-1);
00694   }
00695 
00696   plyfile->which_elem = elem;
00697 }
00698 
00699 
00700 /******************************************************************************
00701 Write an element to the file.  This routine assumes that we're
00702 writing the type of element specified in the last call to the routine
00703 ply_put_element_setup().
00704 
00705 Entry:
00706   plyfile  - file identifier
00707   elem_ptr - pointer to the element
00708 ******************************************************************************/
00709 
00710 void ply_put_element(PlyFile *plyfile, void *elem_ptr)
00711 {
00712   int j, k;
00713   FILE *fp = plyfile->fp;
00714   PlyElement *elem;
00715   PlyProperty *prop;
00716   char *elem_data,*item;
00717   char **item_ptr;
00718   int list_count;
00719   int item_size;
00720   int int_val;
00721   unsigned int uint_val;
00722   double double_val;
00723   char **other_ptr;
00724 
00725   elem = plyfile->which_elem;
00726   elem_data = (char *)elem_ptr;
00727   other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
00728 
00729   /* write out either to an ascii or binary file */
00730 
00731   if (plyfile->file_type == PLY_ASCII) {
00732 
00733     /* write an ascii file */
00734 
00735     /* write out each property of the element */
00736     for (j = 0; j < elem->nprops; j++) {
00737       prop = elem->props[j];
00738       if (elem->store_prop[j] == OTHER_PROP)
00739         elem_data = *other_ptr;
00740       else
00741         elem_data = (char *)elem_ptr;
00742       if (prop->is_list) {
00743         item = elem_data + prop->count_offset;
00744         get_stored_item ((void *) item, prop->count_internal,
00745                          &int_val, &uint_val, &double_val);
00746         write_ascii_item (fp, int_val, uint_val, double_val,
00747                           prop->count_external);
00748         list_count = uint_val;
00749         item_ptr = (char **) (elem_data + prop->offset);
00750         item = item_ptr[0];
00751        item_size = ply_type_size[prop->internal_type];
00752         for (k = 0; k < list_count; k++) {
00753           get_stored_item ((void *) item, prop->internal_type,
00754                            &int_val, &uint_val, &double_val);
00755           write_ascii_item (fp, int_val, uint_val, double_val,
00756                             prop->external_type);
00757           item += item_size;
00758         }
00759       }
00760       else {
00761         item = elem_data + prop->offset;
00762         get_stored_item ((void *) item, prop->internal_type,
00763                          &int_val, &uint_val, &double_val);
00764         write_ascii_item (fp, int_val, uint_val, double_val,
00765                           prop->external_type);
00766       }
00767     }
00768 
00769     fprintf (fp, "\n");
00770   }
00771   else {
00772 
00773     /* write a binary file */
00774 
00775     /* write out each property of the element */
00776     for (j = 0; j < elem->nprops; j++) {
00777       prop = elem->props[j];
00778       if (elem->store_prop[j] == OTHER_PROP)
00779         elem_data = *other_ptr;
00780       else
00781         elem_data = (char *)elem_ptr;
00782       if (prop->is_list) {
00783         item = elem_data + prop->count_offset;
00784         item_size = ply_type_size[prop->count_internal];
00785         get_stored_item ((void *) item, prop->count_internal,
00786                          &int_val, &uint_val, &double_val);
00787         write_binary_item (plyfile, int_val, uint_val, double_val,
00788                            prop->count_external);
00789         list_count = uint_val;
00790         item_ptr = (char **) (elem_data + prop->offset);
00791         item = item_ptr[0];
00792         item_size = ply_type_size[prop->internal_type];
00793         for (k = 0; k < list_count; k++) {
00794           get_stored_item ((void *) item, prop->internal_type,
00795                            &int_val, &uint_val, &double_val);
00796           write_binary_item (plyfile, int_val, uint_val, double_val,
00797                              prop->external_type);
00798           item += item_size;
00799         }
00800       }
00801       else {
00802         item = elem_data + prop->offset;
00803         item_size = ply_type_size[prop->internal_type];
00804         get_stored_item ((void *) item, prop->internal_type,
00805                          &int_val, &uint_val, &double_val);
00806         write_binary_item (plyfile, int_val, uint_val, double_val,
00807                            prop->external_type);
00808       }
00809     }
00810 
00811   }
00812 }
00813 
00814 
00815 /******************************************************************************
00816 Specify a comment that will be written in the header.
00817 
00818 Entry:
00819   plyfile - file identifier
00820   comment - the comment to be written
00821 ******************************************************************************/
00822 
00823 void ply_put_comment(PlyFile *plyfile, const char *comment)
00824 {
00825   /* (re)allocate space for new comment */
00826   if (plyfile->num_comments == 0)
00827     {
00828     plyfile->comments = (char **) myalloc (sizeof (char *));
00829     }
00830   else
00831     {
00832     plyfile->comments = (char **) realloc (plyfile->comments, sizeof (char *) *
00833                                                    (plyfile->num_comments + 1));
00834     }
00835   
00836   /* add comment to list */
00837   plyfile->comments[plyfile->num_comments] = strdup (comment);
00838   plyfile->num_comments++;
00839 }
00840 
00841 
00842 /******************************************************************************
00843 Specify a piece of object information (arbitrary text) that will be written
00844 in the header.
00845 
00846 Entry:
00847   plyfile  - file identifier
00848   obj_info - the text information to be written
00849 ******************************************************************************/
00850 
00851 void ply_put_obj_info(PlyFile *plyfile, const char *obj_info)
00852 {
00853   /* (re)allocate space for new info */
00854   if (plyfile->num_obj_info == 0)
00855     {
00856     plyfile->obj_info = (char **) myalloc (sizeof (char *));
00857     }
00858   else
00859     {
00860     plyfile->obj_info = (char **) realloc (plyfile->obj_info, sizeof (char *) *
00861                                                   (plyfile->num_obj_info + 1));
00862     }
00863   
00864   /* add info to list */
00865   plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
00866   plyfile->num_obj_info++;
00867 }
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 /*************/
00876 /*  Reading  */
00877 /*************/
00878 
00879 
00880 
00881 /******************************************************************************
00882 Given a file pointer, get ready to read PLY data from the file.
00883 
00884 Entry:
00885   fp - the given file pointer
00886 
00887 Exit:
00888   nelems     - number of elements in object
00889   elem_names - list of element names
00890   returns a pointer to a PlyFile, used to refer to this file, or NULL if error
00891 ******************************************************************************/
00892 
00893 PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
00894 {
00895   int i,j;
00896   PlyFile *plyfile;
00897   int nwords;
00898   char **words;
00899   char **elist;
00900   PlyElement *elem;
00901   char *orig_line;
00902 
00903   /* check for NULL file pointer */
00904   if (fp == NULL)
00905     return (NULL);
00906 
00907   /* create record for this object */
00908 
00909   plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
00910   plyfile->nelems = 0;
00911   plyfile->comments = NULL;
00912   plyfile->num_comments = 0;
00913   plyfile->obj_info = NULL;
00914   plyfile->num_obj_info = 0;
00915   plyfile->fp = fp;
00916   plyfile->other_elems = NULL;
00917 
00918   /* read and parse the file's header */
00919 
00920   words = get_words (plyfile->fp, &nwords, &orig_line);
00921   if (!words || !equal_strings (words[0], "ply"))
00922   {
00923     free( plyfile );
00924     return (NULL);
00925   }
00926 
00927   while (words) {
00928 
00929     /* parse words */
00930 
00931     if (equal_strings (words[0], "format")) {
00932       if (nwords != 3)
00933       {
00934           free( plyfile );
00935           return (NULL);
00936       }
00937       if (equal_strings (words[1], "ascii"))
00938         plyfile->file_type = PLY_ASCII;
00939       else if (equal_strings (words[1], "binary_big_endian"))
00940         plyfile->file_type = PLY_BINARY_BE;
00941       else if (equal_strings (words[1], "binary_little_endian"))
00942         plyfile->file_type = PLY_BINARY_LE;
00943       else
00944         {
00945             free (words);
00946             free( plyfile );
00947             return (NULL);
00948         }
00949       plyfile->version = atof (words[2]);
00950     }
00951     else if (equal_strings (words[0], "element"))
00952       add_element (plyfile, words, nwords);
00953     else if (equal_strings (words[0], "property"))
00954       add_property (plyfile, words, nwords);
00955     else if (equal_strings (words[0], "comment"))
00956       add_comment (plyfile, orig_line);
00957     else if (equal_strings (words[0], "obj_info"))
00958       add_obj_info (plyfile, orig_line);
00959     else if (equal_strings (words[0], "end_header"))
00960       {
00961       free (words);
00962       break;
00963       }
00964 
00965     /* free up words space */
00966     free (words);
00967 
00968     words = get_words (plyfile->fp, &nwords, &orig_line);
00969   }
00970   
00971 
00972   /* create tags for each property of each element, to be used */
00973   /* later to say whether or not to store each property for the user */
00974 
00975   for (i = 0; i < plyfile->nelems; i++) {
00976     elem = plyfile->elems[i];
00977     elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
00978     for (j = 0; j < elem->nprops; j++)
00979       elem->store_prop[j] = DONT_STORE_PROP;
00980     elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
00981   }
00982 
00983   /* set return values about the elements */
00984 
00985   elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
00986   for (i = 0; i < plyfile->nelems; i++)
00987     elist[i] = strdup (plyfile->elems[i]->name);
00988 
00989   *elem_names = elist;
00990   *nelems = plyfile->nelems;
00991 
00992   /* return a pointer to the file's information */
00993 
00994   return (plyfile);
00995 }
00996 
00997 
00998 /******************************************************************************
00999 Open a polygon file for reading.
01000 
01001 Entry:
01002   filename - name of file to read from
01003 
01004 Exit:
01005   nelems     - number of elements in object
01006   elem_names - list of element names
01007   file_type  - file type, either ascii or binary
01008   version    - version number of PLY file
01009   returns a file identifier, used to refer to this file, or NULL if error
01010 ******************************************************************************/
01011 
01012 PlyFile *ply_open_for_reading(
01013   char *filename,
01014   int *nelems,
01015   char ***elem_names,
01016   int *file_type,
01017   float *version
01018 )
01019 {
01020   FILE *fp;
01021   PlyFile *plyfile;
01022   char *name;
01023 
01024   /* tack on the extension .ply, if necessary */
01025 
01026   name = (char *) myalloc (sizeof (char) * 
01027                            (static_cast<int>(strlen (filename) + 5)));
01028   strcpy (name, filename);
01029   if (strlen (name) < 4 ||
01030       strcmp (name + strlen (name) - 4, ".ply") != 0)
01031       strcat (name, ".ply");
01032 
01033   /* open the file for reading */
01034 
01035   fp = fopen (name, "rb");
01036   free(name);
01037   if (fp == NULL)
01038     return (NULL);
01039 
01040   /* create the PlyFile data structure */
01041 
01042   plyfile = ply_read (fp, nelems, elem_names);
01043 
01044   /* determine the file type and version */
01045 
01046   *file_type = plyfile->file_type;
01047   *version = plyfile->version;
01048 
01049   /* return a pointer to the file's information */
01050 
01051   return (plyfile);
01052 }
01053 
01054 
01055 /******************************************************************************
01056 Get information about a particular element.
01057 
01058 Entry:
01059   plyfile   - file identifier
01060   elem_name - name of element to get information about
01061 
01062 Exit:
01063   nelems   - number of elements of this type in the file
01064   nprops   - number of properties
01065   returns a list of properties, or NULL if the file doesn't contain that elem
01066 ******************************************************************************/
01067 
01068 PlyProperty **ply_get_element_description(
01069   PlyFile *plyfile,
01070   char *elem_name,
01071   int *nelems,
01072   int *nprops
01073 )
01074 {
01075   int i;
01076   PlyElement *elem;
01077   PlyProperty *prop;
01078   PlyProperty **prop_list;
01079 
01080   /* find information about the element */
01081   elem = find_element (plyfile, elem_name);
01082   if (elem == NULL)
01083     return (NULL);
01084 
01085   *nelems = elem->num;
01086   *nprops = elem->nprops;
01087 
01088   /* make a copy of the element's property list */
01089   prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
01090   for (i = 0; i < elem->nprops; i++) {
01091     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
01092     copy_property (prop, elem->props[i]);
01093     prop_list[i] = prop;
01094   }
01095 
01096   /* return this duplicate property list */
01097   return (prop_list);
01098 }
01099 
01100 
01101 /******************************************************************************
01102 Specify which properties of an element are to be returned.  This should be
01103 called before a call to the routine ply_get_element().
01104 
01105 Entry:
01106   plyfile   - file identifier
01107   elem_name - which element we're talking about
01108   nprops    - number of properties
01109   prop_list - list of properties
01110 ******************************************************************************/
01111 
01112 void ply_get_element_setup( PlyFile *plyfile, char *elem_name, int nprops,
01113                             PlyProperty *prop_list )
01114 {
01115     int i;
01116     PlyElement *elem;
01117     PlyProperty *prop;
01118     int index;
01119 
01120     /* find information about the element */
01121     elem = find_element (plyfile, elem_name);
01122     plyfile->which_elem = elem;
01123 
01124     /* deposit the property information into the element's description */
01125     for (i = 0; i < nprops; i++) 
01126     {
01127         /* look for actual property */
01128         prop = find_property (elem, prop_list[i].name, &index);
01129         if (prop == NULL) 
01130         {
01131             fprintf ( stderr, 
01132                       "Warning:  Can't find property '%s' in element '%s'\n",
01133                       prop_list[i].name, elem_name );
01134             continue;
01135         }
01136 
01137         /* store its description */
01138         prop->internal_type = prop_list[i].internal_type;
01139         prop->offset = prop_list[i].offset;
01140         prop->count_internal = prop_list[i].count_internal;
01141         prop->count_offset = prop_list[i].count_offset;
01142 
01143         /* specify that the user wants this property */
01144         elem->store_prop[index] = STORE_PROP;
01145     }
01146 }
01147 
01148 
01149 /******************************************************************************
01150 Specify a property of an element that is to be returned.  This should be
01151 called (usually multiple times) before a call to the routine ply_get_element().
01152 This routine should be used in preference to the less flexible old routine
01153 called ply_get_element_setup().
01154 
01155 Entry:
01156   plyfile   - file identifier
01157   elem_name - which element we're talking about
01158   prop      - property to add to those that will be returned
01159 ******************************************************************************/
01160 
01161 void ply_get_property(
01162   PlyFile *plyfile,
01163   const char *elem_name,
01164   PlyProperty *prop
01165 )
01166 {
01167   PlyElement *elem;
01168   PlyProperty *prop_ptr;
01169   int index;
01170 
01171   /* find information about the element */
01172   elem = find_element (plyfile, elem_name);
01173   plyfile->which_elem = elem;
01174 
01175   /* deposit the property information into the element's description */
01176 
01177   prop_ptr = find_property (elem, prop->name, &index);
01178   if (prop_ptr == NULL) {
01179     fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
01180              prop->name, elem_name);
01181     return;
01182   }
01183   prop_ptr->internal_type  = prop->internal_type;
01184   prop_ptr->offset         = prop->offset;
01185   prop_ptr->count_internal = prop->count_internal;
01186   prop_ptr->count_offset   = prop->count_offset;
01187 
01188   /* specify that the user wants this property */
01189   elem->store_prop[index] = STORE_PROP;
01190 }
01191 
01192 
01193 /******************************************************************************
01194 Read one element from the file.  This routine assumes that we're reading
01195 the type of element specified in the last call to the routine
01196 ply_get_element_setup().
01197 
01198 Entry:
01199   plyfile  - file identifier
01200   elem_ptr - pointer to location where the element information should be put
01201 ******************************************************************************/
01202 
01203 void ply_get_element(PlyFile *plyfile, void *elem_ptr)
01204 {
01205   if (plyfile->file_type == PLY_ASCII)
01206     ascii_get_element (plyfile, (char *) elem_ptr);
01207   else
01208     binary_get_element (plyfile, (char *) elem_ptr);
01209 }
01210 
01211 
01212 /******************************************************************************
01213 Extract the comments from the header information of a PLY file.
01214 
01215 Entry:
01216   plyfile - file identifier
01217 
01218 Exit:
01219   num_comments - number of comments returned
01220   returns a pointer to a list of comments
01221 ******************************************************************************/
01222 
01223 char **ply_get_comments(PlyFile *plyfile, int *num_comments)
01224 {
01225   *num_comments = plyfile->num_comments;
01226   return (plyfile->comments);
01227 }
01228 
01229 
01230 /******************************************************************************
01231 Extract the object information (arbitrary text) from the header information
01232 of a PLY file.
01233 
01234 Entry:
01235   plyfile - file identifier
01236 
01237 Exit:
01238   num_obj_info - number of lines of text information returned
01239   returns a pointer to a list of object info lines
01240 ******************************************************************************/
01241 
01242 char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
01243 {
01244   *num_obj_info = plyfile->num_obj_info;
01245   return (plyfile->obj_info);
01246 }
01247 
01248 
01249 /******************************************************************************
01250 Make ready for "other" properties of an element-- those properties that
01251 the user has not explicitly asked for, but that are to be stashed away
01252 in a special structure to be carried along with the element's other
01253 information.
01254 
01255 Entry:
01256   plyfile - file identifier
01257   elem    - element for which we want to save away other properties
01258 ******************************************************************************/
01259 
01260 void setup_other_props(PlyFile *, PlyElement *elem)
01261 {
01262   int i;
01263   PlyProperty *prop;
01264   int size = 0;
01265   int type_size;
01266 
01267   /* Examine each property in decreasing order of size. */
01268   /* We do this so that all data types will be aligned by */
01269   /* word, half-word, or whatever within the structure. */
01270 
01271   for (type_size = 8; type_size > 0; type_size /= 2) {
01272 
01273     /* add up the space taken by each property, and save this information */
01274     /* away in the property descriptor */
01275 
01276     for (i = 0; i < elem->nprops; i++) {
01277 
01278       /* don't bother with properties we've been asked to store explicitly */
01279       if (elem->store_prop[i])
01280         continue;
01281 
01282       prop = elem->props[i];
01283 
01284       /* internal types will be same as external */
01285       prop->internal_type = prop->external_type;
01286       prop->count_internal = prop->count_external;
01287 
01288       /* check list case */
01289       if (prop->is_list) {
01290 
01291         /* pointer to list */
01292         if (type_size == sizeof (void *)) {
01293           prop->offset = size;
01294           size += sizeof (void *);    /* always use size of a pointer here */
01295         }
01296 
01297         /* count of number of list elements */
01298         if (type_size == ply_type_size[prop->count_external]) {
01299           prop->count_offset = size;
01300           size += ply_type_size[prop->count_external];
01301         }
01302       }
01303       /* not list */
01304       else if (type_size == ply_type_size[prop->external_type]) {
01305         prop->offset = size;
01306         size += ply_type_size[prop->external_type];
01307       }
01308     }
01309 
01310   }
01311 
01312   /* save the size for the other_props structure */
01313   elem->other_size = size;
01314 }
01315 
01316 
01317 /******************************************************************************
01318 Specify that we want the "other" properties of an element to be tucked
01319 away within the user's structure.  The user needn't be concerned for how
01320 these properties are stored.
01321 
01322 Entry:
01323   plyfile   - file identifier
01324   elem_name - name of element that we want to store other_props in
01325   offset    - offset to where other_props will be stored inside user's structure
01326 
01327 Exit:
01328   returns pointer to structure containing description of other_props
01329 ******************************************************************************/
01330 
01331 PlyOtherProp *ply_get_other_properties(
01332   PlyFile *plyfile,
01333   char *elem_name,
01334   int offset
01335 )
01336 {
01337   int i;
01338   PlyElement *elem;
01339   PlyOtherProp *other;
01340   PlyProperty *prop;
01341   int nprops;
01342 
01343   /* find information about the element */
01344   elem = find_element (plyfile, elem_name);
01345   if (elem == NULL) {
01346     fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
01347              elem_name);
01348     return (NULL);
01349   }
01350 
01351   /* remember that this is the "current" element */
01352   plyfile->which_elem = elem;
01353 
01354   /* save the offset to where to store the other_props */
01355   elem->other_offset = offset;
01356 
01357   /* place the appropriate pointers, etc. in the element's property list */
01358   setup_other_props (plyfile, elem);
01359 
01360   /* create structure for describing other_props */
01361   other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
01362   other->name = strdup (elem_name);
01363 #if 0
01364   if (elem->other_offset == NO_OTHER_PROPS) {
01365     other->size = 0;
01366     other->props = NULL;
01367     other->nprops = 0;
01368     return (other);
01369   }
01370 #endif
01371   other->size = elem->other_size;
01372   other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
01373   
01374   /* save descriptions of each "other" property */
01375   nprops = 0;
01376   for (i = 0; i < elem->nprops; i++) {
01377     if (elem->store_prop[i])
01378       continue;
01379     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
01380     copy_property (prop, elem->props[i]);
01381     other->props[nprops] = prop;
01382     nprops++;
01383   }
01384   other->nprops = nprops;
01385 
01386 #if 1
01387   /* set other_offset pointer appropriately if there are NO other properties */
01388   if (other->nprops == 0) {
01389     elem->other_offset = NO_OTHER_PROPS;
01390   }
01391 #endif
01392   
01393   /* return structure */
01394   return (other);
01395 }
01396 
01397 
01398 
01399 
01400 /*************************/
01401 /*  Other Element Stuff  */
01402 /*************************/
01403 
01404 
01405 
01406 
01407 /******************************************************************************
01408 Grab all the data for an element that a user does not want to explicitly
01409 read in.
01410 
01411 Entry:
01412   plyfile    - pointer to file
01413   elem_name  - name of element whose data is to be read in
01414   elem_count - number of instances of this element stored in the file
01415 
01416 Exit:
01417   returns pointer to ALL the "other" element data for this PLY file
01418 ******************************************************************************/
01419 
01420 PlyOtherElems *ply_get_other_element (
01421   PlyFile *plyfile,
01422   char *elem_name,
01423   int elem_count
01424 )
01425 {
01426   int i;
01427   PlyElement *elem;
01428   PlyOtherElems *other_elems;
01429   OtherElem *other;
01430 
01431   /* look for appropriate element */
01432   elem = find_element (plyfile, elem_name);
01433   if (elem == NULL) {
01434     fprintf (stderr,
01435              "ply_get_other_element: can't find element '%s'\n", elem_name);
01436     exit (-1);
01437   }
01438 
01439   /* create room for the new "other" element, initializing the */
01440   /* other data structure if necessary */
01441 
01442   if (plyfile->other_elems == NULL) {
01443     plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
01444     other_elems = plyfile->other_elems;
01445     other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
01446     other = &(other_elems->other_list[0]);
01447     other_elems->num_elems = 1;
01448   }
01449   else {
01450     other_elems = plyfile->other_elems;
01451     other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
01452                               sizeof (OtherElem) * other_elems->num_elems + 1);
01453     other = &(other_elems->other_list[other_elems->num_elems]);
01454     other_elems->num_elems++;
01455   }
01456 
01457   /* count of element instances in file */
01458   other->elem_count = elem_count;
01459 
01460   /* save name of element */
01461   other->elem_name = strdup (elem_name);
01462 
01463   /* create a list to hold all the current elements */
01464   other->other_data = (OtherData **)
01465                   malloc (sizeof (OtherData *) * other->elem_count);
01466 
01467   /* set up for getting elements */
01468   other->other_props = ply_get_other_properties (plyfile, elem_name,
01469                          offsetof(OtherData,other_props));
01470 
01471   /* grab all these elements */
01472   for (i = 0; i < other->elem_count; i++) {
01473     /* grab and element from the file */
01474     other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
01475     ply_get_element (plyfile, (void *) other->other_data[i]);
01476   }
01477 
01478   /* return pointer to the other elements data */
01479   return (other_elems);
01480 }
01481 
01482 
01483 /******************************************************************************
01484 Pass along a pointer to "other" elements that we want to save in a given
01485 PLY file.  These other elements were presumably read from another PLY file.
01486 
01487 Entry:
01488   plyfile     - file pointer in which to store this other element info
01489   other_elems - info about other elements that we want to store
01490 ******************************************************************************/
01491 
01492 void ply_describe_other_elements (
01493   PlyFile *plyfile,
01494   PlyOtherElems *other_elems
01495 )
01496 {
01497   int i;
01498   OtherElem *other;
01499 
01500   /* ignore this call if there is no other element */
01501   if (other_elems == NULL)
01502     return;
01503 
01504   /* save pointer to this information */
01505   plyfile->other_elems = other_elems;
01506 
01507   /* describe the other properties of this element */
01508 
01509   for (i = 0; i < other_elems->num_elems; i++) {
01510     other = &(other_elems->other_list[i]);
01511     ply_element_count (plyfile, other->elem_name, other->elem_count);
01512     ply_describe_other_properties (plyfile, other->other_props,
01513                                    offsetof(OtherData,other_props));
01514   }
01515 }
01516 
01517 
01518 /******************************************************************************
01519 Write out the "other" elements specified for this PLY file.
01520 
01521 Entry:
01522   plyfile - pointer to PLY file to write out other elements for
01523 ******************************************************************************/
01524 
01525 void ply_put_other_elements (PlyFile *plyfile)
01526 {
01527   int i,j;
01528   OtherElem *other;
01529 
01530   /* make sure we have other elements to write */
01531   if (plyfile->other_elems == NULL)
01532     return;
01533 
01534   /* write out the data for each "other" element */
01535 
01536   for (i = 0; i < plyfile->other_elems->num_elems; i++) {
01537 
01538     other = &(plyfile->other_elems->other_list[i]);
01539     ply_put_element_setup (plyfile, other->elem_name);
01540 
01541     /* write out each instance of the current element */
01542     for (j = 0; j < other->elem_count; j++)
01543       ply_put_element (plyfile, (void *) other->other_data[j]);
01544   }
01545 }
01546 
01547 
01548 /******************************************************************************
01549 Free up storage used by an "other" elements data structure.
01550 
01551 Entry:
01552   other_elems - data structure to free up
01553 ******************************************************************************/
01554 
01555 void ply_free_other_elements (PlyOtherElems *)
01556 {
01557 
01558 }
01559 
01560 
01561 
01562 /*******************/
01563 /*  Miscellaneous  */
01564 /*******************/
01565 
01566 
01567 
01568 /******************************************************************************
01569 Close a PLY file.
01570 
01571 Entry:
01572   plyfile - identifier of file to close
01573 ******************************************************************************/
01574 
01575 void ply_close(PlyFile *plyfile)
01576 {
01577   // Changed by Will Schroeder. Old stuff leaked like a sieve.
01578 
01579   /* free up memory associated with the PLY file */
01580   fclose (plyfile->fp);
01581 
01582   int i, j;
01583   PlyElement *elem;
01584   for (i=0; i<plyfile->nelems; i++)
01585     {
01586     elem = plyfile->elems[i];
01587     if ( elem->name ) {free(elem->name);}
01588     for (j=0; j<elem->nprops; j++)
01589       {
01590       if ( elem->props[j]->name )
01591          {free(const_cast<char *>(elem->props[j]->name));}
01592       free (elem->props[j]);
01593       }
01594     free (elem->props);
01595     free (elem->store_prop);
01596     free (elem);
01597     }
01598   free(plyfile->elems);
01599 
01600   for (i=0; i<plyfile->num_comments; i++)
01601     {
01602     free (plyfile->comments[i]);
01603     }
01604   free (plyfile->comments);
01605   
01606   for (i=0; i<plyfile->num_obj_info; i++)
01607     {
01608     free (plyfile->obj_info[i]);
01609     }
01610   free (plyfile->obj_info);
01611   
01612   free (plyfile);
01613 }
01614 
01615 
01616 /******************************************************************************
01617 Get version number and file type of a PlyFile.
01618 
01619 Entry:
01620   ply - pointer to PLY file
01621 
01622 Exit:
01623   version - version of the file
01624   file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
01625 ******************************************************************************/
01626 
01627 void ply_get_info(PlyFile *ply, float *version, int *file_type)
01628 {
01629   if (ply == NULL)
01630     return;
01631 
01632   *version = ply->version;
01633   *file_type = ply->file_type;
01634 }
01635 
01636 
01637 /******************************************************************************
01638 Compare two strings.  Returns 1 if they are the same, 0 if not.
01639 ******************************************************************************/
01640 
01641 int equal_strings(const char *s1, const char *s2)
01642 {
01643   while (*s1 && *s2)
01644     if (*s1++ != *s2++)
01645       return (0);
01646 
01647   if (*s1 != *s2)
01648     return (0);
01649   else
01650     return (1);
01651 }
01652 
01653 
01654 /******************************************************************************
01655 Find an element from the element list of a given PLY object.
01656 
01657 Entry:
01658   plyfile - file id for PLY file
01659   element - name of element we're looking for
01660 
01661 Exit:
01662   returns the element, or NULL if not found
01663 ******************************************************************************/
01664 
01665 PlyElement *find_element(PlyFile *plyfile, const char *element)
01666 {
01667     int i;
01668 
01669     for (i = 0; i < plyfile->nelems; i++)
01670         if (equal_strings (element, plyfile->elems[i]->name))
01671             return (plyfile->elems[i]);
01672     
01673     return (NULL);
01674 }
01675 
01676 
01677 /******************************************************************************
01678 Find a property in the list of properties of a given element.
01679 
01680 Entry:
01681   elem      - pointer to element in which we want to find the property
01682   prop_name - name of property to find
01683 
01684 Exit:
01685   index - index to position in list
01686   returns a pointer to the property, or NULL if not found
01687 ******************************************************************************/
01688 
01689 PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
01690 {
01691     int i;
01692     
01693     for( i = 0; i < elem->nprops; i++)
01694         if (equal_strings (prop_name, elem->props[i]->name))
01695         {
01696             *index = i;
01697             return (elem->props[i]);
01698         }
01699     
01700     *index = -1;
01701     return (NULL);
01702 }
01703 
01704 
01705 /******************************************************************************
01706 Read an element from an ascii file.
01707 
01708 Entry:
01709   plyfile  - file identifier
01710   elem_ptr - pointer to element
01711 ******************************************************************************/
01712 
01713 void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
01714 {
01715   int j,k;
01716   PlyElement *elem;
01717   PlyProperty *prop;
01718   char **words;
01719   int nwords;
01720   int which_word;
01721   char *elem_data,*item=0;
01722   char *item_ptr;
01723   int item_size=0;
01724   int int_val;
01725   unsigned int uint_val;
01726   double double_val;
01727   int list_count;
01728   int store_it;
01729   char **store_array;
01730   char *orig_line;
01731   char *other_data=0;
01732   int other_flag;
01733 
01734   /* the kind of element we're reading currently */
01735   elem = plyfile->which_elem;
01736 
01737   /* do we need to setup for other_props? */
01738 
01739   if (elem->other_offset != NO_OTHER_PROPS) {
01740     char **ptr;
01741     other_flag = 1;
01742     /* make room for other_props */
01743     other_data = (char *) myalloc (elem->other_size);
01744     /* store pointer in user's structure to the other_props */
01745     ptr = (char **) (elem_ptr + elem->other_offset);
01746     *ptr = other_data;
01747   }
01748   else
01749     other_flag = 0;
01750 
01751   /* read in the element */
01752 
01753   words = get_words (plyfile->fp, &nwords, &orig_line);
01754   if (words == NULL) {
01755     fprintf (stderr, "ply_get_element: unexpected end of file\n");
01756     exit (-1);
01757   }
01758 
01759   which_word = 0;
01760 
01761   for (j = 0; j < elem->nprops; j++) {
01762 
01763     prop = elem->props[j];
01764     store_it = (elem->store_prop[j] | other_flag);
01765 
01766     /* store either in the user's structure or in other_props */
01767     if (elem->store_prop[j])
01768       elem_data = elem_ptr;
01769     else
01770       elem_data = other_data;
01771 
01772     if (prop->is_list) {       /* a list */
01773 
01774       /* get and store the number of items in the list */
01775       get_ascii_item (words[which_word++], prop->count_external,
01776                       &int_val, &uint_val, &double_val);
01777       if (store_it) {
01778         item = elem_data + prop->count_offset;
01779         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01780       }
01781 
01782       /* allocate space for an array of items and store a ptr to the array */
01783       list_count = int_val;
01784       item_size = ply_type_size[prop->internal_type];
01785       store_array = (char **) (elem_data + prop->offset);
01786 
01787       if (list_count == 0) {
01788         if (store_it)
01789           *store_array = NULL;
01790       }
01791       else {
01792         if (store_it) {
01793           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01794           item = item_ptr;
01795           *store_array = item_ptr;
01796         }
01797 
01798         /* read items and store them into the array */
01799         for (k = 0; k < list_count; k++) {
01800           get_ascii_item (words[which_word++], prop->external_type,
01801                           &int_val, &uint_val, &double_val);
01802           if (store_it) {
01803             store_item (item, prop->internal_type,
01804                         int_val, uint_val, double_val);
01805             item += item_size;
01806           }
01807         }
01808       }
01809 
01810     }
01811     else {                     /* not a list */
01812       get_ascii_item (words[which_word++], prop->external_type,
01813                       &int_val, &uint_val, &double_val);
01814       if (store_it) {
01815         item = elem_data + prop->offset;
01816         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01817       }
01818     }
01819 
01820   }
01821 
01822   free (words);
01823 }
01824 
01825 
01826 /******************************************************************************
01827 Read an element from a binary file.
01828 
01829 Entry:
01830   plyfile  - file identifier
01831   elem_ptr - pointer to an element
01832 ******************************************************************************/
01833 
01834 void binary_get_element(PlyFile *plyfile, char *elem_ptr)
01835 {
01836   int j,k;
01837   PlyElement *elem;
01838   PlyProperty *prop;
01839   //FILE *fp = plyfile->fp;
01840   char *elem_data,*item=0;
01841   char *item_ptr;
01842   int item_size=0;
01843   int int_val;
01844   unsigned int uint_val;
01845   double double_val;
01846   int list_count;
01847   int store_it;
01848   char **store_array;
01849   char *other_data=0;
01850   int other_flag;
01851 
01852   /* the kind of element we're reading currently */
01853   elem = plyfile->which_elem;
01854 
01855   /* do we need to setup for other_props? */
01856 
01857   if (elem->other_offset != NO_OTHER_PROPS) {
01858     char **ptr;
01859     other_flag = 1;
01860     /* make room for other_props */
01861     other_data = (char *) myalloc (elem->other_size);
01862     /* store pointer in user's structure to the other_props */
01863     ptr = (char **) (elem_ptr + elem->other_offset);
01864     *ptr = other_data;
01865   }
01866   else
01867     other_flag = 0;
01868 
01869   /* read in a number of elements */
01870 
01871   for (j = 0; j < elem->nprops; j++) {
01872 
01873     prop = elem->props[j];
01874     store_it = (elem->store_prop[j] | other_flag);
01875 
01876     /* store either in the user's structure or in other_props */
01877     if (elem->store_prop[j])
01878       elem_data = elem_ptr;
01879     else
01880       elem_data = other_data;
01881 
01882     if (prop->is_list) {       /* a list */
01883 
01884       /* get and store the number of items in the list */
01885       get_binary_item (plyfile, prop->count_external,
01886                        &int_val, &uint_val, &double_val);
01887       if (store_it) {
01888         item = elem_data + prop->count_offset;
01889         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01890       }
01891 
01892       /* allocate space for an array of items and store a ptr to the array */
01893       list_count = int_val;
01894       /* The "if" was added by Afra Zomorodian 8/22/95
01895        * so that zipper won't crash reading plies that have additional
01896        * properties.
01897        */ 
01898       if (store_it) {
01899         item_size = ply_type_size[prop->internal_type];
01900       }
01901       store_array = (char **) (elem_data + prop->offset);
01902       if (list_count == 0) {
01903         if (store_it)
01904           *store_array = NULL;
01905       }
01906       else {
01907         if (store_it) {
01908           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01909           item = item_ptr;
01910           *store_array = item_ptr;
01911         }
01912 
01913         /* read items and store them into the array */
01914         for (k = 0; k < list_count; k++) {
01915           get_binary_item (plyfile, prop->external_type,
01916                           &int_val, &uint_val, &double_val);
01917           if (store_it) {
01918             store_item (item, prop->internal_type,
01919                         int_val, uint_val, double_val);
01920             item += item_size;
01921           }
01922         }
01923       }
01924 
01925     }
01926     else {                     /* not a list */
01927       get_binary_item (plyfile, prop->external_type,
01928                       &int_val, &uint_val, &double_val);
01929       if (store_it) {
01930         item = elem_data + prop->offset;
01931         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01932       }
01933     }
01934 
01935   }
01936 }
01937 
01938 
01939 /******************************************************************************
01940 Write to a file the word that represents a PLY data type.
01941 
01942 Entry:
01943   fp   - file pointer
01944   code - code for type
01945 ******************************************************************************/
01946 
01947 void write_scalar_type (FILE *fp, int code)
01948 {
01949   /* make sure this is a valid code */
01950 
01951   if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
01952     fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
01953     exit (-1);
01954   }
01955 
01956   /* write the code to a file */
01957 
01958   fprintf (fp, "%s", type_names[code]);
01959 }
01960 
01961 
01962 /******************************************************************************
01963 Get a text line from a file and break it up into words.
01964 
01965 IMPORTANT: The calling routine call "free" on the returned pointer once
01966 finished with it.
01967 
01968 Entry:
01969   fp - file to read from
01970 
01971 Exit:
01972   nwords    - number of words returned
01973   orig_line - the original line of characters
01974   returns a list of words from the line, or NULL if end-of-file
01975 ******************************************************************************/
01976 
01977 char **get_words(FILE *fp, int *nwords, char **orig_line)
01978 {
01979 #define BIG_STRING 4096
01980   static char str[BIG_STRING];
01981   static char str_copy[BIG_STRING];
01982   char **words;
01983   int max_words = 10;
01984   int num_words = 0;
01985   char *ptr,*ptr2;
01986   char *result;
01987 
01988   /* read in a line */
01989   result = fgets (str, BIG_STRING, fp);
01990   if (result == NULL) {
01991     *nwords = 0;
01992     *orig_line = NULL;
01993     return (NULL);
01994   }
01995 
01996   words = (char **) myalloc (sizeof (char *) * max_words);
01997 
01998   /* convert line-feed and tabs into spaces */
01999   /* (this guarentees that there will be a space before the */
02000   /*  null character at the end of the string) */
02001 
02002   str[BIG_STRING-2] = ' ';
02003   str[BIG_STRING-1] = '\0';
02004 
02005   for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
02006     *ptr2 = *ptr;
02007     if (*ptr == '\t') {
02008       *ptr = ' ';
02009       *ptr2 = ' ';
02010     }
02011     else if (*ptr == '\n') {
02012       *ptr = ' ';
02013       *ptr2 = '\0';
02014       break;
02015     }
02016   }
02017 
02018   /* find the words in the line */
02019 
02020   ptr = str;
02021   while (*ptr != '\0') {
02022 
02023     /* jump over leading spaces */
02024     while (*ptr == ' ')
02025       ptr++;
02026 
02027     /* break if we reach the end */
02028     if (*ptr == '\0')
02029       break;
02030 
02031     /* save pointer to beginning of word */
02032     if (num_words >= max_words) {
02033       max_words += 10;
02034       words = (char **) realloc (words, sizeof (char *) * max_words);
02035     }
02036     words[num_words++] = ptr;
02037 
02038     /* jump over non-spaces */
02039     while (*ptr != ' ')
02040       ptr++;
02041 
02042     /* place a null character here to mark the end of the word */
02043     *ptr++ = '\0';
02044   }
02045 
02046   /* return the list of words */
02047   *nwords = num_words;
02048   *orig_line = str_copy;
02049   return (words);
02050 }
02051 
02052 
02053 /******************************************************************************
02054 Return the value of an item, given a pointer to it and its type.
02055 
02056 Entry:
02057   item - pointer to item
02058   type - data type that "item" points to
02059 
02060 Exit:
02061   returns a double-precision float that contains the value of the item
02062 ******************************************************************************/
02063 
02064 double get_item_value(char *item, int type)
02065 {
02066   unsigned char *puchar;
02067   char *pchar;
02068   short int *pshort;
02069   unsigned short int *pushort;
02070   int *pint;
02071   unsigned int *puint;
02072   float *pfloat;
02073   double *pdouble;
02074   int int_value;
02075   unsigned int uint_value;
02076   double double_value;
02077 
02078   switch (type) {
02079     case PLY_CHAR:
02080       pchar = (char *) item;
02081       int_value = *pchar;
02082       return ((double) int_value);
02083     case PLY_UCHAR:
02084     case PLY_UINT8:
02085       puchar = (unsigned char *) item;
02086       int_value = *puchar;
02087       return ((double) int_value);
02088     case PLY_SHORT:
02089       pshort = (short int *) item;
02090       int_value = *pshort;
02091       return ((double) int_value);
02092     case PLY_USHORT:
02093       pushort = (unsigned short int *) item;
02094       int_value = *pushort;
02095       return ((double) int_value);
02096     case PLY_INT:
02097     case PLY_INT32:
02098       pint = (int *) item;
02099       int_value = *pint;
02100       return ((double) int_value);
02101     case PLY_UINT:
02102       puint = (unsigned int *) item;
02103       uint_value = *puint;
02104       return ((double) uint_value);
02105     case PLY_FLOAT:
02106     case PLY_FLOAT32:
02107       pfloat = (float *) item;
02108       double_value = *pfloat;
02109       return (double_value);
02110     case PLY_DOUBLE:
02111       pdouble = (double *) item;
02112       double_value = *pdouble;
02113       return (double_value);
02114   }
02115   fprintf (stderr, "get_item_value: bad type = %d\n", type);
02116   return 0;
02117 }
02118 
02119 
02120 /******************************************************************************
02121 Write out an item to a file as raw binary bytes.
02122 
02123 Entry:
02124   fp         - file to write to
02125   int_val    - integer version of item
02126   uint_val   - unsigned integer version of item
02127   double_val - double-precision float version of item
02128   type       - data type to write out
02129 ******************************************************************************/
02130 
02131 void write_binary_item(PlyFile *plyfile,
02132                                int int_val,
02133                                unsigned int uint_val,
02134                                double double_val,
02135                                int type
02136 )
02137 {
02138   FILE *fp = plyfile->fp;
02139   unsigned char uchar_val;
02140   char char_val;
02141   unsigned short ushort_val;
02142   short short_val;
02143   float float_val;
02144 
02145   switch (type) {
02146     case PLY_CHAR:
02147       char_val = int_val;
02148       fwrite (&char_val, 1, 1, fp);
02149       break;
02150     case PLY_SHORT:
02151       short_val = int_val;
02152       if( plyfile->file_type == PLY_BINARY_BE )
02153           swap2BE(&short_val);
02154       else
02155           swap2LE(&short_val);
02156       fwrite (&short_val, 2, 1, fp);
02157       break;
02158       case PLY_INT:
02159       case PLY_INT32:
02160           if( plyfile->file_type == PLY_BINARY_BE )
02161           {
02162               swap4BE(&int_val);
02163           }
02164           else
02165           {
02166               swap4LE(&int_val);
02167           }
02168           fwrite (&int_val, 4, 1, fp);
02169           break;
02170       case PLY_UCHAR:
02171       case PLY_UINT8:
02172           uchar_val = uint_val;
02173           fwrite (&uchar_val, 1, 1, fp);
02174           break;
02175       case PLY_USHORT:
02176           if( plyfile->file_type == PLY_BINARY_BE )
02177           {
02178               swap2BE(&ushort_val);
02179           }
02180           else
02181           {
02182               swap2LE(&ushort_val);
02183           }
02184           ushort_val = uint_val;
02185           fwrite (&ushort_val, 2, 1, fp);
02186           break;
02187       case PLY_UINT:
02188           if( plyfile->file_type == PLY_BINARY_BE )
02189           {
02190               swap4BE(&uint_val);
02191           }
02192           else
02193           {
02194               swap4LE(&uint_val);
02195           }
02196           fwrite (&uint_val, 4, 1, fp);
02197           break;
02198       case PLY_FLOAT:
02199       case PLY_FLOAT32:
02200           float_val = double_val;
02201           if( plyfile->file_type == PLY_BINARY_BE )
02202           {
02203               swap4BE(&float_val);
02204           }
02205           else
02206           {
02207               swap4LE(&float_val);
02208           }
02209           fwrite (&float_val, 4, 1, fp);
02210           break;
02211       case PLY_DOUBLE:
02212           if( plyfile->file_type == PLY_BINARY_BE )
02213           {
02214               swap8BE(&double_val);
02215           }
02216           else
02217           {
02218               swap8LE(&double_val);
02219           }
02220           fwrite (&double_val, 8, 1, fp);
02221       break;
02222     default:
02223       fprintf (stderr, "write_binary_item: bad type = %d\n", type);
02224       exit (-1);
02225   }
02226 }
02227 
02228 
02229 /******************************************************************************
02230 Write out an item to a file as ascii characters.
02231 
02232 Entry:
02233   fp         - file to write to
02234   int_val    - integer version of item
02235   uint_val   - unsigned integer version of item
02236   double_val - double-precision float version of item
02237   type       - data type to write out
02238 ******************************************************************************/
02239 
02240 void write_ascii_item(
02241   FILE *fp,
02242   int int_val,
02243   unsigned int uint_val,
02244   double double_val,
02245   int type
02246 )
02247 {
02248   switch (type) {
02249     case PLY_CHAR:
02250     case PLY_SHORT:
02251     case PLY_INT:
02252     case PLY_INT32:
02253       fprintf (fp, "%d ", int_val);
02254       break;
02255     case PLY_UCHAR:
02256     case PLY_UINT8:
02257     case PLY_USHORT:
02258     case PLY_UINT:
02259       fprintf (fp, "%u ", uint_val);
02260       break;
02261     case PLY_FLOAT:
02262     case PLY_FLOAT32:
02263     case PLY_DOUBLE:
02264       fprintf (fp, "%g ", double_val);
02265       break;
02266     default:
02267       fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
02268       exit (-1);
02269   }
02270 }
02271 
02272 /******************************************************************************
02273 Get the value of an item that is in memory, and place the result
02274 into an integer, an unsigned integer and a double.
02275 
02276 Entry:
02277   ptr  - pointer to the item
02278   type - data type supposedly in the item
02279 
02280 Exit:
02281   int_val    - integer value
02282   uint_val   - unsigned integer value
02283   double_val - double-precision floating point value
02284 ******************************************************************************/
02285 
02286 void get_stored_item(
02287   void *ptr,
02288   int type,
02289   int *int_val,
02290   unsigned int *uint_val,
02291   double *double_val
02292 )
02293 {
02294   switch (type) {
02295     case PLY_CHAR:
02296       *int_val = *((char *) ptr);
02297       *uint_val = *int_val;
02298       *double_val = *int_val;
02299       break;
02300     case PLY_UCHAR:
02301     case PLY_UINT8:
02302       *uint_val = *((unsigned char *) ptr);
02303       *int_val = *uint_val;
02304       *double_val = *uint_val;
02305       break;
02306     case PLY_SHORT:
02307       *int_val = *((short int *) ptr);
02308       *uint_val = *int_val;
02309       *double_val = *int_val;
02310       break;
02311     case PLY_USHORT:
02312       *uint_val = *((unsigned short int *) ptr);
02313       *int_val = *uint_val;
02314       *double_val = *uint_val;
02315       break;
02316     case PLY_INT:
02317     case PLY_INT32:
02318       *int_val = *((int *) ptr);
02319       *uint_val = *int_val;
02320       *double_val = *int_val;
02321       break;
02322     case PLY_UINT:
02323       *uint_val = *((unsigned int *) ptr);
02324       *int_val = *uint_val;
02325       *double_val = *uint_val;
02326       break;
02327     case PLY_FLOAT:
02328     case PLY_FLOAT32:
02329       *double_val = *((float *) ptr);
02330       *int_val = (int) *double_val;
02331       *uint_val = (unsigned int) *double_val;
02332       break;
02333     case PLY_DOUBLE:
02334       *double_val = *((double *) ptr);
02335       *int_val = (int) *double_val;
02336       *uint_val = (unsigned int) *double_val;
02337       break;
02338     default:
02339       fprintf (stderr, "get_stored_item: bad type = %d\n", type);
02340       exit (-1);
02341   }
02342 }
02343 
02344 
02345 /******************************************************************************
02346 Get the value of an item from a binary file, and place the result
02347 into an integer, an unsigned integer and a double.
02348 
02349 Entry:
02350   fp   - file to get item from
02351   type - data type supposedly in the word
02352 
02353 Exit:
02354   int_val    - integer value
02355   uint_val   - unsigned integer value
02356   double_val - double-precision floating point value
02357 ******************************************************************************/
02358 
02359 void get_binary_item(
02360   PlyFile *plyfile,
02361   int type,
02362   int *int_val,
02363   unsigned int *uint_val,
02364   double *double_val
02365 )
02366 {
02367   char c[8];
02368   void *ptr;
02369 
02370   ptr = (void *) c;
02371 
02372   switch (type) {
02373     case PLY_CHAR:
02374       if( fread (ptr, 1, 1, plyfile->fp) <= 0 )
02375           abort();
02376       *int_val = *((char *) ptr);
02377       *uint_val = *int_val;
02378       *double_val = *int_val;
02379       break;
02380       case PLY_UCHAR:
02381       case PLY_UINT8:
02382           if( fread (ptr, 1, 1, plyfile->fp) <= 0 )
02383               abort();
02384           *uint_val = *((unsigned char *) ptr);
02385           *int_val = *uint_val;
02386           *double_val = *uint_val;
02387           break;
02388       case PLY_SHORT:
02389           if( fread (ptr, 2, 1, plyfile->fp) <= 0 )
02390               abort();
02391           if( plyfile->file_type == PLY_BINARY_BE )
02392           {
02393               swap2BE(ptr);
02394           }
02395           else
02396           {
02397               swap2LE(ptr);
02398           }
02399           *int_val = *((short int *) ptr);
02400           *uint_val = *int_val;
02401           *double_val = *int_val;
02402           break;
02403       case PLY_USHORT:
02404           if( fread (ptr, 2, 1, plyfile->fp) <= 0 )
02405               abort();
02406           if( plyfile->file_type == PLY_BINARY_BE )
02407           {
02408               swap2BE(ptr);
02409           }
02410           else
02411           {
02412               swap2LE(ptr);
02413           }
02414           *uint_val = *((unsigned short int *) ptr);
02415           *int_val = *uint_val;
02416           *double_val = *uint_val;
02417           break;
02418       case PLY_INT:
02419       case PLY_INT32:
02420           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02421               abort();
02422           if( plyfile->file_type == PLY_BINARY_BE )
02423           {
02424               swap4BE(ptr);
02425           }
02426           else
02427           {
02428               swap4LE(ptr);
02429           }
02430           *int_val = *((int *) ptr);
02431           *uint_val = *int_val;
02432           *double_val = *int_val;
02433           break;
02434       case PLY_UINT:
02435           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02436               abort();
02437           if( plyfile->file_type == PLY_BINARY_BE )
02438           {
02439               swap4BE(ptr);
02440           }
02441           else
02442           {
02443               swap4LE(ptr);
02444           }
02445           *uint_val = *((unsigned int *) ptr);
02446           *int_val = *uint_val;
02447           *double_val = *uint_val;
02448           break;
02449       case PLY_FLOAT:
02450       case PLY_FLOAT32:
02451           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02452               abort();
02453           if( plyfile->file_type == PLY_BINARY_BE )
02454           {
02455               swap4BE(ptr);
02456           }
02457           else
02458           {
02459               swap4LE(ptr);
02460           }
02461           *double_val = *((float *) ptr);
02462           *int_val = (int) *double_val;
02463           *uint_val = (unsigned int) *double_val;
02464           break;
02465       case PLY_DOUBLE:
02466           if( fread (ptr, 8, 1, plyfile->fp) <= 0 )
02467               abort();
02468           if( plyfile->file_type == PLY_BINARY_BE )
02469           {
02470               swap8BE(ptr);
02471           }
02472           else
02473           {
02474               swap8LE(ptr);
02475           }
02476       *double_val = *((double *) ptr);
02477       *int_val = (int) *double_val;
02478       *uint_val = (unsigned int) *double_val;
02479       break;
02480     default:
02481       fprintf (stderr, "get_binary_item: bad type = %d\n", type);
02482       exit (-1);
02483   }
02484 }
02485 
02486 
02487 /******************************************************************************
02488 Extract the value of an item from an ascii word, and place the result
02489 into an integer, an unsigned integer and a double.
02490 
02491 Entry:
02492   word - word to extract value from
02493   type - data type supposedly in the word
02494 
02495 Exit:
02496   int_val    - integer value
02497   uint_val   - unsigned integer value
02498   double_val - double-precision floating point value
02499 ******************************************************************************/
02500 
02501 void get_ascii_item(
02502   char *word,
02503   int type,
02504   int *int_val,
02505   unsigned int *uint_val,
02506   double *double_val
02507 )
02508 {
02509   switch (type) {
02510     case PLY_CHAR:
02511     case PLY_UCHAR:
02512     case PLY_UINT8:
02513     case PLY_SHORT:
02514     case PLY_USHORT:
02515     case PLY_INT:
02516     case PLY_INT32:
02517       *int_val = atoi (word);
02518       *uint_val = *int_val;
02519       *double_val = *int_val;
02520       break;
02521 
02522     case PLY_UINT:
02523       *uint_val = strtoul (word, (char **) NULL, 10);
02524       *int_val = *uint_val;
02525       *double_val = *uint_val;
02526       break;
02527 
02528     case PLY_FLOAT:
02529     case PLY_FLOAT32:
02530     case PLY_DOUBLE:
02531       *double_val = atof (word);
02532       *int_val = (int) *double_val;
02533       *uint_val = (unsigned int) *double_val;
02534       break;
02535 
02536     default:
02537       fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
02538       exit (-1);
02539   }
02540 }
02541 
02542 
02543 /******************************************************************************
02544 Store a value into a place being pointed to, guided by a data type.
02545 
02546 Entry:
02547   item       - place to store value
02548   type       - data type
02549   int_val    - integer version of value
02550   uint_val   - unsigned integer version of value
02551   double_val - double version of value
02552 
02553 Exit:
02554   item - pointer to stored value
02555 ******************************************************************************/
02556 
02557 void store_item (
02558   char *item,
02559   int type,
02560   int int_val,
02561   unsigned int uint_val,
02562   double double_val
02563 )
02564 {
02565   unsigned char *puchar;
02566   short int *pshort;
02567   unsigned short int *pushort;
02568   int *pint;
02569   unsigned int *puint;
02570   float *pfloat;
02571   double *pdouble;
02572 
02573   switch (type) {
02574     case PLY_CHAR:
02575       *item = int_val;
02576       break;
02577     case PLY_UCHAR:
02578     case PLY_UINT8:
02579       puchar = (unsigned char *) item;
02580       *puchar = uint_val;
02581       break;
02582     case PLY_SHORT:
02583       pshort = (short *) item;
02584       *pshort = int_val;
02585       break;
02586     case PLY_USHORT:
02587       pushort = (unsigned short *) item;
02588       *pushort = uint_val;
02589       break;
02590     case PLY_INT:
02591     case PLY_INT32:
02592       pint = (int *) item;
02593       *pint = int_val;
02594       break;
02595     case PLY_UINT:
02596       puint = (unsigned int *) item;
02597       *puint = uint_val;
02598       break;
02599     case PLY_FLOAT:
02600     case PLY_FLOAT32:
02601       pfloat = (float *) item;
02602       *pfloat = double_val;
02603       break;
02604     case PLY_DOUBLE:
02605       pdouble = (double *) item;
02606       *pdouble = double_val;
02607       break;
02608     default:
02609       fprintf (stderr, "store_item: bad type = %d\n", type);
02610       exit (-1);
02611   }
02612 }
02613 
02614 
02615 /******************************************************************************
02616 Add an element to a PLY file descriptor.
02617 
02618 Entry:
02619   plyfile - PLY file descriptor
02620   words   - list of words describing the element
02621   nwords  - number of words in the list
02622 ******************************************************************************/
02623 
02624 void add_element (PlyFile *plyfile, char **words, int)
02625 {
02626   PlyElement *elem;
02627 
02628   /* create the new element */
02629   elem = (PlyElement *) myalloc (sizeof (PlyElement));
02630   elem->name = strdup (words[1]);
02631   elem->num = atoi (words[2]);
02632   elem->nprops = 0;
02633 
02634   /* make room for new element in the object's list of elements */
02635   if (plyfile->nelems == 0)
02636     plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
02637   else
02638     plyfile->elems = (PlyElement **) realloc (plyfile->elems,
02639                      sizeof (PlyElement *) * (plyfile->nelems + 1));
02640 
02641   /* add the new element to the object's list */
02642   plyfile->elems[plyfile->nelems] = elem;
02643   plyfile->nelems++;
02644 }
02645 
02646 
02647 /******************************************************************************
02648 Return the type of a property, given the name of the property.
02649 
02650 Entry:
02651   name - name of property type
02652 
02653 Exit:
02654   returns integer code for property, or 0 if not found
02655 ******************************************************************************/
02656 
02657 int get_prop_type(char *type_name)
02658 {
02659   int i;
02660 
02661   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
02662     if (equal_strings (type_name, type_names[i]))
02663       return (i);
02664 
02665   /* if we get here, we didn't find the type */
02666   return (0);
02667 }
02668 
02669 
02670 /******************************************************************************
02671 Add a property to a PLY file descriptor.
02672 
02673 Entry:
02674   plyfile - PLY file descriptor
02675   words   - list of words describing the property
02676   nwords  - number of words in the list
02677 ******************************************************************************/
02678 
02679 void add_property (PlyFile *plyfile, char **words, int )
02680 {
02681   PlyProperty *prop;
02682   PlyElement *elem;
02683 
02684   /* create the new property */
02685 
02686   prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
02687 
02688   if (equal_strings (words[1], "list")) {       /* is a list */
02689     prop->count_external = get_prop_type (words[2]);
02690     prop->external_type = get_prop_type (words[3]);
02691     prop->name = strdup (words[4]);
02692     prop->is_list = 1;
02693   }
02694   else {                                        /* not a list */
02695     prop->external_type = get_prop_type (words[1]);
02696     prop->name = strdup (words[2]);
02697     prop->is_list = 0;
02698   }
02699 
02700   /* add this property to the list of properties of the current element */
02701 
02702   elem = plyfile->elems[plyfile->nelems - 1];
02703 
02704   if (elem->nprops == 0)
02705     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
02706   else
02707     elem->props = (PlyProperty **) realloc (elem->props,
02708                   sizeof (PlyProperty *) * (elem->nprops + 1));
02709 
02710   elem->props[elem->nprops] = prop;
02711   elem->nprops++;
02712 }
02713 
02714 
02715 /******************************************************************************
02716 Add a comment to a PLY file descriptor.
02717 
02718 Entry:
02719   plyfile - PLY file descriptor
02720   line    - line containing comment
02721 ******************************************************************************/
02722 
02723 void add_comment (PlyFile *plyfile, char *line)
02724 {
02725   int i;
02726 
02727   /* skip over "comment" and leading spaces and tabs */
02728   i = 7;
02729   while (line[i] == ' ' || line[i] == '\t')
02730     i++;
02731 
02732   ply_put_comment (plyfile, &line[i]);
02733 }
02734 
02735 
02736 /******************************************************************************
02737 Add a some object information to a PLY file descriptor.
02738 
02739 Entry:
02740   plyfile - PLY file descriptor
02741   line    - line containing text info
02742 ******************************************************************************/
02743 
02744 void add_obj_info (PlyFile *plyfile, char *line)
02745 {
02746   int i;
02747 
02748   /* skip over "obj_info" and leading spaces and tabs */
02749   i = 8;
02750   while (line[i] == ' ' || line[i] == '\t')
02751     i++;
02752 
02753   ply_put_obj_info (plyfile, &line[i]);
02754 }
02755 
02756 
02757 /******************************************************************************
02758 Copy a property.
02759 ******************************************************************************/
02760 
02761 void copy_property(PlyProperty *dest, PlyProperty *src)
02762 {
02763   dest->name = strdup (src->name);
02764   dest->external_type = src->external_type;
02765   dest->internal_type = src->internal_type;
02766   dest->offset = src->offset;
02767 
02768   dest->is_list = src->is_list;
02769   dest->count_external = src->count_external;
02770   dest->count_internal = src->count_internal;
02771   dest->count_offset = src->count_offset;
02772 }
02773 
02774 
02775 /******************************************************************************
02776 Allocate some memory.
02777 
02778 Entry:
02779   size  - amount of memory requested (in bytes)
02780   lnum  - line number from which memory was requested
02781   fname - file name from which memory was requested
02782 ******************************************************************************/
02783 
02784 char *my_alloc(int size, int lnum, const char *fname)
02785 {
02786   char *ptr;
02787 
02788   ptr = (char *) malloc (size);
02789 
02790   if (ptr == 0) 
02791       fprintf( stderr, "Memory allocation bombed on line %d in %s\n", 
02792                lnum, fname);
02793 
02794   return (ptr);
02795 }
02796 
Generated on Fri Jun 8 2012 15:44:32 for Equalizer 1.2.1 by  doxygen 1.8.0