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