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