From 75e64cd47a1217f4200bfcb2c65c5c1ccc196dbf Mon Sep 17 00:00:00 2001 From: Syoyo Fujita Date: Wed, 27 Jul 2016 16:16:51 +0900 Subject: [PATCH] Support parsing `w` element of vertex coordinate, and also third element of texture coordinates. Fixes #88. --- examples/callback_api/main.cc | 16 +++++++++++----- tiny_obj_loader.h | 36 ++++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/examples/callback_api/main.cc b/examples/callback_api/main.cc index 44ec62f..97b8867 100644 --- a/examples/callback_api/main.cc +++ b/examples/callback_api/main.cc @@ -27,13 +27,14 @@ typedef struct { } MyMesh; -void vertex_cb(void *user_data, float x, float y, float z) { +void vertex_cb(void *user_data, float x, float y, float z, float w) { MyMesh *mesh = reinterpret_cast(user_data); - printf("v[%ld] = %f, %f, %f\n", mesh->vertices.size() / 3, x, y, z); + printf("v[%ld] = %f, %f, %f (w %f)\n", mesh->vertices.size() / 3, x, y, z, w); mesh->vertices.push_back(x); mesh->vertices.push_back(y); mesh->vertices.push_back(z); + // Discard w } void normal_cb(void *user_data, float x, float y, float z) { @@ -45,12 +46,13 @@ void normal_cb(void *user_data, float x, float y, float z) { mesh->normals.push_back(z); } -void texcoord_cb(void *user_data, float x, float y) { +void texcoord_cb(void *user_data, float x, float y, float z) { MyMesh *mesh = reinterpret_cast(user_data); - printf("vt[%ld] = %f, %f\n", mesh->texcoords.size() / 2, x, y); + printf("vt[%ld] = %f, %f, %f\n", mesh->texcoords.size() / 3, x, y, z); mesh->texcoords.push_back(x); mesh->texcoords.push_back(y); + mesh->texcoords.push_back(z); } void index_cb(void *user_data, tinyobj::index_t *indices, int num_indices) { @@ -128,7 +130,11 @@ int main(int argc, char **argv) { MyMesh mesh; std::string err; - std::ifstream ifs("../../models/cornell_box.obj"); + std::string filename = "../../models/cornell_box.obj"; + if (argc > 1) { + filename = std::string(argv[1]); + } + std::ifstream ifs(filename.c_str()); if (ifs.fail()) { std::cerr << "file not found." << std::endl; diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h index 4f79f42..d9b8148 100644 --- a/tiny_obj_loader.h +++ b/tiny_obj_loader.h @@ -148,9 +148,12 @@ typedef struct { } attrib_t; typedef struct callback_t_ { - void (*vertex_cb)(void *user_data, float x, float y, float z); + // W is optional and set to 1 if there is no `w` item in `v` line + void (*vertex_cb)(void *user_data, float x, float y, float z, float w); void (*normal_cb)(void *user_data, float x, float y, float z); - void (*texcoord_cb)(void *user_data, float x, float y); + + // y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in `vt` line. + void (*texcoord_cb)(void *user_data, float x, float y, float z); // called per 'f' line. num_indices is the number of face indices(e.g. 3 for // triangle, 4 for quad) @@ -443,18 +446,13 @@ fail: return false; } -static inline float parseFloat(const char **token) { +static inline float parseFloat(const char **token, double default_value = 0.0) { (*token) += strspn((*token), " \t"); -#ifdef TINY_OBJ_LOADER_OLD_FLOAT_PARSER - float f = static_cast(atof(*token)); - (*token) += strcspn((*token), " \t\r"); -#else const char *end = (*token) + strcspn((*token), " \t\r"); - double val = 0.0; + double val = default_value; tryParseDouble((*token), end, &val); float f = static_cast(val); (*token) = end; -#endif return f; } @@ -470,6 +468,14 @@ static inline void parseFloat3(float *x, float *y, float *z, (*z) = parseFloat(token); } +static inline void parseV(float *x, float *y, float *z, float *w, + const char **token) { + (*x) = parseFloat(token); + (*y) = parseFloat(token); + (*z) = parseFloat(token); + (*w) = parseFloat(token, 1.0); +} + static tag_sizes parseTagTriple(const char **token) { tag_sizes ts; @@ -1348,10 +1354,10 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, // vertex if (token[0] == 'v' && IS_SPACE((token[1]))) { token += 2; - float x, y, z; - parseFloat3(&x, &y, &z, &token); + float x, y, z, w; // w is optional. default = 1.0 + parseV(&x, &y, &z, &w, &token); if (callback.vertex_cb) { - callback.vertex_cb(user_data, x, y, z); + callback.vertex_cb(user_data, x, y, z, w); } continue; } @@ -1370,10 +1376,10 @@ bool LoadObjWithCallback(void *user_data, const callback_t &callback, // texcoord if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { token += 3; - float x, y; - parseFloat2(&x, &y, &token); + float x, y, z; // y and z are optional. default = 0.0 + parseFloat3(&x, &y, &z, &token); if (callback.texcoord_cb) { - callback.texcoord_cb(user_data, x, y); + callback.texcoord_cb(user_data, x, y, z); } continue; }