Subversion Repositories gelsvn

Rev

Rev 333 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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