root/OpenSceneGraph/trunk/src/osgPlugins/ply/plyfile.cpp @ 13041

Revision 13041, 74.2 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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