diff --git a/experimental/tinyobj_loader_c.h b/experimental/tinyobj_loader_c.h index def492d..e1b928d 100644 --- a/experimental/tinyobj_loader_c.h +++ b/experimental/tinyobj_loader_c.h @@ -43,7 +43,7 @@ THE SOFTWARE. #include typedef struct { - const char *name; + char *name; float ambient[3]; float diffuse[3]; @@ -56,17 +56,17 @@ typedef struct { /* illumination model (see http://www.fileformat.info/format/material/) */ int illum; - const char *ambient_texname; /* map_Ka */ - const char *diffuse_texname; /* map_Kd */ - const char *specular_texname; /* map_Ks */ - const char *specular_highlight_texname; /* map_Ns */ - const char *bump_texname; /* map_bump, bump */ - const char *displacement_texname; /* disp */ - const char *alpha_texname; /* map_d */ + char *ambient_texname; /* map_Ka */ + char *diffuse_texname; /* map_Kd */ + char *specular_texname; /* map_Ks */ + char *specular_highlight_texname; /* map_Ns */ + char *bump_texname; /* map_bump, bump */ + char *displacement_texname; /* disp */ + char *alpha_texname; /* map_d */ } tinyobj_material_t; typedef struct { - const char *name; /* group name or object name. */ + char *name; /* group name or object name. */ unsigned int face_offset; unsigned int length; } tinyobj_shape_t; @@ -94,6 +94,7 @@ typedef struct { #define TINYOBJ_SUCCESS (0) #define TINYOBJ_ERROR_EMPTY (-1) #define TINYOBJ_ERROR_INVALID_PARAMETER (-2) +#define TINYOBJ_ERROR_FILE_OPERATION (-3) /* Parse wavefront .obj(.obj string data is expanded to linear char array `buf') * flags are combination of TINYOBJ_FLAG_*** @@ -101,15 +102,15 @@ typedef struct { * Retruns TINYOBJ_ERR_*** when there is an error. */ extern int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, - size_t *num_shapes, const char *buf, size_t len, - unsigned int flags); + size_t *num_shapes, tinyobj_material_t **materials, + size_t *num_materials, const char *buf, size_t len, + unsigned int flags); extern void tinyobj_attrib_init(tinyobj_attrib_t *attrib); extern void tinyobj_attrib_free(tinyobj_attrib_t *attrib); -extern void tinyobj_shape_free(tinyobj_shape_t *shapes, size_t num_shapes); - -/* Parse .mtl string and construct material struct */ -static int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const char* buf, size_t len); +extern void tinyobj_shapes_free(tinyobj_shape_t *shapes, size_t num_shapes); +extern void tinyobj_materials_free(tinyobj_material_t *materials, + size_t num_materials); #ifdef TINYOBJ_LOADER_C_IMPLEMENTATION @@ -427,6 +428,41 @@ static void parseFloat3(float *x, float *y, float *z, const char **token) { (*z) = parseFloat(token); } +static char *my_strdup(const char *s) { + char *d; + int len; + + if (s == NULL) return NULL; + + len = strlen(s); + + d = (char *)malloc(len + 1); /* + '\0' */ + memcpy(d, s, len); + d[len] = '\0'; + + return d; +} + +static char *my_strndup(const char *s, size_t len) { + char *d; + int slen; + + if (s == NULL) return NULL; + if (len == 0) return NULL; + + d = (char *)malloc(len + 1); /* + '\0' */ + slen = strlen(s); + if (slen < len) { + memcpy(d, s, slen); + d[slen] = '\0'; + } else { + memcpy(d, s, len); + d[len] = '\0'; + } + + return d; +} + static void initMaterial(tinyobj_material_t *material) { int i; material->name = NULL; @@ -450,76 +486,75 @@ static void initMaterial(tinyobj_material_t *material) { material->ior = 1.f; } -static tinyobj_material_t *tinyobj_material_add(tinyobj_material_t *prev, int num_materials, tinyobj_material_t *new_mat) -{ - tinyobj_material_t* dst = (tinyobj_material_t*)realloc(prev, sizeof(tinyobj_material_t) * (num_materials + 1)); +static tinyobj_material_t *tinyobj_material_add(tinyobj_material_t *prev, + int num_materials, + tinyobj_material_t *new_mat) { + tinyobj_material_t *dst; + dst = (tinyobj_material_t *)realloc( + prev, sizeof(tinyobj_material_t) * (num_materials + 1)); - return dst; + dst[num_materials] = (*new_mat); /* Just copy pointer for char* members */ + return dst; } -int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const char* buf, size_t len) { +static int tinyobj_parse_mtl_file(tinyobj_material_t **materials_out, + size_t *num_materials_out, + const char *filename) { + tinyobj_material_t material; + char linebuf[8192]; /* alloc enough size */ + FILE *fp; + size_t num_materials = 0; + tinyobj_material_t *materials = NULL; + int has_previous_material = 0; + + fp = fopen(filename, "r"); + if (!fp) { + return TINYOBJ_ERROR_FILE_OPERATION; + } + /* Create a default material */ - tinyobj_material_t default_material; - initMaterial(&default_material); + initMaterial(&material); -#if 0 - while (inStream->peek() != -1) { - inStream->getline(&buf[0], static_cast(maxchars)); - - std::string linebuf(&buf[0]); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\n') - linebuf.erase(linebuf.size() - 1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\r') - linebuf.erase(linebuf.size() - 1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char *token = linebuf.c_str(); + while (NULL != fgets(linebuf, 8192 - 1, fp)) { + const char *token = linebuf; + /* Skip leading space. */ token += strspn(token, " \t"); assert(token); - if (token[0] == '\0') continue; // empty line + if (token[0] == '\0') continue; /* empty line */ - if (token[0] == '#') continue; // comment line + if (token[0] == '#') continue; /* comment line */ - // new mtl + /* new mtl */ if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { - // flush previous material. - if (!material.name.empty()) { - material_map->insert(std::pair( - material.name, static_cast(materials->size()))); - materials->push_back(material); - } - - // initial temporary material - InitMaterial(&material); - - // set new mtl name char namebuf[4096]; + + /* flush previous material. */ + if (has_previous_material) { + materials = tinyobj_material_add(materials, num_materials, &material); + num_materials++; + } else { + has_previous_material = 1; + } + + /* initial temporary material */ + initMaterial(&material); + + /* set new mtl name */ token += 7; #ifdef _MSC_VER sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); #else sscanf(token, "%s", namebuf); #endif - material.name = namebuf; + material.name = my_strdup(namebuf); continue; } - // ambient + /* ambient */ if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { - token += 2; float r, g, b; + token += 2; parseFloat3(&r, &g, &b, &token); material.ambient[0] = r; material.ambient[1] = g; @@ -527,10 +562,10 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const continue; } - // diffuse + /* diffuse */ if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { - token += 2; float r, g, b; + token += 2; parseFloat3(&r, &g, &b, &token); material.diffuse[0] = r; material.diffuse[1] = g; @@ -538,10 +573,10 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const continue; } - // specular + /* specular */ if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { - token += 2; float r, g, b; + token += 2; parseFloat3(&r, &g, &b, &token); material.specular[0] = r; material.specular[1] = g; @@ -549,10 +584,10 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const continue; } - // transmittance + /* transmittance */ if (token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) { - token += 2; float r, g, b; + token += 2; parseFloat3(&r, &g, &b, &token); material.transmittance[0] = r; material.transmittance[1] = g; @@ -560,17 +595,17 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const continue; } - // ior(index of refraction) + /* ior(index of refraction) */ if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { token += 2; material.ior = parseFloat(&token); continue; } - // emission + /* emission */ if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { - token += 2; float r, g, b; + token += 2; parseFloat3(&r, &g, &b, &token); material.emission[0] = r; material.emission[1] = g; @@ -578,21 +613,21 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const continue; } - // shininess + /* shininess */ if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { token += 2; material.shininess = parseFloat(&token); continue; } - // illum model + /* illum model */ if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { token += 6; material.illum = parseInt(&token); continue; } - // dissolve + /* dissolve */ if ((token[0] == 'd' && IS_SPACE(token[1]))) { token += 1; material.dissolve = parseFloat(&token); @@ -600,73 +635,74 @@ int tinyobj_parse_mtl(tinyobj_material_t **materials, int *num_materials, const } if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { token += 2; - // Invert value of Tr(assume Tr is in range [0, 1]) + /* Invert value of Tr(assume Tr is in range [0, 1]) */ material.dissolve = 1.0f - parseFloat(&token); continue; } - // ambient texture + /* ambient texture */ if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { token += 7; - material.ambient_texname = strdup(token); + material.ambient_texname = my_strdup(token); continue; } - // diffuse texture + /* diffuse texture */ if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { token += 7; - material.diffuse_texname = strdup(token); + material.diffuse_texname = my_strdup(token); continue; } - // specular texture + /* specular texture */ if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { token += 7; - material.specular_texname = strdup(token); + material.specular_texname = my_strdup(token); continue; } - // specular highlight texture + /* specular highlight texture */ if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { token += 7; - material.specular_highlight_texname = strdup(token); + material.specular_highlight_texname = my_strdup(token); continue; } - // bump texture + /* bump texture */ if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { token += 9; - material.bump_texname = strdup(token); + material.bump_texname = my_strdup(token); continue; } - // alpha texture + /* alpha texture */ if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { token += 6; - material.alpha_texname = strdup(token); + material.alpha_texname = my_strdup(token); continue; } - // bump texture + /* bump texture */ if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { token += 5; - material.bump_texname = strdup(token); + material.bump_texname = my_strdup(token); continue; } - // displacement texture + /* displacement texture */ if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { token += 5; - material.displacement_texname = strdup(token); + material.displacement_texname = my_strdup(token); continue; } /* @todo { unknown parameter } */ } -#endif - - return TINYOBJ_SUCCESS; + (*num_materials_out) = num_materials; + (*materials_out) = materials; + + return TINYOBJ_SUCCESS; } typedef enum { @@ -879,26 +915,6 @@ static int parseLine(Command *command, const char *p, size_t p_len, return 0; } -static char *my_strndup(const char *s, size_t len) -{ - char *d; - int slen; - - if (len == 0) return NULL; - - d = (char *)malloc(len + 1); /* + '\0' */ - slen = strlen(s); - if (slen < len) { - memcpy(d, s, slen); - d[slen] = '\0'; - } else { - memcpy(d, s, len); - d[len] = '\0'; - } - - return d; -} - typedef struct { size_t pos; size_t len; @@ -916,8 +932,9 @@ static int is_line_ending(const char *p, size_t i, size_t end_i) { } int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, - size_t *num_shapes, const char *buf, size_t len, - unsigned int flags) { + size_t *num_shapes, tinyobj_material_t **materials_out, + size_t *num_materials_out, const char *buf, size_t len, + unsigned int flags) { LineInfo *line_infos = NULL; Command *commands = NULL; size_t num_lines = 0; @@ -928,13 +945,18 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, size_t num_f = 0; size_t num_faces = 0; + int mtllib_line_index = -1; + + tinyobj_material_t *materials; + size_t num_materials = 0; + if (len < 1) return TINYOBJ_ERROR_INVALID_PARAMETER; if (attrib == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; if (shapes == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; if (num_shapes == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; if (buf == NULL) return TINYOBJ_ERROR_INVALID_PARAMETER; - tinyobj_attrib_init(attrib); + tinyobj_attrib_init(attrib); /* 1. Find '\n' and create line data. */ { @@ -986,10 +1008,7 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } if (commands[i].type == COMMAND_MTLLIB) { - /* @todo - mtllib_t_index = t; - mtllib_i_index = commands->size(); - */ + mtllib_line_index = i; } } } @@ -1000,36 +1019,21 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, free(line_infos); } -#if 0 + /* Load material(if exits) */ + if (mtllib_line_index >= 0 && commands[mtllib_line_index].mtllib_name && + commands[mtllib_line_index].mtllib_name_len > 0) { + char *filename = my_strndup(commands[mtllib_line_index].mtllib_name, + commands[mtllib_line_index].mtllib_name_len); - std::map material_map; - std::vector materials; + int ret = tinyobj_parse_mtl_file(&materials, &num_materials, filename); - // Load material(if exits) - if (mtllib_i_index >= 0 && mtllib_t_index >= 0 && - commands[mtllib_t_index][mtllib_i_index].mtllib_name && - commands[mtllib_t_index][mtllib_i_index].mtllib_name_len > 0) { - std::string material_filename = - std::string(commands[mtllib_t_index][mtllib_i_index].mtllib_name, - commands[mtllib_t_index][mtllib_i_index].mtllib_name_len); - // std::cout << "mtllib :" << material_filename << std::endl; + free(filename); - auto t1 = std::chrono::high_resolution_clock::now(); - - std::ifstream ifs(material_filename); - if (ifs.good()) { - LoadMtl(&material_map, &materials, &ifs); - - // std::cout << "maetrials = " << materials.size() << std::endl; - - ifs.close(); + if (ret != TINYOBJ_SUCCESS) { + /* warning. */ + fprintf(stderr, "TINYOBJ: Failed to parse .mtl file: %s\n", filename); } - - auto t2 = std::chrono::high_resolution_clock::now(); - - ms_load_mtl = t2 - t1; } -#endif /* Construct attributes */ @@ -1114,74 +1118,76 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, { int face_count = 0; size_t i = 0; - size_t n = 0; - size_t shape_idx = 0; + size_t n = 0; + size_t shape_idx = 0; - const char* shape_name = NULL; - int shape_name_len = 0; - const char* prev_shape_name = NULL; - int prev_shape_name_len = 0; - int prev_shape_face_offset = 0; - int prev_shape_length = 0; + const char *shape_name = NULL; + int shape_name_len = 0; + const char *prev_shape_name = NULL; + int prev_shape_name_len = 0; + int prev_shape_face_offset = 0; + int prev_shape_length = 0; int prev_face_offset = 0; - tinyobj_shape_t prev_shape = {NULL, 0, 0}; + tinyobj_shape_t prev_shape = {NULL, 0, 0}; - /* Find the number of shapes in .obj */ + /* Find the number of shapes in .obj */ for (i = 0; i < num_lines; i++) { if (commands[i].type == COMMAND_O || commands[i].type == COMMAND_G) { - n++; - } - } + n++; + } + } - /* Allocate array of shapes with maximum possible size(+1 for unnamed group/object). + /* Allocate array of shapes with maximum possible size(+1 for unnamed + * group/object). * Actual # of shapes found in .obj is determined in the later */ - (*shapes) = malloc(sizeof(tinyobj_shape_t) * (n + 1)); + (*shapes) = malloc(sizeof(tinyobj_shape_t) * (n + 1)); for (i = 0; i < num_lines; i++) { if (commands[i].type == COMMAND_O || commands[i].type == COMMAND_G) { - - if (commands[i].type == COMMAND_O) { - shape_name = commands[i].object_name; - shape_name_len = commands[i].object_name_len; - } else { - shape_name = commands[i].group_name; - shape_name_len = commands[i].group_name_len; - } + if (commands[i].type == COMMAND_O) { + shape_name = commands[i].object_name; + shape_name_len = commands[i].object_name_len; + } else { + shape_name = commands[i].group_name; + shape_name_len = commands[i].group_name_len; + } - if (face_count == 0) { - /* 'o' or 'g' appears before any 'f' */ - prev_shape_name = shape_name; - prev_shape_name_len = shape_name_len; - prev_shape_face_offset = face_count; + if (face_count == 0) { + /* 'o' or 'g' appears before any 'f' */ + prev_shape_name = shape_name; + prev_shape_name_len = shape_name_len; + prev_shape_face_offset = face_count; + prev_face_offset = face_count; + } else { + if (shape_idx == 0) { + /* 'o' or 'g' after some 'v' lines. */ + (*shapes)[shape_idx].name = my_strndup( + prev_shape_name, prev_shape_name_len); /* may be NULL */ + (*shapes)[shape_idx].face_offset = prev_shape.face_offset; + (*shapes)[shape_idx].length = face_count - prev_face_offset; + shape_idx++; + + prev_shape_length = face_count - prev_face_offset; prev_face_offset = face_count; + } else { - if (shape_idx == 0) { - /* 'o' or 'g' after some 'v' lines. */ - (*shapes)[shape_idx].name = my_strndup(prev_shape_name, prev_shape_name_len); /* may be NULL */ - (*shapes)[shape_idx].face_offset = prev_shape.face_offset; + if ((face_count - prev_face_offset) > 0) { + (*shapes)[shape_idx].name = + my_strndup(prev_shape_name, prev_shape_name_len); + (*shapes)[shape_idx].face_offset = prev_face_offset; (*shapes)[shape_idx].length = face_count - prev_face_offset; - shape_idx++; - - prev_shape_length = face_count - prev_face_offset; + shape_idx++; + prev_shape_length = face_count - prev_face_offset; prev_face_offset = face_count; - - } else { - if ((face_count - prev_face_offset) > 0) { - (*shapes)[shape_idx].name = my_strndup(prev_shape_name, prev_shape_name_len); - (*shapes)[shape_idx].face_offset = prev_face_offset; - (*shapes)[shape_idx].length = face_count - prev_face_offset; - shape_idx++; - prev_shape_length = face_count - prev_face_offset; - prev_face_offset = face_count; - } } - - /* Record shape info for succeeding 'o' or 'g' command. */ - prev_shape_name = shape_name; - prev_shape_name_len = shape_name_len; - prev_shape_face_offset = face_count; - prev_shape_length = 0; } + + /* Record shape info for succeeding 'o' or 'g' command. */ + prev_shape_name = shape_name; + prev_shape_name_len = shape_name_len; + prev_shape_face_offset = face_count; + prev_shape_length = 0; + } } if (commands[i].type == COMMAND_F) { face_count++; @@ -1189,30 +1195,33 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } if ((face_count - prev_face_offset) > 0) { - size_t len = face_count - prev_shape_face_offset; - if (len > 0) { - (*shapes)[shape_idx].name = my_strndup(prev_shape_name, prev_shape_name_len); - (*shapes)[shape_idx].face_offset = prev_face_offset; - (*shapes)[shape_idx].length = face_count - prev_face_offset; - shape_idx++; + size_t len = face_count - prev_shape_face_offset; + if (len > 0) { + (*shapes)[shape_idx].name = + my_strndup(prev_shape_name, prev_shape_name_len); + (*shapes)[shape_idx].face_offset = prev_face_offset; + (*shapes)[shape_idx].length = face_count - prev_face_offset; + shape_idx++; } } else { /* Guess no 'v' line occurrence after 'o' or 'g', so discards current * shape information. */ } - - (*num_shapes) = shape_idx; + + (*num_shapes) = shape_idx; } if (commands) { free(commands); } + (*materials_out) = materials; + (*num_materials_out) = num_materials; + return TINYOBJ_SUCCESS; } -void tinyobj_attrib_init(tinyobj_attrib_t *attrib) -{ +void tinyobj_attrib_init(tinyobj_attrib_t *attrib) { attrib->vertices = NULL; attrib->num_vertices = 0; attrib->normals = NULL; @@ -1226,16 +1235,46 @@ void tinyobj_attrib_init(tinyobj_attrib_t *attrib) attrib->material_ids = NULL; } -void tinyobj_attrib_free(tinyobj_attrib_t *attrib) -{ - if (attrib->vertices) free(attrib->vertices); - if (attrib->normals) free(attrib->normals); - if (attrib->texcoords) free(attrib->texcoords); - if (attrib->faces) free(attrib->faces); - if (attrib->face_num_verts) free(attrib->face_num_verts); - if (attrib->material_ids) free(attrib->material_ids); +void tinyobj_attrib_free(tinyobj_attrib_t *attrib) { + if (attrib->vertices) free(attrib->vertices); + if (attrib->normals) free(attrib->normals); + if (attrib->texcoords) free(attrib->texcoords); + if (attrib->faces) free(attrib->faces); + if (attrib->face_num_verts) free(attrib->face_num_verts); + if (attrib->material_ids) free(attrib->material_ids); } +void tinyobj_shapes_free(tinyobj_shape_t *shapes, size_t num_shapes) { + int i; + if (shapes == NULL) return; + + for (i = 0; i < num_shapes; i++) { + if (shapes[i].name) free(shapes[i].name); + } + + free(shapes); +} + +void tinyobj_materials_free(tinyobj_material_t *materials, + size_t num_materials) { + int i; + if (materials == NULL) return; + + for (i = 0; i < num_materials; i++) { + if (materials[i].name) free(materials[i].name); + if (materials[i].ambient_texname) free(materials[i].ambient_texname); + if (materials[i].diffuse_texname) free(materials[i].diffuse_texname); + if (materials[i].specular_texname) free(materials[i].specular_texname); + if (materials[i].specular_highlight_texname) + free(materials[i].specular_highlight_texname); + if (materials[i].bump_texname) free(materials[i].bump_texname); + if (materials[i].displacement_texname) + free(materials[i].displacement_texname); + if (materials[i].alpha_texname) free(materials[i].alpha_texname); + } + + free(materials); +} #endif /* TINYOBJ_LOADER_C_IMPLEMENTATION */ #endif /* TINOBJ_LOADER_C_H_ */ diff --git a/experimental/viewer-c.c b/experimental/viewer-c.c index 98b254a..5877d15 100644 --- a/experimental/viewer-c.c +++ b/experimental/viewer-c.c @@ -1,7 +1,7 @@ -#include -#include -#include #include +#include +#include +#include #ifdef __APPLE__ #include @@ -66,71 +66,72 @@ static void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) { len2 = N[0] * N[0] + N[1] * N[1] + N[2] * N[2]; if (len2 > 0.0f) { float len = sqrt(len2); - + N[0] /= len; N[1] /= len; } } -static const char *mmap_file(size_t *len, const char* filename) -{ +static const char* mmap_file(size_t* len, const char* filename) { #ifdef _WIN64 - HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); - assert(file != INVALID_HANDLE_VALUE); + HANDLE file = + CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + assert(file != INVALID_HANDLE_VALUE); - HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); - assert(fileMapping != INVALID_HANDLE_VALUE); - - LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0); - auto fileMapViewChar = (const char*)fileMapView; - assert(fileMapView != NULL); + HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + assert(fileMapping != INVALID_HANDLE_VALUE); + + LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0); + auto fileMapViewChar = (const char*)fileMapView; + assert(fileMapView != NULL); #else FILE* f; long file_size; struct stat sb; - char *p; + char* p; int fd; (*len) = 0; - f = fopen(filename, "r" ); + f = fopen(filename, "r"); fseek(f, 0, SEEK_END); file_size = ftell(f); fclose(f); - fd = open (filename, O_RDONLY); + fd = open(filename, O_RDONLY); if (fd == -1) { - perror ("open"); + perror("open"); return NULL; } - if (fstat (fd, &sb) == -1) { - perror ("fstat"); + if (fstat(fd, &sb) == -1) { + perror("fstat"); return NULL; } - if (!S_ISREG (sb.st_mode)) { - fprintf (stderr, "%s is not a file\n", "lineitem.tbl"); + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "%s is not a file\n", "lineitem.tbl"); return NULL; } - p = (char*)mmap (0, (size_t)file_size, PROT_READ, MAP_SHARED, fd, 0); + p = (char*)mmap(0, (size_t)file_size, PROT_READ, MAP_SHARED, fd, 0); if (p == MAP_FAILED) { - perror ("mmap"); + perror("mmap"); return NULL; } - if (close (fd) == -1) { - perror ("close"); + if (close(fd) == -1) { + perror("close"); return NULL; } (*len) = (size_t)file_size; return p; - + #endif } @@ -176,10 +177,8 @@ static int gz_load(std::vector* buf, const char* filename) } #endif -static const char* get_file_data(size_t *len, const char* filename) -{ - - const char *ext = strrchr(filename, '.'); +static const char* get_file_data(size_t* len, const char* filename) { + const char* ext = strrchr(filename, '.'); size_t data_len = 0; const char* data = NULL; @@ -201,7 +200,6 @@ static const char* get_file_data(size_t *len, const char* filename) #endif } else { - data = mmap_file(&data_len, filename); } @@ -209,13 +207,14 @@ static const char* get_file_data(size_t *len, const char* filename) return data; } - -static int LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename) -{ +static int LoadObjAndConvert(float bmin[3], float bmax[3], + const char* filename) { tinyobj_attrib_t attrib; - tinyobj_shape_t *shapes = NULL; + tinyobj_shape_t* shapes = NULL; size_t num_shapes; - + tinyobj_material_t* materials = NULL; + size_t num_materials; + size_t data_len = 0; const char* data = get_file_data(&data_len, filename); if (data == NULL) { @@ -223,20 +222,22 @@ static int LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename) return 0; } printf("filesize: %d\n", (int)data_len); - + { unsigned int flags = TINYOBJ_FLAG_TRIANGULATE; - int ret = tinyobj_parse_obj(&attrib, &shapes, &num_shapes, data, data_len, flags); + int ret = tinyobj_parse_obj(&attrib, &shapes, &num_shapes, &materials, + &num_materials, data, data_len, flags); if (ret != TINYOBJ_SUCCESS) { return 0; } - printf("# of shapes = %d\n", num_shapes); + printf("# of shapes = %d\n", (int)num_shapes); + printf("# of materiasl = %d\n", (int)num_materials); { int i; for (i = 0; i < num_shapes; i++) { - printf("shape[%d] name = %s\n", i, shapes[i].name); + printf("shape[%d] name = %s\n", i, shapes[i].name); } } } @@ -245,137 +246,149 @@ static int LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename) bmax[0] = bmax[1] = bmax[2] = -FLT_MAX; { - DrawObject o; - float *vb; - /* std::vector vb; // */ - size_t face_offset = 0; - size_t i; + DrawObject o; + float* vb; + /* std::vector vb; // */ + size_t face_offset = 0; + size_t i; - /* Assume triangulated face. */ - size_t num_triangles = attrib.num_face_num_verts; - size_t stride = 9; /* 9 = pos(3float), normal(3float), color(3float) */ + /* Assume triangulated face. */ + size_t num_triangles = attrib.num_face_num_verts; + size_t stride = 9; /* 9 = pos(3float), normal(3float), color(3float) */ - vb = (float*)malloc(sizeof(float) * stride * num_triangles * 3); + vb = (float*)malloc(sizeof(float) * stride * num_triangles * 3); - for (i = 0; i < attrib.num_face_num_verts; i++) { - size_t f; - assert(attrib.face_num_verts[i] % 3 == 0); /* assume all triangle faces. */ - for (f = 0; f < attrib.face_num_verts[i] / 3; f++) { - int k; - float v[3][3]; - float n[3][3]; - float c[3]; - float len2; + for (i = 0; i < attrib.num_face_num_verts; i++) { + size_t f; + assert(attrib.face_num_verts[i] % 3 == + 0); /* assume all triangle faces. */ + for (f = 0; f < attrib.face_num_verts[i] / 3; f++) { + int k; + float v[3][3]; + float n[3][3]; + float c[3]; + float len2; - tinyobj_vertex_index_t idx0 = attrib.faces[face_offset+3*f+0]; - tinyobj_vertex_index_t idx1 = attrib.faces[face_offset+3*f+1]; - tinyobj_vertex_index_t idx2 = attrib.faces[face_offset+3*f+2]; + tinyobj_vertex_index_t idx0 = attrib.faces[face_offset + 3 * f + 0]; + tinyobj_vertex_index_t idx1 = attrib.faces[face_offset + 3 * f + 1]; + tinyobj_vertex_index_t idx2 = attrib.faces[face_offset + 3 * f + 2]; - for (k = 0; k < 3; k++) { - int f0 = idx0.v_idx; - int f1 = idx1.v_idx; - int f2 = idx2.v_idx; - assert(f0 >= 0); - assert(f1 >= 0); - assert(f2 >= 0); + for (k = 0; k < 3; k++) { + int f0 = idx0.v_idx; + int f1 = idx1.v_idx; + int f2 = idx2.v_idx; + assert(f0 >= 0); + assert(f1 >= 0); + assert(f2 >= 0); - v[0][k] = attrib.vertices[3*f0+k]; - v[1][k] = attrib.vertices[3*f1+k]; - v[2][k] = attrib.vertices[3*f2+k]; - bmin[k] = (v[0][k] < bmin[k]) ? v[0][k] : bmin[k]; - bmin[k] = (v[1][k] < bmin[k]) ? v[1][k] : bmin[k]; - bmin[k] = (v[2][k] < bmin[k]) ? v[2][k] : bmin[k]; - bmax[k] = (v[0][k] > bmax[k]) ? v[0][k] : bmax[k]; - bmax[k] = (v[1][k] > bmax[k]) ? v[1][k] : bmax[k]; - bmax[k] = (v[2][k] > bmax[k]) ? v[2][k] : bmax[k]; - } - - if (attrib.num_normals > 0) { - int f0 = idx0.vn_idx; - int f1 = idx1.vn_idx; - int f2 = idx2.vn_idx; - if (f0 >=0 && f1 >= 0 && f2 >= 0) { - assert(3*f0+2 < attrib.num_normals); - assert(3*f1+2 < attrib.num_normals); - assert(3*f2+2 < attrib.num_normals); - for (k = 0; k < 3; k++) { - n[0][k] = attrib.normals[3*f0+k]; - n[1][k] = attrib.normals[3*f1+k]; - n[2][k] = attrib.normals[3*f2+k]; - } - } else { /* normal index is not defined for this face */ - /* compute geometric normal */ - CalcNormal(n[0], v[0], v[1], v[2]); - n[1][0] = n[0][0]; n[1][1] = n[0][1]; n[1][2] = n[0][2]; - n[2][0] = n[0][0]; n[2][1] = n[0][1]; n[2][2] = n[0][2]; - } - } else { - /* compute geometric normal */ - CalcNormal(n[0], v[0], v[1], v[2]); - n[1][0] = n[0][0]; n[1][1] = n[0][1]; n[1][2] = n[0][2]; - n[2][0] = n[0][0]; n[2][1] = n[0][1]; n[2][2] = n[0][2]; - } - - for (k = 0; k < 3; k++) { - vb[(3 * i + k) * stride + 0] = v[k][0]; - vb[(3 * i + k) * stride + 1] = v[k][1]; - vb[(3 * i + k) * stride + 2] = v[k][2]; - vb[(3 * i + k) * stride + 3] = n[k][0]; - vb[(3 * i + k) * stride + 4] = n[k][1]; - vb[(3 * i + k) * stride + 5] = n[k][2]; - - /* Use normal as color. */ - c[0] = n[k][0]; - c[1] = n[k][1]; - c[2] = n[k][2]; - len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2]; - if (len2 > 0.0f) { - float len = (float)sqrt(len2); - - c[0] /= len; - c[1] /= len; - c[2] /= len; - } - - vb[(3 * i + k) * stride + 6] = (c[0] * 0.5 + 0.5); - vb[(3 * i + k) * stride + 7] = (c[1] * 0.5 + 0.5); - vb[(3 * i + k) * stride + 8] = (c[2] * 0.5 + 0.5); - } - } - face_offset += attrib.face_num_verts[i]; + v[0][k] = attrib.vertices[3 * f0 + k]; + v[1][k] = attrib.vertices[3 * f1 + k]; + v[2][k] = attrib.vertices[3 * f2 + k]; + bmin[k] = (v[0][k] < bmin[k]) ? v[0][k] : bmin[k]; + bmin[k] = (v[1][k] < bmin[k]) ? v[1][k] : bmin[k]; + bmin[k] = (v[2][k] < bmin[k]) ? v[2][k] : bmin[k]; + bmax[k] = (v[0][k] > bmax[k]) ? v[0][k] : bmax[k]; + bmax[k] = (v[1][k] > bmax[k]) ? v[1][k] : bmax[k]; + bmax[k] = (v[2][k] > bmax[k]) ? v[2][k] : bmax[k]; } - o.vb = 0; - o.numTriangles = 0; - if (num_triangles > 0) { - glGenBuffers(1, &o.vb); - glBindBuffer(GL_ARRAY_BUFFER, o.vb); - glBufferData(GL_ARRAY_BUFFER, num_triangles * 3 * stride * sizeof(float), vb, GL_STATIC_DRAW); - o.numTriangles = num_triangles; + if (attrib.num_normals > 0) { + int f0 = idx0.vn_idx; + int f1 = idx1.vn_idx; + int f2 = idx2.vn_idx; + if (f0 >= 0 && f1 >= 0 && f2 >= 0) { + assert(3 * f0 + 2 < attrib.num_normals); + assert(3 * f1 + 2 < attrib.num_normals); + assert(3 * f2 + 2 < attrib.num_normals); + for (k = 0; k < 3; k++) { + n[0][k] = attrib.normals[3 * f0 + k]; + n[1][k] = attrib.normals[3 * f1 + k]; + n[2][k] = attrib.normals[3 * f2 + k]; + } + } else { /* normal index is not defined for this face */ + /* compute geometric normal */ + CalcNormal(n[0], v[0], v[1], v[2]); + n[1][0] = n[0][0]; + n[1][1] = n[0][1]; + n[1][2] = n[0][2]; + n[2][0] = n[0][0]; + n[2][1] = n[0][1]; + n[2][2] = n[0][2]; + } + } else { + /* compute geometric normal */ + CalcNormal(n[0], v[0], v[1], v[2]); + n[1][0] = n[0][0]; + n[1][1] = n[0][1]; + n[1][2] = n[0][2]; + n[2][0] = n[0][0]; + n[2][1] = n[0][1]; + n[2][2] = n[0][2]; } - free(vb); + for (k = 0; k < 3; k++) { + vb[(3 * i + k) * stride + 0] = v[k][0]; + vb[(3 * i + k) * stride + 1] = v[k][1]; + vb[(3 * i + k) * stride + 2] = v[k][2]; + vb[(3 * i + k) * stride + 3] = n[k][0]; + vb[(3 * i + k) * stride + 4] = n[k][1]; + vb[(3 * i + k) * stride + 5] = n[k][2]; - gDrawObject = o; + /* Use normal as color. */ + c[0] = n[k][0]; + c[1] = n[k][1]; + c[2] = n[k][2]; + len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2]; + if (len2 > 0.0f) { + float len = (float)sqrt(len2); + + c[0] /= len; + c[1] /= len; + c[2] /= len; + } + + vb[(3 * i + k) * stride + 6] = (c[0] * 0.5 + 0.5); + vb[(3 * i + k) * stride + 7] = (c[1] * 0.5 + 0.5); + vb[(3 * i + k) * stride + 8] = (c[2] * 0.5 + 0.5); + } + } + face_offset += attrib.face_num_verts[i]; + } + + o.vb = 0; + o.numTriangles = 0; + if (num_triangles > 0) { + glGenBuffers(1, &o.vb); + glBindBuffer(GL_ARRAY_BUFFER, o.vb); + glBufferData(GL_ARRAY_BUFFER, num_triangles * 3 * stride * sizeof(float), + vb, GL_STATIC_DRAW); + o.numTriangles = num_triangles; + } + + free(vb); + + gDrawObject = o; } - + printf("bmin = %f, %f, %f\n", bmin[0], bmin[1], bmin[2]); printf("bmax = %f, %f, %f\n", bmax[0], bmax[1], bmax[2]); tinyobj_attrib_free(&attrib); + tinyobj_shapes_free(shapes, num_shapes); + tinyobj_materials_free(materials, num_materials); return 1; } -static void reshapeFunc(GLFWwindow* window, int w, int h) -{ +static void reshapeFunc(GLFWwindow* window, int w, int h) { int fb_w, fb_h; glfwGetFramebufferSize(window, &fb_w, &fb_h); glViewport(0, 0, fb_w, fb_h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - gluPerspective(45.0, (GLdouble)w / (GLdouble)h, (GLdouble)0.01f, (GLdouble)100.0f); + gluPerspective(45.0, (GLdouble)w / (GLdouble)h, (GLdouble)0.01f, + (GLdouble)100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); @@ -383,81 +396,87 @@ static void reshapeFunc(GLFWwindow* window, int w, int h) height = h; } -static void keyboardFunc(GLFWwindow *window, int key, int scancode, int action, int mods) { +static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action, + int mods) { (void)window; (void)scancode; (void)mods; - if(action == GLFW_PRESS || action == GLFW_REPEAT){ - /* Move camera */ - float mv_x = 0, mv_y = 0, mv_z = 0; - if(key == GLFW_KEY_K) mv_x += 1; - else if(key == GLFW_KEY_J) mv_x += -1; - else if(key == GLFW_KEY_L) mv_y += 1; - else if(key == GLFW_KEY_H) mv_y += -1; - else if(key == GLFW_KEY_P) mv_z += 1; - else if(key == GLFW_KEY_N) mv_z += -1; + if (action == GLFW_PRESS || action == GLFW_REPEAT) { + /* Move camera */ + float mv_x = 0, mv_y = 0, mv_z = 0; + if (key == GLFW_KEY_K) + mv_x += 1; + else if (key == GLFW_KEY_J) + mv_x += -1; + else if (key == GLFW_KEY_L) + mv_y += 1; + else if (key == GLFW_KEY_H) + mv_y += -1; + else if (key == GLFW_KEY_P) + mv_z += 1; + else if (key == GLFW_KEY_N) + mv_z += -1; - if(key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE); - } + if (key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) + glfwSetWindowShouldClose(window, GL_TRUE); + } } -static void clickFunc(GLFWwindow* window, int button, int action, int mods){ +static void clickFunc(GLFWwindow* window, int button, int action, int mods) { (void)window; (void)mods; - if(button == GLFW_MOUSE_BUTTON_LEFT){ - if(action == GLFW_PRESS){ - mouseLeftPressed = 1; - trackball(prev_quat, 0.0, 0.0, 0.0, 0.0); - } else if(action == GLFW_RELEASE){ - mouseLeftPressed = 0; - } + if (button == GLFW_MOUSE_BUTTON_LEFT) { + if (action == GLFW_PRESS) { + mouseLeftPressed = 1; + trackball(prev_quat, 0.0, 0.0, 0.0, 0.0); + } else if (action == GLFW_RELEASE) { + mouseLeftPressed = 0; } - if(button == GLFW_MOUSE_BUTTON_RIGHT){ - if(action == GLFW_PRESS){ - mouseRightPressed = 1; - } else if(action == GLFW_RELEASE){ - mouseRightPressed = 0; - } + } + if (button == GLFW_MOUSE_BUTTON_RIGHT) { + if (action == GLFW_PRESS) { + mouseRightPressed = 1; + } else if (action == GLFW_RELEASE) { + mouseRightPressed = 0; } - if(button == GLFW_MOUSE_BUTTON_MIDDLE){ - if(action == GLFW_PRESS){ - mouseMiddlePressed = 1; - } else if(action == GLFW_RELEASE){ - mouseMiddlePressed = 0; - } + } + if (button == GLFW_MOUSE_BUTTON_MIDDLE) { + if (action == GLFW_PRESS) { + mouseMiddlePressed = 1; + } else if (action == GLFW_RELEASE) { + mouseMiddlePressed = 0; } + } } -static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){ +static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) { float rotScale = 1.0f; float transScale = 2.0f; (void)window; - if(mouseLeftPressed){ - trackball(prev_quat, - rotScale * (2.0f * prevMouseX - width) / (float)width, - rotScale * (height - 2.0f * prevMouseY) / (float)height, - rotScale * (2.0f * (float)mouse_x - width) / (float)width, - rotScale * (height - 2.0f * (float)mouse_y) / (float)height); + if (mouseLeftPressed) { + trackball(prev_quat, rotScale * (2.0f * prevMouseX - width) / (float)width, + rotScale * (height - 2.0f * prevMouseY) / (float)height, + rotScale * (2.0f * (float)mouse_x - width) / (float)width, + rotScale * (height - 2.0f * (float)mouse_y) / (float)height); - add_quats(prev_quat, curr_quat, curr_quat); - } else if (mouseMiddlePressed) { - eye[0] -= transScale * ((float)mouse_x - prevMouseX) / (float)width; - lookat[0] -= transScale * ((float)mouse_x - prevMouseX) / (float)width; - eye[1] += transScale * ((float)mouse_y - prevMouseY) / (float)height; - lookat[1] += transScale * ((float)mouse_y - prevMouseY) / (float)height; - } else if (mouseRightPressed) { - eye[2] += transScale * ((float)mouse_y - prevMouseY) / (float)height; - lookat[2] += transScale * ((float)mouse_y - prevMouseY) / (float)height; - } + add_quats(prev_quat, curr_quat, curr_quat); + } else if (mouseMiddlePressed) { + eye[0] -= transScale * ((float)mouse_x - prevMouseX) / (float)width; + lookat[0] -= transScale * ((float)mouse_x - prevMouseX) / (float)width; + eye[1] += transScale * ((float)mouse_y - prevMouseY) / (float)height; + lookat[1] += transScale * ((float)mouse_y - prevMouseY) / (float)height; + } else if (mouseRightPressed) { + eye[2] += transScale * ((float)mouse_y - prevMouseY) / (float)height; + lookat[2] += transScale * ((float)mouse_y - prevMouseY) / (float)height; + } - prevMouseX = (float)mouse_x; - prevMouseY = (float)mouse_y; + prevMouseX = (float)mouse_x; + prevMouseY = (float)mouse_y; } -static void Draw(const DrawObject* draw_object) -{ +static void Draw(const DrawObject* draw_object) { int i; glPolygonMode(GL_FRONT, GL_FILL); @@ -472,8 +491,8 @@ static void Draw(const DrawObject* draw_object) glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 36, (const void*)0); - glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float)*3)); - glColorPointer(3, GL_FLOAT, 36, (const void*)(sizeof(float)*6)); + glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float) * 3)); + glColorPointer(3, GL_FLOAT, 36, (const void*)(sizeof(float) * 6)); glDrawArrays(GL_TRIANGLES, 0, 3 * draw_object->numTriangles); CheckErrors("drawarrays"); @@ -492,7 +511,7 @@ static void Draw(const DrawObject* draw_object) glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 36, (const void*)0); - glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float)*3)); + glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float) * 3)); glDrawArrays(GL_TRIANGLES, 0, 3 * draw_object->numTriangles); CheckErrors("drawarrays"); @@ -515,9 +534,7 @@ static void Init() { up[2] = 0.0f; } - -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { if (argc < 2) { fprintf(stderr, "Needs input.obj\n"); return 0; @@ -527,13 +544,13 @@ int main(int argc, char **argv) printf("Initialize GLFW...\n"); - if(!glfwInit()){ + if (!glfwInit()) { fprintf(stderr, "Failed to initialize GLFW.\n"); return -1; } gWindow = glfwCreateWindow(width, height, "Obj viewer", NULL, NULL); - if(gWindow == NULL){ + if (gWindow == NULL) { fprintf(stderr, "Failed to open GLFW window.\n"); glfwTerminate(); return 1; @@ -571,32 +588,34 @@ int main(int argc, char **argv) maxExtent = 0.5f * (bmax[2] - bmin[2]); } - while(glfwWindowShouldClose(gWindow) == GL_FALSE) { - GLfloat mat[4][4]; + while (glfwWindowShouldClose(gWindow) == GL_FALSE) { + GLfloat mat[4][4]; - glfwPollEvents(); - glClearColor(0.1f, 0.2f, 0.3f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glfwPollEvents(); + glClearColor(0.1f, 0.2f, 0.3f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); + glEnable(GL_DEPTH_TEST); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - gluLookAt((GLdouble)eye[0], (GLdouble)eye[1], (GLdouble)eye[2], (GLdouble)lookat[0], (GLdouble)lookat[1], (GLdouble)lookat[2], (GLdouble)up[0], (GLdouble)up[1], (GLdouble)up[2]); - build_rotmatrix(mat, curr_quat); - glMultMatrixf(&mat[0][0]); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + gluLookAt((GLdouble)eye[0], (GLdouble)eye[1], (GLdouble)eye[2], + (GLdouble)lookat[0], (GLdouble)lookat[1], (GLdouble)lookat[2], + (GLdouble)up[0], (GLdouble)up[1], (GLdouble)up[2]); + build_rotmatrix(mat, curr_quat); + glMultMatrixf(&mat[0][0]); - /* Fit to -1, 1 */ - glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent); + /* Fit to -1, 1 */ + glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent); - /* Centerize object. */ - glTranslatef(-0.5f*(bmax[0] + bmin[0]), -0.5f*(bmax[1] + bmin[1]), -0.5f*(bmax[2] + bmin[2])); - - Draw(&gDrawObject); + /* Centerize object. */ + glTranslatef(-0.5f * (bmax[0] + bmin[0]), -0.5f * (bmax[1] + bmin[1]), + -0.5f * (bmax[2] + bmin[2])); - glfwSwapBuffers(gWindow); - } + Draw(&gDrawObject); + glfwSwapBuffers(gWindow); + } } glfwTerminate();