123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180 |
- #ifndef IGL_PLY_H
- #define IGL_PLY_H
- /*
- Header for PLY polygon files.
- - Greg Turk, March 1994
- A PLY file contains a single polygonal _object_.
- An object is composed of lists of _elements_. Typical elements are
- vertices, faces, edges and materials.
- Each type of element for a given object has one or more _properties_
- associated with the element type. For instance, a vertex element may
- have as properties three floating-point values x,y,z and three unsigned
- chars for red, green and blue.
- ---------------------------------------------------------------
- Copyright (c) 1994 The Board of Trustees of The Leland Stanford
- Junior University. All rights reserved.
-
- Permission to use, copy, modify and distribute this software and its
- documentation for any purpose is hereby granted without fee, provided
- that the above copyright notice and this permission notice appear in
- all copies of this software and that you do not sell the software.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
- EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- */
- /*
- --------------------------------------------------------------------------------
- Joao Fradinho Oliveira, July 2005
- Copyright (c) 2005 University College London
- copyright conditions as above
- update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
- --------------------------------------------------------------------------------
- ply_open_for_reading
- * was changed to always open files in binary mode, files written in ascii can also be
- read with this binary mode.
- * allows opening of filenames that are alias files in macintosh
- * code tested on pc and mac
- get_words
- * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
- accordingly for the next read.
- NOTES:
- The ply file, has always an ascii part for the header, and a binary or ascii
- part for the data.
- The header part in ascii, dictates that linebreaks are used, this make models
- operating system dependent, as a line break in unix is indicated with the escape character \n,
- on a macintosh, with \r, and on a pc with \r\n <--2 unsigned chars, 2 bytes, instead of 1 byte.
- get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
- properly to target OSs with binary files.
- */
- #ifndef __PLY_H__
- #define __PLY_H__
- #include <stdlib.h>
- #include <stdio.h>
- #include <stddef.h>
- #include <string.h>
- namespace igl {
- namespace ply {
-
- #define PLY_ASCII 1 /* ascii PLY file */
- #define PLY_BINARY_BE 2 /* binary PLY file, big endian */
- #define PLY_BINARY_LE 3 /* binary PLY file, little endian */
- #define PLY_BINARY_NATIVE 4 /* binary PLY file, same endianness as
- current architecture */
-
- #define PLY_OKAY 0 /* ply routine worked okay */
- #define PLY_ERROR -1 /* error in ply routine */
- /* scalar data types supported by PLY format */
- #define PLY_START_TYPE 0
- #define PLY_CHAR 1
- #define PLY_SHORT 2
- #define PLY_INT 3
- #define PLY_UCHAR 4
- #define PLY_USHORT 5
- #define PLY_UINT 6
- #define PLY_FLOAT 7
- #define PLY_DOUBLE 8
- #define PLY_END_TYPE 9
- #define PLY_SCALAR 0
- #define PLY_LIST 1
- typedef struct PlyProperty { /* description of a property */
- const char *name; /* property name */
- int external_type; /* file's data type */
- int internal_type; /* program's data type */
- int offset; /* offset bytes of prop in a struct */
- int is_list; /* 1 = list, 0 = scalar */
- int count_external; /* file's count type */
- int count_internal; /* program's count type */
- int count_offset; /* offset byte for list count */
- } PlyProperty;
- typedef struct PlyElement { /* description of an element */
- const char *name; /* element name */
- int num; /* number of elements in this object */
- int size; /* size of element (bytes) or -1 if variable */
- int nprops; /* number of properties for this element */
- PlyProperty **props; /* list of properties in the file */
- char *store_prop; /* flags: property wanted by user? */
- int other_offset; /* offset to un-asked-for props, or -1 if none*/
- int other_size; /* size of other_props structure */
- } PlyElement;
- typedef struct PlyOtherProp { /* describes other properties in an element */
- const char *name; /* element name */
- int size; /* size of other_props */
- int nprops; /* number of properties in other_props */
- PlyProperty **props; /* list of properties in other_props */
- } PlyOtherProp;
- typedef struct OtherData { /* for storing other_props for an other element */
- void *other_props;
- } OtherData;
- typedef struct OtherElem { /* data for one "other" element */
- char *elem_name; /* names of other elements */
- int elem_count; /* count of instances of each element */
- OtherData **other_data; /* actual property data for the elements */
- PlyOtherProp *other_props; /* description of the property data */
- } OtherElem;
- typedef struct PlyOtherElems { /* "other" elements, not interpreted by user */
- int num_elems; /* number of other elements */
- OtherElem *other_list; /* list of data for other elements */
- } PlyOtherElems;
- typedef struct PlyFile { /* description of PLY file */
- FILE *fp; /* file pointer */
- int file_type; /* ascii or binary */
- float version; /* version number of file */
- int nelems; /* number of elements of object */
- PlyElement **elems; /* list of elements */
- int num_comments; /* number of comments */
- char **comments; /* list of comments */
- int num_obj_info; /* number of items of object information */
- char **obj_info; /* list of object info items */
- PlyElement *which_elem; /* which element we're currently writing */
- PlyOtherElems *other_elems; /* "other" elements from a PLY file */
- } PlyFile;
- /* memory allocation */
- extern char *my_alloc();
- #define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__)
- #ifndef ALLOCN
- #define REALLOCN(PTR,TYPE,OLD_N,NEW_N) \
- { \
- if ((OLD_N) == 0) \
- { ALLOCN((PTR),TYPE,(NEW_N));} \
- else \
- { \
- (PTR) = (TYPE *)realloc((PTR),(NEW_N)*sizeof(TYPE)); \
- if (((PTR) == NULL) && ((NEW_N) != 0)) \
- { \
- fprintf(stderr, "Memory reallocation failed on line %d in %s\n", \
- __LINE__, __FILE__); \
- fprintf(stderr, " tried to reallocate %d->%d\n", \
- (OLD_N), (NEW_N)); \
- exit(-1); \
- } \
- if ((NEW_N)>(OLD_N)) \
- memset((char *)(PTR)+(OLD_N)*sizeof(TYPE), 0, \
- ((NEW_N)-(OLD_N))*sizeof(TYPE)); \
- } \
- }
- #define ALLOCN(PTR,TYPE,N) \
- { (PTR) = (TYPE *) calloc(((unsigned)(N)),sizeof(TYPE));\
- if ((PTR) == NULL) { \
- fprintf(stderr, "Memory allocation failed on line %d in %s\n", \
- __LINE__, __FILE__); \
- exit(-1); \
- } \
- }
- #define FREE(PTR) { free((PTR)); (PTR) = NULL; }
- #endif
-
- /*** delcaration of routines ***/
- inline int get_native_binary_type2();
- inline PlyFile *ply_write(FILE *, int,const char **, int);
- inline PlyFile *ply_open_for_writing(char *, int,const char **, int, float *);
- inline void ply_describe_element(PlyFile *, const char *, int, int, PlyProperty *);
- inline void ply_describe_property(PlyFile *, const char *, PlyProperty *);
- inline void ply_element_count(PlyFile *, const char *, int);
- inline void ply_header_complete(PlyFile *);
- inline void ply_put_element_setup(PlyFile *, const char *);
- inline void ply_put_element(PlyFile *, void *, int*);
- inline void ply_put_comment(PlyFile *, char *);
- inline void ply_put_obj_info(PlyFile *, char *);
- inline PlyFile *ply_read(FILE *, int *, char ***);
- inline PlyFile *ply_open_for_reading( const char *, int *, char ***, int *, float *);
- inline PlyProperty **ply_get_element_description(PlyFile *, const char *, int*, int*);
- inline void ply_get_element_setup( PlyFile *, const char *, int, PlyProperty *);
- inline void ply_get_property(PlyFile *, const char *, PlyProperty *);
- inline PlyOtherProp *ply_get_other_properties(PlyFile *, const char *, int);
- inline void ply_get_element(PlyFile *, void *, int *);
- inline char **ply_get_comments(PlyFile *, int *);
- inline char **ply_get_obj_info(PlyFile *, int *);
- inline void ply_close(PlyFile *);
- inline void ply_get_info(PlyFile *, float *, int *);
- inline PlyOtherElems *ply_get_other_element (PlyFile *, const char *, int);
- inline void ply_describe_other_elements ( PlyFile *, PlyOtherElems *);
- inline void ply_put_other_elements (PlyFile *);
- inline void ply_free_other_elements (PlyOtherElems *);
- inline void ply_describe_other_properties(PlyFile *, PlyOtherProp *, int);
- inline int equal_strings(const char *, const char *);
- }
- }
- #endif /* !__PLY_H__ */
- /*
- The interface routines for reading and writing PLY polygon files.
- Greg Turk, February 1994
- ---------------------------------------------------------------
- A PLY file contains a single polygonal _object_.
- An object is composed of lists of _elements_. Typical elements are
- vertices, faces, edges and materials.
- Each type of element for a given object has one or more _properties_
- associated with the element type. For instance, a vertex element may
- have as properties the floating-point values x,y,z and the three unsigned
- chars representing red, green and blue.
- ---------------------------------------------------------------
- Copyright (c) 1994 The Board of Trustees of The Leland Stanford
- Junior University. All rights reserved.
-
- Permission to use, copy, modify and distribute this software and its
- documentation for any purpose is hereby granted without fee, provided
- that the above copyright notice and this permission notice appear in
- all copies of this software and that you do not sell the software.
-
- THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
- EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- */
- /*
- --------------------------------------------------------------------------------
- Joao Fradinho Oliveira, July 2005
- University College London
- update for ply reading of multi OS ply files, in any OS (Unix, Macintosh, PC)
- --------------------------------------------------------------------------------
- ply_open_for_reading
- * was changed to always open files in binary mode, files written in ascii can also be
- read with this binary mode.
- * allows opening of filenames that are alias files in macintosh
- * code tested on pc and mac
- get_words
- * was changed to handle line breaks in UNIX, MACINTOSH, PC, it resets the file pointer
- accordingly for the next read.
- NOTES:
- The ply file, has always an ascii part for the header, and a binary or ascii
- part for the data.
- The header part in ascii, dictates that linebreaks are used, this make models
- operating system dependent, as a line break in unix is indicated with the escape character \n,
- on a macintosh, with \r, and on a pc with \r\n <--2 unsigned chars, 2 bytes, instead of 1 byte.
- get_words allows reading of any OS, text editors such as BBEdit do not save the linebreaks
- properly to target OSs with binary files.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <string.h>
- //#include "ply.h"
- namespace igl {
- namespace ply {
- // Use unnamed namespace to avoid duplicate symbols
- /*
- namespace
- {
- const char *type_names[] = {
- "invalid",
- "char", "short", "int",
- "uchar", "ushort", "uint",
- "float", "double",
- };
- // names of scalar types
- const char *alt_type_names[] = {
- "invalid",
- "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
- };
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- }
- typedef union
- {
- int int_value;
- char byte_values[sizeof(int)];
- } endian_test_type;
- namespace
- {
- static int native_binary_type = -1;
- static int types_checked = 0;
- }
- */
- #define NO_OTHER_PROPS -1
- #define DONT_STORE_PROP 0
- #define STORE_PROP 1
- #define OTHER_PROP 0
- #define NAMED_PROP 1
- /* returns 1 if strings are equal, 0 if not */
- inline int equal_strings(const char *, const char *);
- /* find an element in a plyfile's list */
- inline PlyElement *find_element(PlyFile *, const char *);
- /* find a property in an element's list */
- inline PlyProperty *find_property(PlyElement *, const char *, int *);
- /* write to a file the word describing a PLY file data type */
- inline void write_scalar_type (FILE *, int);
- /* read a line from a file and break it up into separate words */
- inline char **get_words(FILE *, int *, char **);
- inline char **old_get_words(FILE *, int *);
- /* write an item to a file */
- inline void write_binary_item(FILE *, int, int, unsigned int, double, int, int*);
- inline void write_ascii_item(FILE *, int, unsigned int, double, int);
- inline double old_write_ascii_item(FILE *, char *, int);
- /* add information to a PLY file descriptor */
- inline void add_element(PlyFile *, char **);
- inline void add_property(PlyFile *, char **);
- inline void add_comment(PlyFile *, char *);
- inline void add_obj_info(PlyFile *, char *);
- /* copy a property */
- inline void copy_property(PlyProperty *, PlyProperty *);
- /* store a value into where a pointer and a type specify */
- inline void store_item(char *, int, int, unsigned int, double);
- /* return the value of a stored item */
- inline void get_stored_item( void *, int, int *, unsigned int *, double *);
- /* return the value stored in an item, given ptr to it and its type */
- inline double get_item_value(char *, int);
- /* get binary or ascii item and store it according to ptr and type */
- inline void get_ascii_item(char *, int, int *, unsigned int *, double *);
- inline void get_binary_item(FILE *, int, int, int *, unsigned int *, double *, int*);
- /* get a bunch of elements from a file */
- inline void ascii_get_element(PlyFile *, char *);
- inline void binary_get_element(PlyFile *, char *, int*);
- /* memory allocation */
- inline char *my_alloc(int, int, const char *);
- /* byte ordering */
- inline void get_native_binary_type(int*);
- inline void swap_bytes(char *, int);
- inline int check_types();
- /*************/
- /* Writing */
- /*************/
- /******************************************************************************
- Given a file pointer, get ready to write PLY data to the file.
- Entry:
- fp - the given file pointer
- nelems - number of elements in object
- elem_names - list of element names
- file_type - file type, either ascii or binary
- Exit:
- returns a pointer to a PlyFile, used to refer to this file, or NULL if error
- ******************************************************************************/
- inline PlyFile *ply_write(
- FILE *fp,
- int nelems,
- const char **elem_names,
- int file_type
- )
- {
- int i;
- PlyFile *plyfile;
- PlyElement *elem;
- /* check for NULL file pointer */
- if (fp == NULL)
- return (NULL);
-
- int native_binary_type = -1;
- int types_checked = 0;
- if (native_binary_type == -1)
- native_binary_type = get_native_binary_type2();
- if (!types_checked)
- types_checked = check_types();
-
- /* create a record for this object */
- plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
- if (file_type == PLY_BINARY_NATIVE)
- plyfile->file_type = native_binary_type;
- else
- plyfile->file_type = file_type;
- plyfile->num_comments = 0;
- plyfile->num_obj_info = 0;
- plyfile->nelems = nelems;
- plyfile->version = 1.0;
- plyfile->fp = fp;
- plyfile->other_elems = NULL;
- /* tuck aside the names of the elements */
- plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems);
- for (i = 0; i < nelems; i++) {
- elem = (PlyElement *) myalloc (sizeof (PlyElement));
- plyfile->elems[i] = elem;
- elem->name = strdup (elem_names[i]);
- elem->num = 0;
- elem->nprops = 0;
- }
- /* return pointer to the file descriptor */
- return (plyfile);
- }
- /******************************************************************************
- Open a polygon file for writing.
- Entry:
- filename - name of file to read from
- nelems - number of elements in object
- elem_names - list of element names
- file_type - file type, either ascii or binary
- Exit:
- version - version number of PLY file
- returns a file identifier, used to refer to this file, or NULL if error
- ******************************************************************************/
- inline PlyFile *ply_open_for_writing(
- const char *filename,
- int nelems,
- const char **elem_names,
- int file_type,
- float *version
- )
- {
- PlyFile *plyfile;
- char *name;
- FILE *fp;
- /* tack on the extension .ply, if necessary */
- name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
- strcpy (name, filename);
- if (strlen (name) < 4 ||
- strcmp (name + strlen (name) - 4, ".ply") != 0)
- strcat (name, ".ply");
- /* open the file for writing */
- fp = fopen (name, "w");
- if (fp == NULL) {
- free(name);
- return (NULL);
- }
- free(name);
- /* create the actual PlyFile structure */
- plyfile = ply_write (fp, nelems, elem_names, file_type);
- if (plyfile == NULL)
- return (NULL);
- /* say what PLY file version number we're writing */
- *version = plyfile->version;
- /* return pointer to the file descriptor */
- return (plyfile);
- }
- /******************************************************************************
- Describe an element, including its properties and how many will be written
- to the file.
- Entry:
- plyfile - file identifier
- elem_name - name of element that information is being specified about
- nelems - number of elements of this type to be written
- nprops - number of properties contained in the element
- prop_list - list of properties
- ******************************************************************************/
- inline void ply_describe_element(
- PlyFile *plyfile,
- const char *elem_name,
- int nelems,
- int nprops,
- PlyProperty *prop_list
- )
- {
- int i;
- PlyElement *elem;
- PlyProperty *prop;
- /* look for appropriate element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name);
- exit (-1);
- }
- elem->num = nelems;
- /* copy the list of properties */
- elem->nprops = nprops;
- elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops);
- elem->store_prop = (char *) myalloc (sizeof (char) * nprops);
- for (i = 0; i < nprops; i++) {
- prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- elem->props[i] = prop;
- elem->store_prop[i] = NAMED_PROP;
- copy_property (prop, &prop_list[i]);
- }
- }
- /******************************************************************************
- Describe a property of an element.
- Entry:
- plyfile - file identifier
- elem_name - name of element that information is being specified about
- prop - the new property
- ******************************************************************************/
- inline void ply_describe_property(
- PlyFile *plyfile,
- const char *elem_name,
- PlyProperty *prop
- )
- {
- PlyElement *elem;
- PlyProperty *elem_prop;
- /* look for appropriate element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf(stderr, "ply_describe_property: can't find element '%s'\n",
- elem_name);
- return;
- }
- /* create room for new property */
- if (elem->nprops == 0) {
- elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
- elem->store_prop = (char *) myalloc (sizeof (char));
- elem->nprops = 1;
- }
- else {
- elem->nprops++;
- elem->props = (PlyProperty **)
- realloc (elem->props, sizeof (PlyProperty *) * elem->nprops);
- elem->store_prop = (char *)
- realloc (elem->store_prop, sizeof (char) * elem->nprops);
- }
- /* copy the new property */
- elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- elem->props[elem->nprops - 1] = elem_prop;
- elem->store_prop[elem->nprops - 1] = NAMED_PROP;
- copy_property (elem_prop, prop);
- }
- /******************************************************************************
- Describe what the "other" properties are that are to be stored, and where
- they are in an element.
- ******************************************************************************/
- inline void ply_describe_other_properties(
- PlyFile *plyfile,
- PlyOtherProp *other,
- int offset
- )
- {
- int i;
- PlyElement *elem;
- PlyProperty *prop;
- /* look for appropriate element */
- elem = find_element (plyfile, other->name);
- if (elem == NULL) {
- fprintf(stderr, "ply_describe_other_properties: can't find element '%s'\n",
- other->name);
- return;
- }
- /* create room for other properties */
- if (elem->nprops == 0) {
- elem->props = (PlyProperty **)
- myalloc (sizeof (PlyProperty *) * other->nprops);
- elem->store_prop = (char *) myalloc (sizeof (char) * other->nprops);
- elem->nprops = 0;
- }
- else {
- int newsize;
- newsize = elem->nprops + other->nprops;
- elem->props = (PlyProperty **)
- realloc (elem->props, sizeof (PlyProperty *) * newsize);
- elem->store_prop = (char *)
- realloc (elem->store_prop, sizeof (char) * newsize);
- }
- /* copy the other properties */
- for (i = 0; i < other->nprops; i++) {
- prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- copy_property (prop, other->props[i]);
- elem->props[elem->nprops] = prop;
- elem->store_prop[elem->nprops] = OTHER_PROP;
- elem->nprops++;
- }
- /* save other info about other properties */
- elem->other_size = other->size;
- elem->other_offset = offset;
- }
- /******************************************************************************
- State how many of a given element will be written.
- Entry:
- plyfile - file identifier
- elem_name - name of element that information is being specified about
- nelems - number of elements of this type to be written
- ******************************************************************************/
- inline void ply_element_count(
- PlyFile *plyfile,
- const char *elem_name,
- int nelems
- )
- {
- PlyElement *elem;
- /* look for appropriate element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name);
- exit (-1);
- }
- elem->num = nelems;
- }
- /******************************************************************************
- Signal that we've described everything a PLY file's header and that the
- header should be written to the file.
- Entry:
- plyfile - file identifier
- ******************************************************************************/
- inline void ply_header_complete(PlyFile *plyfile)
- {
- int i,j;
- FILE *fp = plyfile->fp;
- PlyElement *elem;
- PlyProperty *prop;
- fprintf (fp, "ply\n");
- switch (plyfile->file_type) {
- case PLY_ASCII:
- fprintf (fp, "format ascii 1.0\n");
- break;
- case PLY_BINARY_BE:
- fprintf (fp, "format binary_big_endian 1.0\n");
- break;
- case PLY_BINARY_LE:
- fprintf (fp, "format binary_little_endian 1.0\n");
- break;
- default:
- fprintf (stderr, "ply_header_complete: bad file type = %d\n",
- plyfile->file_type);
- exit (-1);
- }
- /* write out the comments */
- for (i = 0; i < plyfile->num_comments; i++)
- fprintf (fp, "comment %s\n", plyfile->comments[i]);
- /* write out object information */
- for (i = 0; i < plyfile->num_obj_info; i++)
- fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]);
- /* write out information about each element */
- for (i = 0; i < plyfile->nelems; i++) {
- elem = plyfile->elems[i];
- fprintf (fp, "element %s %d\n", elem->name, elem->num);
- /* write out each property */
- for (j = 0; j < elem->nprops; j++) {
- prop = elem->props[j];
- if (prop->is_list) {
- fprintf (fp, "property list ");
- write_scalar_type (fp, prop->count_external);
- fprintf (fp, " ");
- write_scalar_type (fp, prop->external_type);
- fprintf (fp, " %s\n", prop->name);
- }
- else {
- fprintf (fp, "property ");
- write_scalar_type (fp, prop->external_type);
- fprintf (fp, " %s\n", prop->name);
- }
- }
- }
- fprintf (fp, "end_header\n");
- }
- /******************************************************************************
- Specify which elements are going to be written. This should be called
- before a call to the routine ply_put_element().
- Entry:
- plyfile - file identifier
- elem_name - name of element we're talking about
- ******************************************************************************/
- inline void ply_put_element_setup(PlyFile *plyfile, const char *elem_name)
- {
- PlyElement *elem;
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name);
- exit (-1);
- }
-
- plyfile->which_elem = elem;
- }
- /******************************************************************************
- Write an element to the file. This routine assumes that we're
- writing the type of element specified in the last call to the routine
- ply_put_element_setup().
- Entry:
- plyfile - file identifier
- elem_ptr - pointer to the element
- ******************************************************************************/
- inline void ply_put_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
- {
- int j,k;
- FILE *fp = plyfile->fp;
- PlyElement *elem;
- PlyProperty *prop;
- char *elem_data,*item;
- char **item_ptr;
- int list_count;
- int item_size;
- int int_val;
- unsigned int uint_val;
- double double_val;
- char **other_ptr;
- elem = plyfile->which_elem;
- elem_data = (char *)elem_ptr;
- other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset);
- /* write out either to an ascii or binary file */
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- if (plyfile->file_type == PLY_ASCII) {
- /* write an ascii file */
- /* write out each property of the element */
- for (j = 0; j < elem->nprops; j++) {
- prop = elem->props[j];
- if (elem->store_prop[j] == OTHER_PROP)
- elem_data = *other_ptr;
- else
- elem_data = (char *)elem_ptr;
- if (prop->is_list) {
- item = elem_data + prop->count_offset;
- get_stored_item ((void *) item, prop->count_internal,
- &int_val, &uint_val, &double_val);
- write_ascii_item (fp, int_val, uint_val, double_val,
- prop->count_external);
- list_count = uint_val;
- item_ptr = (char **) (elem_data + prop->offset);
- item = item_ptr[0];
- item_size = ply_type_size[prop->internal_type];
- for (k = 0; k < list_count; k++) {
- get_stored_item ((void *) item, prop->internal_type,
- &int_val, &uint_val, &double_val);
- write_ascii_item (fp, int_val, uint_val, double_val,
- prop->external_type);
- item += item_size;
- }
- }
- else {
- item = elem_data + prop->offset;
- get_stored_item ((void *) item, prop->internal_type,
- &int_val, &uint_val, &double_val);
- write_ascii_item (fp, int_val, uint_val, double_val,
- prop->external_type);
- }
- }
- fprintf (fp, "\n");
- }
- else {
- /* write a binary file */
- /* write out each property of the element */
- for (j = 0; j < elem->nprops; j++) {
- prop = elem->props[j];
- if (elem->store_prop[j] == OTHER_PROP)
- elem_data = *other_ptr;
- else
- elem_data = (char *)elem_ptr;
- if (prop->is_list) {
- item = elem_data + prop->count_offset;
- item_size = ply_type_size[prop->count_internal];
- get_stored_item ((void *) item, prop->count_internal,
- &int_val, &uint_val, &double_val);
- write_binary_item (fp, plyfile->file_type, int_val, uint_val,
- double_val, prop->count_external, native_binary_type);
- list_count = uint_val;
- item_ptr = (char **) (elem_data + prop->offset);
- item = item_ptr[0];
- item_size = ply_type_size[prop->internal_type];
- for (k = 0; k < list_count; k++) {
- get_stored_item ((void *) item, prop->internal_type,
- &int_val, &uint_val, &double_val);
- write_binary_item (fp, plyfile->file_type, int_val, uint_val,
- double_val, prop->external_type, native_binary_type);
- item += item_size;
- }
- }
- else {
- item = elem_data + prop->offset;
- item_size = ply_type_size[prop->internal_type];
- get_stored_item ((void *) item, prop->internal_type,
- &int_val, &uint_val, &double_val);
- write_binary_item (fp, plyfile->file_type, int_val, uint_val,
- double_val, prop->external_type, native_binary_type);
- }
- }
- }
- }
- /******************************************************************************
- Specify a comment that will be written in the header.
- Entry:
- plyfile - file identifier
- comment - the comment to be written
- ******************************************************************************/
- inline void ply_put_comment(PlyFile *plyfile, char *comment)
- {
- /* (re)allocate space for new comment */
- if (plyfile->num_comments == 0)
- plyfile->comments = (char **) myalloc (sizeof (char *));
- else
- plyfile->comments = (char **) realloc (plyfile->comments,
- sizeof (char *) * (plyfile->num_comments + 1));
- /* add comment to list */
- plyfile->comments[plyfile->num_comments] = strdup (comment);
- plyfile->num_comments++;
- }
- /******************************************************************************
- Specify a piece of object information (arbitrary text) that will be written
- in the header.
- Entry:
- plyfile - file identifier
- obj_info - the text information to be written
- ******************************************************************************/
- inline void ply_put_obj_info(PlyFile *plyfile, char *obj_info)
- {
- /* (re)allocate space for new info */
- if (plyfile->num_obj_info == 0)
- plyfile->obj_info = (char **) myalloc (sizeof (char *));
- else
- plyfile->obj_info = (char **) realloc (plyfile->obj_info,
- sizeof (char *) * (plyfile->num_obj_info + 1));
- /* add info to list */
- plyfile->obj_info[plyfile->num_obj_info] = strdup (obj_info);
- plyfile->num_obj_info++;
- }
- /*************/
- /* Reading */
- /*************/
- /******************************************************************************
- Given a file pointer, get ready to read PLY data from the file.
- Entry:
- fp - the given file pointer
- Exit:
- nelems - number of elements in object
- elem_names - list of element names
- returns a pointer to a PlyFile, used to refer to this file, or NULL if error
- ******************************************************************************/
- inline PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names)
- {
- int i,j;
- PlyFile *plyfile;
- int nwords;
- char **words;
- char **elist;
- PlyElement *elem;
- char *orig_line;
- /* check for NULL file pointer */
- if (fp == NULL)
- return (NULL);
-
- int native_binary_type = -1;
- int types_checked = 0;
-
- if (native_binary_type == -1)
- native_binary_type = get_native_binary_type2();
- if (!types_checked)
- types_checked = check_types();
-
- /* create record for this object */
- plyfile = (PlyFile *) myalloc (sizeof (PlyFile));
- plyfile->nelems = 0;
- plyfile->comments = NULL;
- plyfile->num_comments = 0;
- plyfile->obj_info = NULL;
- plyfile->num_obj_info = 0;
- plyfile->fp = fp;
- plyfile->other_elems = NULL;
- /* read and parse the file's header */
- words = get_words (plyfile->fp, &nwords, &orig_line);
- if (nwords == 0 || !words || !equal_strings (words[0], "ply"))
- {
- if (words)
- free(words);
-
-
- return (NULL);
- }
-
- while (words) {
- /* parse words */
- if (equal_strings (words[0], "format")) {
- if (nwords != 3) {
- free(words);
- return (NULL);
- }
- if (equal_strings (words[1], "ascii"))
- plyfile->file_type = PLY_ASCII;
- else if (equal_strings (words[1], "binary_big_endian"))
- plyfile->file_type = PLY_BINARY_BE;
- else if (equal_strings (words[1], "binary_little_endian"))
- plyfile->file_type = PLY_BINARY_LE;
- else {
- free(words);
- return (NULL);
- }
- plyfile->version = atof (words[2]);
- }
- else if (equal_strings (words[0], "element"))
- add_element (plyfile, words);
- else if (equal_strings (words[0], "property"))
- add_property (plyfile, words);
- else if (equal_strings (words[0], "comment"))
- add_comment (plyfile, orig_line);
- else if (equal_strings (words[0], "obj_info"))
- add_obj_info (plyfile, orig_line);
- else if (equal_strings (words[0], "end_header")) {
- free(words);
- break;
- }
-
- /* free up words space */
- free (words);
- words = get_words (plyfile->fp, &nwords, &orig_line);
- }
- /* create tags for each property of each element, to be used */
- /* later to say whether or not to store each property for the user */
- for (i = 0; i < plyfile->nelems; i++) {
- elem = plyfile->elems[i];
- elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops);
- for (j = 0; j < elem->nprops; j++)
- elem->store_prop[j] = DONT_STORE_PROP;
- elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */
- }
- /* set return values about the elements */
- elist = (char **) myalloc (sizeof (char *) * plyfile->nelems);
- for (i = 0; i < plyfile->nelems; i++)
- elist[i] = strdup (plyfile->elems[i]->name);
- *elem_names = elist;
- *nelems = plyfile->nelems;
- /* return a pointer to the file's information */
- return (plyfile);
- }
- /******************************************************************************
- Open a polygon file for reading.
- Entry:
- filename - name of file to read from
- Exit:
- nelems - number of elements in object
- elem_names - list of element names
- file_type - file type, either ascii or binary
- version - version number of PLY file
- returns a file identifier, used to refer to this file, or NULL if error
- ******************************************************************************/
- inline PlyFile *ply_open_for_reading(
- char *filename,
- int *nelems,
- char ***elem_names,
- int *file_type,
- float *version
- )
- {
- FILE *fp;
- PlyFile *plyfile;
- //char *name;
-
-
- /* tack on the extension .ply, if necessary */
- // removing below, to handle also macintosh alias filenames
- //name = (char *) myalloc (sizeof (char) * (strlen (filename) + 5));
- //strcpy (name, filename);
- //if (strlen (name) < 4 ||
- // strcmp (name + strlen (name) - 4, ".ply") != 0)
- // strcat (name, ".ply");
- /* open the file for reading */
- //fp = fopen (name, "r");
-
- //opening file in binary, ascii data can be read in binary with get_words
- fp = fopen (filename, "rb");
- if (fp == NULL)
- return (NULL);
-
- /* create the PlyFile data structure */
- plyfile = ply_read (fp, nelems, elem_names);
- /* determine the file type and version */
- *file_type = plyfile->file_type;
- *version = plyfile->version;
- /* return a pointer to the file's information */
- return (plyfile);
- }
- /******************************************************************************
- Get information about a particular element.
- Entry:
- plyfile - file identifier
- elem_name - name of element to get information about
- Exit:
- nelems - number of elements of this type in the file
- nprops - number of properties
- returns a list of properties, or NULL if the file doesn't contain that elem
- ******************************************************************************/
- inline PlyProperty **ply_get_element_description(
- PlyFile *plyfile,
- const char *elem_name,
- int *nelems,
- int *nprops
- )
- {
- int i;
- PlyElement *elem;
- PlyProperty *prop;
- PlyProperty **prop_list;
- /* find information about the element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL)
- return (NULL);
- *nelems = elem->num;
- *nprops = elem->nprops;
- /* make a copy of the element's property list */
- prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops);
- for (i = 0; i < elem->nprops; i++) {
- prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- copy_property (prop, elem->props[i]);
- prop_list[i] = prop;
- }
- /* return this duplicate property list */
- return (prop_list);
- }
- /******************************************************************************
- Specify which properties of an element are to be returned. This should be
- called before a call to the routine ply_get_element().
- Entry:
- plyfile - file identifier
- elem_name - which element we're talking about
- nprops - number of properties
- prop_list - list of properties
- ******************************************************************************/
- inline void ply_get_element_setup(
- PlyFile *plyfile,
- const char *elem_name,
- int nprops,
- PlyProperty *prop_list
- )
- {
- int i;
- PlyElement *elem;
- PlyProperty *prop;
- int index;
- /* find information about the element */
- elem = find_element (plyfile, elem_name);
- plyfile->which_elem = elem;
- /* deposit the property information into the element's description */
- for (i = 0; i < nprops; i++) {
- /* look for actual property */
- prop = find_property (elem, prop_list[i].name, &index);
- if (prop == NULL) {
- fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
- prop_list[i].name, elem_name);
- continue;
- }
- /* store its description */
- prop->internal_type = prop_list[i].internal_type;
- prop->offset = prop_list[i].offset;
- prop->count_internal = prop_list[i].count_internal;
- prop->count_offset = prop_list[i].count_offset;
- /* specify that the user wants this property */
- elem->store_prop[index] = STORE_PROP;
- }
- }
- /******************************************************************************
- Specify a property of an element that is to be returned. This should be
- called (usually multiple times) before a call to the routine ply_get_element().
- This routine should be used in preference to the less flexible old routine
- called ply_get_element_setup().
- Entry:
- plyfile - file identifier
- elem_name - which element we're talking about
- prop - property to add to those that will be returned
- ******************************************************************************/
- inline void ply_get_property(
- PlyFile *plyfile,
- const char *elem_name,
- PlyProperty *prop
- )
- {
- PlyElement *elem;
- PlyProperty *prop_ptr;
- int index;
- /* find information about the element */
- elem = find_element (plyfile, elem_name);
- plyfile->which_elem = elem;
- /* deposit the property information into the element's description */
- prop_ptr = find_property (elem, prop->name, &index);
- if (prop_ptr == NULL) {
- fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n",
- prop->name, elem_name);
- return;
- }
- prop_ptr->internal_type = prop->internal_type;
- prop_ptr->offset = prop->offset;
- prop_ptr->count_internal = prop->count_internal;
- prop_ptr->count_offset = prop->count_offset;
- /* specify that the user wants this property */
- elem->store_prop[index] = STORE_PROP;
- }
- /******************************************************************************
- Read one element from the file. This routine assumes that we're reading
- the type of element specified in the last call to the routine
- ply_get_element_setup().
- Entry:
- plyfile - file identifier
- elem_ptr - pointer to location where the element information should be put
- ******************************************************************************/
- inline void ply_get_element(PlyFile *plyfile, void *elem_ptr, int *native_binary_type)
- {
- if (plyfile->file_type == PLY_ASCII)
- ascii_get_element (plyfile, (char *) elem_ptr);
- else
- binary_get_element (plyfile, (char *) elem_ptr, native_binary_type);
- }
- /******************************************************************************
- Extract the comments from the header information of a PLY file.
- Entry:
- plyfile - file identifier
- Exit:
- num_comments - number of comments returned
- returns a pointer to a list of comments
- ******************************************************************************/
- inline char **ply_get_comments(PlyFile *plyfile, int *num_comments)
- {
- *num_comments = plyfile->num_comments;
- return (plyfile->comments);
- }
- /******************************************************************************
- Extract the object information (arbitrary text) from the header information
- of a PLY file.
- Entry:
- plyfile - file identifier
- Exit:
- num_obj_info - number of lines of text information returned
- returns a pointer to a list of object info lines
- ******************************************************************************/
- inline char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info)
- {
- *num_obj_info = plyfile->num_obj_info;
- return (plyfile->obj_info);
- }
- /******************************************************************************
- Make ready for "other" properties of an element-- those properties that
- the user has not explicitly asked for, but that are to be stashed away
- in a special structure to be carried along with the element's other
- information.
- Entry:
- plyfile - file identifier
- elem - element for which we want to save away other properties
- ******************************************************************************/
- inline void setup_other_props(PlyElement *elem)
- {
- int i;
- PlyProperty *prop;
- int size = 0;
- int type_size;
- /* Examine each property in decreasing order of size. */
- /* We do this so that all data types will be aligned by */
- /* word, half-word, or whatever within the structure. */
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- for (type_size = 8; type_size > 0; type_size /= 2) {
- /* add up the space taken by each property, and save this information */
- /* away in the property descriptor */
- for (i = 0; i < elem->nprops; i++) {
- /* don't bother with properties we've been asked to store explicitly */
- if (elem->store_prop[i])
- continue;
- prop = elem->props[i];
- /* internal types will be same as external */
- prop->internal_type = prop->external_type;
- prop->count_internal = prop->count_external;
- /* check list case */
- if (prop->is_list) {
- /* pointer to list */
- if (type_size == sizeof (void *)) {
- prop->offset = size;
- size += sizeof (void *); /* always use size of a pointer here */
- }
- /* count of number of list elements */
- if (type_size == ply_type_size[prop->count_external]) {
- prop->count_offset = size;
- size += ply_type_size[prop->count_external];
- }
- }
- /* not list */
- else if (type_size == ply_type_size[prop->external_type]) {
- prop->offset = size;
- size += ply_type_size[prop->external_type];
- }
- }
- }
- /* save the size for the other_props structure */
- elem->other_size = size;
- }
- /******************************************************************************
- Specify that we want the "other" properties of an element to be tucked
- away within the user's structure. The user needn't be concerned for how
- these properties are stored.
- Entry:
- plyfile - file identifier
- elem_name - name of element that we want to store other_props in
- offset - offset to where other_props will be stored inside user's structure
- Exit:
- returns pointer to structure containing description of other_props
- ******************************************************************************/
- inline PlyOtherProp *ply_get_other_properties(
- PlyFile *plyfile,
- const char *elem_name,
- int offset
- )
- {
- int i;
- PlyElement *elem;
- PlyOtherProp *other;
- PlyProperty *prop;
- int nprops;
- /* find information about the element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf (stderr, "ply_get_other_properties: Can't find element '%s'\n",
- elem_name);
- return (NULL);
- }
- /* remember that this is the "current" element */
- plyfile->which_elem = elem;
- /* save the offset to where to store the other_props */
- elem->other_offset = offset;
- /* place the appropriate pointers, etc. in the element's property list */
- setup_other_props (elem);
- /* create structure for describing other_props */
- other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp));
- other->name = strdup (elem_name);
- #if 0
- if (elem->other_offset == NO_OTHER_PROPS) {
- other->size = 0;
- other->props = NULL;
- other->nprops = 0;
- return (other);
- }
- #endif
- other->size = elem->other_size;
- other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops);
-
- /* save descriptions of each "other" property */
- nprops = 0;
- for (i = 0; i < elem->nprops; i++) {
- if (elem->store_prop[i])
- continue;
- prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- copy_property (prop, elem->props[i]);
- other->props[nprops] = prop;
- nprops++;
- }
- other->nprops = nprops;
- #if 1
- /* set other_offset pointer appropriately if there are NO other properties */
- if (other->nprops == 0) {
- elem->other_offset = NO_OTHER_PROPS;
- }
- #endif
-
- /* return structure */
- return (other);
- }
- /*************************/
- /* Other Element Stuff */
- /*************************/
- /******************************************************************************
- Grab all the data for an element that a user does not want to explicitly
- read in.
- Entry:
- plyfile - pointer to file
- elem_name - name of element whose data is to be read in
- elem_count - number of instances of this element stored in the file
- Exit:
- returns pointer to ALL the "other" element data for this PLY file
- ******************************************************************************/
- inline PlyOtherElems *ply_get_other_element (
- PlyFile *plyfile,
- char *elem_name,
- int elem_count
- )
- {
- int i;
- PlyElement *elem;
- PlyOtherElems *other_elems;
- OtherElem *other;
- /* look for appropriate element */
- elem = find_element (plyfile, elem_name);
- if (elem == NULL) {
- fprintf (stderr,
- "ply_get_other_element: can't find element '%s'\n", elem_name);
- exit (-1);
- }
- /* create room for the new "other" element, initializing the */
- /* other data structure if necessary */
- if (plyfile->other_elems == NULL) {
- plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems));
- other_elems = plyfile->other_elems;
- other_elems->other_list = (OtherElem *) myalloc (sizeof (OtherElem));
- other = &(other_elems->other_list[0]);
- other_elems->num_elems = 1;
- }
- else {
- other_elems = plyfile->other_elems;
- other_elems->other_list = (OtherElem *) realloc (other_elems->other_list,
- sizeof (OtherElem) * (other_elems->num_elems + 1));
- other = &(other_elems->other_list[other_elems->num_elems]);
- other_elems->num_elems++;
- }
- /* count of element instances in file */
- other->elem_count = elem_count;
- /* save name of element */
- other->elem_name = strdup (elem_name);
- /* create a list to hold all the current elements */
- other->other_data = (OtherData **)
- malloc (sizeof (OtherData *) * other->elem_count);
- /* set up for getting elements */
- other->other_props = ply_get_other_properties (plyfile, elem_name,
- offsetof(OtherData,other_props));
- /* grab all these elements */
- int native_binary_type = get_native_binary_type2();
- for (i = 0; i < other->elem_count; i++) {
- /* grab and element from the file */
- other->other_data[i] = (OtherData *) malloc (sizeof (OtherData));
- ply_get_element (plyfile, (void *) other->other_data[i], &native_binary_type);
- }
- /* return pointer to the other elements data */
- return (other_elems);
- }
- /******************************************************************************
- Pass along a pointer to "other" elements that we want to save in a given
- PLY file. These other elements were presumably read from another PLY file.
- Entry:
- plyfile - file pointer in which to store this other element info
- other_elems - info about other elements that we want to store
- ******************************************************************************/
- inline void ply_describe_other_elements (
- PlyFile *plyfile,
- PlyOtherElems *other_elems
- )
- {
- int i;
- OtherElem *other;
- PlyElement *elem;
-
- /* ignore this call if there is no other element */
- if (other_elems == NULL)
- return;
- /* save pointer to this information */
- plyfile->other_elems = other_elems;
- /* describe the other properties of this element */
- /* store them in the main element list as elements with
- only other properties */
-
- REALLOCN(plyfile->elems, PlyElement *,
- plyfile->nelems, plyfile->nelems + other_elems->num_elems);
- for (i = 0; i < other_elems->num_elems; i++) {
- other = &(other_elems->other_list[i]);
- elem = (PlyElement *) myalloc (sizeof (PlyElement));
- plyfile->elems[plyfile->nelems++] = elem;
- elem->name = strdup (other->elem_name);
- elem->num = other->elem_count;
- elem->nprops = 0;
- ply_describe_other_properties (plyfile, other->other_props,
- offsetof(OtherData,other_props));
- }
- }
- /******************************************************************************
- Write out the "other" elements specified for this PLY file.
- Entry:
- plyfile - pointer to PLY file to write out other elements for
- ******************************************************************************/
- inline void ply_put_other_elements (PlyFile *plyfile, int *native_binary_type)
- {
- int i,j;
- OtherElem *other;
- /* make sure we have other elements to write */
- if (plyfile->other_elems == NULL)
- return;
- /* write out the data for each "other" element */
- for (i = 0; i < plyfile->other_elems->num_elems; i++) {
- other = &(plyfile->other_elems->other_list[i]);
- ply_put_element_setup (plyfile, other->elem_name);
- /* write out each instance of the current element */
- for (j = 0; j < other->elem_count; j++)
- ply_put_element (plyfile, (void *) other->other_data[j], native_binary_type);
- }
- }
- /******************************************************************************
- Free up storage used by an "other" elements data structure.
- Entry:
- other_elems - data structure to free up
- ******************************************************************************/
- inline void ply_free_other_elements (PlyOtherElems *other_elems)
- {
- // Alec:
- //other_elems = other_elems;
- delete(other_elems);
- }
- /*******************/
- /* Miscellaneous */
- /*******************/
- /******************************************************************************
- Close a PLY file.
- Entry:
- plyfile - identifier of file to close
- ******************************************************************************/
- inline void ply_close(PlyFile *plyfile)
- {
- fclose (plyfile->fp);
- // Alec:
- plyfile->fp = NULL;
- /* free up memory associated with the PLY file */
- free (plyfile);
- }
- /******************************************************************************
- Get version number and file type of a PlyFile.
- Entry:
- ply - pointer to PLY file
- Exit:
- version - version of the file
- file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE
- ******************************************************************************/
- inline void ply_get_info(PlyFile *ply, float *version, int *file_type)
- {
- if (ply == NULL)
- return;
- *version = ply->version;
- *file_type = ply->file_type;
- }
- /******************************************************************************
- Compare two strings. Returns 1 if they are the same, 0 if not.
- ******************************************************************************/
- inline int equal_strings(const char *s1, const char *s2)
- {
- while (*s1 && *s2)
- if (*s1++ != *s2++)
- return (0);
- if (*s1 != *s2)
- return (0);
- else
- return (1);
- }
- /******************************************************************************
- Find an element from the element list of a given PLY object.
- Entry:
- plyfile - file id for PLY file
- element - name of element we're looking for
- Exit:
- returns the element, or NULL if not found
- ******************************************************************************/
- inline PlyElement *find_element(PlyFile *plyfile, const char *element)
- {
- int i;
- for (i = 0; i < plyfile->nelems; i++)
- if (equal_strings (element, plyfile->elems[i]->name))
- return (plyfile->elems[i]);
- return (NULL);
- }
- /******************************************************************************
- Find a property in the list of properties of a given element.
- Entry:
- elem - pointer to element in which we want to find the property
- prop_name - name of property to find
- Exit:
- index - index to position in list
- returns a pointer to the property, or NULL if not found
- ******************************************************************************/
- inline PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index)
- {
- int i;
- for (i = 0; i < elem->nprops; i++)
- if (equal_strings (prop_name, elem->props[i]->name)) {
- *index = i;
- return (elem->props[i]);
- }
- *index = -1;
- return (NULL);
- }
- /******************************************************************************
- Read an element from an ascii file.
- Entry:
- plyfile - file identifier
- elem_ptr - pointer to element
- ******************************************************************************/
- inline void ascii_get_element(PlyFile *plyfile, char *elem_ptr)
- {
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- int j,k;
- PlyElement *elem;
- PlyProperty *prop;
- char **words;
- int nwords;
- int which_word;
- char *elem_data,*item=NULL;
- char *item_ptr;
- int item_size;
- int int_val;
- unsigned int uint_val;
- double double_val;
- int list_count;
- int store_it;
- char **store_array;
- char *orig_line;
- char *other_data=NULL;
- int other_flag;
- /* the kind of element we're reading currently */
- elem = plyfile->which_elem;
- /* do we need to setup for other_props? */
- if (elem->other_offset != NO_OTHER_PROPS) {
- char **ptr;
- other_flag = 1;
- /* make room for other_props */
- other_data = (char *) myalloc (elem->other_size);
- /* store pointer in user's structure to the other_props */
- ptr = (char **) (elem_ptr + elem->other_offset);
- *ptr = other_data;
- }
- else
- other_flag = 0;
- /* read in the element */
- words = get_words (plyfile->fp, &nwords, &orig_line);
- if (words == NULL) {
- fprintf (stderr, "ply_get_element: unexpected end of file\n");
- exit (-1);
- }
- which_word = 0;
- for (j = 0; j < elem->nprops; j++) {
- prop = elem->props[j];
- store_it = (elem->store_prop[j] | other_flag);
- /* store either in the user's structure or in other_props */
- // if (elem->store_prop[j])
- elem_data = elem_ptr;
- //else
- //elem_data = other_data;
- if (prop->is_list) { /* a list */
- /* get and store the number of items in the list */
- get_ascii_item (words[which_word++], prop->count_external,
- &int_val, &uint_val, &double_val);
- if (store_it) {
- item = elem_data + prop->count_offset;
- store_item(item, prop->count_internal, int_val, uint_val, double_val);
- }
- /* allocate space for an array of items and store a ptr to the array */
- list_count = int_val;
- item_size = ply_type_size[prop->internal_type];
- store_array = (char **) (elem_data + prop->offset);
- if (list_count == 0) {
- if (store_it)
- *store_array = NULL;
- }
- else {
- if (store_it) {
- item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
-
- item = item_ptr;
- *store_array = item_ptr;
- }
- /* read items and store them into the array */
- for (k = 0; k < list_count; k++) {
- get_ascii_item (words[which_word++], prop->external_type,
- &int_val, &uint_val, &double_val);
- if (store_it) {
- store_item (item, prop->internal_type,
- int_val, uint_val, double_val);
- item += item_size;
- }
- }
- }
- }
- else { /* not a list */
- get_ascii_item (words[which_word++], prop->external_type,
- &int_val, &uint_val, &double_val);
- if (store_it) {
- item = elem_data + prop->offset;
- store_item (item, prop->internal_type, int_val, uint_val, double_val);
- }
- }
- }
- free (words);
- }
- /******************************************************************************
- Read an element from a binary file.
- Entry:
- plyfile - file identifier
- elem_ptr - pointer to an element
- ******************************************************************************/
- inline void binary_get_element(PlyFile *plyfile, char *elem_ptr, int *native_binary_type)
- {
- int j,k;
- PlyElement *elem;
- PlyProperty *prop;
- FILE *fp = plyfile->fp;
- char *elem_data,*item=NULL;
- char *item_ptr;
- int item_size;
- int int_val;
- unsigned int uint_val;
- double double_val;
- int list_count;
- int store_it;
- char **store_array;
- char *other_data=NULL;
- int other_flag;
-
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- /* the kind of element we're reading currently */
- elem = plyfile->which_elem;
- /* do we need to setup for other_props? */
- if (elem->other_offset != NO_OTHER_PROPS) {
- char **ptr;
- other_flag = 1;
- /* make room for other_props */
- other_data = (char *) myalloc (elem->other_size);
- /* store pointer in user's structure to the other_props */
- ptr = (char **) (elem_ptr + elem->other_offset);
- *ptr = other_data;
- }
- else
- other_flag = 0;
- /* read in a number of elements */
- for (j = 0; j < elem->nprops; j++) {
- prop = elem->props[j];
- store_it = (elem->store_prop[j] | other_flag);
- /* store either in the user's structure or in other_props */
- // if (elem->store_prop[j])
- elem_data = elem_ptr;
- // else
- // elem_data = other_data;
- if (prop->is_list) { /* a list */
- /* get and store the number of items in the list */
- get_binary_item (fp, plyfile->file_type, prop->count_external,
- &int_val, &uint_val, &double_val, native_binary_type);
- if (store_it) {
- item = elem_data + prop->count_offset;
- store_item(item, prop->count_internal, int_val, uint_val, double_val);
- }
- /* allocate space for an array of items and store a ptr to the array */
- list_count = int_val;
-
- item_size = ply_type_size[prop->internal_type];
- store_array = (char **) (elem_data + prop->offset);
- if (list_count == 0) {
- if (store_it)
- *store_array = NULL;
- }
- else {
- if (store_it) {
- item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count);
-
- item = item_ptr;
- *store_array = item_ptr;
- }
- // read items and store them into the array
- for (k = 0; k < list_count; k++) {
- get_binary_item (fp, plyfile->file_type, prop->external_type,
- &int_val, &uint_val, &double_val, native_binary_type);
- if (store_it) {
- store_item (item, prop->internal_type,
- int_val, uint_val, double_val);
- item += item_size;
- }
- }
-
-
-
- }
- }
- else { /* not a list */
- get_binary_item (fp, plyfile->file_type, prop->external_type,
- &int_val, &uint_val, &double_val, native_binary_type);
- if (store_it) {
- item = elem_data + prop->offset;
- store_item (item, prop->internal_type, int_val, uint_val, double_val);
- }
- }
- }
- }
- /******************************************************************************
- Write to a file the word that represents a PLY data type.
- Entry:
- fp - file pointer
- code - code for type
- ******************************************************************************/
- inline void write_scalar_type (FILE *fp, int code)
- {
- /* make sure this is a valid code */
- if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) {
- fprintf (stderr, "write_scalar_type: bad data code = %d\n", code);
- exit (-1);
- }
- /* write the code to a file */
- const char *type_names[] = {
- "invalid",
- "char", "short", "int",
- "uchar", "ushort", "uint",
- "float", "double",
- };
- fprintf (fp, "%s", type_names[code]);
- }
- /******************************************************************************
- Reverse the order in an array of bytes. This is the conversion from big
- endian to little endian and vice versa
- Entry:
- bytes - array of bytes to reverse (in place)
- num_bytes - number of bytes in array
- ******************************************************************************/
- inline void swap_bytes(char *bytes, int num_bytes)
- {
- int i;
- char temp;
-
- for (i=0; i < num_bytes/2; i++)
- {
- temp = bytes[i];
- bytes[i] = bytes[(num_bytes-1)-i];
- bytes[(num_bytes-1)-i] = temp;
- }
- }
- /******************************************************************************
- Find out if this machine is big endian or little endian
- Exit:
- set global variable, native_binary_type =
- either PLY_BINARY_BE or PLY_BINARY_LE
- ******************************************************************************/
- inline void get_native_binary_type(int *native_binary_type)
- {
- typedef union
- {
- int int_value;
- char byte_values[sizeof(int)];
- } endian_test_type;
- endian_test_type test;
-
- test.int_value = 0;
- test.int_value = 1;
- if (test.byte_values[0] == 1)
- *native_binary_type = PLY_BINARY_LE;
- else if (test.byte_values[sizeof(int)-1] == 1)
- *native_binary_type = PLY_BINARY_BE;
- else
- {
- fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
- fprintf(stderr, "ply: Exiting...\n");
- exit(1);
- }
- }
- inline int get_native_binary_type2()
- {
- typedef union
- {
- int int_value;
- char byte_values[sizeof(int)];
- } endian_test_type;
- endian_test_type test;
- test.int_value = 0;
- test.int_value = 1;
- if (test.byte_values[0] == 1)
- return PLY_BINARY_LE;
- else if (test.byte_values[sizeof(int)-1] == 1)
- return PLY_BINARY_BE;
- else
- {
- fprintf(stderr, "ply: Couldn't determine machine endianness.\n");
- fprintf(stderr, "ply: Exiting...\n");
- exit(1);
- }
- }
- /******************************************************************************
- Verify that all the native types are the sizes we need
- ******************************************************************************/
- inline int check_types()
- {
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- if ((ply_type_size[PLY_CHAR] != sizeof(char)) ||
- (ply_type_size[PLY_SHORT] != sizeof(short)) ||
- (ply_type_size[PLY_INT] != sizeof(int)) ||
- (ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) ||
- (ply_type_size[PLY_USHORT] != sizeof(unsigned short)) ||
- (ply_type_size[PLY_UINT] != sizeof(unsigned int)) ||
- (ply_type_size[PLY_FLOAT] != sizeof(float)) ||
- (ply_type_size[PLY_DOUBLE] != sizeof(double)))
- {
- fprintf(stderr, "ply: Type sizes do not match built-in types\n");
- fprintf(stderr, "ply: Exiting...\n");
- exit(1);
- }
- return 1;
- }
- /******************************************************************************
- Get a text line from a file and break it up into words.
- IMPORTANT: The calling routine call "free" on the returned pointer once
- finished with it.
- Entry:
- fp - file to read from
- Exit:
- nwords - number of words returned
- orig_line - the original line of characters
- returns a list of words from the line, or NULL if end-of-file
- ******************************************************************************/
- inline char **get_words(FILE *fp, int *nwords, char **orig_line)
- {
- #define BIG_STRING 4096
- char str[BIG_STRING];
- char str_copy[BIG_STRING];
- char **words;
- int max_words = 10;
- int num_words = 0;
- char *ptr,*ptr2;
- char *result;
-
- fpos_t pos; //keep track of file pointer
- int nbytes;
- int nonUNIX;
- nonUNIX=0;
- nbytes=0;
- fgetpos(fp, &pos);
- words = (char **) myalloc (sizeof (char *) * max_words);
- /* read in a line */
- result = fgets (str, BIG_STRING, fp);
- if (result == NULL) {
- *nwords = 0;
- *orig_line = NULL;
- free(words);
- return (NULL);
- }
- /* convert line-feed and tabs into spaces */
- /* (this guarantees that there will be a space before the */
- /* null character at the end of the string) */
- str[BIG_STRING-2] = ' ';
- str[BIG_STRING-1] = '\0';
- for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
- *ptr2 = *ptr;
- nbytes++;
- if (*ptr == '\t') {
- *ptr = ' ';
- *ptr2 = ' ';
- }
- else if (*ptr == '\n') {
- *ptr = ' '; //has to have a space, to be caught later when grouping words
- *ptr2 = '\0';
- break;
- }
- else if (*ptr == '\r')
- { //MAC line break
- nonUNIX=1;
- if(*(ptr+1)=='\n') //actuall PC line break
- {
- nbytes++;
- }
-
- *ptr = ' ';
-
- *(ptr+1) = '\0'; //when reading mac, best end string here
- *ptr2 = '\0'; //note a pc \r is followed by \n
-
- break;
- }
- }
- /*check to see if a PC or MAC header was detected instead of UNIX*/
- if(nonUNIX==1)
- {
- fsetpos(fp, &pos);
- fseek(fp, nbytes, SEEK_CUR);
- }
- /* find the words in the line */
- ptr = str;
- while (*ptr != '\0') {
- /* jump over leading spaces */
- while (*ptr == ' ')
- ptr++;
- /* break if we reach the end */
- if (*ptr == '\0')
- break;
- /* save pointer to beginning of word */
- if (num_words >= max_words) {
- max_words += 10;
- char **temp = (char **) realloc (words, sizeof (char *) * max_words);
- if(temp){
- words = temp;
- }
- else{
- free(words);
- return NULL;
- }
- }
- words[num_words++] = ptr;
- /* jump over non-spaces */
- while (*ptr != ' ')
- ptr++;
- /* place a null character here to mark the end of the word */
- *ptr++ = '\0';
- }
- /* return the list of words */
- *nwords = num_words;
- *orig_line = str_copy; // ToDo: This looks like UB, returns pointer to local variable on stack.
- return (words);
- }
- /*
- char **get_words(FILE *fp, int *nwords, char **orig_line)
- {
- #define BIG_STRING 4096
- static char str[BIG_STRING];
- static char str_copy[BIG_STRING];
- char **words;
- int max_words = 10;
- int num_words = 0;
- char *ptr,*ptr2;
- char *result;
- words = (char **) myalloc (sizeof (char *) * max_words);
- // read in a line
- result = fgets (str, BIG_STRING, fp);
- if (result == NULL) {
- *nwords = 0;
- *orig_line = NULL;
- return (NULL);
- }
- // convert line-feed and tabs into spaces
- // (this guarantees that there will be a space before the
- // null character at the end of the string)
- str[BIG_STRING-2] = ' ';
- str[BIG_STRING-1] = '\0';
- for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) {
- *ptr2 = *ptr;
- if (*ptr == '\t') {
- *ptr = ' ';
- *ptr2 = ' ';
- }
- else if (*ptr == '\n') {
- *ptr = ' ';
- *ptr2 = '\0';
- break;
- }
- else if (*ptr == '\r') {
- *ptr = '\0';
- *ptr2 = '\0'; //note don't break yet, on a pc \r is followed by \n
- }
- }
- // find the words in the line
- ptr = str;
- while (*ptr != '\0') {
- // jump over leading spaces
- while (*ptr == ' ')
- ptr++;
- // break if we reach the end
- if (*ptr == '\0')
- break;
- // save pointer to beginning of word
- if (num_words >= max_words) {
- max_words += 10;
- words = (char **) realloc (words, sizeof (char *) * max_words);
- }
- words[num_words++] = ptr;
- // jump over non-spaces
- while (*ptr != ' ')
- ptr++;
- // place a null character here to mark the end of the word
- *ptr++ = '\0';
- }
- // return the list of words
- *nwords = num_words;
- *orig_line = str_copy;
- return (words);
- }*/
- /******************************************************************************
- Return the value of an item, given a pointer to it and its type.
- Entry:
- item - pointer to item
- type - data type that "item" points to
- Exit:
- returns a double-precision float that contains the value of the item
- ******************************************************************************/
- inline double get_item_value(char *item, int type)
- {
- unsigned char *puchar;
- char *pchar;
- short int *pshort;
- unsigned short int *pushort;
- int *pint;
- unsigned int *puint;
- float *pfloat;
- double *pdouble;
- int int_value;
- unsigned int uint_value;
- double double_value;
- switch (type) {
- case PLY_CHAR:
- pchar = (char *) item;
- int_value = *pchar;
- return ((double) int_value);
- case PLY_UCHAR:
- puchar = (unsigned char *) item;
- int_value = *puchar;
- return ((double) int_value);
- case PLY_SHORT:
- pshort = (short int *) item;
- int_value = *pshort;
- return ((double) int_value);
- case PLY_USHORT:
- pushort = (unsigned short int *) item;
- int_value = *pushort;
- return ((double) int_value);
- case PLY_INT:
- pint = (int *) item;
- int_value = *pint;
- return ((double) int_value);
- case PLY_UINT:
- puint = (unsigned int *) item;
- uint_value = *puint;
- return ((double) uint_value);
- case PLY_FLOAT:
- pfloat = (float *) item;
- double_value = *pfloat;
- return (double_value);
- case PLY_DOUBLE:
- pdouble = (double *) item;
- double_value = *pdouble;
- return (double_value);
- default:
- fprintf (stderr, "get_item_value: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Write out an item to a file as raw binary bytes.
- Entry:
- fp - file to write to
- int_val - integer version of item
- uint_val - unsigned integer version of item
- double_val - double-precision float version of item
- type - data type to write out
- ******************************************************************************/
- inline void write_binary_item(
- FILE *fp,
- int file_type,
- int int_val,
- unsigned int uint_val,
- double double_val,
- int type,
- int *native_binary_type
- )
- {
- unsigned char uchar_val;
- char char_val;
- unsigned short ushort_val;
- short short_val;
- float float_val;
- void *value;
-
- switch (type) {
- case PLY_CHAR:
- char_val = int_val;
- value = &char_val;
- break;
- case PLY_SHORT:
- short_val = int_val;
- value = &short_val;
- break;
- case PLY_INT:
- value = &int_val;
- break;
- case PLY_UCHAR:
- uchar_val = uint_val;
- value = &uchar_val;
- break;
- case PLY_USHORT:
- ushort_val = uint_val;
- value = &ushort_val;
- break;
- case PLY_UINT:
- value = &uint_val;
- break;
- case PLY_FLOAT:
- float_val = double_val;
- value = &float_val;
- break;
- case PLY_DOUBLE:
- value = &double_val;
- break;
- default:
- fprintf (stderr, "write_binary_item: bad type = %d\n", type);
- exit (-1);
- }
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
- swap_bytes((char *)value, ply_type_size[type]);
-
- if (fwrite (value, ply_type_size[type], 1, fp) != 1)
- {
- fprintf(stderr, "PLY ERROR: fwrite() failed -- aborting.\n");
- exit(1);
- }
- }
- /******************************************************************************
- Write out an item to a file as ascii characters.
- Entry:
- fp - file to write to
- int_val - integer version of item
- uint_val - unsigned integer version of item
- double_val - double-precision float version of item
- type - data type to write out
- ******************************************************************************/
- inline void write_ascii_item(
- FILE *fp,
- int int_val,
- unsigned int uint_val,
- double double_val,
- int type
- )
- {
- switch (type) {
- case PLY_CHAR:
- case PLY_SHORT:
- case PLY_INT:
- if (fprintf (fp, "%d ", int_val) <= 0)
- {
- fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
- exit(1);
- }
- break;
- case PLY_UCHAR:
- case PLY_USHORT:
- case PLY_UINT:
- if (fprintf (fp, "%u ", uint_val) <= 0)
- {
- fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
- exit(1);
- }
- break;
- case PLY_FLOAT:
- case PLY_DOUBLE:
- if (fprintf (fp, "%g ", double_val) <= 0)
- {
- fprintf(stderr, "PLY ERROR: fprintf() failed -- aborting.\n");
- exit(1);
- }
- break;
- default:
- fprintf (stderr, "write_ascii_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Write out an item to a file as ascii characters.
- Entry:
- fp - file to write to
- item - pointer to item to write
- type - data type that "item" points to
- Exit:
- returns a double-precision float that contains the value of the written item
- ******************************************************************************/
- inline double old_write_ascii_item(FILE *fp, char *item, int type)
- {
- unsigned char *puchar;
- char *pchar;
- short int *pshort;
- unsigned short int *pushort;
- int *pint;
- unsigned int *puint;
- float *pfloat;
- double *pdouble;
- int int_value;
- unsigned int uint_value;
- double double_value;
- switch (type) {
- case PLY_CHAR:
- pchar = (char *) item;
- int_value = *pchar;
- fprintf (fp, "%d ", int_value);
- return ((double) int_value);
- case PLY_UCHAR:
- puchar = (unsigned char *) item;
- int_value = *puchar;
- fprintf (fp, "%d ", int_value);
- return ((double) int_value);
- case PLY_SHORT:
- pshort = (short int *) item;
- int_value = *pshort;
- fprintf (fp, "%d ", int_value);
- return ((double) int_value);
- case PLY_USHORT:
- pushort = (unsigned short int *) item;
- int_value = *pushort;
- fprintf (fp, "%d ", int_value);
- return ((double) int_value);
- case PLY_INT:
- pint = (int *) item;
- int_value = *pint;
- fprintf (fp, "%d ", int_value);
- return ((double) int_value);
- case PLY_UINT:
- puint = (unsigned int *) item;
- uint_value = *puint;
- fprintf (fp, "%u ", uint_value);
- return ((double) uint_value);
- case PLY_FLOAT:
- pfloat = (float *) item;
- double_value = *pfloat;
- fprintf (fp, "%g ", double_value);
- return (double_value);
- case PLY_DOUBLE:
- pdouble = (double *) item;
- double_value = *pdouble;
- fprintf (fp, "%g ", double_value);
- return (double_value);
- default:
- fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Get the value of an item that is in memory, and place the result
- into an integer, an unsigned integer and a double.
- Entry:
- ptr - pointer to the item
- type - data type supposedly in the item
- Exit:
- int_val - integer value
- uint_val - unsigned integer value
- double_val - double-precision floating point value
- ******************************************************************************/
- inline void get_stored_item(
- void *ptr,
- int type,
- int *int_val,
- unsigned int *uint_val,
- double *double_val
- )
- {
- switch (type) {
- case PLY_CHAR:
- *int_val = *((char *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_UCHAR:
- *uint_val = *((unsigned char *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_SHORT:
- *int_val = *((short int *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_USHORT:
- *uint_val = *((unsigned short int *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_INT:
- *int_val = *((int *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_UINT:
- *uint_val = *((unsigned int *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_FLOAT:
- *double_val = *((float *) ptr);
- *int_val = (int) *double_val;
- *uint_val = (unsigned int) *double_val;
- break;
- case PLY_DOUBLE:
- *double_val = *((double *) ptr);
- *int_val = (int) *double_val;
- *uint_val = (unsigned int) *double_val;
- break;
- default:
- fprintf (stderr, "get_stored_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Get the value of an item from a binary file, and place the result
- into an integer, an unsigned integer and a double.
- Entry:
- fp - file to get item from
- type - data type supposedly in the word
- Exit:
- int_val - integer value
- uint_val - unsigned integer value
- double_val - double-precision floating point value
- ******************************************************************************/
- inline void get_binary_item(
- FILE *fp,
- int file_type,
- int type,
- int *int_val,
- unsigned int *uint_val,
- double *double_val,
- int *native_binary_type
- )
- {
- char c[8];
- void *ptr;
- ptr = (void *) c;
- int ply_type_size[] = {
- 0, 1, 2, 4, 1, 2, 4, 4, 8
- };
- if (fread (ptr, ply_type_size[type], 1, fp) != 1)
- {
- fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n");
- exit(1);
- }
-
- if ((file_type != *native_binary_type) && (ply_type_size[type] > 1))
- swap_bytes((char *)ptr, ply_type_size[type]);
- switch (type) {
- case PLY_CHAR:
- *int_val = *((char *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_UCHAR:
- *uint_val = *((unsigned char *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_SHORT:
- *int_val = *((short int *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_USHORT:
- *uint_val = *((unsigned short int *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_INT:
- *int_val = *((int *) ptr);
- *uint_val = *int_val;
- *double_val = *int_val;
- break;
- case PLY_UINT:
- *uint_val = *((unsigned int *) ptr);
- *int_val = *uint_val;
- *double_val = *uint_val;
- break;
- case PLY_FLOAT:
- *double_val = *((float *) ptr);
- *int_val = (int) *double_val;
- *uint_val = (unsigned int) *double_val;
- break;
- case PLY_DOUBLE:
- *double_val = *((double *) ptr);
- *int_val = (int) *double_val;
- *uint_val = (unsigned int) *double_val;
- break;
- default:
- fprintf (stderr, "get_binary_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Extract the value of an item from an ascii word, and place the result
- into an integer, an unsigned integer and a double.
- Entry:
- word - word to extract value from
- type - data type supposedly in the word
- Exit:
- int_val - integer value
- uint_val - unsigned integer value
- double_val - double-precision floating point value
- ******************************************************************************/
- inline void get_ascii_item(
- char *word,
- int type,
- int *int_val,
- unsigned int *uint_val,
- double *double_val
- )
- {
- switch (type) {
- case PLY_CHAR:
- case PLY_UCHAR:
- case PLY_SHORT:
- case PLY_USHORT:
- case PLY_INT:
- *int_val = atoi (word);
- *uint_val = (unsigned int) *int_val;
- *double_val = (double) *int_val;
- break;
- case PLY_UINT:
- *uint_val = strtol (word, (char **) NULL, 10);
- *int_val = (int) *uint_val;
- *double_val = (double) *uint_val;
- break;
- case PLY_FLOAT:
- case PLY_DOUBLE:
- *double_val = atof (word);
- *int_val = (int) *double_val;
- *uint_val = (unsigned int) *double_val;
- break;
- default:
- fprintf (stderr, "get_ascii_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Store a value into a place being pointed to, guided by a data type.
- Entry:
- item - place to store value
- type - data type
- int_val - integer version of value
- uint_val - unsigned integer version of value
- double_val - double version of value
- Exit:
- item - pointer to stored value
- ******************************************************************************/
- inline void store_item (
- char *item,
- int type,
- int int_val,
- unsigned int uint_val,
- double double_val
- )
- {
- unsigned char *puchar;
- short int *pshort;
- unsigned short int *pushort;
- int *pint;
- unsigned int *puint;
- float *pfloat;
- double *pdouble;
- switch (type) {
- case PLY_CHAR:
- *item = int_val;
- break;
- case PLY_UCHAR:
- puchar = (unsigned char *) item;
- *puchar = uint_val;
- break;
- case PLY_SHORT:
- pshort = (short *) item;
- *pshort = int_val;
- break;
- case PLY_USHORT:
- pushort = (unsigned short *) item;
- *pushort = uint_val;
- break;
- case PLY_INT:
- pint = (int *) item;
- *pint = int_val;
- break;
- case PLY_UINT:
- puint = (unsigned int *) item;
- *puint = uint_val;
- break;
- case PLY_FLOAT:
- pfloat = (float *) item;
- *pfloat = double_val;
- break;
- case PLY_DOUBLE:
- pdouble = (double *) item;
- *pdouble = double_val;
- break;
- default:
- fprintf (stderr, "store_item: bad type = %d\n", type);
- exit (-1);
- }
- }
- /******************************************************************************
- Add an element to a PLY file descriptor.
- Entry:
- plyfile - PLY file descriptor
- words - list of words describing the element
- nwords - number of words in the list
- ******************************************************************************/
- inline void add_element (PlyFile *plyfile, char **words)
- {
- PlyElement *elem;
- /* create the new element */
- elem = (PlyElement *) myalloc (sizeof (PlyElement));
- elem->name = strdup (words[1]);
- elem->num = atoi (words[2]);
- elem->nprops = 0;
- /* make room for new element in the object's list of elements */
- if (plyfile->nelems == 0)
- plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *));
- else
- plyfile->elems = (PlyElement **) realloc (plyfile->elems,
- sizeof (PlyElement *) * (plyfile->nelems + 1));
- /* add the new element to the object's list */
- plyfile->elems[plyfile->nelems] = elem;
- plyfile->nelems++;
- }
- /******************************************************************************
- Return the type of a property, given the name of the property.
- Entry:
- name - name of property type
- Exit:
- returns integer code for property, or 0 if not found
- ******************************************************************************/
- inline int get_prop_type(char *type_name)
- {
- int i;
- const char *type_names[] = {
- "invalid",
- "char", "short", "int",
- "uchar", "ushort", "uint",
- "float", "double",
- };
-
- const char *alt_type_names[] = {
- "invalid",
- "int8", "int16", "int32", "uint8", "uint16", "uint32", "float32", "float64",
- };
- for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
- if (equal_strings (type_name, type_names[i]))
- return (i);
- for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++)
- if (equal_strings (type_name, alt_type_names[i]))
- return (i);
- /* if we get here, we didn't find the type */
- return (0);
- }
- /******************************************************************************
- Add a property to a PLY file descriptor.
- Entry:
- plyfile - PLY file descriptor
- words - list of words describing the property
- nwords - number of words in the list
- ******************************************************************************/
- inline void add_property (PlyFile *plyfile, char **words)
- {
- PlyProperty *prop;
- PlyElement *elem;
- /* create the new property */
- prop = (PlyProperty *) myalloc (sizeof (PlyProperty));
- if (equal_strings (words[1], "list")) { /* is a list */
- prop->count_external = get_prop_type (words[2]);
- prop->external_type = get_prop_type (words[3]);
- prop->name = strdup (words[4]);
- prop->is_list = 1;
- }
- else { /* not a list */
- prop->external_type = get_prop_type (words[1]);
- prop->name = strdup (words[2]);
- prop->is_list = 0;
- }
- /* add this property to the list of properties of the current element */
- elem = plyfile->elems[plyfile->nelems - 1];
- if (elem->nprops == 0)
- elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *));
- else
- elem->props = (PlyProperty **) realloc (elem->props,
- sizeof (PlyProperty *) * (elem->nprops + 1));
- elem->props[elem->nprops] = prop;
- elem->nprops++;
- }
- /******************************************************************************
- Add a comment to a PLY file descriptor.
- Entry:
- plyfile - PLY file descriptor
- line - line containing comment
- ******************************************************************************/
- inline void add_comment (PlyFile *plyfile, char *line)
- {
- int i;
- /* skip over "comment" and leading spaces and tabs */
- i = 7;
- while (line[i] == ' ' || line[i] == '\t')
- i++;
- ply_put_comment (plyfile, &line[i]);
- }
- /******************************************************************************
- Add a some object information to a PLY file descriptor.
- Entry:
- plyfile - PLY file descriptor
- line - line containing text info
- ******************************************************************************/
- inline void add_obj_info (PlyFile *plyfile, char *line)
- {
- int i;
- /* skip over "obj_info" and leading spaces and tabs */
- i = 8;
- while (line[i] == ' ' || line[i] == '\t')
- i++;
- ply_put_obj_info (plyfile, &line[i]);
- }
- /******************************************************************************
- Copy a property.
- ******************************************************************************/
- inline void copy_property(PlyProperty *dest, PlyProperty *src)
- {
- dest->name = strdup (src->name);
- dest->external_type = src->external_type;
- dest->internal_type = src->internal_type;
- dest->offset = src->offset;
- dest->is_list = src->is_list;
- dest->count_external = src->count_external;
- dest->count_internal = src->count_internal;
- dest->count_offset = src->count_offset;
- }
- /******************************************************************************
- Allocate some memory.
- Entry:
- size - amount of memory requested (in bytes)
- lnum - line number from which memory was requested
- fname - file name from which memory was requested
- ******************************************************************************/
- inline char *my_alloc(int size, int lnum, const char *fe)
- {
- char *ptr;
- ptr = (char *) malloc (size);
- if (ptr == 0) {
- fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fe);
- }
- return (ptr);
- }
- }
- }
- #endif
|