1 #ifndef IGL_PLY_H
2 #define IGL_PLY_H
3 /*
4
5 Header for PLY polygon files.
6
7 - Greg Turk, March 1994
8
9 A PLY file contains a single polygonal _object_.
10
11 An object is composed of lists of _elements_. Typical elements are
12 vertices, faces, edges and materials.
13
14 Each type of element for a given object has one or more _properties_
15 associated with the element type. For instance, a vertex element may
16 have as properties three floating-point values x,y,z and three unsigned
17 chars for red, green and blue.
18
19 ---------------------------------------------------------------
20
21 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
22 Junior University. All rights reserved.
23
24 Permission to use, copy, modify and distribute this software and its
25 documentation for any purpose is hereby granted without fee, provided
26 that the above copyright notice and this permission notice appear in
27 all copies of this software and that you do not sell the software.
28
29 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
30 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
31 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
32
33 */
34
35 /*
36 --------------------------------------------------------------------------------
37 Joao Fradinho Oliveira, July 2005
38 Copyright (c) 2005 University College London
39 copyright conditions as above
40
41 update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
42 --------------------------------------------------------------------------------
43
44 ply_open_for_reading
45
46 * was changed to always open files in binary mode, files written in ascii can also be
47 read with this binary mode.
48
49 * allows opening of filenames that are alias files in macintosh
50
51 * code tested on pc and mac
52
53
54 get_words
55
56 * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
57 accordingly for the next read.
58
59
60 NOTES:
61 The ply file, has always an ascii part for the header, and a binary or ascii
62 part for the data.
63 The header part in ascii, dictates that linebreaks are used, this make models
64 operating system dependent, as a line break in unix is indicated with the escape character \n,
65 on a macintosh, with \r, and on a pc with \r\n <--2 unsigned chars, 2 bytes, instead of 1 byte.
66
67 get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
68 properly to target OSs with binary files.
69
70 */
71
72 #ifndef __PLY_H__
73 #define __PLY_H__
74
75
76
77 #include <stdlib.h>
78 #include <stdio.h>
79 #include <stddef.h>
80 #include <string.h>
81
82 namespace igl {
83 namespace ply {
84
85 #define PLY_ASCII 1 /* ascii PLY file */
86 #define PLY_BINARY_BE 2 /* binary PLY file, big endian */
87 #define PLY_BINARY_LE 3 /* binary PLY file, little endian */
88 #define PLY_BINARY_NATIVE 4 /* binary PLY file, same endianness as
89 current architecture */
90
91 #define PLY_OKAY 0 /* ply routine worked okay */
92 #define PLY_ERROR -1 /* error in ply routine */
93
94 /* scalar data types supported by PLY format */
95
96 #define PLY_START_TYPE 0
97 #define PLY_CHAR 1
98 #define PLY_SHORT 2
99 #define PLY_INT 3
100 #define PLY_UCHAR 4
101 #define PLY_USHORT 5
102 #define PLY_UINT 6
103 #define PLY_FLOAT 7
104 #define PLY_DOUBLE 8
105 #define PLY_END_TYPE 9
106
107 #define PLY_SCALAR 0
108 #define PLY_LIST 1
109
110
111
112
113 typedef struct PlyProperty { /* description of a property */
114
115 const char *name; /* property name */
116 int external_type; /* file's data type */
117 int internal_type; /* program's data type */
118 int offset; /* offset bytes of prop in a struct */
119
120 int is_list; /* 1 = list, 0 = scalar */
121 int count_external; /* file's count type */
122 int count_internal; /* program's count type */
123 int count_offset; /* offset byte for list count */
124
125 } PlyProperty;
126
127 typedef struct PlyElement { /* description of an element */
128 const char *name; /* element name */
129 int num; /* number of elements in this object */
130 int size; /* size of element (bytes) or -1 if variable */
131 int nprops; /* number of properties for this element */
132 PlyProperty **props; /* list of properties in the file */
133 char *store_prop; /* flags: property wanted by user? */
134 int other_offset; /* offset to un-asked-for props, or -1 if none*/
135 int other_size; /* size of other_props structure */
136 } PlyElement;
137
138 typedef struct PlyOtherProp { /* describes other properties in an element */
139 const char *name; /* element name */
140 int size; /* size of other_props */
141 int nprops; /* number of properties in other_props */
142 PlyProperty **props; /* list of properties in other_props */
143 } PlyOtherProp;
144
145 typedef struct OtherData { /* for storing other_props for an other element */
146 void *other_props;
147 } OtherData;
148
149 typedef struct OtherElem { /* data for one "other" element */
150 char *elem_name; /* names of other elements */
151 int elem_count; /* count of instances of each element */
152 OtherData **other_data; /* actual property data for the elements */
153 PlyOtherProp *other_props; /* description of the property data */
154 } OtherElem;
155
156 typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
157 int num_elems; /* number of other elements */
158 OtherElem *other_list; /* list of data for other elements */
159 } PlyOtherElems;
160
161 typedef struct PlyFile { /* description of PLY file */
162 FILE *fp; /* file pointer */
163 int file_type; /* ascii or binary */
164 float version; /* version number of file */
165 int nelems; /* number of elements of object */
166 PlyElement **elems; /* list of elements */
167 int num_comments; /* number of comments */
168 char **comments; /* list of comments */
169 int num_obj_info; /* number of items of object information */
170 char **obj_info; /* list of object info items */
171 PlyElement *which_elem; /* which element we're currently writing */
172 PlyOtherElems *other_elems; /* "other" elements from a PLY file */
173 } PlyFile;
174
175 /* memory allocation */
176 extern char *my_alloc();
177 #define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
178
179 #ifndef ALLOCN
180 #define REALLOCN(PTR,TYPE,OLD_N,NEW_N) \
181 { \
182 if ((OLD_N) == 0) \
183 { ALLOCN((PTR),TYPE,(NEW_N));} \
184 else \
185 { \
186 (PTR) = (TYPE *)realloc((PTR),(NEW_N)*sizeof(TYPE)); \
187 if (((PTR) == NULL) && ((NEW_N) != 0)) \
188 { \
189 fprintf(stderr, "Memory reallocation failed on line %d in %s\n", \
190 __LINE__, __FILE__); \
191 fprintf(stderr, " tried to reallocate %d->%d\n", \
192 (OLD_N), (NEW_N)); \
193 exit(-1); \
194 } \
195 if ((NEW_N)>(OLD_N)) \
196 memset((char *)(PTR)+(OLD_N)*sizeof(TYPE), 0, \
197 ((NEW_N)-(OLD_N))*sizeof(TYPE)); \
198 } \
199 }
200
201 #define ALLOCN(PTR,TYPE,N) \
202 { (PTR) = (TYPE *) calloc(((unsigned)(N)),sizeof(TYPE));\
203 if ((PTR) == NULL) { \
204 fprintf(stderr, "Memory allocation failed on line %d in %s\n", \
205 __LINE__, __FILE__); \
206 exit(-1); \
207 } \
208 }
209
210
211 #define FREE(PTR) { free((PTR)); (PTR) = NULL; }
212 #endif
213
214
215 /*** delcaration of routines ***/
216
217 inline int get_native_binary_type2();
218
219 inline PlyFile *ply_write(FILE *, int,const char **, int);
220 inline PlyFile *ply_open_for_writing(char *, int,const char **, int, float *);
221 inline void ply_describe_element(PlyFile *, const char *, int, int, PlyProperty *);
222 inline void ply_describe_property(PlyFile *, const char *, PlyProperty *);
223 inline void ply_element_count(PlyFile *, const char *, int);
224 inline void ply_header_complete(PlyFile *);
225 inline void ply_put_element_setup(PlyFile *, const char *);
226 inline void ply_put_element(PlyFile *, void *, int*);
227 inline void ply_put_comment(PlyFile *, char *);
228 inline void ply_put_obj_info(PlyFile *, char *);
229 inline PlyFile *ply_read(FILE *, int *, char ***);
230 inline PlyFile *ply_open_for_reading( const char *, int *, char ***, int *, float *);
231 inline PlyProperty **ply_get_element_description(PlyFile *, const char *, int*, int*);
232 inline void ply_get_element_setup( PlyFile *, const char *, int, PlyProperty *);
233 inline void ply_get_property(PlyFile *, const char *, PlyProperty *);
234 inline PlyOtherProp *ply_get_other_properties(PlyFile *, const char *, int);
235 inline void ply_get_element(PlyFile *, void *, int *);
236 inline char **ply_get_comments(PlyFile *, int *);
237 inline char **ply_get_obj_info(PlyFile *, int *);
238 inline void ply_close(PlyFile *);
239 inline void ply_get_info(PlyFile *, float *, int *);
240 inline PlyOtherElems *ply_get_other_element (PlyFile *, const char *, int);
241 inline void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
242 inline void ply_put_other_elements (PlyFile *);
243 inline void ply_free_other_elements (PlyOtherElems *);
244 inline void ply_describe_other_properties(PlyFile *, PlyOtherProp *, int);
245
246 inline int equal_strings(const char *, const char *);
247
248
249 }
250 }
251 #endif /* !__PLY_H__ */
252 /*
253
254 The interface routines for reading and writing PLY polygon files.
255
256 Greg Turk, February 1994
257
258 ---------------------------------------------------------------
259
260 A PLY file contains a single polygonal _object_.
261
262 An object is composed of lists of _elements_. Typical elements are
263 vertices, faces, edges and materials.
264
265 Each type of element for a given object has one or more _properties_
266 associated with the element type. For instance, a vertex element may
267 have as properties the floating-point values x,y,z and the three unsigned
268 chars representing red, green and blue.
269
270 ---------------------------------------------------------------
271
272 Copyright (c) 1994 The Board of Trustees of The Leland Stanford
273 Junior University. All rights reserved.
274
275 Permission to use, copy, modify and distribute this software and its
276 documentation for any purpose is hereby granted without fee, provided
277 that the above copyright notice and this permission notice appear in
278 all copies of this software and that you do not sell the software.
279
280 THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
281 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
282 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
283
284 */
285
286 /*
287 --------------------------------------------------------------------------------
288 Joao Fradinho Oliveira, July 2005
289 University College London
290
291 update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
292 --------------------------------------------------------------------------------
293
294 ply_open_for_reading
295
296 * was changed to always open files in binary mode, files written in ascii can also be
297 read with this binary mode.
298
299 * allows opening of filenames that are alias files in macintosh
300
301 * code tested on pc and mac
302
303
304 get_words
305
306 * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
307 accordingly for the next read.
308
309
310 NOTES:
311 The ply file, has always an ascii part for the header, and a binary or ascii
312 part for the data.
313 The header part in ascii, dictates that linebreaks are used, this make models
314 operating system dependent, as a line break in unix is indicated with the escape character \n,
315 on a macintosh, with \r, and on a pc with \r\n <--2 unsigned chars, 2 bytes, instead of 1 byte.
316
317 get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
318 properly to target OSs with binary files.
319
320 */
321
322 #include <stdio.h>
323 #include <stdlib.h>
324 #include <math.h>
325 #include <string.h>
326 //#include "ply.h"
327
328
329 namespace igl {
330 namespace ply {
331
332
333 // Use unnamed namespace to avoid duplicate symbols
334 /*
335 namespace
336 {
337 const char *type_names[] = {
338 "invalid",
339 "char", "short", "int",
340 "uchar", "ushort", "uint",
341 "float", "double",
342 };
343
344 // names of scalar types
345 const char *alt_type_names[] = {
346 "invalid",
347 "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
348 };
349
350 int ply_type_size[] = {
351 0, 1, 2, 4, 1, 2, 4, 4, 8
352 };
353 }
354
355 typedef union
356 {
357 int int_value;
358 char byte_values[sizeof(int)];
359 } endian_test_type;
360
361
362 namespace
363 {
364 static int native_binary_type = -1;
365 static int types_checked = 0;
366 }
367 */
368
369 #define NO_OTHER_PROPS -1
370
371 #define DONT_STORE_PROP 0
372 #define STORE_PROP 1
373
374 #define OTHER_PROP 0
375 #define NAMED_PROP 1
376
377 /* returns 1 if strings are equal, 0 if not */
378 inline int equal_strings(const char *, const char *);
379
380 /* find an element in a plyfile's list */
381 inline PlyElement *find_element(PlyFile *, const char *);
382
383 /* find a property in an element's list */
384 inline PlyProperty *find_property(PlyElement *, const char *, int *);
385
386 /* write to a file the word describing a PLY file data type */
387 inline void write_scalar_type (FILE *, int);
388
389 /* read a line from a file and break it up into separate words */
390 inline char **get_words(FILE *, int *, char **);
391 inline char **old_get_words(FILE *, int *);
392
393 /* write an item to a file */
394 inline void write_binary_item(FILE *, int, int, unsigned int, double, int, int*);
395 inline void write_ascii_item(FILE *, int, unsigned int, double, int);
396 inline double old_write_ascii_item(FILE *, char *, int);
397
398 /* add information to a PLY file descriptor */
399 inline void add_element(PlyFile *, char **);
400 inline void add_property(PlyFile *, char **);
401 inline void add_comment(PlyFile *, char *);
402 inline void add_obj_info(PlyFile *, char *);
403
404 /* copy a property */
405 inline void copy_property(PlyProperty *, PlyProperty *);
406
407 /* store a value into where a pointer and a type specify */
408 inline void store_item(char *, int, int, unsigned int, double);
409
410 /* return the value of a stored item */
411 inline void get_stored_item( void *, int, int *, unsigned int *, double *);
412
413 /* return the value stored in an item, given ptr to it and its type */
414 inline double get_item_value(char *, int);
415
416 /* get binary or ascii item and store it according to ptr and type */
417 inline void get_ascii_item(char *, int, int *, unsigned int *, double *);
418 inline void get_binary_item(FILE *, int, int, int *, unsigned int *, double *, int*);
419
420 /* get a bunch of elements from a file */
421 inline void ascii_get_element(PlyFile *, char *);
422 inline void binary_get_element(PlyFile *, char *, int*);
423
424 /* memory allocation */
425 inline char *my_alloc(int, int, const char *);
426
427 /* byte ordering */
428 inline void get_native_binary_type(int*);
429 inline void swap_bytes(char *, int);
430
431 inline int check_types();
432
433
434 /*************/
435 /* Writing */
436 /*************/
437
438
439 /******************************************************************************
440 Given a file pointer, get ready to write PLY data to the file.
441
442 Entry:
443 fp - the given file pointer
444 nelems - number of elements in object
445 elem_names - list of element names
446 file_type - file type, either ascii or binary
447
448 Exit:
449 returns a pointer to a PlyFile, used to refer to this file, or NULL if error
450 ******************************************************************************/
451
ply_write(FILE * fp,int nelems,const char ** elem_names,int file_type)452 inline PlyFile *ply_write(
453 FILE *fp,
454 int nelems,
455 const char **elem_names,
456 int file_type
457 )
458 {
459 int i;
460 PlyFile *plyfile;
461 PlyElement *elem;
462
463 /* check for NULL file pointer */
464 if (fp == NULL)
465 return (NULL);
466
467 int native_binary_type = -1;
468 int types_checked = 0;
469 if (native_binary_type == -1)
470 native_binary_type = get_native_binary_type2();
471 if (!types_checked)
472 types_checked = check_types();
473
474 /* create a record for this object */
475
476 plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
477 if (file_type == PLY_BINARY_NATIVE)
478 plyfile->file_type = native_binary_type;
479 else
480 plyfile->file_type = file_type;
481 plyfile->num_comments = 0;
482 plyfile->num_obj_info = 0;
483 plyfile->nelems = nelems;
484 plyfile->version = 1.0;
485 plyfile->fp = fp;
486 plyfile->other_elems = NULL;
487
488 /* tuck aside the names of the elements */
489
490 plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
491 for (i = 0; i < nelems; i++) {
492 elem = (PlyElement *) myalloc (sizeof (PlyElement));
493 plyfile->elems[i] = elem;
494 elem->name = strdup (elem_names[i]);
495 elem->num = 0;
496 elem->nprops = 0;
497 }
498
499 /* return pointer to the file descriptor */
500 return (plyfile);
501 }
502
503
504 /******************************************************************************
505 Open a polygon file for writing.
506
507 Entry:
508 filename - name of file to read from
509 nelems - number of elements in object
510 elem_names - list of element names
511 file_type - file type, either ascii or binary
512
513 Exit:
514 version - version number of PLY file
515 returns a file identifier, used to refer to this file, or NULL if error
516 ******************************************************************************/
517
ply_open_for_writing(const char * filename,int nelems,const char ** elem_names,int file_type,float * version)518 inline PlyFile *ply_open_for_writing(
519 const char *filename,
520 int nelems,
521 const char **elem_names,
522 int file_type,
523 float *version
524 )
525 {
526 PlyFile *plyfile;
527 char *name;
528 FILE *fp;
529
530 /* tack on the extension .ply, if necessary */
531
532 name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
533 strcpy (name, filename);
534 if (strlen (name) < 4 ||
535 strcmp (name + strlen (name) - 4, ".ply") != 0)
536 strcat (name, ".ply");
537
538 /* open the file for writing */
539
540 fp = fopen (name, "w");
541 if (fp == NULL) {
542 return (NULL);
543 }
544
545 /* create the actual PlyFile structure */
546
547 plyfile = ply_write (fp, nelems, elem_names, file_type);
548 if (plyfile == NULL)
549 return (NULL);
550
551 /* say what PLY file version number we're writing */
552 *version = plyfile->version;
553
554 /* return pointer to the file descriptor */
555 return (plyfile);
556 }
557
558
559 /******************************************************************************
560 Describe an element, including its properties and how many will be written
561 to the file.
562
563 Entry:
564 plyfile - file identifier
565 elem_name - name of element that information is being specified about
566 nelems - number of elements of this type to be written
567 nprops - number of properties contained in the element
568 prop_list - list of properties
569 ******************************************************************************/
570
ply_describe_element(PlyFile * plyfile,const char * elem_name,int nelems,int nprops,PlyProperty * prop_list)571 inline void ply_describe_element(
572 PlyFile *plyfile,
573 const char *elem_name,
574 int nelems,
575 int nprops,
576 PlyProperty *prop_list
577 )
578 {
579 int i;
580 PlyElement *elem;
581 PlyProperty *prop;
582
583 /* look for appropriate element */
584 elem = find_element (plyfile, elem_name);
585 if (elem == NULL) {
586 fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
587 exit (-1);
588 }
589
590 elem->num = nelems;
591
592 /* copy the list of properties */
593
594 elem->nprops = nprops;
595 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
596 elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
597
598 for (i = 0; i < nprops; i++) {
599 prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
600 elem->props[i] = prop;
601 elem->store_prop[i] = NAMED_PROP;
602 copy_property (prop, &prop_list[i]);
603 }
604 }
605
606
607 /******************************************************************************
608 Describe a property of an element.
609
610 Entry:
611 plyfile - file identifier
612 elem_name - name of element that information is being specified about
613 prop - the new property
614 ******************************************************************************/
615
ply_describe_property(PlyFile * plyfile,const char * elem_name,PlyProperty * prop)616 inline void ply_describe_property(
617 PlyFile *plyfile,
618 const char *elem_name,
619 PlyProperty *prop
620 )
621 {
622 PlyElement *elem;
623 PlyProperty *elem_prop;
624
625 /* look for appropriate element */
626 elem = find_element (plyfile, elem_name);
627 if (elem == NULL) {
628 fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
629 elem_name);
630 return;
631 }
632
633 /* create room for new property */
634
635 if (elem->nprops == 0) {
636 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
637 elem->store_prop = (char *) myalloc (sizeof (char));
638 elem->nprops = 1;
639 }
640 else {
641 elem->nprops++;
642 elem->props = (PlyProperty **)
643 realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
644 elem->store_prop = (char *)
645 realloc (elem->store_prop, sizeof (char) * elem->nprops);
646 }
647
648 /* copy the new property */
649
650 elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
651 elem->props[elem->nprops - 1] = elem_prop;
652 elem->store_prop[elem->nprops - 1] = NAMED_PROP;
653 copy_property (elem_prop, prop);
654 }
655
656
657 /******************************************************************************
658 Describe what the "other" properties are that are to be stored, and where
659 they are in an element.
660 ******************************************************************************/
661
ply_describe_other_properties(PlyFile * plyfile,PlyOtherProp * other,int offset)662 inline void ply_describe_other_properties(
663 PlyFile *plyfile,
664 PlyOtherProp *other,
665 int offset
666 )
667 {
668 int i;
669 PlyElement *elem;
670 PlyProperty *prop;
671
672 /* look for appropriate element */
673 elem = find_element (plyfile, other->name);
674 if (elem == NULL) {
675 fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
676 other->name);
677 return;
678 }
679
680 /* create room for other properties */
681
682 if (elem->nprops == 0) {
683 elem->props = (PlyProperty **)
684 myalloc (sizeof (PlyProperty *) * other->nprops);
685 elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
686 elem->nprops = 0;
687 }
688 else {
689 int newsize;
690 newsize = elem->nprops + other->nprops;
691 elem->props = (PlyProperty **)
692 realloc (elem->props, sizeof (PlyProperty *) * newsize);
693 elem->store_prop = (char *)
694 realloc (elem->store_prop, sizeof (char) * newsize);
695 }
696
697 /* copy the other properties */
698
699 for (i = 0; i < other->nprops; i++) {
700 prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
701 copy_property (prop, other->props[i]);
702 elem->props[elem->nprops] = prop;
703 elem->store_prop[elem->nprops] = OTHER_PROP;
704 elem->nprops++;
705 }
706
707 /* save other info about other properties */
708 elem->other_size = other->size;
709 elem->other_offset = offset;
710 }
711
712
713 /******************************************************************************
714 State how many of a given element will be written.
715
716 Entry:
717 plyfile - file identifier
718 elem_name - name of element that information is being specified about
719 nelems - number of elements of this type to be written
720 ******************************************************************************/
721
ply_element_count(PlyFile * plyfile,const char * elem_name,int nelems)722 inline void ply_element_count(
723 PlyFile *plyfile,
724 const char *elem_name,
725 int nelems
726 )
727 {
728 PlyElement *elem;
729
730 /* look for appropriate element */
731 elem = find_element (plyfile, elem_name);
732 if (elem == NULL) {
733 fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
734 exit (-1);
735 }
736
737 elem->num = nelems;
738 }
739
740
741 /******************************************************************************
742 Signal that we've described everything a PLY file's header and that the
743 header should be written to the file.
744
745 Entry:
746 plyfile - file identifier
747 ******************************************************************************/
748
ply_header_complete(PlyFile * plyfile)749 inline void ply_header_complete(PlyFile *plyfile)
750 {
751 int i,j;
752 FILE *fp = plyfile->fp;
753 PlyElement *elem;
754 PlyProperty *prop;
755
756 fprintf (fp, "ply\n");
757
758 switch (plyfile->file_type) {
759 case PLY_ASCII:
760 fprintf (fp, "format ascii 1.0\n");
761 break;
762 case PLY_BINARY_BE:
763 fprintf (fp, "format binary_big_endian 1.0\n");
764 break;
765 case PLY_BINARY_LE:
766 fprintf (fp, "format binary_little_endian 1.0\n");
767 break;
768 default:
769 fprintf (stderr, "ply_header_complete: bad file type = %d\n",
770 plyfile->file_type);
771 exit (-1);
772 }
773
774 /* write out the comments */
775
776 for (i = 0; i < plyfile->num_comments; i++)
777 fprintf (fp, "comment %s\n", plyfile->comments[i]);
778
779 /* write out object information */
780
781 for (i = 0; i < plyfile->num_obj_info; i++)
782 fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
783
784 /* write out information about each element */
785
786 for (i = 0; i < plyfile->nelems; i++) {
787
788 elem = plyfile->elems[i];
789 fprintf (fp, "element %s %d\n", elem->name, elem->num);
790
791 /* write out each property */
792 for (j = 0; j < elem->nprops; j++) {
793 prop = elem->props[j];
794 if (prop->is_list) {
795 fprintf (fp, "property list ");
796 write_scalar_type (fp, prop->count_external);
797 fprintf (fp, " ");
798 write_scalar_type (fp, prop->external_type);
799 fprintf (fp, " %s\n", prop->name);
800 }
801 else {
802 fprintf (fp, "property ");
803 write_scalar_type (fp, prop->external_type);
804 fprintf (fp, " %s\n", prop->name);
805 }
806 }
807 }
808
809 fprintf (fp, "end_header\n");
810 }
811
812
813 /******************************************************************************
814 Specify which elements are going to be written. This should be called
815 before a call to the routine ply_put_element().
816
817 Entry:
818 plyfile - file identifier
819 elem_name - name of element we're talking about
820 ******************************************************************************/
821
ply_put_element_setup(PlyFile * plyfile,const char * elem_name)822 inline void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
823 {
824 PlyElement *elem;
825
826 elem = find_element (plyfile, elem_name);
827 if (elem == NULL) {
828 fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
829 exit (-1);
830 }
831
832 plyfile->which_elem = elem;
833 }
834
835
836 /******************************************************************************
837 Write an element to the file. This routine assumes that we're
838 writing the type of element specified in the last call to the routine
839 ply_put_element_setup().
840
841 Entry:
842 plyfile - file identifier
843 elem_ptr - pointer to the element
844 ******************************************************************************/
845
ply_put_element(PlyFile * plyfile,void * elem_ptr,int * native_binary_type)846 inline void ply_put_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
847 {
848 int j,k;
849 FILE *fp = plyfile->fp;
850 PlyElement *elem;
851 PlyProperty *prop;
852 char *elem_data,*item;
853 char **item_ptr;
854 int list_count;
855 int item_size;
856 int int_val;
857 unsigned int uint_val;
858 double double_val;
859 char **other_ptr;
860
861 elem = plyfile->which_elem;
862 elem_data = (char *)elem_ptr;
863 other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
864
865 /* write out either to an ascii or binary file */
866 int ply_type_size[] = {
867 0, 1, 2, 4, 1, 2, 4, 4, 8
868 };
869
870 if (plyfile->file_type == PLY_ASCII) {
871
872 /* write an ascii file */
873
874 /* write out each property of the element */
875 for (j = 0; j < elem->nprops; j++) {
876 prop = elem->props[j];
877 if (elem->store_prop[j] == OTHER_PROP)
878 elem_data = *other_ptr;
879 else
880 elem_data = (char *)elem_ptr;
881 if (prop->is_list) {
882 item = elem_data + prop->count_offset;
883 get_stored_item ((void *) item, prop->count_internal,
884 &int_val, &uint_val, &double_val);
885 write_ascii_item (fp, int_val, uint_val, double_val,
886 prop->count_external);
887 list_count = uint_val;
888 item_ptr = (char **) (elem_data + prop->offset);
889 item = item_ptr[0];
890 item_size = ply_type_size[prop->internal_type];
891 for (k = 0; k < list_count; k++) {
892 get_stored_item ((void *) item, prop->internal_type,
893 &int_val, &uint_val, &double_val);
894 write_ascii_item (fp, int_val, uint_val, double_val,
895 prop->external_type);
896 item += item_size;
897 }
898 }
899 else {
900 item = elem_data + prop->offset;
901 get_stored_item ((void *) item, prop->internal_type,
902 &int_val, &uint_val, &double_val);
903 write_ascii_item (fp, int_val, uint_val, double_val,
904 prop->external_type);
905 }
906 }
907
908 fprintf (fp, "\n");
909 }
910 else {
911
912 /* write a binary file */
913
914 /* write out each property of the element */
915 for (j = 0; j < elem->nprops; j++) {
916 prop = elem->props[j];
917 if (elem->store_prop[j] == OTHER_PROP)
918 elem_data = *other_ptr;
919 else
920 elem_data = (char *)elem_ptr;
921 if (prop->is_list) {
922 item = elem_data + prop->count_offset;
923 item_size = ply_type_size[prop->count_internal];
924 get_stored_item ((void *) item, prop->count_internal,
925 &int_val, &uint_val, &double_val);
926 write_binary_item (fp, plyfile->file_type, int_val, uint_val,
927 double_val, prop->count_external, native_binary_type);
928 list_count = uint_val;
929 item_ptr = (char **) (elem_data + prop->offset);
930 item = item_ptr[0];
931 item_size = ply_type_size[prop->internal_type];
932 for (k = 0; k < list_count; k++) {
933 get_stored_item ((void *) item, prop->internal_type,
934 &int_val, &uint_val, &double_val);
935 write_binary_item (fp, plyfile->file_type, int_val, uint_val,
936 double_val, prop->external_type, native_binary_type);
937 item += item_size;
938 }
939 }
940 else {
941 item = elem_data + prop->offset;
942 item_size = ply_type_size[prop->internal_type];
943 get_stored_item ((void *) item, prop->internal_type,
944 &int_val, &uint_val, &double_val);
945 write_binary_item (fp, plyfile->file_type, int_val, uint_val,
946 double_val, prop->external_type, native_binary_type);
947 }
948 }
949
950 }
951 }
952
953
954 /******************************************************************************
955 Specify a comment that will be written in the header.
956
957 Entry:
958 plyfile - file identifier
959 comment - the comment to be written
960 ******************************************************************************/
961
ply_put_comment(PlyFile * plyfile,char * comment)962 inline void ply_put_comment(PlyFile *plyfile, char *comment)
963 {
964 /* (re)allocate space for new comment */
965 if (plyfile->num_comments == 0)
966 plyfile->comments = (char **) myalloc (sizeof (char *));
967 else
968 plyfile->comments = (char **) realloc (plyfile->comments,
969 sizeof (char *) * (plyfile->num_comments + 1));
970
971 /* add comment to list */
972 plyfile->comments[plyfile->num_comments] = strdup (comment);
973 plyfile->num_comments++;
974 }
975
976
977 /******************************************************************************
978 Specify a piece of object information (arbitrary text) that will be written
979 in the header.
980
981 Entry:
982 plyfile - file identifier
983 obj_info - the text information to be written
984 ******************************************************************************/
985
ply_put_obj_info(PlyFile * plyfile,char * obj_info)986 inline void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
987 {
988 /* (re)allocate space for new info */
989 if (plyfile->num_obj_info == 0)
990 plyfile->obj_info = (char **) myalloc (sizeof (char *));
991 else
992 plyfile->obj_info = (char **) realloc (plyfile->obj_info,
993 sizeof (char *) * (plyfile->num_obj_info + 1));
994
995 /* add info to list */
996 plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
997 plyfile->num_obj_info++;
998 }
999
1000
1001
1002
1003
1004
1005
1006 /*************/
1007 /* Reading */
1008 /*************/
1009
1010
1011
1012 /******************************************************************************
1013 Given a file pointer, get ready to read PLY data from the file.
1014
1015 Entry:
1016 fp - the given file pointer
1017
1018 Exit:
1019 nelems - number of elements in object
1020 elem_names - list of element names
1021 returns a pointer to a PlyFile, used to refer to this file, or NULL if error
1022 ******************************************************************************/
1023
ply_read(FILE * fp,int * nelems,char *** elem_names)1024 inline PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
1025 {
1026 int i,j;
1027 PlyFile *plyfile;
1028 int nwords;
1029 char **words;
1030 char **elist;
1031 PlyElement *elem;
1032 char *orig_line;
1033
1034 /* check for NULL file pointer */
1035 if (fp == NULL)
1036 return (NULL);
1037
1038 int native_binary_type = -1;
1039 int types_checked = 0;
1040
1041 if (native_binary_type == -1)
1042 native_binary_type = get_native_binary_type2();
1043 if (!types_checked)
1044 types_checked = check_types();
1045
1046 /* create record for this object */
1047
1048 plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
1049 plyfile->nelems = 0;
1050 plyfile->comments = NULL;
1051 plyfile->num_comments = 0;
1052 plyfile->obj_info = NULL;
1053 plyfile->num_obj_info = 0;
1054 plyfile->fp = fp;
1055 plyfile->other_elems = NULL;
1056
1057 /* read and parse the file's header */
1058
1059 words = get_words (plyfile->fp, &nwords, &orig_line);
1060 if (nwords == 0 || !words || !equal_strings (words[0], "ply"))
1061 {
1062 if (words)
1063 free(words);
1064
1065
1066 return (NULL);
1067 }
1068
1069 while (words) {
1070
1071 /* parse words */
1072
1073 if (equal_strings (words[0], "format")) {
1074 if (nwords != 3) {
1075 free(words);
1076 return (NULL);
1077 }
1078 if (equal_strings (words[1], "ascii"))
1079 plyfile->file_type = PLY_ASCII;
1080 else if (equal_strings (words[1], "binary_big_endian"))
1081 plyfile->file_type = PLY_BINARY_BE;
1082 else if (equal_strings (words[1], "binary_little_endian"))
1083 plyfile->file_type = PLY_BINARY_LE;
1084 else {
1085 free(words);
1086 return (NULL);
1087 }
1088 plyfile->version = atof (words[2]);
1089 }
1090 else if (equal_strings (words[0], "element"))
1091 add_element (plyfile, words);
1092 else if (equal_strings (words[0], "property"))
1093 add_property (plyfile, words);
1094 else if (equal_strings (words[0], "comment"))
1095 add_comment (plyfile, orig_line);
1096 else if (equal_strings (words[0], "obj_info"))
1097 add_obj_info (plyfile, orig_line);
1098 else if (equal_strings (words[0], "end_header")) {
1099 free(words);
1100 break;
1101 }
1102
1103 /* free up words space */
1104 free (words);
1105
1106 words = get_words (plyfile->fp, &nwords, &orig_line);
1107 }
1108
1109 /* create tags for each property of each element, to be used */
1110 /* later to say whether or not to store each property for the user */
1111
1112 for (i = 0; i < plyfile->nelems; i++) {
1113 elem = plyfile->elems[i];
1114 elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
1115 for (j = 0; j < elem->nprops; j++)
1116 elem->store_prop[j] = DONT_STORE_PROP;
1117 elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
1118 }
1119
1120 /* set return values about the elements */
1121
1122 elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
1123 for (i = 0; i < plyfile->nelems; i++)
1124 elist[i] = strdup (plyfile->elems[i]->name);
1125
1126 *elem_names = elist;
1127 *nelems = plyfile->nelems;
1128
1129 /* return a pointer to the file's information */
1130
1131 return (plyfile);
1132 }
1133
1134
1135 /******************************************************************************
1136 Open a polygon file for reading.
1137
1138 Entry:
1139 filename - name of file to read from
1140
1141 Exit:
1142 nelems - number of elements in object
1143 elem_names - list of element names
1144 file_type - file type, either ascii or binary
1145 version - version number of PLY file
1146 returns a file identifier, used to refer to this file, or NULL if error
1147 ******************************************************************************/
1148
ply_open_for_reading(char * filename,int * nelems,char *** elem_names,int * file_type,float * version)1149 inline PlyFile *ply_open_for_reading(
1150 char *filename,
1151 int *nelems,
1152 char ***elem_names,
1153 int *file_type,
1154 float *version
1155 )
1156 {
1157 FILE *fp;
1158 PlyFile *plyfile;
1159 //char *name;
1160
1161
1162
1163 /* tack on the extension .ply, if necessary */
1164
1165 // removing below, to handle also macintosh alias filenames
1166 //name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
1167 //strcpy (name, filename);
1168 //if (strlen (name) < 4 ||
1169 // strcmp (name + strlen (name) - 4, ".ply") != 0)
1170 // strcat (name, ".ply");
1171
1172 /* open the file for reading */
1173
1174 //fp = fopen (name, "r");
1175
1176 //opening file in binary, ascii data can be read in binary with get_words
1177 fp = fopen (filename, "rb");
1178
1179 if (fp == NULL)
1180 return (NULL);
1181
1182 /* create the PlyFile data structure */
1183
1184 plyfile = ply_read (fp, nelems, elem_names);
1185
1186 /* determine the file type and version */
1187
1188 *file_type = plyfile->file_type;
1189 *version = plyfile->version;
1190
1191 /* return a pointer to the file's information */
1192
1193 return (plyfile);
1194 }
1195
1196
1197 /******************************************************************************
1198 Get information about a particular element.
1199
1200 Entry:
1201 plyfile - file identifier
1202 elem_name - name of element to get information about
1203
1204 Exit:
1205 nelems - number of elements of this type in the file
1206 nprops - number of properties
1207 returns a list of properties, or NULL if the file doesn't contain that elem
1208 ******************************************************************************/
1209
ply_get_element_description(PlyFile * plyfile,const char * elem_name,int * nelems,int * nprops)1210 inline PlyProperty **ply_get_element_description(
1211 PlyFile *plyfile,
1212 const char *elem_name,
1213 int *nelems,
1214 int *nprops
1215 )
1216 {
1217 int i;
1218 PlyElement *elem;
1219 PlyProperty *prop;
1220 PlyProperty **prop_list;
1221
1222 /* find information about the element */
1223 elem = find_element (plyfile, elem_name);
1224 if (elem == NULL)
1225 return (NULL);
1226
1227 *nelems = elem->num;
1228 *nprops = elem->nprops;
1229
1230 /* make a copy of the element's property list */
1231 prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
1232 for (i = 0; i < elem->nprops; i++) {
1233 prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
1234 copy_property (prop, elem->props[i]);
1235 prop_list[i] = prop;
1236 }
1237
1238 /* return this duplicate property list */
1239 return (prop_list);
1240 }
1241
1242
1243 /******************************************************************************
1244 Specify which properties of an element are to be returned. This should be
1245 called before a call to the routine ply_get_element().
1246
1247 Entry:
1248 plyfile - file identifier
1249 elem_name - which element we're talking about
1250 nprops - number of properties
1251 prop_list - list of properties
1252 ******************************************************************************/
1253
ply_get_element_setup(PlyFile * plyfile,const char * elem_name,int nprops,PlyProperty * prop_list)1254 inline void ply_get_element_setup(
1255 PlyFile *plyfile,
1256 const char *elem_name,
1257 int nprops,
1258 PlyProperty *prop_list
1259 )
1260 {
1261 int i;
1262 PlyElement *elem;
1263 PlyProperty *prop;
1264 int index;
1265
1266 /* find information about the element */
1267 elem = find_element (plyfile, elem_name);
1268 plyfile->which_elem = elem;
1269
1270 /* deposit the property information into the element's description */
1271 for (i = 0; i < nprops; i++) {
1272
1273 /* look for actual property */
1274 prop = find_property (elem, prop_list[i].name, &index);
1275 if (prop == NULL) {
1276 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
1277 prop_list[i].name, elem_name);
1278 continue;
1279 }
1280
1281 /* store its description */
1282 prop->internal_type = prop_list[i].internal_type;
1283 prop->offset = prop_list[i].offset;
1284 prop->count_internal = prop_list[i].count_internal;
1285 prop->count_offset = prop_list[i].count_offset;
1286
1287 /* specify that the user wants this property */
1288 elem->store_prop[index] = STORE_PROP;
1289 }
1290 }
1291
1292
1293 /******************************************************************************
1294 Specify a property of an element that is to be returned. This should be
1295 called (usually multiple times) before a call to the routine ply_get_element().
1296 This routine should be used in preference to the less flexible old routine
1297 called ply_get_element_setup().
1298
1299 Entry:
1300 plyfile - file identifier
1301 elem_name - which element we're talking about
1302 prop - property to add to those that will be returned
1303 ******************************************************************************/
1304
ply_get_property(PlyFile * plyfile,const char * elem_name,PlyProperty * prop)1305 inline void ply_get_property(
1306 PlyFile *plyfile,
1307 const char *elem_name,
1308 PlyProperty *prop
1309 )
1310 {
1311 PlyElement *elem;
1312 PlyProperty *prop_ptr;
1313 int index;
1314
1315 /* find information about the element */
1316 elem = find_element (plyfile, elem_name);
1317 plyfile->which_elem = elem;
1318
1319 /* deposit the property information into the element's description */
1320
1321 prop_ptr = find_property (elem, prop->name, &index);
1322 if (prop_ptr == NULL) {
1323 fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
1324 prop->name, elem_name);
1325 return;
1326 }
1327 prop_ptr->internal_type = prop->internal_type;
1328 prop_ptr->offset = prop->offset;
1329 prop_ptr->count_internal = prop->count_internal;
1330 prop_ptr->count_offset = prop->count_offset;
1331
1332 /* specify that the user wants this property */
1333 elem->store_prop[index] = STORE_PROP;
1334 }
1335
1336
1337 /******************************************************************************
1338 Read one element from the file. This routine assumes that we're reading
1339 the type of element specified in the last call to the routine
1340 ply_get_element_setup().
1341
1342 Entry:
1343 plyfile - file identifier
1344 elem_ptr - pointer to location where the element information should be put
1345 ******************************************************************************/
1346
ply_get_element(PlyFile * plyfile,void * elem_ptr,int * native_binary_type)1347 inline void ply_get_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
1348 {
1349 if (plyfile->file_type == PLY_ASCII)
1350 ascii_get_element (plyfile, (char *) elem_ptr);
1351 else
1352 binary_get_element (plyfile, (char *) elem_ptr, native_binary_type);
1353 }
1354
1355
1356 /******************************************************************************
1357 Extract the comments from the header information of a PLY file.
1358
1359 Entry:
1360 plyfile - file identifier
1361
1362 Exit:
1363 num_comments - number of comments returned
1364 returns a pointer to a list of comments
1365 ******************************************************************************/
1366
ply_get_comments(PlyFile * plyfile,int * num_comments)1367 inline char **ply_get_comments(PlyFile *plyfile, int *num_comments)
1368 {
1369 *num_comments = plyfile->num_comments;
1370 return (plyfile->comments);
1371 }
1372
1373
1374 /******************************************************************************
1375 Extract the object information (arbitrary text) from the header information
1376 of a PLY file.
1377
1378 Entry:
1379 plyfile - file identifier
1380
1381 Exit:
1382 num_obj_info - number of lines of text information returned
1383 returns a pointer to a list of object info lines
1384 ******************************************************************************/
1385
ply_get_obj_info(PlyFile * plyfile,int * num_obj_info)1386 inline char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
1387 {
1388 *num_obj_info = plyfile->num_obj_info;
1389 return (plyfile->obj_info);
1390 }
1391
1392
1393 /******************************************************************************
1394 Make ready for "other" properties of an element-- those properties that
1395 the user has not explicitly asked for, but that are to be stashed away
1396 in a special structure to be carried along with the element's other
1397 information.
1398
1399 Entry:
1400 plyfile - file identifier
1401 elem - element for which we want to save away other properties
1402 ******************************************************************************/
1403
setup_other_props(PlyElement * elem)1404 inline void setup_other_props(PlyElement *elem)
1405 {
1406 int i;
1407 PlyProperty *prop;
1408 int size = 0;
1409 int type_size;
1410
1411 /* Examine each property in decreasing order of size. */
1412 /* We do this so that all data types will be aligned by */
1413 /* word, half-word, or whatever within the structure. */
1414 int ply_type_size[] = {
1415 0, 1, 2, 4, 1, 2, 4, 4, 8
1416 };
1417
1418 for (type_size = 8; type_size > 0; type_size /= 2) {
1419
1420 /* add up the space taken by each property, and save this information */
1421 /* away in the property descriptor */
1422
1423 for (i = 0; i < elem->nprops; i++) {
1424
1425 /* don't bother with properties we've been asked to store explicitly */
1426 if (elem->store_prop[i])
1427 continue;
1428
1429 prop = elem->props[i];
1430
1431 /* internal types will be same as external */
1432 prop->internal_type = prop->external_type;
1433 prop->count_internal = prop->count_external;
1434
1435 /* check list case */
1436 if (prop->is_list) {
1437
1438 /* pointer to list */
1439 if (type_size == sizeof (void *)) {
1440 prop->offset = size;
1441 size += sizeof (void *); /* always use size of a pointer here */
1442 }
1443
1444 /* count of number of list elements */
1445 if (type_size == ply_type_size[prop->count_external]) {
1446 prop->count_offset = size;
1447 size += ply_type_size[prop->count_external];
1448 }
1449 }
1450 /* not list */
1451 else if (type_size == ply_type_size[prop->external_type]) {
1452 prop->offset = size;
1453 size += ply_type_size[prop->external_type];
1454 }
1455 }
1456
1457 }
1458
1459 /* save the size for the other_props structure */
1460 elem->other_size = size;
1461 }
1462
1463
1464 /******************************************************************************
1465 Specify that we want the "other" properties of an element to be tucked
1466 away within the user's structure. The user needn't be concerned for how
1467 these properties are stored.
1468
1469 Entry:
1470 plyfile - file identifier
1471 elem_name - name of element that we want to store other_props in
1472 offset - offset to where other_props will be stored inside user's structure
1473
1474 Exit:
1475 returns pointer to structure containing description of other_props
1476 ******************************************************************************/
1477
ply_get_other_properties(PlyFile * plyfile,const char * elem_name,int offset)1478 inline PlyOtherProp *ply_get_other_properties(
1479 PlyFile *plyfile,
1480 const char *elem_name,
1481 int offset
1482 )
1483 {
1484 int i;
1485 PlyElement *elem;
1486 PlyOtherProp *other;
1487 PlyProperty *prop;
1488 int nprops;
1489
1490 /* find information about the element */
1491 elem = find_element (plyfile, elem_name);
1492 if (elem == NULL) {
1493 fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
1494 elem_name);
1495 return (NULL);
1496 }
1497
1498 /* remember that this is the "current" element */
1499 plyfile->which_elem = elem;
1500
1501 /* save the offset to where to store the other_props */
1502 elem->other_offset = offset;
1503
1504 /* place the appropriate pointers, etc. in the element's property list */
1505 setup_other_props (elem);
1506
1507 /* create structure for describing other_props */
1508 other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
1509 other->name = strdup (elem_name);
1510 #if 0
1511 if (elem->other_offset == NO_OTHER_PROPS) {
1512 other->size = 0;
1513 other->props = NULL;
1514 other->nprops = 0;
1515 return (other);
1516 }
1517 #endif
1518 other->size = elem->other_size;
1519 other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
1520
1521 /* save descriptions of each "other" property */
1522 nprops = 0;
1523 for (i = 0; i < elem->nprops; i++) {
1524 if (elem->store_prop[i])
1525 continue;
1526 prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
1527 copy_property (prop, elem->props[i]);
1528 other->props[nprops] = prop;
1529 nprops++;
1530 }
1531 other->nprops = nprops;
1532
1533 #if 1
1534 /* set other_offset pointer appropriately if there are NO other properties */
1535 if (other->nprops == 0) {
1536 elem->other_offset = NO_OTHER_PROPS;
1537 }
1538 #endif
1539
1540 /* return structure */
1541 return (other);
1542 }
1543
1544
1545
1546
1547 /*************************/
1548 /* Other Element Stuff */
1549 /*************************/
1550
1551
1552
1553
1554 /******************************************************************************
1555 Grab all the data for an element that a user does not want to explicitly
1556 read in.
1557
1558 Entry:
1559 plyfile - pointer to file
1560 elem_name - name of element whose data is to be read in
1561 elem_count - number of instances of this element stored in the file
1562
1563 Exit:
1564 returns pointer to ALL the "other" element data for this PLY file
1565 ******************************************************************************/
1566
ply_get_other_element(PlyFile * plyfile,char * elem_name,int elem_count)1567 inline PlyOtherElems *ply_get_other_element (
1568 PlyFile *plyfile,
1569 char *elem_name,
1570 int elem_count
1571 )
1572 {
1573 int i;
1574 PlyElement *elem;
1575 PlyOtherElems *other_elems;
1576 OtherElem *other;
1577
1578 /* look for appropriate element */
1579 elem = find_element (plyfile, elem_name);
1580 if (elem == NULL) {
1581 fprintf (stderr,
1582 "ply_get_other_element: can't find element '%s'\n", elem_name);
1583 exit (-1);
1584 }
1585
1586 /* create room for the new "other" element, initializing the */
1587 /* other data structure if necessary */
1588
1589 if (plyfile->other_elems == NULL) {
1590 plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
1591 other_elems = plyfile->other_elems;
1592 other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
1593 other = &(other_elems->other_list[0]);
1594 other_elems->num_elems = 1;
1595 }
1596 else {
1597 other_elems = plyfile->other_elems;
1598 other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
1599 sizeof (OtherElem) * (other_elems->num_elems + 1));
1600 other = &(other_elems->other_list[other_elems->num_elems]);
1601 other_elems->num_elems++;
1602 }
1603
1604 /* count of element instances in file */
1605 other->elem_count = elem_count;
1606
1607 /* save name of element */
1608 other->elem_name = strdup (elem_name);
1609
1610 /* create a list to hold all the current elements */
1611 other->other_data = (OtherData **)
1612 malloc (sizeof (OtherData *) * other->elem_count);
1613
1614 /* set up for getting elements */
1615 other->other_props = ply_get_other_properties (plyfile, elem_name,
1616 offsetof(OtherData,other_props));
1617
1618 /* grab all these elements */
1619 int native_binary_type = get_native_binary_type2();
1620 for (i = 0; i < other->elem_count; i++) {
1621 /* grab and element from the file */
1622 other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
1623 ply_get_element (plyfile, (void *) other->other_data[i], &native_binary_type);
1624 }
1625
1626 /* return pointer to the other elements data */
1627 return (other_elems);
1628 }
1629
1630
1631 /******************************************************************************
1632 Pass along a pointer to "other" elements that we want to save in a given
1633 PLY file. These other elements were presumably read from another PLY file.
1634
1635 Entry:
1636 plyfile - file pointer in which to store this other element info
1637 other_elems - info about other elements that we want to store
1638 ******************************************************************************/
1639
ply_describe_other_elements(PlyFile * plyfile,PlyOtherElems * other_elems)1640 inline void ply_describe_other_elements (
1641 PlyFile *plyfile,
1642 PlyOtherElems *other_elems
1643 )
1644 {
1645 int i;
1646 OtherElem *other;
1647 PlyElement *elem;
1648
1649 /* ignore this call if there is no other element */
1650 if (other_elems == NULL)
1651 return;
1652
1653 /* save pointer to this information */
1654 plyfile->other_elems = other_elems;
1655
1656 /* describe the other properties of this element */
1657 /* store them in the main element list as elements with
1658 only other properties */
1659
1660 REALLOCN(plyfile->elems, PlyElement *,
1661 plyfile->nelems, plyfile->nelems + other_elems->num_elems);
1662 for (i = 0; i < other_elems->num_elems; i++) {
1663 other = &(other_elems->other_list[i]);
1664 elem = (PlyElement *) myalloc (sizeof (PlyElement));
1665 plyfile->elems[plyfile->nelems++] = elem;
1666 elem->name = strdup (other->elem_name);
1667 elem->num = other->elem_count;
1668 elem->nprops = 0;
1669 ply_describe_other_properties (plyfile, other->other_props,
1670 offsetof(OtherData,other_props));
1671 }
1672 }
1673
1674
1675 /******************************************************************************
1676 Write out the "other" elements specified for this PLY file.
1677
1678 Entry:
1679 plyfile - pointer to PLY file to write out other elements for
1680 ******************************************************************************/
1681
ply_put_other_elements(PlyFile * plyfile,int * native_binary_type)1682 inline void ply_put_other_elements (PlyFile *plyfile, int *native_binary_type)
1683 {
1684 int i,j;
1685 OtherElem *other;
1686
1687 /* make sure we have other elements to write */
1688 if (plyfile->other_elems == NULL)
1689 return;
1690
1691 /* write out the data for each "other" element */
1692
1693 for (i = 0; i < plyfile->other_elems->num_elems; i++) {
1694
1695 other = &(plyfile->other_elems->other_list[i]);
1696 ply_put_element_setup (plyfile, other->elem_name);
1697
1698 /* write out each instance of the current element */
1699 for (j = 0; j < other->elem_count; j++)
1700 ply_put_element (plyfile, (void *) other->other_data[j], native_binary_type);
1701 }
1702 }
1703
1704
1705 /******************************************************************************
1706 Free up storage used by an "other" elements data structure.
1707
1708 Entry:
1709 other_elems - data structure to free up
1710 ******************************************************************************/
1711
ply_free_other_elements(PlyOtherElems * other_elems)1712 inline void ply_free_other_elements (PlyOtherElems *other_elems)
1713 {
1714 // Alec:
1715 //other_elems = other_elems;
1716 delete(other_elems);
1717 }
1718
1719
1720
1721 /*******************/
1722 /* Miscellaneous */
1723 /*******************/
1724
1725
1726
1727 /******************************************************************************
1728 Close a PLY file.
1729
1730 Entry:
1731 plyfile - identifier of file to close
1732 ******************************************************************************/
1733
ply_close(PlyFile * plyfile)1734 inline void ply_close(PlyFile *plyfile)
1735 {
1736 fclose (plyfile->fp);
1737 // Alec:
1738 plyfile->fp = NULL;
1739
1740 /* free up memory associated with the PLY file */
1741 free (plyfile);
1742 }
1743
1744
1745 /******************************************************************************
1746 Get version number and file type of a PlyFile.
1747
1748 Entry:
1749 ply - pointer to PLY file
1750
1751 Exit:
1752 version - version of the file
1753 file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
1754 ******************************************************************************/
1755
ply_get_info(PlyFile * ply,float * version,int * file_type)1756 inline void ply_get_info(PlyFile *ply, float *version, int *file_type)
1757 {
1758 if (ply == NULL)
1759 return;
1760
1761 *version = ply->version;
1762 *file_type = ply->file_type;
1763 }
1764
1765
1766 /******************************************************************************
1767 Compare two strings. Returns 1 if they are the same, 0 if not.
1768 ******************************************************************************/
1769
equal_strings(const char * s1,const char * s2)1770 inline int equal_strings(const char *s1, const char *s2)
1771 {
1772
1773 while (*s1 && *s2)
1774 if (*s1++ != *s2++)
1775 return (0);
1776
1777 if (*s1 != *s2)
1778 return (0);
1779 else
1780 return (1);
1781 }
1782
1783
1784 /******************************************************************************
1785 Find an element from the element list of a given PLY object.
1786
1787 Entry:
1788 plyfile - file id for PLY file
1789 element - name of element we're looking for
1790
1791 Exit:
1792 returns the element, or NULL if not found
1793 ******************************************************************************/
1794
find_element(PlyFile * plyfile,const char * element)1795 inline PlyElement *find_element(PlyFile *plyfile, const char *element)
1796 {
1797 int i;
1798
1799 for (i = 0; i < plyfile->nelems; i++)
1800 if (equal_strings (element, plyfile->elems[i]->name))
1801 return (plyfile->elems[i]);
1802
1803 return (NULL);
1804 }
1805
1806
1807 /******************************************************************************
1808 Find a property in the list of properties of a given element.
1809
1810 Entry:
1811 elem - pointer to element in which we want to find the property
1812 prop_name - name of property to find
1813
1814 Exit:
1815 index - index to position in list
1816 returns a pointer to the property, or NULL if not found
1817 ******************************************************************************/
1818
find_property(PlyElement * elem,const char * prop_name,int * index)1819 inline PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
1820 {
1821 int i;
1822
1823 for (i = 0; i < elem->nprops; i++)
1824 if (equal_strings (prop_name, elem->props[i]->name)) {
1825 *index = i;
1826 return (elem->props[i]);
1827 }
1828
1829 *index = -1;
1830 return (NULL);
1831 }
1832
1833
1834 /******************************************************************************
1835 Read an element from an ascii file.
1836
1837 Entry:
1838 plyfile - file identifier
1839 elem_ptr - pointer to element
1840 ******************************************************************************/
1841
ascii_get_element(PlyFile * plyfile,char * elem_ptr)1842 inline void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
1843 {
1844 int ply_type_size[] = {
1845 0, 1, 2, 4, 1, 2, 4, 4, 8
1846 };
1847
1848 int j,k;
1849 PlyElement *elem;
1850 PlyProperty *prop;
1851 char **words;
1852 int nwords;
1853 int which_word;
1854 char *elem_data,*item=NULL;
1855 char *item_ptr;
1856 int item_size;
1857 int int_val;
1858 unsigned int uint_val;
1859 double double_val;
1860 int list_count;
1861 int store_it;
1862 char **store_array;
1863 char *orig_line;
1864 char *other_data=NULL;
1865 int other_flag;
1866
1867 /* the kind of element we're reading currently */
1868 elem = plyfile->which_elem;
1869
1870 /* do we need to setup for other_props? */
1871
1872 if (elem->other_offset != NO_OTHER_PROPS) {
1873 char **ptr;
1874 other_flag = 1;
1875 /* make room for other_props */
1876 other_data = (char *) myalloc (elem->other_size);
1877 /* store pointer in user's structure to the other_props */
1878 ptr = (char **) (elem_ptr + elem->other_offset);
1879 *ptr = other_data;
1880 }
1881 else
1882 other_flag = 0;
1883
1884 /* read in the element */
1885
1886 words = get_words (plyfile->fp, &nwords, &orig_line);
1887 if (words == NULL) {
1888 fprintf (stderr, "ply_get_element: unexpected end of file\n");
1889 exit (-1);
1890 }
1891
1892 which_word = 0;
1893
1894 for (j = 0; j < elem->nprops; j++) {
1895
1896 prop = elem->props[j];
1897 store_it = (elem->store_prop[j] | other_flag);
1898
1899 /* store either in the user's structure or in other_props */
1900 // if (elem->store_prop[j])
1901 elem_data = elem_ptr;
1902 //else
1903 //elem_data = other_data;
1904
1905 if (prop->is_list) { /* a list */
1906
1907 /* get and store the number of items in the list */
1908 get_ascii_item (words[which_word++], prop->count_external,
1909 &int_val, &uint_val, &double_val);
1910 if (store_it) {
1911 item = elem_data + prop->count_offset;
1912 store_item(item, prop->count_internal, int_val, uint_val, double_val);
1913 }
1914
1915 /* allocate space for an array of items and store a ptr to the array */
1916 list_count = int_val;
1917 item_size = ply_type_size[prop->internal_type];
1918 store_array = (char **) (elem_data + prop->offset);
1919
1920 if (list_count == 0) {
1921 if (store_it)
1922 *store_array = NULL;
1923 }
1924 else {
1925 if (store_it) {
1926 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
1927
1928 item = item_ptr;
1929 *store_array = item_ptr;
1930 }
1931
1932 /* read items and store them into the array */
1933 for (k = 0; k < list_count; k++) {
1934 get_ascii_item (words[which_word++], prop->external_type,
1935 &int_val, &uint_val, &double_val);
1936 if (store_it) {
1937 store_item (item, prop->internal_type,
1938 int_val, uint_val, double_val);
1939 item += item_size;
1940 }
1941 }
1942 }
1943
1944 }
1945 else { /* not a list */
1946 get_ascii_item (words[which_word++], prop->external_type,
1947 &int_val, &uint_val, &double_val);
1948 if (store_it) {
1949 item = elem_data + prop->offset;
1950 store_item (item, prop->internal_type, int_val, uint_val, double_val);
1951 }
1952 }
1953
1954 }
1955
1956 free (words);
1957 }
1958
1959
1960 /******************************************************************************
1961 Read an element from a binary file.
1962
1963 Entry:
1964 plyfile - file identifier
1965 elem_ptr - pointer to an element
1966 ******************************************************************************/
1967
binary_get_element(PlyFile * plyfile,char * elem_ptr,int * native_binary_type)1968 inline void binary_get_element(PlyFile *plyfile, char *elem_ptr, int *native_binary_type)
1969 {
1970 int j,k;
1971 PlyElement *elem;
1972 PlyProperty *prop;
1973 FILE *fp = plyfile->fp;
1974 char *elem_data,*item=NULL;
1975 char *item_ptr;
1976 int item_size;
1977 int int_val;
1978 unsigned int uint_val;
1979 double double_val;
1980 int list_count;
1981 int store_it;
1982 char **store_array;
1983 char *other_data=NULL;
1984 int other_flag;
1985
1986 int ply_type_size[] = {
1987 0, 1, 2, 4, 1, 2, 4, 4, 8
1988 };
1989
1990
1991 /* the kind of element we're reading currently */
1992 elem = plyfile->which_elem;
1993
1994 /* do we need to setup for other_props? */
1995
1996 if (elem->other_offset != NO_OTHER_PROPS) {
1997 char **ptr;
1998 other_flag = 1;
1999 /* make room for other_props */
2000 other_data = (char *) myalloc (elem->other_size);
2001 /* store pointer in user's structure to the other_props */
2002 ptr = (char **) (elem_ptr + elem->other_offset);
2003 *ptr = other_data;
2004 }
2005 else
2006 other_flag = 0;
2007
2008 /* read in a number of elements */
2009
2010 for (j = 0; j < elem->nprops; j++) {
2011
2012 prop = elem->props[j];
2013 store_it = (elem->store_prop[j] | other_flag);
2014
2015 /* store either in the user's structure or in other_props */
2016 // if (elem->store_prop[j])
2017 elem_data = elem_ptr;
2018 // else
2019 // elem_data = other_data;
2020
2021 if (prop->is_list) { /* a list */
2022
2023 /* get and store the number of items in the list */
2024 get_binary_item (fp, plyfile->file_type, prop->count_external,
2025 &int_val, &uint_val, &double_val, native_binary_type);
2026 if (store_it) {
2027 item = elem_data + prop->count_offset;
2028 store_item(item, prop->count_internal, int_val, uint_val, double_val);
2029 }
2030
2031 /* allocate space for an array of items and store a ptr to the array */
2032 list_count = int_val;
2033
2034 item_size = ply_type_size[prop->internal_type];
2035 store_array = (char **) (elem_data + prop->offset);
2036 if (list_count == 0) {
2037 if (store_it)
2038 *store_array = NULL;
2039 }
2040 else {
2041 if (store_it) {
2042 item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
2043
2044 item = item_ptr;
2045 *store_array = item_ptr;
2046 }
2047
2048 // read items and store them into the array
2049 for (k = 0; k < list_count; k++) {
2050 get_binary_item (fp, plyfile->file_type, prop->external_type,
2051 &int_val, &uint_val, &double_val, native_binary_type);
2052 if (store_it) {
2053 store_item (item, prop->internal_type,
2054 int_val, uint_val, double_val);
2055 item += item_size;
2056 }
2057 }
2058
2059
2060
2061 }
2062
2063 }
2064 else { /* not a list */
2065 get_binary_item (fp, plyfile->file_type, prop->external_type,
2066 &int_val, &uint_val, &double_val, native_binary_type);
2067 if (store_it) {
2068 item = elem_data + prop->offset;
2069 store_item (item, prop->internal_type, int_val, uint_val, double_val);
2070 }
2071 }
2072
2073 }
2074 }
2075
2076
2077 /******************************************************************************
2078 Write to a file the word that represents a PLY data type.
2079
2080 Entry:
2081 fp - file pointer
2082 code - code for type
2083 ******************************************************************************/
2084
write_scalar_type(FILE * fp,int code)2085 inline void write_scalar_type (FILE *fp, int code)
2086 {
2087 /* make sure this is a valid code */
2088
2089 if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
2090 fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
2091 exit (-1);
2092 }
2093
2094 /* write the code to a file */
2095 const char *type_names[] = {
2096 "invalid",
2097 "char", "short", "int",
2098 "uchar", "ushort", "uint",
2099 "float", "double",
2100 };
2101
2102
2103 fprintf (fp, "%s", type_names[code]);
2104 }
2105
2106 /******************************************************************************
2107 Reverse the order in an array of bytes. This is the conversion from big
2108 endian to little endian and vice versa
2109
2110 Entry:
2111 bytes - array of bytes to reverse (in place)
2112 num_bytes - number of bytes in array
2113 ******************************************************************************/
2114
swap_bytes(char * bytes,int num_bytes)2115 inline void swap_bytes(char *bytes, int num_bytes)
2116 {
2117 int i;
2118 char temp;
2119
2120 for (i=0; i < num_bytes/2; i++)
2121 {
2122 temp = bytes[i];
2123 bytes[i] = bytes[(num_bytes-1)-i];
2124 bytes[(num_bytes-1)-i] = temp;
2125 }
2126 }
2127
2128 /******************************************************************************
2129 Find out if this machine is big endian or little endian
2130
2131 Exit:
2132 set global variable, native_binary_type =
2133 either PLY_BINARY_BE or PLY_BINARY_LE
2134
2135 ******************************************************************************/
2136
get_native_binary_type(int * native_binary_type)2137 inline void get_native_binary_type(int *native_binary_type)
2138 {
2139 typedef union
2140 {
2141 int int_value;
2142 char byte_values[sizeof(int)];
2143 } endian_test_type;
2144
2145
2146 endian_test_type test;
2147
2148 test.int_value = 0;
2149 test.int_value = 1;
2150 if (test.byte_values[0] == 1)
2151 *native_binary_type = PLY_BINARY_LE;
2152 else if (test.byte_values[sizeof(int)-1] == 1)
2153 *native_binary_type = PLY_BINARY_BE;
2154 else
2155 {
2156 fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
2157 fprintf(stderr, "ply: Exiting...\n");
2158 exit(1);
2159 }
2160 }
2161
get_native_binary_type2()2162 inline int get_native_binary_type2()
2163 {
2164 typedef union
2165 {
2166 int int_value;
2167 char byte_values[sizeof(int)];
2168 } endian_test_type;
2169
2170
2171 endian_test_type test;
2172
2173 test.int_value = 0;
2174 test.int_value = 1;
2175 if (test.byte_values[0] == 1)
2176 return PLY_BINARY_LE;
2177 else if (test.byte_values[sizeof(int)-1] == 1)
2178 return PLY_BINARY_BE;
2179 else
2180 {
2181 fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
2182 fprintf(stderr, "ply: Exiting...\n");
2183 exit(1);
2184 }
2185 }
2186
2187 /******************************************************************************
2188 Verify that all the native types are the sizes we need
2189
2190
2191 ******************************************************************************/
2192
check_types()2193 inline int check_types()
2194 {
2195 int ply_type_size[] = {
2196 0, 1, 2, 4, 1, 2, 4, 4, 8
2197 };
2198
2199 if ((ply_type_size[PLY_CHAR] != sizeof(char)) ||
2200 (ply_type_size[PLY_SHORT] != sizeof(short)) ||
2201 (ply_type_size[PLY_INT] != sizeof(int)) ||
2202 (ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) ||
2203 (ply_type_size[PLY_USHORT] != sizeof(unsigned short)) ||
2204 (ply_type_size[PLY_UINT] != sizeof(unsigned int)) ||
2205 (ply_type_size[PLY_FLOAT] != sizeof(float)) ||
2206 (ply_type_size[PLY_DOUBLE] != sizeof(double)))
2207 {
2208 fprintf(stderr, "ply: Type sizes do not match built-in types\n");
2209 fprintf(stderr, "ply: Exiting...\n");
2210 exit(1);
2211 }
2212
2213 return 1;
2214 }
2215
2216 /******************************************************************************
2217 Get a text line from a file and break it up into words.
2218
2219 IMPORTANT: The calling routine call "free" on the returned pointer once
2220 finished with it.
2221
2222 Entry:
2223 fp - file to read from
2224
2225 Exit:
2226 nwords - number of words returned
2227 orig_line - the original line of characters
2228 returns a list of words from the line, or NULL if end-of-file
2229 ******************************************************************************/
2230
get_words(FILE * fp,int * nwords,char ** orig_line)2231 inline char **get_words(FILE *fp, int *nwords, char **orig_line)
2232 {
2233 #define BIG_STRING 4096
2234 char str[BIG_STRING];
2235 char str_copy[BIG_STRING];
2236 char **words;
2237 int max_words = 10;
2238 int num_words = 0;
2239 char *ptr,*ptr2;
2240 char *result;
2241
2242 fpos_t pos; //keep track of file pointer
2243 int nbytes;
2244 int nonUNIX;
2245 nonUNIX=0;
2246 nbytes=0;
2247 fgetpos(fp, &pos);
2248
2249 words = (char **) myalloc (sizeof (char *) * max_words);
2250
2251 /* read in a line */
2252 result = fgets (str, BIG_STRING, fp);
2253 if (result == NULL) {
2254 *nwords = 0;
2255 *orig_line = NULL;
2256 return (NULL);
2257 }
2258
2259 /* convert line-feed and tabs into spaces */
2260 /* (this guarantees that there will be a space before the */
2261 /* null character at the end of the string) */
2262
2263 str[BIG_STRING-2] = ' ';
2264 str[BIG_STRING-1] = '\0';
2265
2266 for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
2267 *ptr2 = *ptr;
2268 nbytes++;
2269 if (*ptr == '\t') {
2270 *ptr = ' ';
2271 *ptr2 = ' ';
2272 }
2273 else if (*ptr == '\n') {
2274 *ptr = ' '; //has to have a space, to be caught later when grouping words
2275 *ptr2 = '\0';
2276 break;
2277 }
2278 else if (*ptr == '\r')
2279 { //MAC line break
2280 nonUNIX=1;
2281 if(*(ptr+1)=='\n') //actuall PC line break
2282 {
2283 nbytes++;
2284 }
2285
2286 *ptr = ' ';
2287
2288 *(ptr+1) = '\0'; //when reading mac, best end string here
2289 *ptr2 = '\0'; //note a pc \r is followed by \n
2290
2291 break;
2292 }
2293 }
2294
2295
2296 /*check to see if a PC or MAC header was detected instead of UNIX*/
2297 if(nonUNIX==1)
2298 {
2299 fsetpos(fp, &pos);
2300 fseek(fp, nbytes, SEEK_CUR);
2301 }
2302
2303 /* find the words in the line */
2304
2305 ptr = str;
2306 while (*ptr != '\0') {
2307
2308 /* jump over leading spaces */
2309 while (*ptr == ' ')
2310 ptr++;
2311
2312 /* break if we reach the end */
2313 if (*ptr == '\0')
2314 break;
2315
2316 /* save pointer to beginning of word */
2317 if (num_words >= max_words) {
2318 max_words += 10;
2319 words = (char **) realloc (words, sizeof (char *) * max_words);
2320 }
2321 words[num_words++] = ptr;
2322
2323 /* jump over non-spaces */
2324 while (*ptr != ' ')
2325 ptr++;
2326
2327 /* place a null character here to mark the end of the word */
2328 *ptr++ = '\0';
2329 }
2330
2331 /* return the list of words */
2332 *nwords = num_words;
2333 *orig_line = str_copy;
2334 return (words);
2335 }
2336
2337 /*
2338 char **get_words(FILE *fp, int *nwords, char **orig_line)
2339 {
2340 #define BIG_STRING 4096
2341 static char str[BIG_STRING];
2342 static char str_copy[BIG_STRING];
2343 char **words;
2344 int max_words = 10;
2345 int num_words = 0;
2346 char *ptr,*ptr2;
2347 char *result;
2348
2349 words = (char **) myalloc (sizeof (char *) * max_words);
2350
2351 // read in a line
2352 result = fgets (str, BIG_STRING, fp);
2353 if (result == NULL) {
2354 *nwords = 0;
2355 *orig_line = NULL;
2356 return (NULL);
2357 }
2358
2359 // convert line-feed and tabs into spaces
2360 // (this guarantees that there will be a space before the
2361 // null character at the end of the string)
2362
2363 str[BIG_STRING-2] = ' ';
2364 str[BIG_STRING-1] = '\0';
2365
2366 for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
2367 *ptr2 = *ptr;
2368 if (*ptr == '\t') {
2369 *ptr = ' ';
2370 *ptr2 = ' ';
2371 }
2372 else if (*ptr == '\n') {
2373 *ptr = ' ';
2374 *ptr2 = '\0';
2375 break;
2376 }
2377 else if (*ptr == '\r') {
2378 *ptr = '\0';
2379 *ptr2 = '\0'; //note don't break yet, on a pc \r is followed by \n
2380 }
2381 }
2382
2383 // find the words in the line
2384
2385 ptr = str;
2386 while (*ptr != '\0') {
2387
2388 // jump over leading spaces
2389 while (*ptr == ' ')
2390 ptr++;
2391
2392 // break if we reach the end
2393 if (*ptr == '\0')
2394 break;
2395
2396 // save pointer to beginning of word
2397 if (num_words >= max_words) {
2398 max_words += 10;
2399 words = (char **) realloc (words, sizeof (char *) * max_words);
2400 }
2401 words[num_words++] = ptr;
2402
2403 // jump over non-spaces
2404 while (*ptr != ' ')
2405 ptr++;
2406
2407 // place a null character here to mark the end of the word
2408 *ptr++ = '\0';
2409 }
2410
2411 // return the list of words
2412 *nwords = num_words;
2413 *orig_line = str_copy;
2414 return (words);
2415 }*/
2416
2417 /******************************************************************************
2418 Return the value of an item, given a pointer to it and its type.
2419
2420 Entry:
2421 item - pointer to item
2422 type - data type that "item" points to
2423
2424 Exit:
2425 returns a double-precision float that contains the value of the item
2426 ******************************************************************************/
2427
get_item_value(char * item,int type)2428 inline double get_item_value(char *item, int type)
2429 {
2430 unsigned char *puchar;
2431 char *pchar;
2432 short int *pshort;
2433 unsigned short int *pushort;
2434 int *pint;
2435 unsigned int *puint;
2436 float *pfloat;
2437 double *pdouble;
2438 int int_value;
2439 unsigned int uint_value;
2440 double double_value;
2441
2442 switch (type) {
2443 case PLY_CHAR:
2444 pchar = (char *) item;
2445 int_value = *pchar;
2446 return ((double) int_value);
2447 case PLY_UCHAR:
2448 puchar = (unsigned char *) item;
2449 int_value = *puchar;
2450 return ((double) int_value);
2451 case PLY_SHORT:
2452 pshort = (short int *) item;
2453 int_value = *pshort;
2454 return ((double) int_value);
2455 case PLY_USHORT:
2456 pushort = (unsigned short int *) item;
2457 int_value = *pushort;
2458 return ((double) int_value);
2459 case PLY_INT:
2460 pint = (int *) item;
2461 int_value = *pint;
2462 return ((double) int_value);
2463 case PLY_UINT:
2464 puint = (unsigned int *) item;
2465 uint_value = *puint;
2466 return ((double) uint_value);
2467 case PLY_FLOAT:
2468 pfloat = (float *) item;
2469 double_value = *pfloat;
2470 return (double_value);
2471 case PLY_DOUBLE:
2472 pdouble = (double *) item;
2473 double_value = *pdouble;
2474 return (double_value);
2475 default:
2476 fprintf (stderr, "get_item_value: bad type = %d\n", type);
2477 exit (-1);
2478 }
2479 }
2480
2481
2482 /******************************************************************************
2483 Write out an item to a file as raw binary bytes.
2484
2485 Entry:
2486 fp - file to write to
2487 int_val - integer version of item
2488 uint_val - unsigned integer version of item
2489 double_val - double-precision float version of item
2490 type - data type to write out
2491 ******************************************************************************/
2492
write_binary_item(FILE * fp,int file_type,int int_val,unsigned int uint_val,double double_val,int type,int * native_binary_type)2493 inline void write_binary_item(
2494 FILE *fp,
2495 int file_type,
2496 int int_val,
2497 unsigned int uint_val,
2498 double double_val,
2499 int type,
2500 int *native_binary_type
2501 )
2502 {
2503 unsigned char uchar_val;
2504 char char_val;
2505 unsigned short ushort_val;
2506 short short_val;
2507 float float_val;
2508 void *value;
2509
2510 switch (type) {
2511 case PLY_CHAR:
2512 char_val = int_val;
2513 value = &char_val;
2514 break;
2515 case PLY_SHORT:
2516 short_val = int_val;
2517 value = &short_val;
2518 break;
2519 case PLY_INT:
2520 value = &int_val;
2521 break;
2522 case PLY_UCHAR:
2523 uchar_val = uint_val;
2524 value = &uchar_val;
2525 break;
2526 case PLY_USHORT:
2527 ushort_val = uint_val;
2528 value = &ushort_val;
2529 break;
2530 case PLY_UINT:
2531 value = &uint_val;
2532 break;
2533 case PLY_FLOAT:
2534 float_val = double_val;
2535 value = &float_val;
2536 break;
2537 case PLY_DOUBLE:
2538 value = &double_val;
2539 break;
2540 default:
2541 fprintf (stderr, "write_binary_item: bad type = %d\n", type);
2542 exit (-1);
2543 }
2544 int ply_type_size[] = {
2545 0, 1, 2, 4, 1, 2, 4, 4, 8
2546 };
2547
2548 if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
2549 swap_bytes((char *)value, ply_type_size[type]);
2550
2551 if (fwrite (value, ply_type_size[type], 1, fp) != 1)
2552 {
2553 fprintf(stderr, "PLY ERROR: fwrite() failed -- aborting.\n");
2554 exit(1);
2555 }
2556 }
2557
2558
2559 /******************************************************************************
2560 Write out an item to a file as ascii characters.
2561
2562 Entry:
2563 fp - file to write to
2564 int_val - integer version of item
2565 uint_val - unsigned integer version of item
2566 double_val - double-precision float version of item
2567 type - data type to write out
2568 ******************************************************************************/
2569
write_ascii_item(FILE * fp,int int_val,unsigned int uint_val,double double_val,int type)2570 inline void write_ascii_item(
2571 FILE *fp,
2572 int int_val,
2573 unsigned int uint_val,
2574 double double_val,
2575 int type
2576 )
2577 {
2578 switch (type) {
2579 case PLY_CHAR:
2580 case PLY_SHORT:
2581 case PLY_INT:
2582 if (fprintf (fp, "%d ", int_val) <= 0)
2583 {
2584 fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2585 exit(1);
2586 }
2587 break;
2588 case PLY_UCHAR:
2589 case PLY_USHORT:
2590 case PLY_UINT:
2591 if (fprintf (fp, "%u ", uint_val) <= 0)
2592 {
2593 fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2594 exit(1);
2595 }
2596 break;
2597 case PLY_FLOAT:
2598 case PLY_DOUBLE:
2599 if (fprintf (fp, "%g ", double_val) <= 0)
2600 {
2601 fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
2602 exit(1);
2603 }
2604 break;
2605 default:
2606 fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
2607 exit (-1);
2608 }
2609 }
2610
2611
2612 /******************************************************************************
2613 Write out an item to a file as ascii characters.
2614
2615 Entry:
2616 fp - file to write to
2617 item - pointer to item to write
2618 type - data type that "item" points to
2619
2620 Exit:
2621 returns a double-precision float that contains the value of the written item
2622 ******************************************************************************/
2623
old_write_ascii_item(FILE * fp,char * item,int type)2624 inline double old_write_ascii_item(FILE *fp, char *item, int type)
2625 {
2626 unsigned char *puchar;
2627 char *pchar;
2628 short int *pshort;
2629 unsigned short int *pushort;
2630 int *pint;
2631 unsigned int *puint;
2632 float *pfloat;
2633 double *pdouble;
2634 int int_value;
2635 unsigned int uint_value;
2636 double double_value;
2637
2638 switch (type) {
2639 case PLY_CHAR:
2640 pchar = (char *) item;
2641 int_value = *pchar;
2642 fprintf (fp, "%d ", int_value);
2643 return ((double) int_value);
2644 case PLY_UCHAR:
2645 puchar = (unsigned char *) item;
2646 int_value = *puchar;
2647 fprintf (fp, "%d ", int_value);
2648 return ((double) int_value);
2649 case PLY_SHORT:
2650 pshort = (short int *) item;
2651 int_value = *pshort;
2652 fprintf (fp, "%d ", int_value);
2653 return ((double) int_value);
2654 case PLY_USHORT:
2655 pushort = (unsigned short int *) item;
2656 int_value = *pushort;
2657 fprintf (fp, "%d ", int_value);
2658 return ((double) int_value);
2659 case PLY_INT:
2660 pint = (int *) item;
2661 int_value = *pint;
2662 fprintf (fp, "%d ", int_value);
2663 return ((double) int_value);
2664 case PLY_UINT:
2665 puint = (unsigned int *) item;
2666 uint_value = *puint;
2667 fprintf (fp, "%u ", uint_value);
2668 return ((double) uint_value);
2669 case PLY_FLOAT:
2670 pfloat = (float *) item;
2671 double_value = *pfloat;
2672 fprintf (fp, "%g ", double_value);
2673 return (double_value);
2674 case PLY_DOUBLE:
2675 pdouble = (double *) item;
2676 double_value = *pdouble;
2677 fprintf (fp, "%g ", double_value);
2678 return (double_value);
2679 default:
2680 fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
2681 exit (-1);
2682 }
2683 }
2684
2685
2686 /******************************************************************************
2687 Get the value of an item that is in memory, and place the result
2688 into an integer, an unsigned integer and a double.
2689
2690 Entry:
2691 ptr - pointer to the item
2692 type - data type supposedly in the item
2693
2694 Exit:
2695 int_val - integer value
2696 uint_val - unsigned integer value
2697 double_val - double-precision floating point value
2698 ******************************************************************************/
2699
get_stored_item(void * ptr,int type,int * int_val,unsigned int * uint_val,double * double_val)2700 inline void get_stored_item(
2701 void *ptr,
2702 int type,
2703 int *int_val,
2704 unsigned int *uint_val,
2705 double *double_val
2706 )
2707 {
2708 switch (type) {
2709 case PLY_CHAR:
2710 *int_val = *((char *) ptr);
2711 *uint_val = *int_val;
2712 *double_val = *int_val;
2713 break;
2714 case PLY_UCHAR:
2715 *uint_val = *((unsigned char *) ptr);
2716 *int_val = *uint_val;
2717 *double_val = *uint_val;
2718 break;
2719 case PLY_SHORT:
2720 *int_val = *((short int *) ptr);
2721 *uint_val = *int_val;
2722 *double_val = *int_val;
2723 break;
2724 case PLY_USHORT:
2725 *uint_val = *((unsigned short int *) ptr);
2726 *int_val = *uint_val;
2727 *double_val = *uint_val;
2728 break;
2729 case PLY_INT:
2730 *int_val = *((int *) ptr);
2731 *uint_val = *int_val;
2732 *double_val = *int_val;
2733 break;
2734 case PLY_UINT:
2735 *uint_val = *((unsigned int *) ptr);
2736 *int_val = *uint_val;
2737 *double_val = *uint_val;
2738 break;
2739 case PLY_FLOAT:
2740 *double_val = *((float *) ptr);
2741 *int_val = (int) *double_val;
2742 *uint_val = (unsigned int) *double_val;
2743 break;
2744 case PLY_DOUBLE:
2745 *double_val = *((double *) ptr);
2746 *int_val = (int) *double_val;
2747 *uint_val = (unsigned int) *double_val;
2748 break;
2749 default:
2750 fprintf (stderr, "get_stored_item: bad type = %d\n", type);
2751 exit (-1);
2752 }
2753 }
2754
2755
2756 /******************************************************************************
2757 Get the value of an item from a binary file, and place the result
2758 into an integer, an unsigned integer and a double.
2759
2760 Entry:
2761 fp - file to get item from
2762 type - data type supposedly in the word
2763
2764 Exit:
2765 int_val - integer value
2766 uint_val - unsigned integer value
2767 double_val - double-precision floating point value
2768 ******************************************************************************/
2769
get_binary_item(FILE * fp,int file_type,int type,int * int_val,unsigned int * uint_val,double * double_val,int * native_binary_type)2770 inline void get_binary_item(
2771 FILE *fp,
2772 int file_type,
2773 int type,
2774 int *int_val,
2775 unsigned int *uint_val,
2776 double *double_val,
2777 int *native_binary_type
2778 )
2779 {
2780 char c[8];
2781 void *ptr;
2782
2783 ptr = (void *) c;
2784 int ply_type_size[] = {
2785 0, 1, 2, 4, 1, 2, 4, 4, 8
2786 };
2787
2788 if (fread (ptr, ply_type_size[type], 1, fp) != 1)
2789 {
2790 fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n");
2791 exit(1);
2792 }
2793
2794
2795 if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
2796 swap_bytes((char *)ptr, ply_type_size[type]);
2797
2798 switch (type) {
2799 case PLY_CHAR:
2800 *int_val = *((char *) ptr);
2801 *uint_val = *int_val;
2802 *double_val = *int_val;
2803 break;
2804 case PLY_UCHAR:
2805 *uint_val = *((unsigned char *) ptr);
2806 *int_val = *uint_val;
2807 *double_val = *uint_val;
2808 break;
2809 case PLY_SHORT:
2810 *int_val = *((short int *) ptr);
2811 *uint_val = *int_val;
2812 *double_val = *int_val;
2813 break;
2814 case PLY_USHORT:
2815 *uint_val = *((unsigned short int *) ptr);
2816 *int_val = *uint_val;
2817 *double_val = *uint_val;
2818 break;
2819 case PLY_INT:
2820 *int_val = *((int *) ptr);
2821 *uint_val = *int_val;
2822 *double_val = *int_val;
2823 break;
2824 case PLY_UINT:
2825 *uint_val = *((unsigned int *) ptr);
2826 *int_val = *uint_val;
2827 *double_val = *uint_val;
2828 break;
2829 case PLY_FLOAT:
2830 *double_val = *((float *) ptr);
2831 *int_val = (int) *double_val;
2832 *uint_val = (unsigned int) *double_val;
2833 break;
2834 case PLY_DOUBLE:
2835 *double_val = *((double *) ptr);
2836 *int_val = (int) *double_val;
2837 *uint_val = (unsigned int) *double_val;
2838 break;
2839 default:
2840 fprintf (stderr, "get_binary_item: bad type = %d\n", type);
2841 exit (-1);
2842 }
2843 }
2844
2845
2846 /******************************************************************************
2847 Extract the value of an item from an ascii word, and place the result
2848 into an integer, an unsigned integer and a double.
2849
2850 Entry:
2851 word - word to extract value from
2852 type - data type supposedly in the word
2853
2854 Exit:
2855 int_val - integer value
2856 uint_val - unsigned integer value
2857 double_val - double-precision floating point value
2858 ******************************************************************************/
2859
get_ascii_item(char * word,int type,int * int_val,unsigned int * uint_val,double * double_val)2860 inline void get_ascii_item(
2861 char *word,
2862 int type,
2863 int *int_val,
2864 unsigned int *uint_val,
2865 double *double_val
2866 )
2867 {
2868 switch (type) {
2869 case PLY_CHAR:
2870 case PLY_UCHAR:
2871 case PLY_SHORT:
2872 case PLY_USHORT:
2873 case PLY_INT:
2874 *int_val = atoi (word);
2875 *uint_val = (unsigned int) *int_val;
2876 *double_val = (double) *int_val;
2877 break;
2878
2879 case PLY_UINT:
2880 *uint_val = strtol (word, (char **) NULL, 10);
2881 *int_val = (int) *uint_val;
2882 *double_val = (double) *uint_val;
2883 break;
2884
2885 case PLY_FLOAT:
2886 case PLY_DOUBLE:
2887 *double_val = atof (word);
2888 *int_val = (int) *double_val;
2889 *uint_val = (unsigned int) *double_val;
2890 break;
2891
2892 default:
2893 fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
2894 exit (-1);
2895 }
2896 }
2897
2898
2899 /******************************************************************************
2900 Store a value into a place being pointed to, guided by a data type.
2901
2902 Entry:
2903 item - place to store value
2904 type - data type
2905 int_val - integer version of value
2906 uint_val - unsigned integer version of value
2907 double_val - double version of value
2908
2909 Exit:
2910 item - pointer to stored value
2911 ******************************************************************************/
2912
store_item(char * item,int type,int int_val,unsigned int uint_val,double double_val)2913 inline void store_item (
2914 char *item,
2915 int type,
2916 int int_val,
2917 unsigned int uint_val,
2918 double double_val
2919 )
2920 {
2921 unsigned char *puchar;
2922 short int *pshort;
2923 unsigned short int *pushort;
2924 int *pint;
2925 unsigned int *puint;
2926 float *pfloat;
2927 double *pdouble;
2928
2929 switch (type) {
2930 case PLY_CHAR:
2931 *item = int_val;
2932 break;
2933 case PLY_UCHAR:
2934 puchar = (unsigned char *) item;
2935 *puchar = uint_val;
2936 break;
2937 case PLY_SHORT:
2938 pshort = (short *) item;
2939 *pshort = int_val;
2940 break;
2941 case PLY_USHORT:
2942 pushort = (unsigned short *) item;
2943 *pushort = uint_val;
2944 break;
2945 case PLY_INT:
2946 pint = (int *) item;
2947 *pint = int_val;
2948 break;
2949 case PLY_UINT:
2950 puint = (unsigned int *) item;
2951 *puint = uint_val;
2952 break;
2953 case PLY_FLOAT:
2954 pfloat = (float *) item;
2955 *pfloat = double_val;
2956 break;
2957 case PLY_DOUBLE:
2958 pdouble = (double *) item;
2959 *pdouble = double_val;
2960 break;
2961 default:
2962 fprintf (stderr, "store_item: bad type = %d\n", type);
2963 exit (-1);
2964 }
2965 }
2966
2967
2968 /******************************************************************************
2969 Add an element to a PLY file descriptor.
2970
2971 Entry:
2972 plyfile - PLY file descriptor
2973 words - list of words describing the element
2974 nwords - number of words in the list
2975 ******************************************************************************/
2976
add_element(PlyFile * plyfile,char ** words)2977 inline void add_element (PlyFile *plyfile, char **words)
2978 {
2979 PlyElement *elem;
2980
2981 /* create the new element */
2982 elem = (PlyElement *) myalloc (sizeof (PlyElement));
2983 elem->name = strdup (words[1]);
2984 elem->num = atoi (words[2]);
2985 elem->nprops = 0;
2986
2987 /* make room for new element in the object's list of elements */
2988 if (plyfile->nelems == 0)
2989 plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
2990 else
2991 plyfile->elems = (PlyElement **) realloc (plyfile->elems,
2992 sizeof (PlyElement *) * (plyfile->nelems + 1));
2993
2994 /* add the new element to the object's list */
2995 plyfile->elems[plyfile->nelems] = elem;
2996 plyfile->nelems++;
2997 }
2998
2999
3000 /******************************************************************************
3001 Return the type of a property, given the name of the property.
3002
3003 Entry:
3004 name - name of property type
3005
3006 Exit:
3007 returns integer code for property, or 0 if not found
3008 ******************************************************************************/
3009
get_prop_type(char * type_name)3010 inline int get_prop_type(char *type_name)
3011 {
3012 int i;
3013 const char *type_names[] = {
3014 "invalid",
3015 "char", "short", "int",
3016 "uchar", "ushort", "uint",
3017 "float", "double",
3018 };
3019
3020 const char *alt_type_names[] = {
3021 "invalid",
3022 "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
3023 };
3024
3025
3026 for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
3027 if (equal_strings (type_name, type_names[i]))
3028 return (i);
3029
3030 for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
3031 if (equal_strings (type_name, alt_type_names[i]))
3032 return (i);
3033
3034 /* if we get here, we didn't find the type */
3035 return (0);
3036 }
3037
3038
3039 /******************************************************************************
3040 Add a property to a PLY file descriptor.
3041
3042 Entry:
3043 plyfile - PLY file descriptor
3044 words - list of words describing the property
3045 nwords - number of words in the list
3046 ******************************************************************************/
3047
add_property(PlyFile * plyfile,char ** words)3048 inline void add_property (PlyFile *plyfile, char **words)
3049 {
3050 PlyProperty *prop;
3051 PlyElement *elem;
3052
3053 /* create the new property */
3054
3055 prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
3056
3057 if (equal_strings (words[1], "list")) { /* is a list */
3058 prop->count_external = get_prop_type (words[2]);
3059 prop->external_type = get_prop_type (words[3]);
3060 prop->name = strdup (words[4]);
3061 prop->is_list = 1;
3062 }
3063 else { /* not a list */
3064 prop->external_type = get_prop_type (words[1]);
3065 prop->name = strdup (words[2]);
3066 prop->is_list = 0;
3067 }
3068
3069 /* add this property to the list of properties of the current element */
3070
3071 elem = plyfile->elems[plyfile->nelems - 1];
3072
3073 if (elem->nprops == 0)
3074 elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
3075 else
3076 elem->props = (PlyProperty **) realloc (elem->props,
3077 sizeof (PlyProperty *) * (elem->nprops + 1));
3078
3079 elem->props[elem->nprops] = prop;
3080 elem->nprops++;
3081 }
3082
3083
3084 /******************************************************************************
3085 Add a comment to a PLY file descriptor.
3086
3087 Entry:
3088 plyfile - PLY file descriptor
3089 line - line containing comment
3090 ******************************************************************************/
3091
add_comment(PlyFile * plyfile,char * line)3092 inline void add_comment (PlyFile *plyfile, char *line)
3093 {
3094 int i;
3095
3096 /* skip over "comment" and leading spaces and tabs */
3097 i = 7;
3098 while (line[i] == ' ' || line[i] == '\t')
3099 i++;
3100
3101 ply_put_comment (plyfile, &line[i]);
3102 }
3103
3104
3105 /******************************************************************************
3106 Add a some object information to a PLY file descriptor.
3107
3108 Entry:
3109 plyfile - PLY file descriptor
3110 line - line containing text info
3111 ******************************************************************************/
3112
add_obj_info(PlyFile * plyfile,char * line)3113 inline void add_obj_info (PlyFile *plyfile, char *line)
3114 {
3115 int i;
3116
3117 /* skip over "obj_info" and leading spaces and tabs */
3118 i = 8;
3119 while (line[i] == ' ' || line[i] == '\t')
3120 i++;
3121
3122 ply_put_obj_info (plyfile, &line[i]);
3123 }
3124
3125
3126 /******************************************************************************
3127 Copy a property.
3128 ******************************************************************************/
3129
copy_property(PlyProperty * dest,PlyProperty * src)3130 inline void copy_property(PlyProperty *dest, PlyProperty *src)
3131 {
3132 dest->name = strdup (src->name);
3133 dest->external_type = src->external_type;
3134 dest->internal_type = src->internal_type;
3135 dest->offset = src->offset;
3136
3137 dest->is_list = src->is_list;
3138 dest->count_external = src->count_external;
3139 dest->count_internal = src->count_internal;
3140 dest->count_offset = src->count_offset;
3141 }
3142
3143
3144 /******************************************************************************
3145 Allocate some memory.
3146
3147 Entry:
3148 size - amount of memory requested (in bytes)
3149 lnum - line number from which memory was requested
3150 fname - file name from which memory was requested
3151 ******************************************************************************/
3152
my_alloc(int size,int lnum,const char * fe)3153 inline char *my_alloc(int size, int lnum, const char *fe)
3154 {
3155 char *ptr;
3156
3157 ptr = (char *) malloc (size);
3158
3159 if (ptr == 0) {
3160 fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fe);
3161 }
3162
3163 return (ptr);
3164 }
3165
3166 }
3167 }
3168 #endif
3169