Equalizer 1.0

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         return (NULL);
00934       if (equal_strings (words[1], "ascii"))
00935         plyfile->file_type = PLY_ASCII;
00936       else if (equal_strings (words[1], "binary_big_endian"))
00937         plyfile->file_type = PLY_BINARY_BE;
00938       else if (equal_strings (words[1], "binary_little_endian"))
00939         plyfile->file_type = PLY_BINARY_LE;
00940       else
00941         {
00942         free (words);
00943         return (NULL);
00944         }
00945       plyfile->version = atof (words[2]);
00946     }
00947     else if (equal_strings (words[0], "element"))
00948       add_element (plyfile, words, nwords);
00949     else if (equal_strings (words[0], "property"))
00950       add_property (plyfile, words, nwords);
00951     else if (equal_strings (words[0], "comment"))
00952       add_comment (plyfile, orig_line);
00953     else if (equal_strings (words[0], "obj_info"))
00954       add_obj_info (plyfile, orig_line);
00955     else if (equal_strings (words[0], "end_header"))
00956       {
00957       free (words);
00958       break;
00959       }
00960 
00961     /* free up words space */
00962     free (words);
00963 
00964     words = get_words (plyfile->fp, &nwords, &orig_line);
00965   }
00966   
00967 
00968   /* create tags for each property of each element, to be used */
00969   /* later to say whether or not to store each property for the user */
00970 
00971   for (i = 0; i < plyfile->nelems; i++) {
00972     elem = plyfile->elems[i];
00973     elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
00974     for (j = 0; j < elem->nprops; j++)
00975       elem->store_prop[j] = DONT_STORE_PROP;
00976     elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
00977   }
00978 
00979   /* set return values about the elements */
00980 
00981   elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
00982   for (i = 0; i < plyfile->nelems; i++)
00983     elist[i] = strdup (plyfile->elems[i]->name);
00984 
00985   *elem_names = elist;
00986   *nelems = plyfile->nelems;
00987 
00988   /* return a pointer to the file's information */
00989 
00990   return (plyfile);
00991 }
00992 
00993 
00994 /******************************************************************************
00995 Open a polygon file for reading.
00996 
00997 Entry:
00998   filename - name of file to read from
00999 
01000 Exit:
01001   nelems     - number of elements in object
01002   elem_names - list of element names
01003   file_type  - file type, either ascii or binary
01004   version    - version number of PLY file
01005   returns a file identifier, used to refer to this file, or NULL if error
01006 ******************************************************************************/
01007 
01008 PlyFile *ply_open_for_reading(
01009   char *filename,
01010   int *nelems,
01011   char ***elem_names,
01012   int *file_type,
01013   float *version
01014 )
01015 {
01016   FILE *fp;
01017   PlyFile *plyfile;
01018   char *name;
01019 
01020   /* tack on the extension .ply, if necessary */
01021 
01022   name = (char *) myalloc (sizeof (char) * 
01023                            (static_cast<int>(strlen (filename) + 5)));
01024   strcpy (name, filename);
01025   if (strlen (name) < 4 ||
01026       strcmp (name + strlen (name) - 4, ".ply") != 0)
01027       strcat (name, ".ply");
01028 
01029   /* open the file for reading */
01030 
01031   fp = fopen (name, "rb");
01032   free(name);
01033   if (fp == NULL)
01034     return (NULL);
01035 
01036   /* create the PlyFile data structure */
01037 
01038   plyfile = ply_read (fp, nelems, elem_names);
01039 
01040   /* determine the file type and version */
01041 
01042   *file_type = plyfile->file_type;
01043   *version = plyfile->version;
01044 
01045   /* return a pointer to the file's information */
01046 
01047   return (plyfile);
01048 }
01049 
01050 
01051 /******************************************************************************
01052 Get information about a particular element.
01053 
01054 Entry:
01055   plyfile   - file identifier
01056   elem_name - name of element to get information about
01057 
01058 Exit:
01059   nelems   - number of elements of this type in the file
01060   nprops   - number of properties
01061   returns a list of properties, or NULL if the file doesn't contain that elem
01062 ******************************************************************************/
01063 
01064 PlyProperty **ply_get_element_description(
01065   PlyFile *plyfile,
01066   char *elem_name,
01067   int *nelems,
01068   int *nprops
01069 )
01070 {
01071   int i;
01072   PlyElement *elem;
01073   PlyProperty *prop;
01074   PlyProperty **prop_list;
01075 
01076   /* find information about the element */
01077   elem = find_element (plyfile, elem_name);
01078   if (elem == NULL)
01079     return (NULL);
01080 
01081   *nelems = elem->num;
01082   *nprops = elem->nprops;
01083 
01084   /* make a copy of the element's property list */
01085   prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
01086   for (i = 0; i < elem->nprops; i++) {
01087     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
01088     copy_property (prop, elem->props[i]);
01089     prop_list[i] = prop;
01090   }
01091 
01092   /* return this duplicate property list */
01093   return (prop_list);
01094 }
01095 
01096 
01097 /******************************************************************************
01098 Specify which properties of an element are to be returned.  This should be
01099 called before a call to the routine ply_get_element().
01100 
01101 Entry:
01102   plyfile   - file identifier
01103   elem_name - which element we're talking about
01104   nprops    - number of properties
01105   prop_list - list of properties
01106 ******************************************************************************/
01107 
01108 void ply_get_element_setup( PlyFile *plyfile, char *elem_name, int nprops,
01109                             PlyProperty *prop_list )
01110 {
01111     int i;
01112     PlyElement *elem;
01113     PlyProperty *prop;
01114     int index;
01115 
01116     /* find information about the element */
01117     elem = find_element (plyfile, elem_name);
01118     plyfile->which_elem = elem;
01119 
01120     /* deposit the property information into the element's description */
01121     for (i = 0; i < nprops; i++) 
01122     {
01123         /* look for actual property */
01124         prop = find_property (elem, prop_list[i].name, &index);
01125         if (prop == NULL) 
01126         {
01127             fprintf ( stderr, 
01128                       "Warning:  Can't find property '%s' in element '%s'\n",
01129                       prop_list[i].name, elem_name );
01130             continue;
01131         }
01132 
01133         /* store its description */
01134         prop->internal_type = prop_list[i].internal_type;
01135         prop->offset = prop_list[i].offset;
01136         prop->count_internal = prop_list[i].count_internal;
01137         prop->count_offset = prop_list[i].count_offset;
01138 
01139         /* specify that the user wants this property */
01140         elem->store_prop[index] = STORE_PROP;
01141     }
01142 }
01143 
01144 
01145 /******************************************************************************
01146 Specify a property of an element that is to be returned.  This should be
01147 called (usually multiple times) before a call to the routine ply_get_element().
01148 This routine should be used in preference to the less flexible old routine
01149 called ply_get_element_setup().
01150 
01151 Entry:
01152   plyfile   - file identifier
01153   elem_name - which element we're talking about
01154   prop      - property to add to those that will be returned
01155 ******************************************************************************/
01156 
01157 void ply_get_property(
01158   PlyFile *plyfile,
01159   const char *elem_name,
01160   PlyProperty *prop
01161 )
01162 {
01163   PlyElement *elem;
01164   PlyProperty *prop_ptr;
01165   int index;
01166 
01167   /* find information about the element */
01168   elem = find_element (plyfile, elem_name);
01169   plyfile->which_elem = elem;
01170 
01171   /* deposit the property information into the element's description */
01172 
01173   prop_ptr = find_property (elem, prop->name, &index);
01174   if (prop_ptr == NULL) {
01175     fprintf (stderr, "Warning:  Can't find property '%s' in element '%s'\n",
01176              prop->name, elem_name);
01177     return;
01178   }
01179   prop_ptr->internal_type  = prop->internal_type;
01180   prop_ptr->offset         = prop->offset;
01181   prop_ptr->count_internal = prop->count_internal;
01182   prop_ptr->count_offset   = prop->count_offset;
01183 
01184   /* specify that the user wants this property */
01185   elem->store_prop[index] = STORE_PROP;
01186 }
01187 
01188 
01189 /******************************************************************************
01190 Read one element from the file.  This routine assumes that we're reading
01191 the type of element specified in the last call to the routine
01192 ply_get_element_setup().
01193 
01194 Entry:
01195   plyfile  - file identifier
01196   elem_ptr - pointer to location where the element information should be put
01197 ******************************************************************************/
01198 
01199 void ply_get_element(PlyFile *plyfile, void *elem_ptr)
01200 {
01201   if (plyfile->file_type == PLY_ASCII)
01202     ascii_get_element (plyfile, (char *) elem_ptr);
01203   else
01204     binary_get_element (plyfile, (char *) elem_ptr);
01205 }
01206 
01207 
01208 /******************************************************************************
01209 Extract the comments from the header information of a PLY file.
01210 
01211 Entry:
01212   plyfile - file identifier
01213 
01214 Exit:
01215   num_comments - number of comments returned
01216   returns a pointer to a list of comments
01217 ******************************************************************************/
01218 
01219 char **ply_get_comments(PlyFile *plyfile, int *num_comments)
01220 {
01221   *num_comments = plyfile->num_comments;
01222   return (plyfile->comments);
01223 }
01224 
01225 
01226 /******************************************************************************
01227 Extract the object information (arbitrary text) from the header information
01228 of a PLY file.
01229 
01230 Entry:
01231   plyfile - file identifier
01232 
01233 Exit:
01234   num_obj_info - number of lines of text information returned
01235   returns a pointer to a list of object info lines
01236 ******************************************************************************/
01237 
01238 char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
01239 {
01240   *num_obj_info = plyfile->num_obj_info;
01241   return (plyfile->obj_info);
01242 }
01243 
01244 
01245 /******************************************************************************
01246 Make ready for "other" properties of an element-- those properties that
01247 the user has not explicitly asked for, but that are to be stashed away
01248 in a special structure to be carried along with the element's other
01249 information.
01250 
01251 Entry:
01252   plyfile - file identifier
01253   elem    - element for which we want to save away other properties
01254 ******************************************************************************/
01255 
01256 void setup_other_props(PlyFile *, PlyElement *elem)
01257 {
01258   int i;
01259   PlyProperty *prop;
01260   int size = 0;
01261   int type_size;
01262 
01263   /* Examine each property in decreasing order of size. */
01264   /* We do this so that all data types will be aligned by */
01265   /* word, half-word, or whatever within the structure. */
01266 
01267   for (type_size = 8; type_size > 0; type_size /= 2) {
01268 
01269     /* add up the space taken by each property, and save this information */
01270     /* away in the property descriptor */
01271 
01272     for (i = 0; i < elem->nprops; i++) {
01273 
01274       /* don't bother with properties we've been asked to store explicitly */
01275       if (elem->store_prop[i])
01276         continue;
01277 
01278       prop = elem->props[i];
01279 
01280       /* internal types will be same as external */
01281       prop->internal_type = prop->external_type;
01282       prop->count_internal = prop->count_external;
01283 
01284       /* check list case */
01285       if (prop->is_list) {
01286 
01287         /* pointer to list */
01288         if (type_size == sizeof (void *)) {
01289           prop->offset = size;
01290           size += sizeof (void *);    /* always use size of a pointer here */
01291         }
01292 
01293         /* count of number of list elements */
01294         if (type_size == ply_type_size[prop->count_external]) {
01295           prop->count_offset = size;
01296           size += ply_type_size[prop->count_external];
01297         }
01298       }
01299       /* not list */
01300       else if (type_size == ply_type_size[prop->external_type]) {
01301         prop->offset = size;
01302         size += ply_type_size[prop->external_type];
01303       }
01304     }
01305 
01306   }
01307 
01308   /* save the size for the other_props structure */
01309   elem->other_size = size;
01310 }
01311 
01312 
01313 /******************************************************************************
01314 Specify that we want the "other" properties of an element to be tucked
01315 away within the user's structure.  The user needn't be concerned for how
01316 these properties are stored.
01317 
01318 Entry:
01319   plyfile   - file identifier
01320   elem_name - name of element that we want to store other_props in
01321   offset    - offset to where other_props will be stored inside user's structure
01322 
01323 Exit:
01324   returns pointer to structure containing description of other_props
01325 ******************************************************************************/
01326 
01327 PlyOtherProp *ply_get_other_properties(
01328   PlyFile *plyfile,
01329   char *elem_name,
01330   int offset
01331 )
01332 {
01333   int i;
01334   PlyElement *elem;
01335   PlyOtherProp *other;
01336   PlyProperty *prop;
01337   int nprops;
01338 
01339   /* find information about the element */
01340   elem = find_element (plyfile, elem_name);
01341   if (elem == NULL) {
01342     fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
01343              elem_name);
01344     return (NULL);
01345   }
01346 
01347   /* remember that this is the "current" element */
01348   plyfile->which_elem = elem;
01349 
01350   /* save the offset to where to store the other_props */
01351   elem->other_offset = offset;
01352 
01353   /* place the appropriate pointers, etc. in the element's property list */
01354   setup_other_props (plyfile, elem);
01355 
01356   /* create structure for describing other_props */
01357   other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
01358   other->name = strdup (elem_name);
01359 #if 0
01360   if (elem->other_offset == NO_OTHER_PROPS) {
01361     other->size = 0;
01362     other->props = NULL;
01363     other->nprops = 0;
01364     return (other);
01365   }
01366 #endif
01367   other->size = elem->other_size;
01368   other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
01369   
01370   /* save descriptions of each "other" property */
01371   nprops = 0;
01372   for (i = 0; i < elem->nprops; i++) {
01373     if (elem->store_prop[i])
01374       continue;
01375     prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
01376     copy_property (prop, elem->props[i]);
01377     other->props[nprops] = prop;
01378     nprops++;
01379   }
01380   other->nprops = nprops;
01381 
01382 #if 1
01383   /* set other_offset pointer appropriately if there are NO other properties */
01384   if (other->nprops == 0) {
01385     elem->other_offset = NO_OTHER_PROPS;
01386   }
01387 #endif
01388   
01389   /* return structure */
01390   return (other);
01391 }
01392 
01393 
01394 
01395 
01396 /*************************/
01397 /*  Other Element Stuff  */
01398 /*************************/
01399 
01400 
01401 
01402 
01403 /******************************************************************************
01404 Grab all the data for an element that a user does not want to explicitly
01405 read in.
01406 
01407 Entry:
01408   plyfile    - pointer to file
01409   elem_name  - name of element whose data is to be read in
01410   elem_count - number of instances of this element stored in the file
01411 
01412 Exit:
01413   returns pointer to ALL the "other" element data for this PLY file
01414 ******************************************************************************/
01415 
01416 PlyOtherElems *ply_get_other_element (
01417   PlyFile *plyfile,
01418   char *elem_name,
01419   int elem_count
01420 )
01421 {
01422   int i;
01423   PlyElement *elem;
01424   PlyOtherElems *other_elems;
01425   OtherElem *other;
01426 
01427   /* look for appropriate element */
01428   elem = find_element (plyfile, elem_name);
01429   if (elem == NULL) {
01430     fprintf (stderr,
01431              "ply_get_other_element: can't find element '%s'\n", elem_name);
01432     exit (-1);
01433   }
01434 
01435   /* create room for the new "other" element, initializing the */
01436   /* other data structure if necessary */
01437 
01438   if (plyfile->other_elems == NULL) {
01439     plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
01440     other_elems = plyfile->other_elems;
01441     other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
01442     other = &(other_elems->other_list[0]);
01443     other_elems->num_elems = 1;
01444   }
01445   else {
01446     other_elems = plyfile->other_elems;
01447     other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
01448                               sizeof (OtherElem) * other_elems->num_elems + 1);
01449     other = &(other_elems->other_list[other_elems->num_elems]);
01450     other_elems->num_elems++;
01451   }
01452 
01453   /* count of element instances in file */
01454   other->elem_count = elem_count;
01455 
01456   /* save name of element */
01457   other->elem_name = strdup (elem_name);
01458 
01459   /* create a list to hold all the current elements */
01460   other->other_data = (OtherData **)
01461                   malloc (sizeof (OtherData *) * other->elem_count);
01462 
01463   /* set up for getting elements */
01464   other->other_props = ply_get_other_properties (plyfile, elem_name,
01465                          offsetof(OtherData,other_props));
01466 
01467   /* grab all these elements */
01468   for (i = 0; i < other->elem_count; i++) {
01469     /* grab and element from the file */
01470     other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
01471     ply_get_element (plyfile, (void *) other->other_data[i]);
01472   }
01473 
01474   /* return pointer to the other elements data */
01475   return (other_elems);
01476 }
01477 
01478 
01479 /******************************************************************************
01480 Pass along a pointer to "other" elements that we want to save in a given
01481 PLY file.  These other elements were presumably read from another PLY file.
01482 
01483 Entry:
01484   plyfile     - file pointer in which to store this other element info
01485   other_elems - info about other elements that we want to store
01486 ******************************************************************************/
01487 
01488 void ply_describe_other_elements (
01489   PlyFile *plyfile,
01490   PlyOtherElems *other_elems
01491 )
01492 {
01493   int i;
01494   OtherElem *other;
01495 
01496   /* ignore this call if there is no other element */
01497   if (other_elems == NULL)
01498     return;
01499 
01500   /* save pointer to this information */
01501   plyfile->other_elems = other_elems;
01502 
01503   /* describe the other properties of this element */
01504 
01505   for (i = 0; i < other_elems->num_elems; i++) {
01506     other = &(other_elems->other_list[i]);
01507     ply_element_count (plyfile, other->elem_name, other->elem_count);
01508     ply_describe_other_properties (plyfile, other->other_props,
01509                                    offsetof(OtherData,other_props));
01510   }
01511 }
01512 
01513 
01514 /******************************************************************************
01515 Write out the "other" elements specified for this PLY file.
01516 
01517 Entry:
01518   plyfile - pointer to PLY file to write out other elements for
01519 ******************************************************************************/
01520 
01521 void ply_put_other_elements (PlyFile *plyfile)
01522 {
01523   int i,j;
01524   OtherElem *other;
01525 
01526   /* make sure we have other elements to write */
01527   if (plyfile->other_elems == NULL)
01528     return;
01529 
01530   /* write out the data for each "other" element */
01531 
01532   for (i = 0; i < plyfile->other_elems->num_elems; i++) {
01533 
01534     other = &(plyfile->other_elems->other_list[i]);
01535     ply_put_element_setup (plyfile, other->elem_name);
01536 
01537     /* write out each instance of the current element */
01538     for (j = 0; j < other->elem_count; j++)
01539       ply_put_element (plyfile, (void *) other->other_data[j]);
01540   }
01541 }
01542 
01543 
01544 /******************************************************************************
01545 Free up storage used by an "other" elements data structure.
01546 
01547 Entry:
01548   other_elems - data structure to free up
01549 ******************************************************************************/
01550 
01551 void ply_free_other_elements (PlyOtherElems *)
01552 {
01553 
01554 }
01555 
01556 
01557 
01558 /*******************/
01559 /*  Miscellaneous  */
01560 /*******************/
01561 
01562 
01563 
01564 /******************************************************************************
01565 Close a PLY file.
01566 
01567 Entry:
01568   plyfile - identifier of file to close
01569 ******************************************************************************/
01570 
01571 void ply_close(PlyFile *plyfile)
01572 {
01573   // Changed by Will Schroeder. Old stuff leaked like a sieve.
01574 
01575   /* free up memory associated with the PLY file */
01576   fclose (plyfile->fp);
01577 
01578   int i, j;
01579   PlyElement *elem;
01580   for (i=0; i<plyfile->nelems; i++)
01581     {
01582     elem = plyfile->elems[i];
01583     if ( elem->name ) {free(elem->name);}
01584     for (j=0; j<elem->nprops; j++)
01585       {
01586       if ( elem->props[j]->name )
01587          {free(const_cast<char *>(elem->props[j]->name));}
01588       free (elem->props[j]);
01589       }
01590     free (elem->props);
01591     free (elem->store_prop);
01592     free (elem);
01593     }
01594   free(plyfile->elems);
01595 
01596   for (i=0; i<plyfile->num_comments; i++)
01597     {
01598     free (plyfile->comments[i]);
01599     }
01600   free (plyfile->comments);
01601   
01602   for (i=0; i<plyfile->num_obj_info; i++)
01603     {
01604     free (plyfile->obj_info[i]);
01605     }
01606   free (plyfile->obj_info);
01607   
01608   free (plyfile);
01609 }
01610 
01611 
01612 /******************************************************************************
01613 Get version number and file type of a PlyFile.
01614 
01615 Entry:
01616   ply - pointer to PLY file
01617 
01618 Exit:
01619   version - version of the file
01620   file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
01621 ******************************************************************************/
01622 
01623 void ply_get_info(PlyFile *ply, float *version, int *file_type)
01624 {
01625   if (ply == NULL)
01626     return;
01627 
01628   *version = ply->version;
01629   *file_type = ply->file_type;
01630 }
01631 
01632 
01633 /******************************************************************************
01634 Compare two strings.  Returns 1 if they are the same, 0 if not.
01635 ******************************************************************************/
01636 
01637 int equal_strings(const char *s1, const char *s2)
01638 {
01639   while (*s1 && *s2)
01640     if (*s1++ != *s2++)
01641       return (0);
01642 
01643   if (*s1 != *s2)
01644     return (0);
01645   else
01646     return (1);
01647 }
01648 
01649 
01650 /******************************************************************************
01651 Find an element from the element list of a given PLY object.
01652 
01653 Entry:
01654   plyfile - file id for PLY file
01655   element - name of element we're looking for
01656 
01657 Exit:
01658   returns the element, or NULL if not found
01659 ******************************************************************************/
01660 
01661 PlyElement *find_element(PlyFile *plyfile, const char *element)
01662 {
01663     int i;
01664 
01665     for (i = 0; i < plyfile->nelems; i++)
01666         if (equal_strings (element, plyfile->elems[i]->name))
01667             return (plyfile->elems[i]);
01668     
01669     return (NULL);
01670 }
01671 
01672 
01673 /******************************************************************************
01674 Find a property in the list of properties of a given element.
01675 
01676 Entry:
01677   elem      - pointer to element in which we want to find the property
01678   prop_name - name of property to find
01679 
01680 Exit:
01681   index - index to position in list
01682   returns a pointer to the property, or NULL if not found
01683 ******************************************************************************/
01684 
01685 PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
01686 {
01687     int i;
01688     
01689     for( i = 0; i < elem->nprops; i++)
01690         if (equal_strings (prop_name, elem->props[i]->name))
01691         {
01692             *index = i;
01693             return (elem->props[i]);
01694         }
01695     
01696     *index = -1;
01697     return (NULL);
01698 }
01699 
01700 
01701 /******************************************************************************
01702 Read an element from an ascii file.
01703 
01704 Entry:
01705   plyfile  - file identifier
01706   elem_ptr - pointer to element
01707 ******************************************************************************/
01708 
01709 void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
01710 {
01711   int j,k;
01712   PlyElement *elem;
01713   PlyProperty *prop;
01714   char **words;
01715   int nwords;
01716   int which_word;
01717   char *elem_data,*item=0;
01718   char *item_ptr;
01719   int item_size=0;
01720   int int_val;
01721   unsigned int uint_val;
01722   double double_val;
01723   int list_count;
01724   int store_it;
01725   char **store_array;
01726   char *orig_line;
01727   char *other_data=0;
01728   int other_flag;
01729 
01730   /* the kind of element we're reading currently */
01731   elem = plyfile->which_elem;
01732 
01733   /* do we need to setup for other_props? */
01734 
01735   if (elem->other_offset != NO_OTHER_PROPS) {
01736     char **ptr;
01737     other_flag = 1;
01738     /* make room for other_props */
01739     other_data = (char *) myalloc (elem->other_size);
01740     /* store pointer in user's structure to the other_props */
01741     ptr = (char **) (elem_ptr + elem->other_offset);
01742     *ptr = other_data;
01743   }
01744   else
01745     other_flag = 0;
01746 
01747   /* read in the element */
01748 
01749   words = get_words (plyfile->fp, &nwords, &orig_line);
01750   if (words == NULL) {
01751     fprintf (stderr, "ply_get_element: unexpected end of file\n");
01752     exit (-1);
01753   }
01754 
01755   which_word = 0;
01756 
01757   for (j = 0; j < elem->nprops; j++) {
01758 
01759     prop = elem->props[j];
01760     store_it = (elem->store_prop[j] | other_flag);
01761 
01762     /* store either in the user's structure or in other_props */
01763     if (elem->store_prop[j])
01764       elem_data = elem_ptr;
01765     else
01766       elem_data = other_data;
01767 
01768     if (prop->is_list) {       /* a list */
01769 
01770       /* get and store the number of items in the list */
01771       get_ascii_item (words[which_word++], prop->count_external,
01772                       &int_val, &uint_val, &double_val);
01773       if (store_it) {
01774         item = elem_data + prop->count_offset;
01775         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01776       }
01777 
01778       /* allocate space for an array of items and store a ptr to the array */
01779       list_count = int_val;
01780       item_size = ply_type_size[prop->internal_type];
01781       store_array = (char **) (elem_data + prop->offset);
01782 
01783       if (list_count == 0) {
01784         if (store_it)
01785           *store_array = NULL;
01786       }
01787       else {
01788         if (store_it) {
01789           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01790           item = item_ptr;
01791           *store_array = item_ptr;
01792         }
01793 
01794         /* read items and store them into the array */
01795         for (k = 0; k < list_count; k++) {
01796           get_ascii_item (words[which_word++], prop->external_type,
01797                           &int_val, &uint_val, &double_val);
01798           if (store_it) {
01799             store_item (item, prop->internal_type,
01800                         int_val, uint_val, double_val);
01801             item += item_size;
01802           }
01803         }
01804       }
01805 
01806     }
01807     else {                     /* not a list */
01808       get_ascii_item (words[which_word++], prop->external_type,
01809                       &int_val, &uint_val, &double_val);
01810       if (store_it) {
01811         item = elem_data + prop->offset;
01812         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01813       }
01814     }
01815 
01816   }
01817 
01818   free (words);
01819 }
01820 
01821 
01822 /******************************************************************************
01823 Read an element from a binary file.
01824 
01825 Entry:
01826   plyfile  - file identifier
01827   elem_ptr - pointer to an element
01828 ******************************************************************************/
01829 
01830 void binary_get_element(PlyFile *plyfile, char *elem_ptr)
01831 {
01832   int j,k;
01833   PlyElement *elem;
01834   PlyProperty *prop;
01835   //FILE *fp = plyfile->fp;
01836   char *elem_data,*item=0;
01837   char *item_ptr;
01838   int item_size=0;
01839   int int_val;
01840   unsigned int uint_val;
01841   double double_val;
01842   int list_count;
01843   int store_it;
01844   char **store_array;
01845   char *other_data=0;
01846   int other_flag;
01847 
01848   /* the kind of element we're reading currently */
01849   elem = plyfile->which_elem;
01850 
01851   /* do we need to setup for other_props? */
01852 
01853   if (elem->other_offset != NO_OTHER_PROPS) {
01854     char **ptr;
01855     other_flag = 1;
01856     /* make room for other_props */
01857     other_data = (char *) myalloc (elem->other_size);
01858     /* store pointer in user's structure to the other_props */
01859     ptr = (char **) (elem_ptr + elem->other_offset);
01860     *ptr = other_data;
01861   }
01862   else
01863     other_flag = 0;
01864 
01865   /* read in a number of elements */
01866 
01867   for (j = 0; j < elem->nprops; j++) {
01868 
01869     prop = elem->props[j];
01870     store_it = (elem->store_prop[j] | other_flag);
01871 
01872     /* store either in the user's structure or in other_props */
01873     if (elem->store_prop[j])
01874       elem_data = elem_ptr;
01875     else
01876       elem_data = other_data;
01877 
01878     if (prop->is_list) {       /* a list */
01879 
01880       /* get and store the number of items in the list */
01881       get_binary_item (plyfile, prop->count_external,
01882                        &int_val, &uint_val, &double_val);
01883       if (store_it) {
01884         item = elem_data + prop->count_offset;
01885         store_item(item, prop->count_internal, int_val, uint_val, double_val);
01886       }
01887 
01888       /* allocate space for an array of items and store a ptr to the array */
01889       list_count = int_val;
01890       /* The "if" was added by Afra Zomorodian 8/22/95
01891        * so that zipper won't crash reading plies that have additional
01892        * properties.
01893        */ 
01894       if (store_it) {
01895         item_size = ply_type_size[prop->internal_type];
01896       }
01897       store_array = (char **) (elem_data + prop->offset);
01898       if (list_count == 0) {
01899         if (store_it)
01900           *store_array = NULL;
01901       }
01902       else {
01903         if (store_it) {
01904           item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
01905           item = item_ptr;
01906           *store_array = item_ptr;
01907         }
01908 
01909         /* read items and store them into the array */
01910         for (k = 0; k < list_count; k++) {
01911           get_binary_item (plyfile, prop->external_type,
01912                           &int_val, &uint_val, &double_val);
01913           if (store_it) {
01914             store_item (item, prop->internal_type,
01915                         int_val, uint_val, double_val);
01916             item += item_size;
01917           }
01918         }
01919       }
01920 
01921     }
01922     else {                     /* not a list */
01923       get_binary_item (plyfile, prop->external_type,
01924                       &int_val, &uint_val, &double_val);
01925       if (store_it) {
01926         item = elem_data + prop->offset;
01927         store_item (item, prop->internal_type, int_val, uint_val, double_val);
01928       }
01929     }
01930 
01931   }
01932 }
01933 
01934 
01935 /******************************************************************************
01936 Write to a file the word that represents a PLY data type.
01937 
01938 Entry:
01939   fp   - file pointer
01940   code - code for type
01941 ******************************************************************************/
01942 
01943 void write_scalar_type (FILE *fp, int code)
01944 {
01945   /* make sure this is a valid code */
01946 
01947   if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
01948     fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
01949     exit (-1);
01950   }
01951 
01952   /* write the code to a file */
01953 
01954   fprintf (fp, "%s", type_names[code]);
01955 }
01956 
01957 
01958 /******************************************************************************
01959 Get a text line from a file and break it up into words.
01960 
01961 IMPORTANT: The calling routine call "free" on the returned pointer once
01962 finished with it.
01963 
01964 Entry:
01965   fp - file to read from
01966 
01967 Exit:
01968   nwords    - number of words returned
01969   orig_line - the original line of characters
01970   returns a list of words from the line, or NULL if end-of-file
01971 ******************************************************************************/
01972 
01973 char **get_words(FILE *fp, int *nwords, char **orig_line)
01974 {
01975 #define BIG_STRING 4096
01976   static char str[BIG_STRING];
01977   static char str_copy[BIG_STRING];
01978   char **words;
01979   int max_words = 10;
01980   int num_words = 0;
01981   char *ptr,*ptr2;
01982   char *result;
01983 
01984   /* read in a line */
01985   result = fgets (str, BIG_STRING, fp);
01986   if (result == NULL) {
01987     *nwords = 0;
01988     *orig_line = NULL;
01989     return (NULL);
01990   }
01991 
01992   words = (char **) myalloc (sizeof (char *) * max_words);
01993 
01994   /* convert line-feed and tabs into spaces */
01995   /* (this guarentees that there will be a space before the */
01996   /*  null character at the end of the string) */
01997 
01998   str[BIG_STRING-2] = ' ';
01999   str[BIG_STRING-1] = '\0';
02000 
02001   for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
02002     *ptr2 = *ptr;
02003     if (*ptr == '\t') {
02004       *ptr = ' ';
02005       *ptr2 = ' ';
02006     }
02007     else if (*ptr == '\n') {
02008       *ptr = ' ';
02009       *ptr2 = '\0';
02010       break;
02011     }
02012   }
02013 
02014   /* find the words in the line */
02015 
02016   ptr = str;
02017   while (*ptr != '\0') {
02018 
02019     /* jump over leading spaces */
02020     while (*ptr == ' ')
02021       ptr++;
02022 
02023     /* break if we reach the end */
02024     if (*ptr == '\0')
02025       break;
02026 
02027     /* save pointer to beginning of word */
02028     if (num_words >= max_words) {
02029       max_words += 10;
02030       words = (char **) realloc (words, sizeof (char *) * max_words);
02031     }
02032     words[num_words++] = ptr;
02033 
02034     /* jump over non-spaces */
02035     while (*ptr != ' ')
02036       ptr++;
02037 
02038     /* place a null character here to mark the end of the word */
02039     *ptr++ = '\0';
02040   }
02041 
02042   /* return the list of words */
02043   *nwords = num_words;
02044   *orig_line = str_copy;
02045   return (words);
02046 }
02047 
02048 
02049 /******************************************************************************
02050 Return the value of an item, given a pointer to it and its type.
02051 
02052 Entry:
02053   item - pointer to item
02054   type - data type that "item" points to
02055 
02056 Exit:
02057   returns a double-precision float that contains the value of the item
02058 ******************************************************************************/
02059 
02060 double get_item_value(char *item, int type)
02061 {
02062   unsigned char *puchar;
02063   char *pchar;
02064   short int *pshort;
02065   unsigned short int *pushort;
02066   int *pint;
02067   unsigned int *puint;
02068   float *pfloat;
02069   double *pdouble;
02070   int int_value;
02071   unsigned int uint_value;
02072   double double_value;
02073 
02074   switch (type) {
02075     case PLY_CHAR:
02076       pchar = (char *) item;
02077       int_value = *pchar;
02078       return ((double) int_value);
02079     case PLY_UCHAR:
02080     case PLY_UINT8:
02081       puchar = (unsigned char *) item;
02082       int_value = *puchar;
02083       return ((double) int_value);
02084     case PLY_SHORT:
02085       pshort = (short int *) item;
02086       int_value = *pshort;
02087       return ((double) int_value);
02088     case PLY_USHORT:
02089       pushort = (unsigned short int *) item;
02090       int_value = *pushort;
02091       return ((double) int_value);
02092     case PLY_INT:
02093     case PLY_INT32:
02094       pint = (int *) item;
02095       int_value = *pint;
02096       return ((double) int_value);
02097     case PLY_UINT:
02098       puint = (unsigned int *) item;
02099       uint_value = *puint;
02100       return ((double) uint_value);
02101     case PLY_FLOAT:
02102     case PLY_FLOAT32:
02103       pfloat = (float *) item;
02104       double_value = *pfloat;
02105       return (double_value);
02106     case PLY_DOUBLE:
02107       pdouble = (double *) item;
02108       double_value = *pdouble;
02109       return (double_value);
02110   }
02111   fprintf (stderr, "get_item_value: bad type = %d\n", type);
02112   return 0;
02113 }
02114 
02115 
02116 /******************************************************************************
02117 Write out an item to a file as raw binary bytes.
02118 
02119 Entry:
02120   fp         - file to write to
02121   int_val    - integer version of item
02122   uint_val   - unsigned integer version of item
02123   double_val - double-precision float version of item
02124   type       - data type to write out
02125 ******************************************************************************/
02126 
02127 void write_binary_item(PlyFile *plyfile,
02128                                int int_val,
02129                                unsigned int uint_val,
02130                                double double_val,
02131                                int type
02132 )
02133 {
02134   FILE *fp = plyfile->fp;
02135   unsigned char uchar_val;
02136   char char_val;
02137   unsigned short ushort_val;
02138   short short_val;
02139   float float_val;
02140 
02141   switch (type) {
02142     case PLY_CHAR:
02143       char_val = int_val;
02144       fwrite (&char_val, 1, 1, fp);
02145       break;
02146     case PLY_SHORT:
02147       short_val = int_val;
02148       if( plyfile->file_type == PLY_BINARY_BE )
02149           swap2BE(&short_val);
02150       else
02151           swap2LE(&short_val);
02152       fwrite (&short_val, 2, 1, fp);
02153       break;
02154       case PLY_INT:
02155       case PLY_INT32:
02156           if( plyfile->file_type == PLY_BINARY_BE )
02157           {
02158               swap4BE(&int_val);
02159           }
02160           else
02161           {
02162               swap4LE(&int_val);
02163           }
02164           fwrite (&int_val, 4, 1, fp);
02165           break;
02166       case PLY_UCHAR:
02167       case PLY_UINT8:
02168           uchar_val = uint_val;
02169           fwrite (&uchar_val, 1, 1, fp);
02170           break;
02171       case PLY_USHORT:
02172           if( plyfile->file_type == PLY_BINARY_BE )
02173           {
02174               swap2BE(&ushort_val);
02175           }
02176           else
02177           {
02178               swap2LE(&ushort_val);
02179           }
02180           ushort_val = uint_val;
02181           fwrite (&ushort_val, 2, 1, fp);
02182           break;
02183       case PLY_UINT:
02184           if( plyfile->file_type == PLY_BINARY_BE )
02185           {
02186               swap4BE(&uint_val);
02187           }
02188           else
02189           {
02190               swap4LE(&uint_val);
02191           }
02192           fwrite (&uint_val, 4, 1, fp);
02193           break;
02194       case PLY_FLOAT:
02195       case PLY_FLOAT32:
02196           float_val = double_val;
02197           if( plyfile->file_type == PLY_BINARY_BE )
02198           {
02199               swap4BE(&float_val);
02200           }
02201           else
02202           {
02203               swap4LE(&float_val);
02204           }
02205           fwrite (&float_val, 4, 1, fp);
02206           break;
02207       case PLY_DOUBLE:
02208           if( plyfile->file_type == PLY_BINARY_BE )
02209           {
02210               swap8BE(&double_val);
02211           }
02212           else
02213           {
02214               swap8LE(&double_val);
02215           }
02216           fwrite (&double_val, 8, 1, fp);
02217       break;
02218     default:
02219       fprintf (stderr, "write_binary_item: bad type = %d\n", type);
02220       exit (-1);
02221   }
02222 }
02223 
02224 
02225 /******************************************************************************
02226 Write out an item to a file as ascii characters.
02227 
02228 Entry:
02229   fp         - file to write to
02230   int_val    - integer version of item
02231   uint_val   - unsigned integer version of item
02232   double_val - double-precision float version of item
02233   type       - data type to write out
02234 ******************************************************************************/
02235 
02236 void write_ascii_item(
02237   FILE *fp,
02238   int int_val,
02239   unsigned int uint_val,
02240   double double_val,
02241   int type
02242 )
02243 {
02244   switch (type) {
02245     case PLY_CHAR:
02246     case PLY_SHORT:
02247     case PLY_INT:
02248     case PLY_INT32:
02249       fprintf (fp, "%d ", int_val);
02250       break;
02251     case PLY_UCHAR:
02252     case PLY_UINT8:
02253     case PLY_USHORT:
02254     case PLY_UINT:
02255       fprintf (fp, "%u ", uint_val);
02256       break;
02257     case PLY_FLOAT:
02258     case PLY_FLOAT32:
02259     case PLY_DOUBLE:
02260       fprintf (fp, "%g ", double_val);
02261       break;
02262     default:
02263       fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
02264       exit (-1);
02265   }
02266 }
02267 
02268 /******************************************************************************
02269 Get the value of an item that is in memory, and place the result
02270 into an integer, an unsigned integer and a double.
02271 
02272 Entry:
02273   ptr  - pointer to the item
02274   type - data type supposedly in the item
02275 
02276 Exit:
02277   int_val    - integer value
02278   uint_val   - unsigned integer value
02279   double_val - double-precision floating point value
02280 ******************************************************************************/
02281 
02282 void get_stored_item(
02283   void *ptr,
02284   int type,
02285   int *int_val,
02286   unsigned int *uint_val,
02287   double *double_val
02288 )
02289 {
02290   switch (type) {
02291     case PLY_CHAR:
02292       *int_val = *((char *) ptr);
02293       *uint_val = *int_val;
02294       *double_val = *int_val;
02295       break;
02296     case PLY_UCHAR:
02297     case PLY_UINT8:
02298       *uint_val = *((unsigned char *) ptr);
02299       *int_val = *uint_val;
02300       *double_val = *uint_val;
02301       break;
02302     case PLY_SHORT:
02303       *int_val = *((short int *) ptr);
02304       *uint_val = *int_val;
02305       *double_val = *int_val;
02306       break;
02307     case PLY_USHORT:
02308       *uint_val = *((unsigned short int *) ptr);
02309       *int_val = *uint_val;
02310       *double_val = *uint_val;
02311       break;
02312     case PLY_INT:
02313     case PLY_INT32:
02314       *int_val = *((int *) ptr);
02315       *uint_val = *int_val;
02316       *double_val = *int_val;
02317       break;
02318     case PLY_UINT:
02319       *uint_val = *((unsigned int *) ptr);
02320       *int_val = *uint_val;
02321       *double_val = *uint_val;
02322       break;
02323     case PLY_FLOAT:
02324     case PLY_FLOAT32:
02325       *double_val = *((float *) ptr);
02326       *int_val = (int) *double_val;
02327       *uint_val = (unsigned int) *double_val;
02328       break;
02329     case PLY_DOUBLE:
02330       *double_val = *((double *) ptr);
02331       *int_val = (int) *double_val;
02332       *uint_val = (unsigned int) *double_val;
02333       break;
02334     default:
02335       fprintf (stderr, "get_stored_item: bad type = %d\n", type);
02336       exit (-1);
02337   }
02338 }
02339 
02340 
02341 /******************************************************************************
02342 Get the value of an item from a binary file, and place the result
02343 into an integer, an unsigned integer and a double.
02344 
02345 Entry:
02346   fp   - file to get item from
02347   type - data type supposedly in the word
02348 
02349 Exit:
02350   int_val    - integer value
02351   uint_val   - unsigned integer value
02352   double_val - double-precision floating point value
02353 ******************************************************************************/
02354 
02355 void get_binary_item(
02356   PlyFile *plyfile,
02357   int type,
02358   int *int_val,
02359   unsigned int *uint_val,
02360   double *double_val
02361 )
02362 {
02363   char c[8];
02364   void *ptr;
02365 
02366   ptr = (void *) c;
02367 
02368   switch (type) {
02369     case PLY_CHAR:
02370       if( fread (ptr, 1, 1, plyfile->fp) <= 0 )
02371           abort();
02372       *int_val = *((char *) ptr);
02373       *uint_val = *int_val;
02374       *double_val = *int_val;
02375       break;
02376       case PLY_UCHAR:
02377       case PLY_UINT8:
02378           if( fread (ptr, 1, 1, plyfile->fp) <= 0 )
02379               abort();
02380           *uint_val = *((unsigned char *) ptr);
02381           *int_val = *uint_val;
02382           *double_val = *uint_val;
02383           break;
02384       case PLY_SHORT:
02385           if( fread (ptr, 2, 1, plyfile->fp) <= 0 )
02386               abort();
02387           if( plyfile->file_type == PLY_BINARY_BE )
02388           {
02389               swap2BE(ptr);
02390           }
02391           else
02392           {
02393               swap2LE(ptr);
02394           }
02395           *int_val = *((short int *) ptr);
02396           *uint_val = *int_val;
02397           *double_val = *int_val;
02398           break;
02399       case PLY_USHORT:
02400           if( fread (ptr, 2, 1, plyfile->fp) <= 0 )
02401               abort();
02402           if( plyfile->file_type == PLY_BINARY_BE )
02403           {
02404               swap2BE(ptr);
02405           }
02406           else
02407           {
02408               swap2LE(ptr);
02409           }
02410           *uint_val = *((unsigned short int *) ptr);
02411           *int_val = *uint_val;
02412           *double_val = *uint_val;
02413           break;
02414       case PLY_INT:
02415       case PLY_INT32:
02416           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02417               abort();
02418           if( plyfile->file_type == PLY_BINARY_BE )
02419           {
02420               swap4BE(ptr);
02421           }
02422           else
02423           {
02424               swap4LE(ptr);
02425           }
02426           *int_val = *((int *) ptr);
02427           *uint_val = *int_val;
02428           *double_val = *int_val;
02429           break;
02430       case PLY_UINT:
02431           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02432               abort();
02433           if( plyfile->file_type == PLY_BINARY_BE )
02434           {
02435               swap4BE(ptr);
02436           }
02437           else
02438           {
02439               swap4LE(ptr);
02440           }
02441           *uint_val = *((unsigned int *) ptr);
02442           *int_val = *uint_val;
02443           *double_val = *uint_val;
02444           break;
02445       case PLY_FLOAT:
02446       case PLY_FLOAT32:
02447           if( fread (ptr, 4, 1, plyfile->fp) <= 0 )
02448               abort();
02449           if( plyfile->file_type == PLY_BINARY_BE )
02450           {
02451               swap4BE(ptr);
02452           }
02453           else
02454           {
02455               swap4LE(ptr);
02456           }
02457           *double_val = *((float *) ptr);
02458           *int_val = (int) *double_val;
02459           *uint_val = (unsigned int) *double_val;
02460           break;
02461       case PLY_DOUBLE:
02462           if( fread (ptr, 8, 1, plyfile->fp) <= 0 )
02463               abort();
02464           if( plyfile->file_type == PLY_BINARY_BE )
02465           {
02466               swap8BE(ptr);
02467           }
02468           else
02469           {
02470               swap8LE(ptr);
02471           }
02472       *double_val = *((double *) ptr);
02473       *int_val = (int) *double_val;
02474       *uint_val = (unsigned int) *double_val;
02475       break;
02476     default:
02477       fprintf (stderr, "get_binary_item: bad type = %d\n", type);
02478       exit (-1);
02479   }
02480 }
02481 
02482 
02483 /******************************************************************************
02484 Extract the value of an item from an ascii word, and place the result
02485 into an integer, an unsigned integer and a double.
02486 
02487 Entry:
02488   word - word to extract value from
02489   type - data type supposedly in the word
02490 
02491 Exit:
02492   int_val    - integer value
02493   uint_val   - unsigned integer value
02494   double_val - double-precision floating point value
02495 ******************************************************************************/
02496 
02497 void get_ascii_item(
02498   char *word,
02499   int type,
02500   int *int_val,
02501   unsigned int *uint_val,
02502   double *double_val
02503 )
02504 {
02505   switch (type) {
02506     case PLY_CHAR:
02507     case PLY_UCHAR:
02508     case PLY_UINT8:
02509     case PLY_SHORT:
02510     case PLY_USHORT:
02511     case PLY_INT:
02512     case PLY_INT32:
02513       *int_val = atoi (word);
02514       *uint_val = *int_val;
02515       *double_val = *int_val;
02516       break;
02517 
02518     case PLY_UINT:
02519       *uint_val = strtoul (word, (char **) NULL, 10);
02520       *int_val = *uint_val;
02521       *double_val = *uint_val;
02522       break;
02523 
02524     case PLY_FLOAT:
02525     case PLY_FLOAT32:
02526     case PLY_DOUBLE:
02527       *double_val = atof (word);
02528       *int_val = (int) *double_val;
02529       *uint_val = (unsigned int) *double_val;
02530       break;
02531 
02532     default:
02533       fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
02534       exit (-1);
02535   }
02536 }
02537 
02538 
02539 /******************************************************************************
02540 Store a value into a place being pointed to, guided by a data type.
02541 
02542 Entry:
02543   item       - place to store value
02544   type       - data type
02545   int_val    - integer version of value
02546   uint_val   - unsigned integer version of value
02547   double_val - double version of value
02548 
02549 Exit:
02550   item - pointer to stored value
02551 ******************************************************************************/
02552 
02553 void store_item (
02554   char *item,
02555   int type,
02556   int int_val,
02557   unsigned int uint_val,
02558   double double_val
02559 )
02560 {
02561   unsigned char *puchar;
02562   short int *pshort;
02563   unsigned short int *pushort;
02564   int *pint;
02565   unsigned int *puint;
02566   float *pfloat;
02567   double *pdouble;
02568 
02569   switch (type) {
02570     case PLY_CHAR:
02571       *item = int_val;
02572       break;
02573     case PLY_UCHAR:
02574     case PLY_UINT8:
02575       puchar = (unsigned char *) item;
02576       *puchar = uint_val;
02577       break;
02578     case PLY_SHORT:
02579       pshort = (short *) item;
02580       *pshort = int_val;
02581       break;
02582     case PLY_USHORT:
02583       pushort = (unsigned short *) item;
02584       *pushort = uint_val;
02585       break;
02586     case PLY_INT:
02587     case PLY_INT32:
02588       pint = (int *) item;
02589       *pint = int_val;
02590       break;
02591     case PLY_UINT:
02592       puint = (unsigned int *) item;
02593       *puint = uint_val;
02594       break;
02595     case PLY_FLOAT:
02596     case PLY_FLOAT32:
02597       pfloat = (float *) item;
02598       *pfloat = double_val;
02599       break;
02600     case PLY_DOUBLE:
02601       pdouble = (double *) item;
02602       *pdouble = double_val;
02603       break;
02604     default:
02605       fprintf (stderr, "store_item: bad type = %d\n", type);
02606       exit (-1);
02607   }
02608 }
02609 
02610 
02611 /******************************************************************************
02612 Add an element to a PLY file descriptor.
02613 
02614 Entry:
02615   plyfile - PLY file descriptor
02616   words   - list of words describing the element
02617   nwords  - number of words in the list
02618 ******************************************************************************/
02619 
02620 void add_element (PlyFile *plyfile, char **words, int)
02621 {
02622   PlyElement *elem;
02623 
02624   /* create the new element */
02625   elem = (PlyElement *) myalloc (sizeof (PlyElement));
02626   elem->name = strdup (words[1]);
02627   elem->num = atoi (words[2]);
02628   elem->nprops = 0;
02629 
02630   /* make room for new element in the object's list of elements */
02631   if (plyfile->nelems == 0)
02632     plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
02633   else
02634     plyfile->elems = (PlyElement **) realloc (plyfile->elems,
02635                      sizeof (PlyElement *) * (plyfile->nelems + 1));
02636 
02637   /* add the new element to the object's list */
02638   plyfile->elems[plyfile->nelems] = elem;
02639   plyfile->nelems++;
02640 }
02641 
02642 
02643 /******************************************************************************
02644 Return the type of a property, given the name of the property.
02645 
02646 Entry:
02647   name - name of property type
02648 
02649 Exit:
02650   returns integer code for property, or 0 if not found
02651 ******************************************************************************/
02652 
02653 int get_prop_type(char *type_name)
02654 {
02655   int i;
02656 
02657   for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
02658     if (equal_strings (type_name, type_names[i]))
02659       return (i);
02660 
02661   /* if we get here, we didn't find the type */
02662   return (0);
02663 }
02664 
02665 
02666 /******************************************************************************
02667 Add a property to a PLY file descriptor.
02668 
02669 Entry:
02670   plyfile - PLY file descriptor
02671   words   - list of words describing the property
02672   nwords  - number of words in the list
02673 ******************************************************************************/
02674 
02675 void add_property (PlyFile *plyfile, char **words, int )
02676 {
02677   PlyProperty *prop;
02678   PlyElement *elem;
02679 
02680   /* create the new property */
02681 
02682   prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
02683 
02684   if (equal_strings (words[1], "list")) {       /* is a list */
02685     prop->count_external = get_prop_type (words[2]);
02686     prop->external_type = get_prop_type (words[3]);
02687     prop->name = strdup (words[4]);
02688     prop->is_list = 1;
02689   }
02690   else {                                        /* not a list */
02691     prop->external_type = get_prop_type (words[1]);
02692     prop->name = strdup (words[2]);
02693     prop->is_list = 0;
02694   }
02695 
02696   /* add this property to the list of properties of the current element */
02697 
02698   elem = plyfile->elems[plyfile->nelems - 1];
02699 
02700   if (elem->nprops == 0)
02701     elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
02702   else
02703     elem->props = (PlyProperty **) realloc (elem->props,
02704                   sizeof (PlyProperty *) * (elem->nprops + 1));
02705 
02706   elem->props[elem->nprops] = prop;
02707   elem->nprops++;
02708 }
02709 
02710 
02711 /******************************************************************************
02712 Add a comment to a PLY file descriptor.
02713 
02714 Entry:
02715   plyfile - PLY file descriptor
02716   line    - line containing comment
02717 ******************************************************************************/
02718 
02719 void add_comment (PlyFile *plyfile, char *line)
02720 {
02721   int i;
02722 
02723   /* skip over "comment" and leading spaces and tabs */
02724   i = 7;
02725   while (line[i] == ' ' || line[i] == '\t')
02726     i++;
02727 
02728   ply_put_comment (plyfile, &line[i]);
02729 }
02730 
02731 
02732 /******************************************************************************
02733 Add a some object information to a PLY file descriptor.
02734 
02735 Entry:
02736   plyfile - PLY file descriptor
02737   line    - line containing text info
02738 ******************************************************************************/
02739 
02740 void add_obj_info (PlyFile *plyfile, char *line)
02741 {
02742   int i;
02743 
02744   /* skip over "obj_info" and leading spaces and tabs */
02745   i = 8;
02746   while (line[i] == ' ' || line[i] == '\t')
02747     i++;
02748 
02749   ply_put_obj_info (plyfile, &line[i]);
02750 }
02751 
02752 
02753 /******************************************************************************
02754 Copy a property.
02755 ******************************************************************************/
02756 
02757 void copy_property(PlyProperty *dest, PlyProperty *src)
02758 {
02759   dest->name = strdup (src->name);
02760   dest->external_type = src->external_type;
02761   dest->internal_type = src->internal_type;
02762   dest->offset = src->offset;
02763 
02764   dest->is_list = src->is_list;
02765   dest->count_external = src->count_external;
02766   dest->count_internal = src->count_internal;
02767   dest->count_offset = src->count_offset;
02768 }
02769 
02770 
02771 /******************************************************************************
02772 Allocate some memory.
02773 
02774 Entry:
02775   size  - amount of memory requested (in bytes)
02776   lnum  - line number from which memory was requested
02777   fname - file name from which memory was requested
02778 ******************************************************************************/
02779 
02780 char *my_alloc(int size, int lnum, const char *fname)
02781 {
02782   char *ptr;
02783 
02784   ptr = (char *) malloc (size);
02785 
02786   if (ptr == 0) 
02787       fprintf( stderr, "Memory allocation bombed on line %d in %s\n", 
02788                lnum, fname);
02789 
02790   return (ptr);
02791 }
02792 
Generated on Sun May 8 2011 19:11:07 for Equalizer 1.0 by  doxygen 1.7.3