diff options
Diffstat (limited to 'loader_example.cc')
-rw-r--r-- | loader_example.cc | 419 |
1 files changed, 419 insertions, 0 deletions
diff --git a/loader_example.cc b/loader_example.cc new file mode 100644 index 0000000..203fbf8 --- /dev/null +++ b/loader_example.cc @@ -0,0 +1,419 @@ +// +// g++ loader_example.cc +// +#define TINYOBJLOADER_IMPLEMENTATION +#include "tiny_obj_loader.h" + +#include <cassert> +#include <cstdio> +#include <cstdlib> +#include <fstream> +#include <iostream> +#include <sstream> + +#ifdef _WIN32 +#ifdef __cplusplus +extern "C" { +#endif +#include <windows.h> +#include <mmsystem.h> +#ifdef __cplusplus +} +#endif +#pragma comment(lib, "winmm.lib") +#else +#if defined(__unix__) || defined(__APPLE__) +#include <sys/time.h> +#else +#include <ctime> +#endif +#endif + +class timerutil { + public: +#ifdef _WIN32 + typedef DWORD time_t; + + timerutil() { ::timeBeginPeriod(1); } + ~timerutil() { ::timeEndPeriod(1); } + + void start() { t_[0] = ::timeGetTime(); } + void end() { t_[1] = ::timeGetTime(); } + + time_t sec() { return (time_t)((t_[1] - t_[0]) / 1000); } + time_t msec() { return (time_t)((t_[1] - t_[0])); } + time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000); } + time_t current() { return ::timeGetTime(); } + +#else +#if defined(__unix__) || defined(__APPLE__) + typedef unsigned long int time_t; + + void start() { gettimeofday(tv + 0, &tz); } + void end() { gettimeofday(tv + 1, &tz); } + + time_t sec() { return static_cast<time_t>(tv[1].tv_sec - tv[0].tv_sec); } + time_t msec() { + return this->sec() * 1000 + + static_cast<time_t>((tv[1].tv_usec - tv[0].tv_usec) / 1000); + } + time_t usec() { + return this->sec() * 1000000 + + static_cast<time_t>(tv[1].tv_usec - tv[0].tv_usec); + } + time_t current() { + struct timeval t; + gettimeofday(&t, NULL); + return static_cast<time_t>(t.tv_sec * 1000 + t.tv_usec); + } + +#else // C timer + // using namespace std; + typedef clock_t time_t; + + void start() { t_[0] = clock(); } + void end() { t_[1] = clock(); } + + time_t sec() { return (time_t)((t_[1] - t_[0]) / CLOCKS_PER_SEC); } + time_t msec() { return (time_t)((t_[1] - t_[0]) * 1000 / CLOCKS_PER_SEC); } + time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000000 / CLOCKS_PER_SEC); } + time_t current() { return (time_t)clock(); } + +#endif +#endif + + private: +#ifdef _WIN32 + DWORD t_[2]; +#else +#if defined(__unix__) || defined(__APPLE__) + struct timeval tv[2]; + struct timezone tz; +#else + time_t t_[2]; +#endif +#endif +}; + +static void PrintInfo(const tinyobj::attrib_t& attrib, + const std::vector<tinyobj::shape_t>& shapes, + const std::vector<tinyobj::material_t>& materials) { + std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl; + std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl; + std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2) + << std::endl; + + std::cout << "# of shapes : " << shapes.size() << std::endl; + std::cout << "# of materials : " << materials.size() << std::endl; + + for (size_t v = 0; v < attrib.vertices.size() / 3; v++) { + printf(" v[%ld] = (%f, %f, %f)\n", static_cast<long>(v), + static_cast<const double>(attrib.vertices[3 * v + 0]), + static_cast<const double>(attrib.vertices[3 * v + 1]), + static_cast<const double>(attrib.vertices[3 * v + 2])); + } + + for (size_t v = 0; v < attrib.normals.size() / 3; v++) { + printf(" n[%ld] = (%f, %f, %f)\n", static_cast<long>(v), + static_cast<const double>(attrib.normals[3 * v + 0]), + static_cast<const double>(attrib.normals[3 * v + 1]), + static_cast<const double>(attrib.normals[3 * v + 2])); + } + + for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) { + printf(" uv[%ld] = (%f, %f)\n", static_cast<long>(v), + static_cast<const double>(attrib.texcoords[2 * v + 0]), + static_cast<const double>(attrib.texcoords[2 * v + 1])); + } + + // For each shape + for (size_t i = 0; i < shapes.size(); i++) { + printf("shape[%ld].name = %s\n", static_cast<long>(i), + shapes[i].name.c_str()); + printf("Size of shape[%ld].indices: %lu\n", static_cast<long>(i), + static_cast<unsigned long>(shapes[i].mesh.indices.size())); + + size_t index_offset = 0; + + assert(shapes[i].mesh.num_face_vertices.size() == + shapes[i].mesh.material_ids.size()); + + printf("shape[%ld].num_faces: %lu\n", static_cast<long>(i), + static_cast<unsigned long>(shapes[i].mesh.num_face_vertices.size())); + + // For each face + for (size_t f = 0; f < shapes[i].mesh.num_face_vertices.size(); f++) { + size_t fnum = shapes[i].mesh.num_face_vertices[f]; + + printf(" face[%ld].fnum = %ld\n", static_cast<long>(f), + static_cast<unsigned long>(fnum)); + + // For each vertex in the face + for (size_t v = 0; v < fnum; v++) { + tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v]; + printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast<long>(f), + static_cast<long>(v), idx.vertex_index, idx.normal_index, + idx.texcoord_index); + } + + printf(" face[%ld].material_id = %d\n", static_cast<long>(f), + shapes[i].mesh.material_ids[f]); + + index_offset += fnum; + } + + printf("shape[%ld].num_tags: %lu\n", static_cast<long>(i), + static_cast<unsigned long>(shapes[i].mesh.tags.size())); + for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) { + printf(" tag[%ld] = %s ", static_cast<long>(t), + shapes[i].mesh.tags[t].name.c_str()); + printf(" ints: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j) { + printf("%ld", static_cast<long>(shapes[i].mesh.tags[t].intValues[j])); + if (j < (shapes[i].mesh.tags[t].intValues.size() - 1)) { + printf(", "); + } + } + printf("]"); + + printf(" floats: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j) { + printf("%f", static_cast<const double>( + shapes[i].mesh.tags[t].floatValues[j])); + if (j < (shapes[i].mesh.tags[t].floatValues.size() - 1)) { + printf(", "); + } + } + printf("]"); + + printf(" strings: ["); + for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j) { + printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str()); + if (j < (shapes[i].mesh.tags[t].stringValues.size() - 1)) { + printf(", "); + } + } + printf("]"); + printf("\n"); + } + } + + for (size_t i = 0; i < materials.size(); i++) { + printf("material[%ld].name = %s\n", static_cast<long>(i), + materials[i].name.c_str()); + printf(" material.Ka = (%f, %f ,%f)\n", + static_cast<const double>(materials[i].ambient[0]), + static_cast<const double>(materials[i].ambient[1]), + static_cast<const double>(materials[i].ambient[2])); + printf(" material.Kd = (%f, %f ,%f)\n", + static_cast<const double>(materials[i].diffuse[0]), + static_cast<const double>(materials[i].diffuse[1]), + static_cast<const double>(materials[i].diffuse[2])); + printf(" material.Ks = (%f, %f ,%f)\n", + static_cast<const double>(materials[i].specular[0]), + static_cast<const double>(materials[i].specular[1]), + static_cast<const double>(materials[i].specular[2])); + printf(" material.Tr = (%f, %f ,%f)\n", + static_cast<const double>(materials[i].transmittance[0]), + static_cast<const double>(materials[i].transmittance[1]), + static_cast<const double>(materials[i].transmittance[2])); + printf(" material.Ke = (%f, %f ,%f)\n", + static_cast<const double>(materials[i].emission[0]), + static_cast<const double>(materials[i].emission[1]), + static_cast<const double>(materials[i].emission[2])); + printf(" material.Ns = %f\n", + static_cast<const double>(materials[i].shininess)); + printf(" material.Ni = %f\n", static_cast<const double>(materials[i].ior)); + printf(" material.dissolve = %f\n", + static_cast<const double>(materials[i].dissolve)); + printf(" material.illum = %d\n", materials[i].illum); + printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str()); + printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str()); + printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str()); + printf(" material.map_Ns = %s\n", + materials[i].specular_highlight_texname.c_str()); + printf(" material.map_bump = %s\n", materials[i].bump_texname.c_str()); + printf(" bump_multiplier = %f\n", static_cast<const double>(materials[i].bump_texopt.bump_multiplier)); + printf(" material.map_d = %s\n", materials[i].alpha_texname.c_str()); + printf(" material.disp = %s\n", materials[i].displacement_texname.c_str()); + printf(" <<PBR>>\n"); + printf(" material.Pr = %f\n", static_cast<const double>(materials[i].roughness)); + printf(" material.Pm = %f\n", static_cast<const double>(materials[i].metallic)); + printf(" material.Ps = %f\n", static_cast<const double>(materials[i].sheen)); + printf(" material.Pc = %f\n", static_cast<const double>(materials[i].clearcoat_thickness)); + printf(" material.Pcr = %f\n", static_cast<const double>(materials[i].clearcoat_thickness)); + printf(" material.aniso = %f\n", static_cast<const double>(materials[i].anisotropy)); + printf(" material.anisor = %f\n", static_cast<const double>(materials[i].anisotropy_rotation)); + printf(" material.map_Ke = %s\n", materials[i].emissive_texname.c_str()); + printf(" material.map_Pr = %s\n", materials[i].roughness_texname.c_str()); + printf(" material.map_Pm = %s\n", materials[i].metallic_texname.c_str()); + printf(" material.map_Ps = %s\n", materials[i].sheen_texname.c_str()); + printf(" material.norm = %s\n", materials[i].normal_texname.c_str()); + std::map<std::string, std::string>::const_iterator it( + materials[i].unknown_parameter.begin()); + std::map<std::string, std::string>::const_iterator itEnd( + materials[i].unknown_parameter.end()); + + for (; it != itEnd; it++) { + printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str()); + } + printf("\n"); + } +} + +static bool TestLoadObj(const char* filename, const char* basepath = NULL, + bool triangulate = true) { + std::cout << "Loading " << filename << std::endl; + + tinyobj::attrib_t attrib; + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> materials; + + timerutil t; + t.start(); + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, + basepath, triangulate); + t.end(); + printf("Parsing time: %lu [msecs]\n", t.msec()); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + printf("Failed to load/parse .obj.\n"); + return false; + } + + PrintInfo(attrib, shapes, materials); + + return true; +} + +static bool TestStreamLoadObj() { + std::cout << "Stream Loading " << std::endl; + + std::stringstream objStream; + objStream << "mtllib cube.mtl\n" + "\n" + "v 0.000000 2.000000 2.000000\n" + "v 0.000000 0.000000 2.000000\n" + "v 2.000000 0.000000 2.000000\n" + "v 2.000000 2.000000 2.000000\n" + "v 0.000000 2.000000 0.000000\n" + "v 0.000000 0.000000 0.000000\n" + "v 2.000000 0.000000 0.000000\n" + "v 2.000000 2.000000 0.000000\n" + "# 8 vertices\n" + "\n" + "g front cube\n" + "usemtl white\n" + "f 1 2 3 4\n" + "g back cube\n" + "# expects white material\n" + "f 8 7 6 5\n" + "g right cube\n" + "usemtl red\n" + "f 4 3 7 8\n" + "g top cube\n" + "usemtl white\n" + "f 5 1 4 8\n" + "g left cube\n" + "usemtl green\n" + "f 5 6 2 1\n" + "g bottom cube\n" + "usemtl white\n" + "f 2 6 7 3\n" + "# 6 elements"; + + std::string matStream( + "newmtl white\n" + "Ka 0 0 0\n" + "Kd 1 1 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl red\n" + "Ka 0 0 0\n" + "Kd 1 0 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl green\n" + "Ka 0 0 0\n" + "Kd 0 1 0\n" + "Ks 0 0 0\n" + "\n" + "newmtl blue\n" + "Ka 0 0 0\n" + "Kd 0 0 1\n" + "Ks 0 0 0\n" + "\n" + "newmtl light\n" + "Ka 20 20 20\n" + "Kd 1 1 1\n" + "Ks 0 0 0"); + + using namespace tinyobj; + class MaterialStringStreamReader : public MaterialReader { + public: + MaterialStringStreamReader(const std::string& matSStream) + : m_matSStream(matSStream) {} + virtual ~MaterialStringStreamReader() {} + virtual bool operator()(const std::string& matId, + std::vector<material_t>* materials, + std::map<std::string, int>* matMap, + std::string* err) { + (void)matId; + std::string warning; + LoadMtl(matMap, materials, &m_matSStream, &warning); + + if (!warning.empty()) { + if (err) { + (*err) += warning; + } + } + return true; + } + + private: + std::stringstream m_matSStream; + }; + + MaterialStringStreamReader matSSReader(matStream); + tinyobj::attrib_t attrib; + std::vector<tinyobj::shape_t> shapes; + std::vector<tinyobj::material_t> materials; + std::string err; + bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &objStream, + &matSSReader); + + if (!err.empty()) { + std::cerr << err << std::endl; + } + + if (!ret) { + return false; + } + + PrintInfo(attrib, shapes, materials); + + return true; +} + +int main(int argc, char** argv) { + if (argc > 1) { + const char* basepath = "models/"; + if (argc > 2) { + basepath = argv[2]; + } + assert(true == TestLoadObj(argv[1], basepath)); + } else { + // assert(true == TestLoadObj("cornell_box.obj")); + // assert(true == TestLoadObj("cube.obj")); + assert(true == TestStreamLoadObj()); + assert(true == + TestLoadObj("models/catmark_torus_creases0.obj", "models/", false)); + } + + return 0; +} |