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