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