⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rply.c

📁 游戏编程精粹6中关于用自适度二叉树进行空间剖分
💻 C
📖 第 1 页 / 共 4 页
字号:
/* ---------------------------------------------------------------------- * RPly library, read/write PLY files * Diego Nehab, Princeton University * http://www.cs.princeton.edu/~diego/professional/rply * * This library is distributed under the MIT License. See notice * at the end of this file. * ---------------------------------------------------------------------- */#include <stdio.h>#include <ctype.h>#include <assert.h>#include <string.h>#include <limits.h>#include <float.h>#include <stdarg.h>#include <stdlib.h>#include <stddef.h>#include "rply.h"/* ---------------------------------------------------------------------- * Constants  * ---------------------------------------------------------------------- */#define WORDSIZE 256#define LINESIZE 1024#define BUFFERSIZE (8*1024)typedef enum e_ply_io_mode_ {    PLY_READ,     PLY_WRITE} e_ply_io_mode;static const char *const ply_storage_mode_list[] = {    "binary_big_endian", "binary_little_endian", "ascii", NULL};     /* order matches e_ply_storage_mode enum */static const char *const ply_type_list[] = {    "int8", "uint8", "int16", "uint16",     "int32", "uint32", "float32", "float64",    "char", "uchar", "short", "ushort",     "int", "uint", "float", "double",    "list", NULL};     /* order matches e_ply_type enum *//* ---------------------------------------------------------------------- * Property reading callback argument * * element: name of element being processed * property: name of property being processed * nelements: number of elements of this kind in file * instance_index: index current element of this kind being processed * length: number of values in current list (or 1 for scalars) * value_index: index of current value int this list (or 0 for scalars) * value: value of property * pdata/idata: user data defined with ply_set_cb * * Returns handle to ply file if succesful, NULL otherwise. * ---------------------------------------------------------------------- */typedef struct t_ply_argument_ {    p_ply_element element;    long instance_index;    p_ply_property property;    long length, value_index;    double value;    void *pdata;    long idata;} t_ply_argument;/* ---------------------------------------------------------------------- * Property information * * name: name of this property * type: type of this property (list or type of scalar value) * length_type, value_type: type of list property count and values * read_cb: function to be called when this property is called * * Returns 1 if should continue processing file, 0 if should abort. * ---------------------------------------------------------------------- */typedef struct t_ply_property_ {    char name[WORDSIZE];    e_ply_type type, value_type, length_type;    p_ply_read_cb read_cb;    void *pdata;    long idata;} t_ply_property; /* ---------------------------------------------------------------------- * Element information * * name: name of this property * ninstances: number of elements of this type in file * property: property descriptions for this element * nproperty: number of properties in this element * * Returns 1 if should continue processing file, 0 if should abort. * ---------------------------------------------------------------------- */typedef struct t_ply_element_ {    char name[WORDSIZE];    long ninstances;    p_ply_property property;    long nproperties;} t_ply_element;/* ---------------------------------------------------------------------- * Input/output driver * * Depending on file mode, different functions are used to read/write  * property fields. The drivers make it transparent to read/write in ascii,  * big endian or little endian cases. * ---------------------------------------------------------------------- */typedef int (*p_ply_ihandler)(p_ply ply, double *value);typedef int (*p_ply_ichunk)(p_ply ply, void *anydata, size_t size);typedef struct t_ply_idriver_ {    p_ply_ihandler ihandler[16];    p_ply_ichunk ichunk;    const char *name;} t_ply_idriver;typedef t_ply_idriver *p_ply_idriver;typedef int (*p_ply_ohandler)(p_ply ply, double value);typedef int (*p_ply_ochunk)(p_ply ply, void *anydata, size_t size);typedef struct t_ply_odriver_ {    p_ply_ohandler ohandler[16];    p_ply_ochunk ochunk;    const char *name;} t_ply_odriver;typedef t_ply_odriver *p_ply_odriver;/* ---------------------------------------------------------------------- * Ply file handle.  * * io_mode: read or write (from e_ply_io_mode) * storage_mode: mode of file associated with handle (from e_ply_storage_mode) * element: elements description for this file * nelement: number of different elements in file * comment: comments for this file * ncomments: number of comments in file * obj_info: obj_info items for this file * nobj_infos: number of obj_info items in file * fp: file pointer associated with ply file * c: last character read from ply file * buffer: last word/chunck of data read from ply file * buffer_first, buffer_last: interval of untouched good data in buffer * buffer_token: start of parsed token (line or word) in buffer * idriver, odriver: input driver used to get property fields from file  * argument: storage space for callback arguments * welement, wproperty: element/property type being written * winstance_index: index of instance of current element being written * wvalue_index: index of list property value being written  * wlength: number of values in list property being written * error_cb: callback for error messages * ---------------------------------------------------------------------- */typedef struct t_ply_ {    e_ply_io_mode io_mode;    e_ply_storage_mode storage_mode;    p_ply_element element;    long nelements;    char *comment;    long ncomments;    char *obj_info;    long nobj_infos;    FILE *fp;    int c;    char buffer[BUFFERSIZE];    size_t buffer_first, buffer_token, buffer_last;    p_ply_idriver idriver;    p_ply_odriver odriver;    t_ply_argument argument;    long welement, wproperty;    long winstance_index, wvalue_index, wlength;    p_ply_error_cb error_cb;} t_ply;/* ---------------------------------------------------------------------- * I/O functions and drivers * ---------------------------------------------------------------------- */static t_ply_idriver ply_idriver_ascii;static t_ply_idriver ply_idriver_binary;static t_ply_idriver ply_idriver_binary_reverse;static t_ply_odriver ply_odriver_ascii;static t_ply_odriver ply_odriver_binary;static t_ply_odriver ply_odriver_binary_reverse;static int ply_read_word(p_ply ply);static int ply_check_word(p_ply ply);static int ply_read_line(p_ply ply);static int ply_check_line(p_ply ply);static int ply_read_chunk(p_ply ply, void *anybuffer, size_t size);static int ply_read_chunk_reverse(p_ply ply, void *anybuffer, size_t size);static int ply_write_chunk(p_ply ply, void *anybuffer, size_t size);static int ply_write_chunk_reverse(p_ply ply, void *anybuffer, size_t size);static void ply_reverse(void *anydata, size_t size);/* ---------------------------------------------------------------------- * String functions * ---------------------------------------------------------------------- */static int ply_find_string(const char *item, const char* const list[]);static p_ply_element ply_find_element(p_ply ply, const char *name);static p_ply_property ply_find_property(p_ply_element element,         const char *name);/* ---------------------------------------------------------------------- * Header parsing * ---------------------------------------------------------------------- */static int ply_read_header_format(p_ply ply);static int ply_read_header_comment(p_ply ply);static int ply_read_header_obj_info(p_ply ply);static int ply_read_header_property(p_ply ply);static int ply_read_header_element(p_ply ply);/* ---------------------------------------------------------------------- * Error handling * ---------------------------------------------------------------------- */static void ply_error_cb(const char *message);static void ply_error(p_ply ply, const char *fmt, ...);/* ---------------------------------------------------------------------- * Memory allocation and initialization * ---------------------------------------------------------------------- */static void ply_init(p_ply ply);static void ply_element_init(p_ply_element element);static void ply_property_init(p_ply_property property);static p_ply ply_alloc(void);static p_ply_element ply_grow_element(p_ply ply);static p_ply_property ply_grow_property(p_ply ply, p_ply_element element);static void *ply_grow_array(p_ply ply, void **pointer, long *nmemb, long size);/* ---------------------------------------------------------------------- * Special functions * ---------------------------------------------------------------------- */static e_ply_storage_mode ply_arch_endian(void);static int ply_type_check(void); /* ---------------------------------------------------------------------- * Auxiliary read functions * ---------------------------------------------------------------------- */static int ply_read_element(p_ply ply, p_ply_element element,         p_ply_argument argument);static int ply_read_property(p_ply ply, p_ply_element element,         p_ply_property property, p_ply_argument argument);static int ply_read_list_property(p_ply ply, p_ply_element element,         p_ply_property property, p_ply_argument argument);static int ply_read_scalar_property(p_ply ply, p_ply_element element,         p_ply_property property, p_ply_argument argument);/* ---------------------------------------------------------------------- * Buffer support functions * ---------------------------------------------------------------------- *//* pointers to tokenized word and line in buffer */#define BWORD(p) (p->buffer + p->buffer_token)#define BLINE(p) (p->buffer + p->buffer_token)/* pointer to start of untouched bytes in buffer */#define BFIRST(p) (p->buffer + p->buffer_first) /* number of bytes untouched in buffer */#define BSIZE(p) (p->buffer_last - p->buffer_first) /* consumes data from buffer */#define BSKIP(p, s) (p->buffer_first += s)/* refills the buffer */static int BREFILL(p_ply ply) {    /* move untouched data to beginning of buffer */    size_t size = BSIZE(ply);    memmove(ply->buffer, BFIRST(ply), size);    ply->buffer_last = size;    ply->buffer_first = ply->buffer_token = 0;    /* fill remaining with new data */    size = fread(ply->buffer+size, 1, BUFFERSIZE-size-1, ply->fp);    /* place sentinel so we can use str* functions with buffer */    ply->buffer[BUFFERSIZE-1] = '\0';    /* check if read failed */    if (size <= 0) return 0;    /* increase size to account for new data */    ply->buffer_last += size;    return 1;}/* ---------------------------------------------------------------------- * Exported functions * ---------------------------------------------------------------------- *//* ---------------------------------------------------------------------- * Read support functions * ---------------------------------------------------------------------- */p_ply ply_open(const char *name, p_ply_error_cb error_cb) {    char magic[5] = "    ";    FILE *fp = NULL;     p_ply ply = NULL;    if (error_cb == NULL) error_cb = ply_error_cb;    if (!ply_type_check()) {        error_cb("Incompatible type system");        return NULL;    }    assert(name);    fp = fopen(name, "rb");    if (!fp) {        error_cb("Unable to open file");        return NULL;    }    if (fread(magic, 1, 4, fp) < 4) {        error_cb("Error reading from file");        fclose(fp);        return NULL;    }    if (strcmp(magic, "ply\n")) {        fclose(fp);        error_cb("Not a PLY file. Expected magic number 'ply\\n'");        return NULL;    }    ply = ply_alloc();    if (!ply) {        error_cb("Out of memory");        fclose(fp);        return NULL;    }    ply->fp = fp;    ply->io_mode = PLY_READ;    ply->error_cb = error_cb;    return ply;}int ply_read_header(p_ply ply) {    assert(ply && ply->fp && ply->io_mode == PLY_READ);    if (!ply_read_word(ply)) return 0;    /* parse file format */    if (!ply_read_header_format(ply)) {        ply_error(ply, "Invalid file format");        return 0;    }    /* parse elements, comments or obj_infos until the end of header */    while (strcmp(BWORD(ply), "end_header")) {        if (!ply_read_header_comment(ply) &&                 !ply_read_header_element(ply) &&                 !ply_read_header_obj_info(ply)) {            ply_error(ply, "Unexpected token '%s'", BWORD(ply));            return 0;        }    }    return 1;}long ply_set_read_cb(p_ply ply, const char *element_name,         const char* property_name, p_ply_read_cb read_cb,         void *pdata, long idata) {    p_ply_element element = NULL;     p_ply_property property = NULL;    assert(ply && element_name && property_name);    element = ply_find_element(ply, element_name);    if (!element) return 0;    property = ply_find_property(element, property_name);    if (!property) return 0;    property->read_cb = read_cb;    property->pdata = pdata;    property->idata = idata;    return (int) element->ninstances;}int ply_read(p_ply ply) {    long i;    p_ply_argument argument;    assert(ply && ply->fp && ply->io_mode == PLY_READ);    argument = &ply->argument;    /* for each element type */    for (i = 0; i < ply->nelements; i++) {        p_ply_element element = &ply->element[i];        argument->element = element;        if (!ply_read_element(ply, element, argument))            return 0;    }    return 1;}/* ----------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -