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