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

Revision 10012, 71.8 kB (checked in by robert, 4 years ago)

From Santosh Gaikwad, ply plugin, based on Equalizer and other LGPL compatible sources.

"Attached is the osg-plugin for reading ply ( Stanford Triangle Format ) file. I have written the plugin according to OSG standard and have also added cmake build system. The plugin is working fine on both Linux and Windows and should behave similarly on other OS as well."

"I developed this plugin while working on a project based on Equalizer. So VertexData? which I am using is taken from equalizer and modified to make them work as separate OSG plugin.
Before contributing this plugin to OSG community, I asked project manager of Equalizer project Stefen regarding potential licensing issues and this is what he has said

"The kd-Tree (VertexBuffer?*) is LGPL-licensed, and the base ply loader (ply*) is BSD. As long as you leave the copyright notices intact, there is no issue."

so I think using these files in OSG should not be a problem.

As far as author of ReaderWriterPLY.cpp is concerned I am the author. I am working for Darshan3d which is a subsidiary of VizExperts? thats why I have put VizExperts? copyright."

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