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


blort
Author(s): Thomas Mörwald , Michael Zillich , Andreas Richtsfeld , Johann Prankl , Markus Vincze , Bence Magyar
autogenerated on Wed Aug 26 2015 15:24:12