Equalizer 1.0
|
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 return (NULL); 00934 if (equal_strings (words[1], "ascii")) 00935 plyfile->file_type = PLY_ASCII; 00936 else if (equal_strings (words[1], "binary_big_endian")) 00937 plyfile->file_type = PLY_BINARY_BE; 00938 else if (equal_strings (words[1], "binary_little_endian")) 00939 plyfile->file_type = PLY_BINARY_LE; 00940 else 00941 { 00942 free (words); 00943 return (NULL); 00944 } 00945 plyfile->version = atof (words[2]); 00946 } 00947 else if (equal_strings (words[0], "element")) 00948 add_element (plyfile, words, nwords); 00949 else if (equal_strings (words[0], "property")) 00950 add_property (plyfile, words, nwords); 00951 else if (equal_strings (words[0], "comment")) 00952 add_comment (plyfile, orig_line); 00953 else if (equal_strings (words[0], "obj_info")) 00954 add_obj_info (plyfile, orig_line); 00955 else if (equal_strings (words[0], "end_header")) 00956 { 00957 free (words); 00958 break; 00959 } 00960 00961 /* free up words space */ 00962 free (words); 00963 00964 words = get_words (plyfile->fp, &nwords, &orig_line); 00965 } 00966 00967 00968 /* create tags for each property of each element, to be used */ 00969 /* later to say whether or not to store each property for the user */ 00970 00971 for (i = 0; i < plyfile->nelems; i++) { 00972 elem = plyfile->elems[i]; 00973 elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); 00974 for (j = 0; j < elem->nprops; j++) 00975 elem->store_prop[j] = DONT_STORE_PROP; 00976 elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ 00977 } 00978 00979 /* set return values about the elements */ 00980 00981 elist = (char **) myalloc (sizeof (char *) * plyfile->nelems); 00982 for (i = 0; i < plyfile->nelems; i++) 00983 elist[i] = strdup (plyfile->elems[i]->name); 00984 00985 *elem_names = elist; 00986 *nelems = plyfile->nelems; 00987 00988 /* return a pointer to the file's information */ 00989 00990 return (plyfile); 00991 } 00992 00993 00994 /****************************************************************************** 00995 Open a polygon file for reading. 00996 00997 Entry: 00998 filename - name of file to read from 00999 01000 Exit: 01001 nelems - number of elements in object 01002 elem_names - list of element names 01003 file_type - file type, either ascii or binary 01004 version - version number of PLY file 01005 returns a file identifier, used to refer to this file, or NULL if error 01006 ******************************************************************************/ 01007 01008 PlyFile *ply_open_for_reading( 01009 char *filename, 01010 int *nelems, 01011 char ***elem_names, 01012 int *file_type, 01013 float *version 01014 ) 01015 { 01016 FILE *fp; 01017 PlyFile *plyfile; 01018 char *name; 01019 01020 /* tack on the extension .ply, if necessary */ 01021 01022 name = (char *) myalloc (sizeof (char) * 01023 (static_cast<int>(strlen (filename) + 5))); 01024 strcpy (name, filename); 01025 if (strlen (name) < 4 || 01026 strcmp (name + strlen (name) - 4, ".ply") != 0) 01027 strcat (name, ".ply"); 01028 01029 /* open the file for reading */ 01030 01031 fp = fopen (name, "rb"); 01032 free(name); 01033 if (fp == NULL) 01034 return (NULL); 01035 01036 /* create the PlyFile data structure */ 01037 01038 plyfile = ply_read (fp, nelems, elem_names); 01039 01040 /* determine the file type and version */ 01041 01042 *file_type = plyfile->file_type; 01043 *version = plyfile->version; 01044 01045 /* return a pointer to the file's information */ 01046 01047 return (plyfile); 01048 } 01049 01050 01051 /****************************************************************************** 01052 Get information about a particular element. 01053 01054 Entry: 01055 plyfile - file identifier 01056 elem_name - name of element to get information about 01057 01058 Exit: 01059 nelems - number of elements of this type in the file 01060 nprops - number of properties 01061 returns a list of properties, or NULL if the file doesn't contain that elem 01062 ******************************************************************************/ 01063 01064 PlyProperty **ply_get_element_description( 01065 PlyFile *plyfile, 01066 char *elem_name, 01067 int *nelems, 01068 int *nprops 01069 ) 01070 { 01071 int i; 01072 PlyElement *elem; 01073 PlyProperty *prop; 01074 PlyProperty **prop_list; 01075 01076 /* find information about the element */ 01077 elem = find_element (plyfile, elem_name); 01078 if (elem == NULL) 01079 return (NULL); 01080 01081 *nelems = elem->num; 01082 *nprops = elem->nprops; 01083 01084 /* make a copy of the element's property list */ 01085 prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); 01086 for (i = 0; i < elem->nprops; i++) { 01087 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 01088 copy_property (prop, elem->props[i]); 01089 prop_list[i] = prop; 01090 } 01091 01092 /* return this duplicate property list */ 01093 return (prop_list); 01094 } 01095 01096 01097 /****************************************************************************** 01098 Specify which properties of an element are to be returned. This should be 01099 called before a call to the routine ply_get_element(). 01100 01101 Entry: 01102 plyfile - file identifier 01103 elem_name - which element we're talking about 01104 nprops - number of properties 01105 prop_list - list of properties 01106 ******************************************************************************/ 01107 01108 void ply_get_element_setup( PlyFile *plyfile, char *elem_name, int nprops, 01109 PlyProperty *prop_list ) 01110 { 01111 int i; 01112 PlyElement *elem; 01113 PlyProperty *prop; 01114 int index; 01115 01116 /* find information about the element */ 01117 elem = find_element (plyfile, elem_name); 01118 plyfile->which_elem = elem; 01119 01120 /* deposit the property information into the element's description */ 01121 for (i = 0; i < nprops; i++) 01122 { 01123 /* look for actual property */ 01124 prop = find_property (elem, prop_list[i].name, &index); 01125 if (prop == NULL) 01126 { 01127 fprintf ( stderr, 01128 "Warning: Can't find property '%s' in element '%s'\n", 01129 prop_list[i].name, elem_name ); 01130 continue; 01131 } 01132 01133 /* store its description */ 01134 prop->internal_type = prop_list[i].internal_type; 01135 prop->offset = prop_list[i].offset; 01136 prop->count_internal = prop_list[i].count_internal; 01137 prop->count_offset = prop_list[i].count_offset; 01138 01139 /* specify that the user wants this property */ 01140 elem->store_prop[index] = STORE_PROP; 01141 } 01142 } 01143 01144 01145 /****************************************************************************** 01146 Specify a property of an element that is to be returned. This should be 01147 called (usually multiple times) before a call to the routine ply_get_element(). 01148 This routine should be used in preference to the less flexible old routine 01149 called ply_get_element_setup(). 01150 01151 Entry: 01152 plyfile - file identifier 01153 elem_name - which element we're talking about 01154 prop - property to add to those that will be returned 01155 ******************************************************************************/ 01156 01157 void ply_get_property( 01158 PlyFile *plyfile, 01159 const char *elem_name, 01160 PlyProperty *prop 01161 ) 01162 { 01163 PlyElement *elem; 01164 PlyProperty *prop_ptr; 01165 int index; 01166 01167 /* find information about the element */ 01168 elem = find_element (plyfile, elem_name); 01169 plyfile->which_elem = elem; 01170 01171 /* deposit the property information into the element's description */ 01172 01173 prop_ptr = find_property (elem, prop->name, &index); 01174 if (prop_ptr == NULL) { 01175 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", 01176 prop->name, elem_name); 01177 return; 01178 } 01179 prop_ptr->internal_type = prop->internal_type; 01180 prop_ptr->offset = prop->offset; 01181 prop_ptr->count_internal = prop->count_internal; 01182 prop_ptr->count_offset = prop->count_offset; 01183 01184 /* specify that the user wants this property */ 01185 elem->store_prop[index] = STORE_PROP; 01186 } 01187 01188 01189 /****************************************************************************** 01190 Read one element from the file. This routine assumes that we're reading 01191 the type of element specified in the last call to the routine 01192 ply_get_element_setup(). 01193 01194 Entry: 01195 plyfile - file identifier 01196 elem_ptr - pointer to location where the element information should be put 01197 ******************************************************************************/ 01198 01199 void ply_get_element(PlyFile *plyfile, void *elem_ptr) 01200 { 01201 if (plyfile->file_type == PLY_ASCII) 01202 ascii_get_element (plyfile, (char *) elem_ptr); 01203 else 01204 binary_get_element (plyfile, (char *) elem_ptr); 01205 } 01206 01207 01208 /****************************************************************************** 01209 Extract the comments from the header information of a PLY file. 01210 01211 Entry: 01212 plyfile - file identifier 01213 01214 Exit: 01215 num_comments - number of comments returned 01216 returns a pointer to a list of comments 01217 ******************************************************************************/ 01218 01219 char **ply_get_comments(PlyFile *plyfile, int *num_comments) 01220 { 01221 *num_comments = plyfile->num_comments; 01222 return (plyfile->comments); 01223 } 01224 01225 01226 /****************************************************************************** 01227 Extract the object information (arbitrary text) from the header information 01228 of a PLY file. 01229 01230 Entry: 01231 plyfile - file identifier 01232 01233 Exit: 01234 num_obj_info - number of lines of text information returned 01235 returns a pointer to a list of object info lines 01236 ******************************************************************************/ 01237 01238 char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info) 01239 { 01240 *num_obj_info = plyfile->num_obj_info; 01241 return (plyfile->obj_info); 01242 } 01243 01244 01245 /****************************************************************************** 01246 Make ready for "other" properties of an element-- those properties that 01247 the user has not explicitly asked for, but that are to be stashed away 01248 in a special structure to be carried along with the element's other 01249 information. 01250 01251 Entry: 01252 plyfile - file identifier 01253 elem - element for which we want to save away other properties 01254 ******************************************************************************/ 01255 01256 void setup_other_props(PlyFile *, PlyElement *elem) 01257 { 01258 int i; 01259 PlyProperty *prop; 01260 int size = 0; 01261 int type_size; 01262 01263 /* Examine each property in decreasing order of size. */ 01264 /* We do this so that all data types will be aligned by */ 01265 /* word, half-word, or whatever within the structure. */ 01266 01267 for (type_size = 8; type_size > 0; type_size /= 2) { 01268 01269 /* add up the space taken by each property, and save this information */ 01270 /* away in the property descriptor */ 01271 01272 for (i = 0; i < elem->nprops; i++) { 01273 01274 /* don't bother with properties we've been asked to store explicitly */ 01275 if (elem->store_prop[i]) 01276 continue; 01277 01278 prop = elem->props[i]; 01279 01280 /* internal types will be same as external */ 01281 prop->internal_type = prop->external_type; 01282 prop->count_internal = prop->count_external; 01283 01284 /* check list case */ 01285 if (prop->is_list) { 01286 01287 /* pointer to list */ 01288 if (type_size == sizeof (void *)) { 01289 prop->offset = size; 01290 size += sizeof (void *); /* always use size of a pointer here */ 01291 } 01292 01293 /* count of number of list elements */ 01294 if (type_size == ply_type_size[prop->count_external]) { 01295 prop->count_offset = size; 01296 size += ply_type_size[prop->count_external]; 01297 } 01298 } 01299 /* not list */ 01300 else if (type_size == ply_type_size[prop->external_type]) { 01301 prop->offset = size; 01302 size += ply_type_size[prop->external_type]; 01303 } 01304 } 01305 01306 } 01307 01308 /* save the size for the other_props structure */ 01309 elem->other_size = size; 01310 } 01311 01312 01313 /****************************************************************************** 01314 Specify that we want the "other" properties of an element to be tucked 01315 away within the user's structure. The user needn't be concerned for how 01316 these properties are stored. 01317 01318 Entry: 01319 plyfile - file identifier 01320 elem_name - name of element that we want to store other_props in 01321 offset - offset to where other_props will be stored inside user's structure 01322 01323 Exit: 01324 returns pointer to structure containing description of other_props 01325 ******************************************************************************/ 01326 01327 PlyOtherProp *ply_get_other_properties( 01328 PlyFile *plyfile, 01329 char *elem_name, 01330 int offset 01331 ) 01332 { 01333 int i; 01334 PlyElement *elem; 01335 PlyOtherProp *other; 01336 PlyProperty *prop; 01337 int nprops; 01338 01339 /* find information about the element */ 01340 elem = find_element (plyfile, elem_name); 01341 if (elem == NULL) { 01342 fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n", 01343 elem_name); 01344 return (NULL); 01345 } 01346 01347 /* remember that this is the "current" element */ 01348 plyfile->which_elem = elem; 01349 01350 /* save the offset to where to store the other_props */ 01351 elem->other_offset = offset; 01352 01353 /* place the appropriate pointers, etc. in the element's property list */ 01354 setup_other_props (plyfile, elem); 01355 01356 /* create structure for describing other_props */ 01357 other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); 01358 other->name = strdup (elem_name); 01359 #if 0 01360 if (elem->other_offset == NO_OTHER_PROPS) { 01361 other->size = 0; 01362 other->props = NULL; 01363 other->nprops = 0; 01364 return (other); 01365 } 01366 #endif 01367 other->size = elem->other_size; 01368 other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); 01369 01370 /* save descriptions of each "other" property */ 01371 nprops = 0; 01372 for (i = 0; i < elem->nprops; i++) { 01373 if (elem->store_prop[i]) 01374 continue; 01375 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 01376 copy_property (prop, elem->props[i]); 01377 other->props[nprops] = prop; 01378 nprops++; 01379 } 01380 other->nprops = nprops; 01381 01382 #if 1 01383 /* set other_offset pointer appropriately if there are NO other properties */ 01384 if (other->nprops == 0) { 01385 elem->other_offset = NO_OTHER_PROPS; 01386 } 01387 #endif 01388 01389 /* return structure */ 01390 return (other); 01391 } 01392 01393 01394 01395 01396 /*************************/ 01397 /* Other Element Stuff */ 01398 /*************************/ 01399 01400 01401 01402 01403 /****************************************************************************** 01404 Grab all the data for an element that a user does not want to explicitly 01405 read in. 01406 01407 Entry: 01408 plyfile - pointer to file 01409 elem_name - name of element whose data is to be read in 01410 elem_count - number of instances of this element stored in the file 01411 01412 Exit: 01413 returns pointer to ALL the "other" element data for this PLY file 01414 ******************************************************************************/ 01415 01416 PlyOtherElems *ply_get_other_element ( 01417 PlyFile *plyfile, 01418 char *elem_name, 01419 int elem_count 01420 ) 01421 { 01422 int i; 01423 PlyElement *elem; 01424 PlyOtherElems *other_elems; 01425 OtherElem *other; 01426 01427 /* look for appropriate element */ 01428 elem = find_element (plyfile, elem_name); 01429 if (elem == NULL) { 01430 fprintf (stderr, 01431 "ply_get_other_element: can't find element '%s'\n", elem_name); 01432 exit (-1); 01433 } 01434 01435 /* create room for the new "other" element, initializing the */ 01436 /* other data structure if necessary */ 01437 01438 if (plyfile->other_elems == NULL) { 01439 plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); 01440 other_elems = plyfile->other_elems; 01441 other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem)); 01442 other = &(other_elems->other_list[0]); 01443 other_elems->num_elems = 1; 01444 } 01445 else { 01446 other_elems = plyfile->other_elems; 01447 other_elems->other_list = (OtherElem *) realloc (other_elems->other_list, 01448 sizeof (OtherElem) * other_elems->num_elems + 1); 01449 other = &(other_elems->other_list[other_elems->num_elems]); 01450 other_elems->num_elems++; 01451 } 01452 01453 /* count of element instances in file */ 01454 other->elem_count = elem_count; 01455 01456 /* save name of element */ 01457 other->elem_name = strdup (elem_name); 01458 01459 /* create a list to hold all the current elements */ 01460 other->other_data = (OtherData **) 01461 malloc (sizeof (OtherData *) * other->elem_count); 01462 01463 /* set up for getting elements */ 01464 other->other_props = ply_get_other_properties (plyfile, elem_name, 01465 offsetof(OtherData,other_props)); 01466 01467 /* grab all these elements */ 01468 for (i = 0; i < other->elem_count; i++) { 01469 /* grab and element from the file */ 01470 other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); 01471 ply_get_element (plyfile, (void *) other->other_data[i]); 01472 } 01473 01474 /* return pointer to the other elements data */ 01475 return (other_elems); 01476 } 01477 01478 01479 /****************************************************************************** 01480 Pass along a pointer to "other" elements that we want to save in a given 01481 PLY file. These other elements were presumably read from another PLY file. 01482 01483 Entry: 01484 plyfile - file pointer in which to store this other element info 01485 other_elems - info about other elements that we want to store 01486 ******************************************************************************/ 01487 01488 void ply_describe_other_elements ( 01489 PlyFile *plyfile, 01490 PlyOtherElems *other_elems 01491 ) 01492 { 01493 int i; 01494 OtherElem *other; 01495 01496 /* ignore this call if there is no other element */ 01497 if (other_elems == NULL) 01498 return; 01499 01500 /* save pointer to this information */ 01501 plyfile->other_elems = other_elems; 01502 01503 /* describe the other properties of this element */ 01504 01505 for (i = 0; i < other_elems->num_elems; i++) { 01506 other = &(other_elems->other_list[i]); 01507 ply_element_count (plyfile, other->elem_name, other->elem_count); 01508 ply_describe_other_properties (plyfile, other->other_props, 01509 offsetof(OtherData,other_props)); 01510 } 01511 } 01512 01513 01514 /****************************************************************************** 01515 Write out the "other" elements specified for this PLY file. 01516 01517 Entry: 01518 plyfile - pointer to PLY file to write out other elements for 01519 ******************************************************************************/ 01520 01521 void ply_put_other_elements (PlyFile *plyfile) 01522 { 01523 int i,j; 01524 OtherElem *other; 01525 01526 /* make sure we have other elements to write */ 01527 if (plyfile->other_elems == NULL) 01528 return; 01529 01530 /* write out the data for each "other" element */ 01531 01532 for (i = 0; i < plyfile->other_elems->num_elems; i++) { 01533 01534 other = &(plyfile->other_elems->other_list[i]); 01535 ply_put_element_setup (plyfile, other->elem_name); 01536 01537 /* write out each instance of the current element */ 01538 for (j = 0; j < other->elem_count; j++) 01539 ply_put_element (plyfile, (void *) other->other_data[j]); 01540 } 01541 } 01542 01543 01544 /****************************************************************************** 01545 Free up storage used by an "other" elements data structure. 01546 01547 Entry: 01548 other_elems - data structure to free up 01549 ******************************************************************************/ 01550 01551 void ply_free_other_elements (PlyOtherElems *) 01552 { 01553 01554 } 01555 01556 01557 01558 /*******************/ 01559 /* Miscellaneous */ 01560 /*******************/ 01561 01562 01563 01564 /****************************************************************************** 01565 Close a PLY file. 01566 01567 Entry: 01568 plyfile - identifier of file to close 01569 ******************************************************************************/ 01570 01571 void ply_close(PlyFile *plyfile) 01572 { 01573 // Changed by Will Schroeder. Old stuff leaked like a sieve. 01574 01575 /* free up memory associated with the PLY file */ 01576 fclose (plyfile->fp); 01577 01578 int i, j; 01579 PlyElement *elem; 01580 for (i=0; i<plyfile->nelems; i++) 01581 { 01582 elem = plyfile->elems[i]; 01583 if ( elem->name ) {free(elem->name);} 01584 for (j=0; j<elem->nprops; j++) 01585 { 01586 if ( elem->props[j]->name ) 01587 {free(const_cast<char *>(elem->props[j]->name));} 01588 free (elem->props[j]); 01589 } 01590 free (elem->props); 01591 free (elem->store_prop); 01592 free (elem); 01593 } 01594 free(plyfile->elems); 01595 01596 for (i=0; i<plyfile->num_comments; i++) 01597 { 01598 free (plyfile->comments[i]); 01599 } 01600 free (plyfile->comments); 01601 01602 for (i=0; i<plyfile->num_obj_info; i++) 01603 { 01604 free (plyfile->obj_info[i]); 01605 } 01606 free (plyfile->obj_info); 01607 01608 free (plyfile); 01609 } 01610 01611 01612 /****************************************************************************** 01613 Get version number and file type of a PlyFile. 01614 01615 Entry: 01616 ply - pointer to PLY file 01617 01618 Exit: 01619 version - version of the file 01620 file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE 01621 ******************************************************************************/ 01622 01623 void ply_get_info(PlyFile *ply, float *version, int *file_type) 01624 { 01625 if (ply == NULL) 01626 return; 01627 01628 *version = ply->version; 01629 *file_type = ply->file_type; 01630 } 01631 01632 01633 /****************************************************************************** 01634 Compare two strings. Returns 1 if they are the same, 0 if not. 01635 ******************************************************************************/ 01636 01637 int equal_strings(const char *s1, const char *s2) 01638 { 01639 while (*s1 && *s2) 01640 if (*s1++ != *s2++) 01641 return (0); 01642 01643 if (*s1 != *s2) 01644 return (0); 01645 else 01646 return (1); 01647 } 01648 01649 01650 /****************************************************************************** 01651 Find an element from the element list of a given PLY object. 01652 01653 Entry: 01654 plyfile - file id for PLY file 01655 element - name of element we're looking for 01656 01657 Exit: 01658 returns the element, or NULL if not found 01659 ******************************************************************************/ 01660 01661 PlyElement *find_element(PlyFile *plyfile, const char *element) 01662 { 01663 int i; 01664 01665 for (i = 0; i < plyfile->nelems; i++) 01666 if (equal_strings (element, plyfile->elems[i]->name)) 01667 return (plyfile->elems[i]); 01668 01669 return (NULL); 01670 } 01671 01672 01673 /****************************************************************************** 01674 Find a property in the list of properties of a given element. 01675 01676 Entry: 01677 elem - pointer to element in which we want to find the property 01678 prop_name - name of property to find 01679 01680 Exit: 01681 index - index to position in list 01682 returns a pointer to the property, or NULL if not found 01683 ******************************************************************************/ 01684 01685 PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index) 01686 { 01687 int i; 01688 01689 for( i = 0; i < elem->nprops; i++) 01690 if (equal_strings (prop_name, elem->props[i]->name)) 01691 { 01692 *index = i; 01693 return (elem->props[i]); 01694 } 01695 01696 *index = -1; 01697 return (NULL); 01698 } 01699 01700 01701 /****************************************************************************** 01702 Read an element from an ascii file. 01703 01704 Entry: 01705 plyfile - file identifier 01706 elem_ptr - pointer to element 01707 ******************************************************************************/ 01708 01709 void ascii_get_element(PlyFile *plyfile, char *elem_ptr) 01710 { 01711 int j,k; 01712 PlyElement *elem; 01713 PlyProperty *prop; 01714 char **words; 01715 int nwords; 01716 int which_word; 01717 char *elem_data,*item=0; 01718 char *item_ptr; 01719 int item_size=0; 01720 int int_val; 01721 unsigned int uint_val; 01722 double double_val; 01723 int list_count; 01724 int store_it; 01725 char **store_array; 01726 char *orig_line; 01727 char *other_data=0; 01728 int other_flag; 01729 01730 /* the kind of element we're reading currently */ 01731 elem = plyfile->which_elem; 01732 01733 /* do we need to setup for other_props? */ 01734 01735 if (elem->other_offset != NO_OTHER_PROPS) { 01736 char **ptr; 01737 other_flag = 1; 01738 /* make room for other_props */ 01739 other_data = (char *) myalloc (elem->other_size); 01740 /* store pointer in user's structure to the other_props */ 01741 ptr = (char **) (elem_ptr + elem->other_offset); 01742 *ptr = other_data; 01743 } 01744 else 01745 other_flag = 0; 01746 01747 /* read in the element */ 01748 01749 words = get_words (plyfile->fp, &nwords, &orig_line); 01750 if (words == NULL) { 01751 fprintf (stderr, "ply_get_element: unexpected end of file\n"); 01752 exit (-1); 01753 } 01754 01755 which_word = 0; 01756 01757 for (j = 0; j < elem->nprops; j++) { 01758 01759 prop = elem->props[j]; 01760 store_it = (elem->store_prop[j] | other_flag); 01761 01762 /* store either in the user's structure or in other_props */ 01763 if (elem->store_prop[j]) 01764 elem_data = elem_ptr; 01765 else 01766 elem_data = other_data; 01767 01768 if (prop->is_list) { /* a list */ 01769 01770 /* get and store the number of items in the list */ 01771 get_ascii_item (words[which_word++], prop->count_external, 01772 &int_val, &uint_val, &double_val); 01773 if (store_it) { 01774 item = elem_data + prop->count_offset; 01775 store_item(item, prop->count_internal, int_val, uint_val, double_val); 01776 } 01777 01778 /* allocate space for an array of items and store a ptr to the array */ 01779 list_count = int_val; 01780 item_size = ply_type_size[prop->internal_type]; 01781 store_array = (char **) (elem_data + prop->offset); 01782 01783 if (list_count == 0) { 01784 if (store_it) 01785 *store_array = NULL; 01786 } 01787 else { 01788 if (store_it) { 01789 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); 01790 item = item_ptr; 01791 *store_array = item_ptr; 01792 } 01793 01794 /* read items and store them into the array */ 01795 for (k = 0; k < list_count; k++) { 01796 get_ascii_item (words[which_word++], prop->external_type, 01797 &int_val, &uint_val, &double_val); 01798 if (store_it) { 01799 store_item (item, prop->internal_type, 01800 int_val, uint_val, double_val); 01801 item += item_size; 01802 } 01803 } 01804 } 01805 01806 } 01807 else { /* not a list */ 01808 get_ascii_item (words[which_word++], prop->external_type, 01809 &int_val, &uint_val, &double_val); 01810 if (store_it) { 01811 item = elem_data + prop->offset; 01812 store_item (item, prop->internal_type, int_val, uint_val, double_val); 01813 } 01814 } 01815 01816 } 01817 01818 free (words); 01819 } 01820 01821 01822 /****************************************************************************** 01823 Read an element from a binary file. 01824 01825 Entry: 01826 plyfile - file identifier 01827 elem_ptr - pointer to an element 01828 ******************************************************************************/ 01829 01830 void binary_get_element(PlyFile *plyfile, char *elem_ptr) 01831 { 01832 int j,k; 01833 PlyElement *elem; 01834 PlyProperty *prop; 01835 //FILE *fp = plyfile->fp; 01836 char *elem_data,*item=0; 01837 char *item_ptr; 01838 int item_size=0; 01839 int int_val; 01840 unsigned int uint_val; 01841 double double_val; 01842 int list_count; 01843 int store_it; 01844 char **store_array; 01845 char *other_data=0; 01846 int other_flag; 01847 01848 /* the kind of element we're reading currently */ 01849 elem = plyfile->which_elem; 01850 01851 /* do we need to setup for other_props? */ 01852 01853 if (elem->other_offset != NO_OTHER_PROPS) { 01854 char **ptr; 01855 other_flag = 1; 01856 /* make room for other_props */ 01857 other_data = (char *) myalloc (elem->other_size); 01858 /* store pointer in user's structure to the other_props */ 01859 ptr = (char **) (elem_ptr + elem->other_offset); 01860 *ptr = other_data; 01861 } 01862 else 01863 other_flag = 0; 01864 01865 /* read in a number of elements */ 01866 01867 for (j = 0; j < elem->nprops; j++) { 01868 01869 prop = elem->props[j]; 01870 store_it = (elem->store_prop[j] | other_flag); 01871 01872 /* store either in the user's structure or in other_props */ 01873 if (elem->store_prop[j]) 01874 elem_data = elem_ptr; 01875 else 01876 elem_data = other_data; 01877 01878 if (prop->is_list) { /* a list */ 01879 01880 /* get and store the number of items in the list */ 01881 get_binary_item (plyfile, prop->count_external, 01882 &int_val, &uint_val, &double_val); 01883 if (store_it) { 01884 item = elem_data + prop->count_offset; 01885 store_item(item, prop->count_internal, int_val, uint_val, double_val); 01886 } 01887 01888 /* allocate space for an array of items and store a ptr to the array */ 01889 list_count = int_val; 01890 /* The "if" was added by Afra Zomorodian 8/22/95 01891 * so that zipper won't crash reading plies that have additional 01892 * properties. 01893 */ 01894 if (store_it) { 01895 item_size = ply_type_size[prop->internal_type]; 01896 } 01897 store_array = (char **) (elem_data + prop->offset); 01898 if (list_count == 0) { 01899 if (store_it) 01900 *store_array = NULL; 01901 } 01902 else { 01903 if (store_it) { 01904 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); 01905 item = item_ptr; 01906 *store_array = item_ptr; 01907 } 01908 01909 /* read items and store them into the array */ 01910 for (k = 0; k < list_count; k++) { 01911 get_binary_item (plyfile, prop->external_type, 01912 &int_val, &uint_val, &double_val); 01913 if (store_it) { 01914 store_item (item, prop->internal_type, 01915 int_val, uint_val, double_val); 01916 item += item_size; 01917 } 01918 } 01919 } 01920 01921 } 01922 else { /* not a list */ 01923 get_binary_item (plyfile, prop->external_type, 01924 &int_val, &uint_val, &double_val); 01925 if (store_it) { 01926 item = elem_data + prop->offset; 01927 store_item (item, prop->internal_type, int_val, uint_val, double_val); 01928 } 01929 } 01930 01931 } 01932 } 01933 01934 01935 /****************************************************************************** 01936 Write to a file the word that represents a PLY data type. 01937 01938 Entry: 01939 fp - file pointer 01940 code - code for type 01941 ******************************************************************************/ 01942 01943 void write_scalar_type (FILE *fp, int code) 01944 { 01945 /* make sure this is a valid code */ 01946 01947 if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) { 01948 fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); 01949 exit (-1); 01950 } 01951 01952 /* write the code to a file */ 01953 01954 fprintf (fp, "%s", type_names[code]); 01955 } 01956 01957 01958 /****************************************************************************** 01959 Get a text line from a file and break it up into words. 01960 01961 IMPORTANT: The calling routine call "free" on the returned pointer once 01962 finished with it. 01963 01964 Entry: 01965 fp - file to read from 01966 01967 Exit: 01968 nwords - number of words returned 01969 orig_line - the original line of characters 01970 returns a list of words from the line, or NULL if end-of-file 01971 ******************************************************************************/ 01972 01973 char **get_words(FILE *fp, int *nwords, char **orig_line) 01974 { 01975 #define BIG_STRING 4096 01976 static char str[BIG_STRING]; 01977 static char str_copy[BIG_STRING]; 01978 char **words; 01979 int max_words = 10; 01980 int num_words = 0; 01981 char *ptr,*ptr2; 01982 char *result; 01983 01984 /* read in a line */ 01985 result = fgets (str, BIG_STRING, fp); 01986 if (result == NULL) { 01987 *nwords = 0; 01988 *orig_line = NULL; 01989 return (NULL); 01990 } 01991 01992 words = (char **) myalloc (sizeof (char *) * max_words); 01993 01994 /* convert line-feed and tabs into spaces */ 01995 /* (this guarentees that there will be a space before the */ 01996 /* null character at the end of the string) */ 01997 01998 str[BIG_STRING-2] = ' '; 01999 str[BIG_STRING-1] = '\0'; 02000 02001 for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { 02002 *ptr2 = *ptr; 02003 if (*ptr == '\t') { 02004 *ptr = ' '; 02005 *ptr2 = ' '; 02006 } 02007 else if (*ptr == '\n') { 02008 *ptr = ' '; 02009 *ptr2 = '\0'; 02010 break; 02011 } 02012 } 02013 02014 /* find the words in the line */ 02015 02016 ptr = str; 02017 while (*ptr != '\0') { 02018 02019 /* jump over leading spaces */ 02020 while (*ptr == ' ') 02021 ptr++; 02022 02023 /* break if we reach the end */ 02024 if (*ptr == '\0') 02025 break; 02026 02027 /* save pointer to beginning of word */ 02028 if (num_words >= max_words) { 02029 max_words += 10; 02030 words = (char **) realloc (words, sizeof (char *) * max_words); 02031 } 02032 words[num_words++] = ptr; 02033 02034 /* jump over non-spaces */ 02035 while (*ptr != ' ') 02036 ptr++; 02037 02038 /* place a null character here to mark the end of the word */ 02039 *ptr++ = '\0'; 02040 } 02041 02042 /* return the list of words */ 02043 *nwords = num_words; 02044 *orig_line = str_copy; 02045 return (words); 02046 } 02047 02048 02049 /****************************************************************************** 02050 Return the value of an item, given a pointer to it and its type. 02051 02052 Entry: 02053 item - pointer to item 02054 type - data type that "item" points to 02055 02056 Exit: 02057 returns a double-precision float that contains the value of the item 02058 ******************************************************************************/ 02059 02060 double get_item_value(char *item, int type) 02061 { 02062 unsigned char *puchar; 02063 char *pchar; 02064 short int *pshort; 02065 unsigned short int *pushort; 02066 int *pint; 02067 unsigned int *puint; 02068 float *pfloat; 02069 double *pdouble; 02070 int int_value; 02071 unsigned int uint_value; 02072 double double_value; 02073 02074 switch (type) { 02075 case PLY_CHAR: 02076 pchar = (char *) item; 02077 int_value = *pchar; 02078 return ((double) int_value); 02079 case PLY_UCHAR: 02080 case PLY_UINT8: 02081 puchar = (unsigned char *) item; 02082 int_value = *puchar; 02083 return ((double) int_value); 02084 case PLY_SHORT: 02085 pshort = (short int *) item; 02086 int_value = *pshort; 02087 return ((double) int_value); 02088 case PLY_USHORT: 02089 pushort = (unsigned short int *) item; 02090 int_value = *pushort; 02091 return ((double) int_value); 02092 case PLY_INT: 02093 case PLY_INT32: 02094 pint = (int *) item; 02095 int_value = *pint; 02096 return ((double) int_value); 02097 case PLY_UINT: 02098 puint = (unsigned int *) item; 02099 uint_value = *puint; 02100 return ((double) uint_value); 02101 case PLY_FLOAT: 02102 case PLY_FLOAT32: 02103 pfloat = (float *) item; 02104 double_value = *pfloat; 02105 return (double_value); 02106 case PLY_DOUBLE: 02107 pdouble = (double *) item; 02108 double_value = *pdouble; 02109 return (double_value); 02110 } 02111 fprintf (stderr, "get_item_value: bad type = %d\n", type); 02112 return 0; 02113 } 02114 02115 02116 /****************************************************************************** 02117 Write out an item to a file as raw binary bytes. 02118 02119 Entry: 02120 fp - file to write to 02121 int_val - integer version of item 02122 uint_val - unsigned integer version of item 02123 double_val - double-precision float version of item 02124 type - data type to write out 02125 ******************************************************************************/ 02126 02127 void write_binary_item(PlyFile *plyfile, 02128 int int_val, 02129 unsigned int uint_val, 02130 double double_val, 02131 int type 02132 ) 02133 { 02134 FILE *fp = plyfile->fp; 02135 unsigned char uchar_val; 02136 char char_val; 02137 unsigned short ushort_val; 02138 short short_val; 02139 float float_val; 02140 02141 switch (type) { 02142 case PLY_CHAR: 02143 char_val = int_val; 02144 fwrite (&char_val, 1, 1, fp); 02145 break; 02146 case PLY_SHORT: 02147 short_val = int_val; 02148 if( plyfile->file_type == PLY_BINARY_BE ) 02149 swap2BE(&short_val); 02150 else 02151 swap2LE(&short_val); 02152 fwrite (&short_val, 2, 1, fp); 02153 break; 02154 case PLY_INT: 02155 case PLY_INT32: 02156 if( plyfile->file_type == PLY_BINARY_BE ) 02157 { 02158 swap4BE(&int_val); 02159 } 02160 else 02161 { 02162 swap4LE(&int_val); 02163 } 02164 fwrite (&int_val, 4, 1, fp); 02165 break; 02166 case PLY_UCHAR: 02167 case PLY_UINT8: 02168 uchar_val = uint_val; 02169 fwrite (&uchar_val, 1, 1, fp); 02170 break; 02171 case PLY_USHORT: 02172 if( plyfile->file_type == PLY_BINARY_BE ) 02173 { 02174 swap2BE(&ushort_val); 02175 } 02176 else 02177 { 02178 swap2LE(&ushort_val); 02179 } 02180 ushort_val = uint_val; 02181 fwrite (&ushort_val, 2, 1, fp); 02182 break; 02183 case PLY_UINT: 02184 if( plyfile->file_type == PLY_BINARY_BE ) 02185 { 02186 swap4BE(&uint_val); 02187 } 02188 else 02189 { 02190 swap4LE(&uint_val); 02191 } 02192 fwrite (&uint_val, 4, 1, fp); 02193 break; 02194 case PLY_FLOAT: 02195 case PLY_FLOAT32: 02196 float_val = double_val; 02197 if( plyfile->file_type == PLY_BINARY_BE ) 02198 { 02199 swap4BE(&float_val); 02200 } 02201 else 02202 { 02203 swap4LE(&float_val); 02204 } 02205 fwrite (&float_val, 4, 1, fp); 02206 break; 02207 case PLY_DOUBLE: 02208 if( plyfile->file_type == PLY_BINARY_BE ) 02209 { 02210 swap8BE(&double_val); 02211 } 02212 else 02213 { 02214 swap8LE(&double_val); 02215 } 02216 fwrite (&double_val, 8, 1, fp); 02217 break; 02218 default: 02219 fprintf (stderr, "write_binary_item: bad type = %d\n", type); 02220 exit (-1); 02221 } 02222 } 02223 02224 02225 /****************************************************************************** 02226 Write out an item to a file as ascii characters. 02227 02228 Entry: 02229 fp - file to write to 02230 int_val - integer version of item 02231 uint_val - unsigned integer version of item 02232 double_val - double-precision float version of item 02233 type - data type to write out 02234 ******************************************************************************/ 02235 02236 void write_ascii_item( 02237 FILE *fp, 02238 int int_val, 02239 unsigned int uint_val, 02240 double double_val, 02241 int type 02242 ) 02243 { 02244 switch (type) { 02245 case PLY_CHAR: 02246 case PLY_SHORT: 02247 case PLY_INT: 02248 case PLY_INT32: 02249 fprintf (fp, "%d ", int_val); 02250 break; 02251 case PLY_UCHAR: 02252 case PLY_UINT8: 02253 case PLY_USHORT: 02254 case PLY_UINT: 02255 fprintf (fp, "%u ", uint_val); 02256 break; 02257 case PLY_FLOAT: 02258 case PLY_FLOAT32: 02259 case PLY_DOUBLE: 02260 fprintf (fp, "%g ", double_val); 02261 break; 02262 default: 02263 fprintf (stderr, "write_ascii_item: bad type = %d\n", type); 02264 exit (-1); 02265 } 02266 } 02267 02268 /****************************************************************************** 02269 Get the value of an item that is in memory, and place the result 02270 into an integer, an unsigned integer and a double. 02271 02272 Entry: 02273 ptr - pointer to the item 02274 type - data type supposedly in the item 02275 02276 Exit: 02277 int_val - integer value 02278 uint_val - unsigned integer value 02279 double_val - double-precision floating point value 02280 ******************************************************************************/ 02281 02282 void get_stored_item( 02283 void *ptr, 02284 int type, 02285 int *int_val, 02286 unsigned int *uint_val, 02287 double *double_val 02288 ) 02289 { 02290 switch (type) { 02291 case PLY_CHAR: 02292 *int_val = *((char *) ptr); 02293 *uint_val = *int_val; 02294 *double_val = *int_val; 02295 break; 02296 case PLY_UCHAR: 02297 case PLY_UINT8: 02298 *uint_val = *((unsigned char *) ptr); 02299 *int_val = *uint_val; 02300 *double_val = *uint_val; 02301 break; 02302 case PLY_SHORT: 02303 *int_val = *((short int *) ptr); 02304 *uint_val = *int_val; 02305 *double_val = *int_val; 02306 break; 02307 case PLY_USHORT: 02308 *uint_val = *((unsigned short int *) ptr); 02309 *int_val = *uint_val; 02310 *double_val = *uint_val; 02311 break; 02312 case PLY_INT: 02313 case PLY_INT32: 02314 *int_val = *((int *) ptr); 02315 *uint_val = *int_val; 02316 *double_val = *int_val; 02317 break; 02318 case PLY_UINT: 02319 *uint_val = *((unsigned int *) ptr); 02320 *int_val = *uint_val; 02321 *double_val = *uint_val; 02322 break; 02323 case PLY_FLOAT: 02324 case PLY_FLOAT32: 02325 *double_val = *((float *) ptr); 02326 *int_val = (int) *double_val; 02327 *uint_val = (unsigned int) *double_val; 02328 break; 02329 case PLY_DOUBLE: 02330 *double_val = *((double *) ptr); 02331 *int_val = (int) *double_val; 02332 *uint_val = (unsigned int) *double_val; 02333 break; 02334 default: 02335 fprintf (stderr, "get_stored_item: bad type = %d\n", type); 02336 exit (-1); 02337 } 02338 } 02339 02340 02341 /****************************************************************************** 02342 Get the value of an item from a binary file, and place the result 02343 into an integer, an unsigned integer and a double. 02344 02345 Entry: 02346 fp - file to get item from 02347 type - data type supposedly in the word 02348 02349 Exit: 02350 int_val - integer value 02351 uint_val - unsigned integer value 02352 double_val - double-precision floating point value 02353 ******************************************************************************/ 02354 02355 void get_binary_item( 02356 PlyFile *plyfile, 02357 int type, 02358 int *int_val, 02359 unsigned int *uint_val, 02360 double *double_val 02361 ) 02362 { 02363 char c[8]; 02364 void *ptr; 02365 02366 ptr = (void *) c; 02367 02368 switch (type) { 02369 case PLY_CHAR: 02370 if( fread (ptr, 1, 1, plyfile->fp) <= 0 ) 02371 abort(); 02372 *int_val = *((char *) ptr); 02373 *uint_val = *int_val; 02374 *double_val = *int_val; 02375 break; 02376 case PLY_UCHAR: 02377 case PLY_UINT8: 02378 if( fread (ptr, 1, 1, plyfile->fp) <= 0 ) 02379 abort(); 02380 *uint_val = *((unsigned char *) ptr); 02381 *int_val = *uint_val; 02382 *double_val = *uint_val; 02383 break; 02384 case PLY_SHORT: 02385 if( fread (ptr, 2, 1, plyfile->fp) <= 0 ) 02386 abort(); 02387 if( plyfile->file_type == PLY_BINARY_BE ) 02388 { 02389 swap2BE(ptr); 02390 } 02391 else 02392 { 02393 swap2LE(ptr); 02394 } 02395 *int_val = *((short int *) ptr); 02396 *uint_val = *int_val; 02397 *double_val = *int_val; 02398 break; 02399 case PLY_USHORT: 02400 if( fread (ptr, 2, 1, plyfile->fp) <= 0 ) 02401 abort(); 02402 if( plyfile->file_type == PLY_BINARY_BE ) 02403 { 02404 swap2BE(ptr); 02405 } 02406 else 02407 { 02408 swap2LE(ptr); 02409 } 02410 *uint_val = *((unsigned short int *) ptr); 02411 *int_val = *uint_val; 02412 *double_val = *uint_val; 02413 break; 02414 case PLY_INT: 02415 case PLY_INT32: 02416 if( fread (ptr, 4, 1, plyfile->fp) <= 0 ) 02417 abort(); 02418 if( plyfile->file_type == PLY_BINARY_BE ) 02419 { 02420 swap4BE(ptr); 02421 } 02422 else 02423 { 02424 swap4LE(ptr); 02425 } 02426 *int_val = *((int *) ptr); 02427 *uint_val = *int_val; 02428 *double_val = *int_val; 02429 break; 02430 case PLY_UINT: 02431 if( fread (ptr, 4, 1, plyfile->fp) <= 0 ) 02432 abort(); 02433 if( plyfile->file_type == PLY_BINARY_BE ) 02434 { 02435 swap4BE(ptr); 02436 } 02437 else 02438 { 02439 swap4LE(ptr); 02440 } 02441 *uint_val = *((unsigned int *) ptr); 02442 *int_val = *uint_val; 02443 *double_val = *uint_val; 02444 break; 02445 case PLY_FLOAT: 02446 case PLY_FLOAT32: 02447 if( fread (ptr, 4, 1, plyfile->fp) <= 0 ) 02448 abort(); 02449 if( plyfile->file_type == PLY_BINARY_BE ) 02450 { 02451 swap4BE(ptr); 02452 } 02453 else 02454 { 02455 swap4LE(ptr); 02456 } 02457 *double_val = *((float *) ptr); 02458 *int_val = (int) *double_val; 02459 *uint_val = (unsigned int) *double_val; 02460 break; 02461 case PLY_DOUBLE: 02462 if( fread (ptr, 8, 1, plyfile->fp) <= 0 ) 02463 abort(); 02464 if( plyfile->file_type == PLY_BINARY_BE ) 02465 { 02466 swap8BE(ptr); 02467 } 02468 else 02469 { 02470 swap8LE(ptr); 02471 } 02472 *double_val = *((double *) ptr); 02473 *int_val = (int) *double_val; 02474 *uint_val = (unsigned int) *double_val; 02475 break; 02476 default: 02477 fprintf (stderr, "get_binary_item: bad type = %d\n", type); 02478 exit (-1); 02479 } 02480 } 02481 02482 02483 /****************************************************************************** 02484 Extract the value of an item from an ascii word, and place the result 02485 into an integer, an unsigned integer and a double. 02486 02487 Entry: 02488 word - word to extract value from 02489 type - data type supposedly in the word 02490 02491 Exit: 02492 int_val - integer value 02493 uint_val - unsigned integer value 02494 double_val - double-precision floating point value 02495 ******************************************************************************/ 02496 02497 void get_ascii_item( 02498 char *word, 02499 int type, 02500 int *int_val, 02501 unsigned int *uint_val, 02502 double *double_val 02503 ) 02504 { 02505 switch (type) { 02506 case PLY_CHAR: 02507 case PLY_UCHAR: 02508 case PLY_UINT8: 02509 case PLY_SHORT: 02510 case PLY_USHORT: 02511 case PLY_INT: 02512 case PLY_INT32: 02513 *int_val = atoi (word); 02514 *uint_val = *int_val; 02515 *double_val = *int_val; 02516 break; 02517 02518 case PLY_UINT: 02519 *uint_val = strtoul (word, (char **) NULL, 10); 02520 *int_val = *uint_val; 02521 *double_val = *uint_val; 02522 break; 02523 02524 case PLY_FLOAT: 02525 case PLY_FLOAT32: 02526 case PLY_DOUBLE: 02527 *double_val = atof (word); 02528 *int_val = (int) *double_val; 02529 *uint_val = (unsigned int) *double_val; 02530 break; 02531 02532 default: 02533 fprintf (stderr, "get_ascii_item: bad type = %d\n", type); 02534 exit (-1); 02535 } 02536 } 02537 02538 02539 /****************************************************************************** 02540 Store a value into a place being pointed to, guided by a data type. 02541 02542 Entry: 02543 item - place to store value 02544 type - data type 02545 int_val - integer version of value 02546 uint_val - unsigned integer version of value 02547 double_val - double version of value 02548 02549 Exit: 02550 item - pointer to stored value 02551 ******************************************************************************/ 02552 02553 void store_item ( 02554 char *item, 02555 int type, 02556 int int_val, 02557 unsigned int uint_val, 02558 double double_val 02559 ) 02560 { 02561 unsigned char *puchar; 02562 short int *pshort; 02563 unsigned short int *pushort; 02564 int *pint; 02565 unsigned int *puint; 02566 float *pfloat; 02567 double *pdouble; 02568 02569 switch (type) { 02570 case PLY_CHAR: 02571 *item = int_val; 02572 break; 02573 case PLY_UCHAR: 02574 case PLY_UINT8: 02575 puchar = (unsigned char *) item; 02576 *puchar = uint_val; 02577 break; 02578 case PLY_SHORT: 02579 pshort = (short *) item; 02580 *pshort = int_val; 02581 break; 02582 case PLY_USHORT: 02583 pushort = (unsigned short *) item; 02584 *pushort = uint_val; 02585 break; 02586 case PLY_INT: 02587 case PLY_INT32: 02588 pint = (int *) item; 02589 *pint = int_val; 02590 break; 02591 case PLY_UINT: 02592 puint = (unsigned int *) item; 02593 *puint = uint_val; 02594 break; 02595 case PLY_FLOAT: 02596 case PLY_FLOAT32: 02597 pfloat = (float *) item; 02598 *pfloat = double_val; 02599 break; 02600 case PLY_DOUBLE: 02601 pdouble = (double *) item; 02602 *pdouble = double_val; 02603 break; 02604 default: 02605 fprintf (stderr, "store_item: bad type = %d\n", type); 02606 exit (-1); 02607 } 02608 } 02609 02610 02611 /****************************************************************************** 02612 Add an element to a PLY file descriptor. 02613 02614 Entry: 02615 plyfile - PLY file descriptor 02616 words - list of words describing the element 02617 nwords - number of words in the list 02618 ******************************************************************************/ 02619 02620 void add_element (PlyFile *plyfile, char **words, int) 02621 { 02622 PlyElement *elem; 02623 02624 /* create the new element */ 02625 elem = (PlyElement *) myalloc (sizeof (PlyElement)); 02626 elem->name = strdup (words[1]); 02627 elem->num = atoi (words[2]); 02628 elem->nprops = 0; 02629 02630 /* make room for new element in the object's list of elements */ 02631 if (plyfile->nelems == 0) 02632 plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); 02633 else 02634 plyfile->elems = (PlyElement **) realloc (plyfile->elems, 02635 sizeof (PlyElement *) * (plyfile->nelems + 1)); 02636 02637 /* add the new element to the object's list */ 02638 plyfile->elems[plyfile->nelems] = elem; 02639 plyfile->nelems++; 02640 } 02641 02642 02643 /****************************************************************************** 02644 Return the type of a property, given the name of the property. 02645 02646 Entry: 02647 name - name of property type 02648 02649 Exit: 02650 returns integer code for property, or 0 if not found 02651 ******************************************************************************/ 02652 02653 int get_prop_type(char *type_name) 02654 { 02655 int i; 02656 02657 for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++) 02658 if (equal_strings (type_name, type_names[i])) 02659 return (i); 02660 02661 /* if we get here, we didn't find the type */ 02662 return (0); 02663 } 02664 02665 02666 /****************************************************************************** 02667 Add a property to a PLY file descriptor. 02668 02669 Entry: 02670 plyfile - PLY file descriptor 02671 words - list of words describing the property 02672 nwords - number of words in the list 02673 ******************************************************************************/ 02674 02675 void add_property (PlyFile *plyfile, char **words, int ) 02676 { 02677 PlyProperty *prop; 02678 PlyElement *elem; 02679 02680 /* create the new property */ 02681 02682 prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); 02683 02684 if (equal_strings (words[1], "list")) { /* is a list */ 02685 prop->count_external = get_prop_type (words[2]); 02686 prop->external_type = get_prop_type (words[3]); 02687 prop->name = strdup (words[4]); 02688 prop->is_list = 1; 02689 } 02690 else { /* not a list */ 02691 prop->external_type = get_prop_type (words[1]); 02692 prop->name = strdup (words[2]); 02693 prop->is_list = 0; 02694 } 02695 02696 /* add this property to the list of properties of the current element */ 02697 02698 elem = plyfile->elems[plyfile->nelems - 1]; 02699 02700 if (elem->nprops == 0) 02701 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); 02702 else 02703 elem->props = (PlyProperty **) realloc (elem->props, 02704 sizeof (PlyProperty *) * (elem->nprops + 1)); 02705 02706 elem->props[elem->nprops] = prop; 02707 elem->nprops++; 02708 } 02709 02710 02711 /****************************************************************************** 02712 Add a comment to a PLY file descriptor. 02713 02714 Entry: 02715 plyfile - PLY file descriptor 02716 line - line containing comment 02717 ******************************************************************************/ 02718 02719 void add_comment (PlyFile *plyfile, char *line) 02720 { 02721 int i; 02722 02723 /* skip over "comment" and leading spaces and tabs */ 02724 i = 7; 02725 while (line[i] == ' ' || line[i] == '\t') 02726 i++; 02727 02728 ply_put_comment (plyfile, &line[i]); 02729 } 02730 02731 02732 /****************************************************************************** 02733 Add a some object information to a PLY file descriptor. 02734 02735 Entry: 02736 plyfile - PLY file descriptor 02737 line - line containing text info 02738 ******************************************************************************/ 02739 02740 void add_obj_info (PlyFile *plyfile, char *line) 02741 { 02742 int i; 02743 02744 /* skip over "obj_info" and leading spaces and tabs */ 02745 i = 8; 02746 while (line[i] == ' ' || line[i] == '\t') 02747 i++; 02748 02749 ply_put_obj_info (plyfile, &line[i]); 02750 } 02751 02752 02753 /****************************************************************************** 02754 Copy a property. 02755 ******************************************************************************/ 02756 02757 void copy_property(PlyProperty *dest, PlyProperty *src) 02758 { 02759 dest->name = strdup (src->name); 02760 dest->external_type = src->external_type; 02761 dest->internal_type = src->internal_type; 02762 dest->offset = src->offset; 02763 02764 dest->is_list = src->is_list; 02765 dest->count_external = src->count_external; 02766 dest->count_internal = src->count_internal; 02767 dest->count_offset = src->count_offset; 02768 } 02769 02770 02771 /****************************************************************************** 02772 Allocate some memory. 02773 02774 Entry: 02775 size - amount of memory requested (in bytes) 02776 lnum - line number from which memory was requested 02777 fname - file name from which memory was requested 02778 ******************************************************************************/ 02779 02780 char *my_alloc(int size, int lnum, const char *fname) 02781 { 02782 char *ptr; 02783 02784 ptr = (char *) malloc (size); 02785 02786 if (ptr == 0) 02787 fprintf( stderr, "Memory allocation bombed on line %d in %s\n", 02788 lnum, fname); 02789 02790 return (ptr); 02791 } 02792