diff --git a/src/external/tinyobj_loader_c.h b/src/external/tinyobj_loader_c.h index 4b51be4b0..242b47d85 100644 --- a/src/external/tinyobj_loader_c.h +++ b/src/external/tinyobj_loader_c.h @@ -24,8 +24,8 @@ #ifndef TINOBJ_LOADER_C_H_ #define TINOBJ_LOADER_C_H_ -/* @todo { Remove stddef dependency. size_t? } */ -#include +/* @todo { Remove stddef dependency. unsigned int? } ---> RAY: DONE. */ +//#include typedef struct { char *name; @@ -87,57 +87,24 @@ typedef struct { #define TINYOBJ_ERROR_INVALID_PARAMETER (-2) #define TINYOBJ_ERROR_FILE_OPERATION (-3) -/* Provide a callback that can read text file without any parsing or modification. - * The obj and mtl parser is going to read all the necessary data: - * tinyobj_parse_obj - * tinyobj_parse_mtl_file - * - * @param[in] filename Filename to be loaded. - * @param[in] is_mtl 1 when the callback is invoked for loading .mtl. 0 for .obj - * @param[in] obj_filename .obj filename. Useful when you load .mtl from same location of .obj. When the callback is called to load .obj, `filename` and `obj_filename` are same. - * @param[out] buf Content of loaded file - * @param[out] len Size of content(file) - */ -typedef void (*file_reader_callback)(const char *filename, int is_mtl, const char *obj_filename, char **buf, size_t *len); - -/* Parse wavefront .obj - * @param[out] attrib Attibutes - * @param[out] shapes Array of parsed shapes - * @param[out] num_shapes Array length of `shapes` - * @param[out] materials Array of parsed materials - * @param[out] num_materials Array length of `materials` - * @param[in] file_name File name of .obj - * @param[in] file_reader File reader callback function(to read .obj and .mtl). - * @param[in] flags combination of TINYOBJ_FLAG_*** - * +/* Parse wavefront .obj(.obj string data is expanded to linear char array `buf') + * flags are combination of TINYOBJ_FLAG_*** * Returns TINYOBJ_SUCCESS if things goes well. * Returns TINYOBJ_ERR_*** when there is an error. */ extern int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, - size_t *num_shapes, tinyobj_material_t **materials, - size_t *num_materials, const char *file_name, file_reader_callback file_reader, + unsigned int *num_shapes, tinyobj_material_t **materials, + unsigned int *num_materials, const char *buf, unsigned int len, unsigned int flags); - -/* Parse wavefront .mtl - * - * @param[out] materials_out - * @param[out] num_materials_out - * @param[in] filename .mtl filename - * @param[in] filename of .obj filename. could be NULL if you just want to parse .mtl file. - * @param[in] file_reader File reader callback - - * Returns TINYOBJ_SUCCESS if things goes well. - * Returns TINYOBJ_ERR_*** when there is an error. - */ extern int tinyobj_parse_mtl_file(tinyobj_material_t **materials_out, - size_t *num_materials_out, - const char *filename, const char *obj_filename, file_reader_callback file_reader); + unsigned int *num_materials_out, + const char *filename); extern void tinyobj_attrib_init(tinyobj_attrib_t *attrib); extern void tinyobj_attrib_free(tinyobj_attrib_t *attrib); -extern void tinyobj_shapes_free(tinyobj_shape_t *shapes, size_t num_shapes); +extern void tinyobj_shapes_free(tinyobj_shape_t *shapes, unsigned int num_shapes); extern void tinyobj_materials_free(tinyobj_material_t *materials, - size_t num_materials); + unsigned int num_materials); #ifdef TINYOBJ_LOADER_C_IMPLEMENTATION #include @@ -162,7 +129,6 @@ extern void tinyobj_materials_free(tinyobj_material_t *materials, #endif #define TINYOBJ_MAX_FACES_PER_F_LINE (16) -#define TINYOBJ_MAX_FILEPATH (8192) #define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) #define IS_DIGIT(x) ((unsigned int)((x) - '0') < (unsigned int)(10)) @@ -189,8 +155,8 @@ static int until_space(const char *token) { return (int)(p - token); } -static size_t length_until_newline(const char *token, size_t n) { - size_t len = 0; +static unsigned int length_until_newline(const char *token, unsigned int n) { + unsigned int len = 0; /* Assume token[n-1] = '\0' */ for (len = 0; len < n - 1; len++) { @@ -205,8 +171,8 @@ static size_t length_until_newline(const char *token, size_t n) { return len; } -static size_t length_until_line_feed(const char *token, size_t n) { - size_t len = 0; +static unsigned int length_until_line_feed(const char *token, unsigned int n) { + unsigned int len = 0; /* Assume token[n-1] = '\0' */ for (len = 0; len < n; len++) { @@ -236,7 +202,7 @@ static int my_atoi(const char *c) { } /* Make index zero-base, and also support relative index. */ -static int fixIndex(int idx, size_t n) { +static int fixIndex(int idx, unsigned int n) { if (idx > 0) return idx - 1; if (idx == 0) return 0; return (int)n + idx; /* negative value = relative */ @@ -487,14 +453,14 @@ static void parseFloat3(float *x, float *y, float *z, const char **token) { (*z) = parseFloat(token); } -static size_t my_strnlen(const char *s, size_t n) { +static unsigned int my_strnlen(const char *s, unsigned int n) { const char *p = memchr(s, 0, n); - return p ? (size_t)(p - s) : n; + return p ? (unsigned int)(p - s) : n; } -static char *my_strdup(const char *s, size_t max_length) { +static char *my_strdup(const char *s, unsigned int max_length) { char *d; - size_t len; + unsigned int len; if (s == NULL) return NULL; @@ -504,15 +470,15 @@ static char *my_strdup(const char *s, size_t max_length) { /* trim line ending and append '\0' */ d = (char *)TINYOBJ_MALLOC(len + 1); /* + '\0' */ - memcpy(d, s, (size_t)(len)); + memcpy(d, s, (unsigned int)(len)); d[len] = '\0'; return d; } -static char *my_strndup(const char *s, size_t len) { +static char *my_strndup(const char *s, unsigned int len) { char *d; - size_t slen; + unsigned int slen; if (s == NULL) return NULL; if (len == 0) return NULL; @@ -528,36 +494,10 @@ static char *my_strndup(const char *s, size_t len) { return d; } -static char *my_joinpath(const char *s, const char *t, const char delim, size_t max_len) { - char *d; - size_t slen; - size_t tlen; - size_t len; - - if ((s == NULL) && (t == NULL)) return NULL; - if (max_len == 0) return NULL; - - slen = my_strnlen(s, max_len); - tlen = my_strnlen(t, max_len); - len = slen + tlen + 1; /* +1 for delimiter */ - - d = (char *)TINYOBJ_MALLOC(len + 1); /* + '\0' */ - if (!d) { - return NULL; - } - memcpy(d, s, slen); - d[slen] = delim; - memcpy(d + slen +1, t, tlen); - - d[len] = '\0'; - - return d; -} - -char *dynamic_fgets(char **buf, size_t *size, FILE *file) { +char *dynamic_fgets(char **buf, unsigned int *size, FILE *file) { char *offset; char *ret; - size_t old_size; + unsigned int old_size; if (!(ret = fgets(*buf, (int)*size, file))) { return ret; @@ -604,7 +544,7 @@ static void initMaterial(tinyobj_material_t *material) { /* Implementation of string to int hashtable */ -#define HASH_TABLE_ERROR 1 +#define HASH_TABLE_ERROR 1 #define HASH_TABLE_SUCCESS 0 #define HASH_TABLE_DEFAULT_SIZE 10 @@ -623,8 +563,8 @@ typedef struct { unsigned long* hashes; hash_table_entry_t* entries; - size_t capacity; - size_t n; + unsigned int capacity; + unsigned int n; } hash_table_t; static unsigned long hash_djb2(const unsigned char* str) @@ -639,7 +579,7 @@ static unsigned long hash_djb2(const unsigned char* str) return hash; } -static void create_hash_table(size_t start_capacity, hash_table_t* hash_table) +static void create_hash_table(unsigned int start_capacity, hash_table_t* hash_table) { if (start_capacity < 1) start_capacity = HASH_TABLE_DEFAULT_SIZE; @@ -659,17 +599,17 @@ static void destroy_hash_table(hash_table_t* hash_table) static int hash_table_insert_value(unsigned long hash, long value, hash_table_t* hash_table) { /* Insert value */ - size_t start_index = hash % hash_table->capacity; - size_t index = start_index; + unsigned int start_index = hash % hash_table->capacity; + unsigned int index = start_index; hash_table_entry_t* start_entry = hash_table->entries + start_index; - size_t i; + unsigned int i; hash_table_entry_t* entry; for (i = 1; hash_table->entries[index].filled; i++) { if (i >= hash_table->capacity) return HASH_TABLE_ERROR; - index = (start_index + (i * i)) % hash_table->capacity; + index = (start_index + (i * i)) % hash_table->capacity; } entry = hash_table->entries + index; @@ -711,11 +651,11 @@ static hash_table_entry_t* hash_table_find(unsigned long hash, hash_table_t* has return NULL; } -static void hash_table_maybe_grow(size_t new_n, hash_table_t* hash_table) +static void hash_table_maybe_grow(unsigned int new_n, hash_table_t* hash_table) { - size_t new_capacity; + unsigned int new_capacity; hash_table_t new_hash_table; - size_t i; + unsigned int i; if (new_n <= hash_table->capacity) { return; @@ -743,7 +683,7 @@ static int hash_table_exists(const char* name, hash_table_t* hash_table) return hash_table_find(hash_djb2((const unsigned char*)name), hash_table) != NULL; } -static void hash_table_set(const char* name, size_t val, hash_table_t* hash_table) +static void hash_table_set(const char* name, unsigned int val, hash_table_t* hash_table) { /* Hash name */ unsigned long hash = hash_djb2((const unsigned char *)name); @@ -772,7 +712,7 @@ static long hash_table_get(const char* name, hash_table_t* hash_table) } static tinyobj_material_t *tinyobj_material_add(tinyobj_material_t *prev, - size_t num_materials, + unsigned int num_materials, tinyobj_material_t *new_mat) { tinyobj_material_t *dst; dst = (tinyobj_material_t *)TINYOBJ_REALLOC( @@ -782,81 +722,18 @@ static tinyobj_material_t *tinyobj_material_add(tinyobj_material_t *prev, return dst; } -static int is_line_ending(const char *p, size_t i, size_t end_i) { - if (p[i] == '\0') return 1; - if (p[i] == '\n') return 1; /* this includes \r\n */ - if (p[i] == '\r') { - if (((i + 1) < end_i) && (p[i + 1] != '\n')) { /* detect only \r case */ - return 1; - } - } - return 0; -} - -typedef struct { - size_t pos; - size_t len; -} LineInfo; - -/* Find '\n' and create line data. */ -static int get_line_infos(const char *buf, size_t buf_len, LineInfo **line_infos, size_t *num_lines) -{ - size_t i = 0; - size_t end_idx = buf_len; - size_t prev_pos = 0; - size_t line_no = 0; - size_t last_line_ending = 0; - - /* Count # of lines. */ - for (i = 0; i < end_idx; i++) { - if (is_line_ending(buf, i, end_idx)) { - (*num_lines)++; - last_line_ending = i; - } - } - /* The last char from the input may not be a line - * ending character so add an extra line if there - * are more characters after the last line ending - * that was found. */ - if (end_idx - last_line_ending > 0) { - (*num_lines)++; - } - - if (*num_lines == 0) return TINYOBJ_ERROR_EMPTY; - - *line_infos = (LineInfo *)TINYOBJ_MALLOC(sizeof(LineInfo) * (*num_lines)); - - /* Fill line infos. */ - for (i = 0; i < end_idx; i++) { - if (is_line_ending(buf, i, end_idx)) { - (*line_infos)[line_no].pos = prev_pos; - (*line_infos)[line_no].len = i - prev_pos; - prev_pos = i + 1; - line_no++; - } - } - if (end_idx - last_line_ending > 0) { - (*line_infos)[line_no].pos = prev_pos; - (*line_infos)[line_no].len = end_idx - 1 - last_line_ending; - } - - return 0; -} - static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out, - size_t *num_materials_out, - const char *mtl_filename, const char *obj_filename, file_reader_callback file_reader, + unsigned int *num_materials_out, + const char *filename, hash_table_t* material_table) { tinyobj_material_t material; - size_t num_materials = 0; + unsigned int buffer_size = 128; + char *linebuf; + FILE *fp; + unsigned int num_materials = 0; tinyobj_material_t *materials = NULL; int has_previous_material = 0; const char *line_end = NULL; - size_t num_lines = 0; - LineInfo *line_infos = NULL; - size_t i = 0; - char *buf = NULL; - size_t len = 0; if (materials_out == NULL) { return TINYOBJ_ERROR_INVALID_PARAMETER; @@ -869,30 +746,20 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out, (*materials_out) = NULL; (*num_materials_out) = 0; - file_reader(mtl_filename, 1, obj_filename, &buf, &len); - if (len < 1) return TINYOBJ_ERROR_INVALID_PARAMETER; - if (buf == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; - - if (get_line_infos(buf, len, &line_infos, &num_lines) != 0) { - return TINYOBJ_ERROR_EMPTY; + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "TINYOBJ: Error reading file '%s': %s (%d)\n", filename, strerror(errno), errno); + return TINYOBJ_ERROR_FILE_OPERATION; } /* Create a default material */ initMaterial(&material); - for (i = 0; i < num_lines; i++) { - const char *p = &buf[line_infos[i].pos]; - size_t p_len = line_infos[i].len; + linebuf = (char*)TINYOBJ_MALLOC(buffer_size); + while (NULL != dynamic_fgets(&linebuf, &buffer_size, fp)) { + const char *token = linebuf; - char linebuf[4096]; - const char *token; - assert(p_len < 4095); - - memcpy(linebuf, p, p_len); - linebuf[p_len] = '\0'; - - token = linebuf; - line_end = token + p_len; + line_end = token + strlen(token); /* Skip leading space. */ token += strspn(token, " \t"); @@ -924,7 +791,7 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out, #else sscanf(token, "%s", namebuf); #endif - material.name = my_strdup(namebuf, (size_t) (line_end - token)); + material.name = my_strdup(namebuf, (unsigned int) (line_end - token)); /* Add material to material table */ if (material_table) @@ -1025,56 +892,56 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out, /* ambient texture */ if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { token += 7; - material.ambient_texname = my_strdup(token, (size_t) (line_end - token)); + material.ambient_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* diffuse texture */ if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { token += 7; - material.diffuse_texname = my_strdup(token, (size_t) (line_end - token)); + material.diffuse_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* specular texture */ if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { token += 7; - material.specular_texname = my_strdup(token, (size_t) (line_end - token)); + material.specular_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* specular highlight texture */ if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { token += 7; - material.specular_highlight_texname = my_strdup(token, (size_t) (line_end - token)); + material.specular_highlight_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* bump texture */ if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { token += 9; - material.bump_texname = my_strdup(token, (size_t) (line_end - token)); + material.bump_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* alpha texture */ if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { token += 6; - material.alpha_texname = my_strdup(token, (size_t) (line_end - token)); + material.alpha_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* bump texture */ if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { token += 5; - material.bump_texname = my_strdup(token, (size_t) (line_end - token)); + material.bump_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } /* displacement texture */ if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { token += 5; - material.displacement_texname = my_strdup(token, (size_t) (line_end - token)); + material.displacement_texname = my_strdup(token, (unsigned int) (line_end - token)); continue; } @@ -1090,14 +957,18 @@ static int tinyobj_parse_and_index_mtl_file(tinyobj_material_t **materials_out, (*num_materials_out) = num_materials; (*materials_out) = materials; + if (linebuf) { + TINYOBJ_FREE(linebuf); + } + return TINYOBJ_SUCCESS; } int tinyobj_parse_mtl_file(tinyobj_material_t **materials_out, - size_t *num_materials_out, - const char *mtl_filename, const char *obj_filename, file_reader_callback file_reader) { - return tinyobj_parse_and_index_mtl_file(materials_out, num_materials_out, mtl_filename, obj_filename, file_reader, NULL); -} + unsigned int *num_materials_out, + const char *filename) { + return tinyobj_parse_and_index_mtl_file(materials_out, num_materials_out, filename, NULL); +} typedef enum { @@ -1120,10 +991,10 @@ typedef struct { /* @todo { Use dynamic array } */ tinyobj_vertex_index_t f[TINYOBJ_MAX_FACES_PER_F_LINE]; - size_t num_f; + unsigned int num_f; int f_num_verts[TINYOBJ_MAX_FACES_PER_F_LINE]; - size_t num_f_num_verts; + unsigned int num_f_num_verts; const char *group_name; unsigned int group_name_len; @@ -1143,7 +1014,7 @@ typedef struct { CommandType type; } Command; -static int parseLine(Command *command, const char *p, size_t p_len, +static int parseLine(Command *command, const char *p, unsigned int p_len, int triangulate) { char linebuf[4096]; const char *token; @@ -1205,7 +1076,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, /* face */ if (token[0] == 'f' && IS_SPACE((token[1]))) { - size_t num_f = 0; + unsigned int num_f = 0; tinyobj_vertex_index_t f[TINYOBJ_MAX_FACES_PER_F_LINE]; token += 2; @@ -1222,8 +1093,8 @@ static int parseLine(Command *command, const char *p, size_t p_len, command->type = COMMAND_F; if (triangulate) { - size_t k; - size_t n = 0; + unsigned int k; + unsigned int n = 0; tinyobj_vertex_index_t i0 = f[0]; tinyobj_vertex_index_t i1; @@ -1245,7 +1116,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, command->num_f_num_verts = n; } else { - size_t k = 0; + unsigned int k = 0; assert(num_f < TINYOBJ_MAX_FACES_PER_F_LINE); for (k = 0; k < num_f; k++) { command->f[k] = f[k]; @@ -1266,7 +1137,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, skip_space(&token); command->material_name = p + (token - linebuf); command->material_name_len = (unsigned int)length_until_newline( - token, (p_len - (size_t)(token - linebuf)) + 1); + token, (p_len - (unsigned int)(token - linebuf)) + 1); command->type = COMMAND_USEMTL; return 1; @@ -1280,7 +1151,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, skip_space(&token); command->mtllib_name = p + (token - linebuf); command->mtllib_name_len = (unsigned int)length_until_newline( - token, p_len - (size_t)(token - linebuf)) + + token, p_len - (unsigned int)(token - linebuf)) + 1; command->type = COMMAND_MTLLIB; @@ -1294,7 +1165,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, command->group_name = p + (token - linebuf); command->group_name_len = (unsigned int)length_until_newline( - token, p_len - (size_t)(token - linebuf)) + + token, p_len - (unsigned int)(token - linebuf)) + 1; command->type = COMMAND_G; @@ -1308,7 +1179,7 @@ static int parseLine(Command *command, const char *p, size_t p_len, command->object_name = p + (token - linebuf); command->object_name_len = (unsigned int)length_until_newline( - token, p_len - (size_t)(token - linebuf)) + + token, p_len - (unsigned int)(token - linebuf)) + 1; command->type = COMMAND_O; @@ -1318,61 +1189,43 @@ static int parseLine(Command *command, const char *p, size_t p_len, return 0; } -#if 0 -/* `path` content will be modified - */ -static char *get_dirname(char *path) -{ - char *last_delim = NULL; +typedef struct { + unsigned int pos; + unsigned int len; +} LineInfo; - if (path == NULL) { - return path; +static int is_line_ending(const char *p, unsigned int i, unsigned int end_i) { + if (p[i] == '\0') return 1; + if (p[i] == '\n') return 1; /* this includes \r\n */ + if (p[i] == '\r') { + if (((i + 1) < end_i) && (p[i + 1] != '\n')) { /* detect only \r case */ + return 1; + } } - -#if defined(_WIN32) - last_delim = strrchr(path, '\\'); -#else - last_delim = strrchr(path, '/'); -#endif - - if (last_delim == NULL) { - /* no delimiter in the string. */ - return path; - } - - /* remove '/' */ - last_delim[0] = '\0'; - - return path; + return 0; } -#endif - int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, - size_t *num_shapes, tinyobj_material_t **materials_out, - size_t *num_materials_out, const char *obj_filename, file_reader_callback file_reader, + unsigned int *num_shapes, tinyobj_material_t **materials_out, + unsigned int *num_materials_out, const char *buf, unsigned int len, unsigned int flags) { LineInfo *line_infos = NULL; Command *commands = NULL; - size_t num_lines = 0; + unsigned int num_lines = 0; - size_t num_v = 0; - size_t num_vn = 0; - size_t num_vt = 0; - size_t num_f = 0; - size_t num_faces = 0; + unsigned int num_v = 0; + unsigned int num_vn = 0; + unsigned int num_vt = 0; + unsigned int num_f = 0; + unsigned int num_faces = 0; int mtllib_line_index = -1; tinyobj_material_t *materials = NULL; - size_t num_materials = 0; + unsigned int num_materials = 0; hash_table_t material_table; - char *buf = NULL; - size_t len = 0; - file_reader(obj_filename, /* is_mtl */0, obj_filename, &buf, &len); - if (len < 1) return TINYOBJ_ERROR_INVALID_PARAMETER; if (attrib == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; if (shapes == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; @@ -1382,19 +1235,55 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, if (num_materials_out == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; tinyobj_attrib_init(attrib); + /* 1. Find '\n' and create line data. */ + { + unsigned int i; + unsigned int end_idx = len; + unsigned int prev_pos = 0; + unsigned int line_no = 0; + unsigned int last_line_ending = 0; - /* 1. create line data */ - if (get_line_infos(buf, len, &line_infos, &num_lines) != 0) { - return TINYOBJ_ERROR_EMPTY; + /* Count # of lines. */ + for (i = 0; i < end_idx; i++) { + if (is_line_ending(buf, i, end_idx)) { + num_lines++; + last_line_ending = i; + } + } + /* The last char from the input may not be a line + * ending character so add an extra line if there + * are more characters after the last line ending + * that was found. */ + if (end_idx - last_line_ending > 0) { + num_lines++; + } + + if (num_lines == 0) return TINYOBJ_ERROR_EMPTY; + + line_infos = (LineInfo *)TINYOBJ_MALLOC(sizeof(LineInfo) * num_lines); + + /* Fill line infos. */ + for (i = 0; i < end_idx; i++) { + if (is_line_ending(buf, i, end_idx)) { + line_infos[line_no].pos = prev_pos; + line_infos[line_no].len = i - prev_pos; + prev_pos = i + 1; + line_no++; + } + } + if (end_idx - last_line_ending > 0) { + line_infos[line_no].pos = prev_pos; + line_infos[line_no].len = end_idx - 1 - last_line_ending; + } } - commands = (Command *)TINYOBJ_MALLOC(sizeof(Command) * num_lines); + commands = (Command *)TINYOBJ_MALLOC(sizeof(Command) * num_lines); create_hash_table(HASH_TABLE_DEFAULT_SIZE, &material_table); /* 2. parse each line */ { - size_t i = 0; + unsigned int i = 0; for (i = 0; i < num_lines; i++) { int ret = parseLine(&commands[i], &buf[line_infos[i].pos], line_infos[i].len, flags & TINYOBJ_FLAG_TRIANGULATE); @@ -1425,26 +1314,10 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, /* Load material(if exits) */ if (mtllib_line_index >= 0 && commands[mtllib_line_index].mtllib_name && commands[mtllib_line_index].mtllib_name_len > 0) { - - /* Extract .obj filepath. */ - /*char *search_path = NULL; */ - char *filename = NULL; - int ret; - -#if 0 - /* Simply find last delimiter `/` - * TODO(syoyo): Robust extraction of base directory of filename. - */ - if (obj_filename) { - char *basedir = my_strdup(file_name, my_strnlen(file_name, TINYOBJ_MAX_FILEPATH)); - search_path = get_dirname(basedir); - } -#endif - - filename = my_strndup(commands[mtllib_line_index].mtllib_name, + char *filename = my_strndup(commands[mtllib_line_index].mtllib_name, commands[mtllib_line_index].mtllib_name_len); - ret = tinyobj_parse_and_index_mtl_file(&materials, &num_materials, filename, obj_filename, file_reader, &material_table); + int ret = tinyobj_parse_and_index_mtl_file(&materials, &num_materials, filename, &material_table); if (ret != TINYOBJ_SUCCESS) { /* warning. */ @@ -1452,24 +1325,19 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } TINYOBJ_FREE(filename); -#if 0 - if (search_path) { - TINYOBJ_FREE(search_path); - } -#endif } /* Construct attributes */ { - size_t v_count = 0; - size_t n_count = 0; - size_t t_count = 0; - size_t f_count = 0; - size_t face_count = 0; + unsigned int v_count = 0; + unsigned int n_count = 0; + unsigned int t_count = 0; + unsigned int f_count = 0; + unsigned int face_count = 0; int material_id = -1; /* -1 = default unknown material. */ - size_t i = 0; + unsigned int i = 0; attrib->vertices = (float *)TINYOBJ_MALLOC(sizeof(float) * num_v * 3); attrib->num_vertices = (unsigned int)num_v; @@ -1477,12 +1345,13 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, attrib->num_normals = (unsigned int)num_vn; attrib->texcoords = (float *)TINYOBJ_MALLOC(sizeof(float) * num_vt * 2); attrib->num_texcoords = (unsigned int)num_vt; - attrib->faces = (tinyobj_vertex_index_t *)TINYOBJ_MALLOC( - sizeof(tinyobj_vertex_index_t) * num_f); - attrib->num_faces = (unsigned int)num_f; + attrib->faces = (tinyobj_vertex_index_t *)TINYOBJ_MALLOC(sizeof(tinyobj_vertex_index_t) * num_f); attrib->face_num_verts = (int *)TINYOBJ_MALLOC(sizeof(int) * num_faces); + + attrib->num_faces = (unsigned int)num_faces; + attrib->num_face_num_verts = (unsigned int)num_f; + attrib->material_ids = (int *)TINYOBJ_MALLOC(sizeof(int) * num_faces); - attrib->num_face_num_verts = (unsigned int)num_faces; for (i = 0; i < num_lines; i++) { if (commands[i].type == COMMAND_EMPTY) { @@ -1503,12 +1372,12 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } */ if (commands[i].material_name && - commands[i].material_name_len >0) + commands[i].material_name_len >0) { /* Create a null terminated string */ char* material_name_null_term = (char*) TINYOBJ_MALLOC(commands[i].material_name_len + 1); memcpy((void*) material_name_null_term, (const void*) commands[i].material_name, commands[i].material_name_len); - material_name_null_term[commands[i].material_name_len] = 0; + material_name_null_term[commands[i].material_name_len - 1] = 0; if (hash_table_exists(material_name_null_term, &material_table)) material_id = (int)hash_table_get(material_name_null_term, &material_table); @@ -1532,7 +1401,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, attrib->texcoords[2 * t_count + 1] = commands[i].ty; t_count++; } else if (commands[i].type == COMMAND_F) { - size_t k = 0; + unsigned int k = 0; for (k = 0; k < commands[i].num_f; k++) { tinyobj_vertex_index_t vi = commands[i].f[k]; int v_idx = fixIndex(vi.v_idx, v_count); @@ -1557,9 +1426,9 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, /* 5. Construct shape information. */ { unsigned int face_count = 0; - size_t i = 0; - size_t n = 0; - size_t shape_idx = 0; + unsigned int i = 0; + unsigned int n = 0; + unsigned int shape_idx = 0; const char *shape_name = NULL; unsigned int shape_name_len = 0; @@ -1631,7 +1500,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } if ((face_count - prev_face_offset) > 0) { - size_t length = face_count - prev_shape_face_offset; + unsigned int length = face_count - prev_shape_face_offset; if (length > 0) { (*shapes)[shape_idx].name = my_strndup(prev_shape_name, prev_shape_name_len); @@ -1652,7 +1521,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } destroy_hash_table(&material_table); - + (*materials_out) = materials; (*num_materials_out) = num_materials; @@ -1682,8 +1551,8 @@ void tinyobj_attrib_free(tinyobj_attrib_t *attrib) { if (attrib->material_ids) TINYOBJ_FREE(attrib->material_ids); } -void tinyobj_shapes_free(tinyobj_shape_t *shapes, size_t num_shapes) { - size_t i; +void tinyobj_shapes_free(tinyobj_shape_t *shapes, unsigned int num_shapes) { + unsigned int i; if (shapes == NULL) return; for (i = 0; i < num_shapes; i++) { @@ -1694,8 +1563,8 @@ void tinyobj_shapes_free(tinyobj_shape_t *shapes, size_t num_shapes) { } void tinyobj_materials_free(tinyobj_material_t *materials, - size_t num_materials) { - size_t i; + unsigned int num_materials) { + unsigned int i; if (materials == NULL) return; for (i = 0; i < num_materials; i++) { diff --git a/src/models.c b/src/models.c index 1e4e63722..68de05043 100644 --- a/src/models.c +++ b/src/models.c @@ -898,7 +898,7 @@ Material *LoadMaterials(const char *fileName, int *materialCount) { tinyobj_material_t *mats = NULL; - int result = tinyobj_parse_mtl_file(&mats, &count, fileName, NULL, NULL); + int result = tinyobj_parse_mtl_file(&mats, &count, fileName); if (result != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MATERIAL: [%s] Failed to parse materials file", fileName); // TODO: Process materials to return @@ -2946,10 +2946,6 @@ RayHitInfo GetCollisionRayGround(Ray ray, float groundHeight) #if defined(SUPPORT_FILEFORMAT_OBJ) // Load OBJ mesh data - -// TODO used by loadOBJ, could change to a function that could handle -// data coming from a file, memory or archive... - static Model LoadOBJ(const char *fileName) { Model model = { 0 }; @@ -2961,17 +2957,17 @@ static Model LoadOBJ(const char *fileName) tinyobj_material_t *materials = NULL; unsigned int materialCount = 0; - //char *fileData = LoadFileText(fileName); + char *fileData = LoadFileText(fileName); - //if (fileData != NULL) + if (fileData != NULL) { - //unsigned int dataSize = (unsigned int)strlen(fileData); + unsigned int dataSize = (unsigned int)strlen(fileData); char currentDir[1024] = { 0 }; strcpy(currentDir, GetWorkingDirectory()); chdir(GetDirectoryPath(fileName)); unsigned int flags = TINYOBJ_FLAG_TRIANGULATE; - int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileName, NULL, flags); + int ret = tinyobj_parse_obj(&attrib, &meshes, &meshCount, &materials, &materialCount, fileData, dataSize, flags); if (ret != TINYOBJ_SUCCESS) TRACELOG(LOG_WARNING, "MODEL: [%s] Failed to load OBJ data", fileName); else TRACELOG(LOG_INFO, "MODEL: [%s] OBJ data loaded successfully: %i meshes / %i materials", fileName, meshCount, materialCount);