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