Subversion Repositories gelsvn

Rev

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