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