diff --git a/examples/viewer/viewer.c b/examples/viewer/viewer.c index e4b7d0e..22b8f04 100644 --- a/examples/viewer/viewer.c +++ b/examples/viewer/viewer.c @@ -41,12 +41,13 @@ static DrawObject gDrawObject; static int width = 768; static int height = 768; -static bool use_colors = false; +static enum { COLOR_FROM_NORMALS, COLOR_FROM_MATERIAL, COLOR_FROM_SHAPE, __COLOR_FROM_LAST } color_source = COLOR_FROM_NORMALS; static bool draw_wireframe = true; static const size_t OBJ_SIZE = sizeof(float) * 3 // pos + sizeof(float) * 3 // normal + sizeof(float) * 3 // color (based on normal) + + sizeof(float) * 3 // color (based on shape) + sizeof(float) * 3; // color from material file. static float prevMouseX, prevMouseY; @@ -364,6 +365,28 @@ static int LoadObjAndConvert(float bmin[3], float bmax[3], face_offset += (size_t)attrib.face_num_verts[i]; } + face_offset = 0; + for (i = 0; i < num_shapes; i++) + { + /* Get unique color based on shape index */ + float r = (cosf(6.283185f * ((float)i / num_shapes + 0.0f / 3.0f)) + 1.0f) / 2.0f; + float g = (cosf(6.283185f * ((float)i / num_shapes + 2.0f / 3.0f)) + 1.0f) / 2.0f; + float b = (cosf(6.283185f * ((float)i / num_shapes + 1.0f / 3.0f)) + 1.0f) / 2.0f; + size_t s; + for (s = 0; s < (size_t)shapes[i].length; s++) + { + size_t f = (size_t)shapes[i].face_offset + s; + size_t k; + for(k = 0; k < (size_t)attrib.face_num_verts[f]; k++) + { + vb[(face_offset + k) * stride + 12] = r; + vb[(face_offset + k) * stride + 13] = g; + vb[(face_offset + k) * stride + 14] = b; + } + face_offset += k; + } + } + o.vb = 0; o.numTriangles = 0; if (num_triangles > 0) { @@ -431,7 +454,8 @@ static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action, if (key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE); - if (key == GLFW_KEY_C) use_colors = !use_colors; + if (key == GLFW_KEY_C && ++color_source >= __COLOR_FROM_LAST) + color_source = COLOR_FROM_NORMALS; if (key == GLFW_KEY_W) draw_wireframe = !draw_wireframe; } } @@ -504,10 +528,10 @@ static void Draw(const DrawObject* draw_object) { glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)0); glNormalPointer(GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 3)); - if (use_colors) { - glColorPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 9)); - } else { - glColorPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 6)); + switch (color_source) { + case COLOR_FROM_NORMALS: glColorPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 6)); break; + case COLOR_FROM_MATERIAL: glColorPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 9)); break; + case COLOR_FROM_SHAPE: glColorPointer(3, GL_FLOAT, OBJ_SIZE, (const void*)(sizeof(float) * 12)); break; } glDrawArrays(GL_TRIANGLES, 0, 3 * draw_object->numTriangles); CheckErrors("drawarrays"); diff --git a/test/fixtures/shapes-triangulation.obj b/test/fixtures/shapes-triangulation.obj new file mode 100644 index 0000000..e7a8031 --- /dev/null +++ b/test/fixtures/shapes-triangulation.obj @@ -0,0 +1,47 @@ +# OBJ File: 'house' +# for tinyobjloader-c project + +o house +v -1.0000 0.0000 -1.0000 +v 1.0000 0.0000 -1.0000 +v 1.0000 0.0000 1.0000 +v -1.0000 0.0000 1.0000 +v -1.0000 1.0000 -1.0000 +v 1.0000 1.0000 -1.0000 +v 1.0000 1.0000 1.0000 +v -1.0000 1.0000 1.0000 +v 0.0000 2.0000 -1.0000 +v 0.0000 2.0000 1.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 1.0000 0.0000 +vn -0.7071 0.7071 0.0000 +vn 0.7071 0.7071 0.0000 + +s off +g base +f 1//1 2//1 3//1 4//1 +g facade +f 1//2 2//2 6//2 5//2 +f 5//2 6//2 9//2 +g left_wall +f 4//3 1//3 5//3 8//3 +g back_wall +f 3//4 4//4 8//4 7//4 +g back_roof_wall +f 7//4 8//4 10//4 +g right_wall +f 2//5 3//5 7//5 6//5 +g floor +f 5//6 6//6 7//6 +f 5//6 7//6 8//6 +g left_roof +f 8//7 5//7 9//7 10//7 +g right_roof +f 6//8 7//8 10//8 9//8 + +# TODO: Remove extra content at the end of the file when +# https://github.com/syoyo/tinyobjloader-c/issues/12 is fixed diff --git a/test/tinyobj_regression_tests.c b/test/tinyobj_regression_tests.c index ba0b985..53591a6 100644 --- a/test/tinyobj_regression_tests.c +++ b/test/tinyobj_regression_tests.c @@ -83,3 +83,44 @@ void test_tinyobj_negative_exponent(void) TEST_CHECK(float_equals(attrib.vertices[2], 2.0e-0f)); } } + +void test_tinyobj_shapes_triangulation(void) +{ + { + const char * filename = "fixtures/shapes-triangulation.obj"; + + tinyobj_shape_t * shape = NULL; + tinyobj_material_t * material = NULL; + tinyobj_attrib_t attrib; + + unsigned long num_shapes; + unsigned long num_materials; + + tinyobj_attrib_init(&attrib); + + int result = tinyobj_parse_obj(&attrib, &shape, &num_shapes, &material, &num_materials, filename, loadFile, NULL, TINYOBJ_FLAG_TRIANGULATE); + + TEST_CHECK(result == TINYOBJ_SUCCESS); + + TEST_CHECK(num_shapes == 9); + + TEST_CHECK(shape[0].face_offset == 0); + TEST_CHECK(shape[0].length == 2); + TEST_CHECK(shape[1].face_offset == 2); + TEST_CHECK(shape[1].length == 3); + TEST_CHECK(shape[2].face_offset == 5); + TEST_CHECK(shape[2].length == 2); + TEST_CHECK(shape[3].face_offset == 7); + TEST_CHECK(shape[3].length == 2); + TEST_CHECK(shape[4].face_offset == 9); + TEST_CHECK(shape[4].length == 1); + TEST_CHECK(shape[5].face_offset == 10); + TEST_CHECK(shape[5].length == 2); + TEST_CHECK(shape[6].face_offset == 12); + TEST_CHECK(shape[6].length == 2); + TEST_CHECK(shape[7].face_offset == 14); + TEST_CHECK(shape[7].length == 2); + TEST_CHECK(shape[8].face_offset == 16); + TEST_CHECK(shape[8].length == 2); + } +} \ No newline at end of file diff --git a/test/tinyobj_regression_tests.h b/test/tinyobj_regression_tests.h index 3861fa3..607574c 100644 --- a/test/tinyobj_regression_tests.h +++ b/test/tinyobj_regression_tests.h @@ -3,5 +3,6 @@ void test_tinyobj_crlf_string(void); void test_tinyobj_negative_exponent(void); +void test_tinyobj_shapes_triangulation(void); #endif diff --git a/test/tinyobj_tests.c b/test/tinyobj_tests.c index 0137ed1..645dae0 100644 --- a/test/tinyobj_tests.c +++ b/test/tinyobj_tests.c @@ -34,6 +34,7 @@ TEST_LIST = { { "crlf_string", test_tinyobj_crlf_string }, { "negative_exponent_issue26", test_tinyobj_negative_exponent }, + { "shapes_triangulation", test_tinyobj_shapes_triangulation }, { 0 } // required by acutest }; diff --git a/tinyobj_loader_c.h b/tinyobj_loader_c.h index 0cfc6f8..c1625fe 100644 --- a/tinyobj_loader_c.h +++ b/tinyobj_loader_c.h @@ -1647,7 +1647,11 @@ int tinyobj_parse_obj(tinyobj_attrib_t *attrib, tinyobj_shape_t **shapes, } } if (commands[i].type == COMMAND_F) { - face_count++; + if (flags & TINYOBJ_FLAG_TRIANGULATE) { + face_count += commands[i].num_f_num_verts; + } else { + face_count++; + } } }