Subversion Repositories gelsvn

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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