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

Revision 10415, 74.1 kB (checked in by robert, 5 years ago)

From Mathias Froehlich, "We are currently getting issues with locale settings and some osg plugins.
Therefore I have changed all the occurances of atof by asciiToFloat or
asciiToDouble.

I believe that it is safe to do so at least for all the plugins.
Included here are also asciiToFloat conversion of environment variables. One
might argue that these should be locale dependent. But IMO these should be
set and interpreted by osg independent of the current locale.
"

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