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