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