aboutsummaryrefslogtreecommitdiff
path: root/examples/obj_sticher
diff options
context:
space:
mode:
Diffstat (limited to 'examples/obj_sticher')
-rw-r--r--examples/obj_sticher/obj_sticher.cc110
-rw-r--r--examples/obj_sticher/obj_writer.cc176
-rw-r--r--examples/obj_sticher/obj_writer.h9
-rw-r--r--examples/obj_sticher/premake4.lua38
4 files changed, 333 insertions, 0 deletions
diff --git a/examples/obj_sticher/obj_sticher.cc b/examples/obj_sticher/obj_sticher.cc
new file mode 100644
index 0000000..f59fee4
--- /dev/null
+++ b/examples/obj_sticher/obj_sticher.cc
@@ -0,0 +1,110 @@
+//
+// Stiches multiple .obj files into one .obj.
+//
+#include "../../tiny_obj_loader.h"
+#include "obj_writer.h"
+
+#include <cassert>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+
+typedef std::vector<tinyobj::shape_t> Shape;
+typedef std::vector<tinyobj::material_t> Material;
+
+void
+StichObjs(
+ std::vector<tinyobj::shape_t>& out_shape,
+ std::vector<tinyobj::material_t>& out_material,
+ const std::vector<Shape>& shapes,
+ const std::vector<Material>& materials)
+{
+ int numShapes = 0;
+ for (size_t i = 0; i < shapes.size(); i++) {
+ numShapes += (int)shapes[i].size();
+ }
+
+ printf("Total # of shapes = %d\n", numShapes);
+ int materialIdOffset = 0;
+
+ size_t face_offset = 0;
+ for (size_t i = 0; i < shapes.size(); i++) {
+
+ for (size_t k = 0; k < shapes[i].size(); k++) {
+
+ std::string new_name = shapes[i][k].name;
+ // Add suffix
+ char buf[1024];
+ sprintf(buf, "_%04d", (int)i);
+ new_name += std::string(buf);
+
+ printf("shape[%ld][%ld].name = %s\n", i, k, shapes[i][k].name.c_str());
+ assert((shapes[i][k].mesh.indices.size() % 3) == 0);
+ assert((shapes[i][k].mesh.positions.size() % 3) == 0);
+
+ tinyobj::shape_t new_shape = shapes[i][k];
+ // Add offset.
+ for (size_t f = 0; f < new_shape.mesh.material_ids.size(); f++) {
+ new_shape.mesh.material_ids[f] += materialIdOffset;
+ }
+
+ new_shape.name = new_name;
+ printf("shape[%ld][%ld].new_name = %s\n", i, k, new_shape.name.c_str());
+
+ out_shape.push_back(new_shape);
+ }
+
+ materialIdOffset += materials[i].size();
+ }
+
+ for (size_t i = 0; i < materials.size(); i++) {
+ for (size_t k = 0; k < materials[i].size(); k++) {
+ out_material.push_back(materials[i][k]);
+ }
+ }
+
+}
+
+int
+main(
+ int argc,
+ char **argv)
+{
+ if (argc < 3) {
+ printf("Usage: obj_sticher input0.obj input1.obj ... output.obj\n");
+ exit(1);
+ }
+
+ int num_objfiles = argc - 2;
+ std::string out_filename = std::string(argv[argc-1]); // last element
+
+ std::vector<Shape> shapes;
+ std::vector<Material> materials;
+ shapes.resize(num_objfiles);
+ materials.resize(num_objfiles);
+
+ for (int i = 0; i < num_objfiles; i++) {
+ std::cout << "Loading " << argv[i+1] << " ... " << std::flush;
+
+ std::string err;
+ bool ret = tinyobj::LoadObj(shapes[i], materials[i], err, argv[i+1]);
+ if (!err.empty()) {
+ std::cerr << err << std::endl;
+ }
+ if (!ret) {
+ exit(1);
+ }
+
+ std::cout << "DONE." << std::endl;
+ }
+
+ std::vector<tinyobj::shape_t> out_shape;
+ std::vector<tinyobj::material_t> out_material;
+ StichObjs(out_shape, out_material, shapes, materials);
+
+ bool coordTransform = true;
+ bool ret = WriteObj(out_filename, out_shape, out_material, coordTransform);
+ assert(ret);
+
+ return 0;
+}
diff --git a/examples/obj_sticher/obj_writer.cc b/examples/obj_sticher/obj_writer.cc
new file mode 100644
index 0000000..2c8bd7b
--- /dev/null
+++ b/examples/obj_sticher/obj_writer.cc
@@ -0,0 +1,176 @@
+//
+// Simple wavefront .obj writer
+//
+#include "obj_writer.h"
+#include <cstdio>
+
+static std::string GetFileBasename(const std::string& FileName)
+{
+ if(FileName.find_last_of(".") != std::string::npos)
+ return FileName.substr(0, FileName.find_last_of("."));
+ return "";
+}
+
+bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t>& materials) {
+ FILE* fp = fopen(filename.c_str(), "w");
+ if (!fp) {
+ fprintf(stderr, "Failed to open file [ %s ] for write.\n", filename.c_str());
+ return false;
+ }
+
+ for (size_t i = 0; i < materials.size(); i++) {
+
+ tinyobj::material_t mat = materials[i];
+
+ fprintf(fp, "newmtl %s\n", mat.name.c_str());
+ fprintf(fp, "Ka %f %f %f\n", mat.ambient[0], mat.ambient[1], mat.ambient[2]);
+ fprintf(fp, "Kd %f %f %f\n", mat.diffuse[0], mat.diffuse[1], mat.diffuse[2]);
+ fprintf(fp, "Ks %f %f %f\n", mat.specular[0], mat.specular[1], mat.specular[2]);
+ fprintf(fp, "Kt %f %f %f\n", mat.transmittance[0], mat.specular[1], mat.specular[2]);
+ fprintf(fp, "Ke %f %f %f\n", mat.emission[0], mat.emission[1], mat.emission[2]);
+ fprintf(fp, "Ns %f\n", mat.shininess);
+ fprintf(fp, "Ni %f\n", mat.ior);
+ // @todo { texture }
+ }
+
+ fclose(fp);
+
+ return true;
+}
+
+bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform) {
+ FILE* fp = fopen(filename.c_str(), "w");
+ if (!fp) {
+ fprintf(stderr, "Failed to open file [ %s ] for write.\n", filename.c_str());
+ return false;
+ }
+
+ std::string basename = GetFileBasename(filename);
+ std::string material_filename = basename + ".mtl";
+
+ int v_offset = 0;
+ int vn_offset = 0;
+ int vt_offset = 0;
+ int prev_material_id = -1;
+
+ fprintf(fp, "mtllib %s\n", material_filename.c_str());
+
+ for (size_t i = 0; i < shapes.size(); i++) {
+
+ bool has_vn = false;
+ bool has_vt = false;
+
+ if (shapes[i].name.empty()) {
+ fprintf(fp, "g Unknown\n");
+ } else {
+ fprintf(fp, "g %s\n", shapes[i].name.c_str());
+ }
+
+ //if (!shapes[i].material.name.empty()) {
+ // fprintf(fp, "usemtl %s\n", shapes[i].material.name.c_str());
+ //}
+
+ // facevarying vtx
+ for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
+ for (int j = 0; j < 3; j++) {
+ int idx = shapes[i].mesh.indices[3*k+j];
+ if (coordTransform) {
+ fprintf(fp, "v %f %f %f\n",
+ shapes[i].mesh.positions[3*idx+0],
+ shapes[i].mesh.positions[3*idx+2],
+ -shapes[i].mesh.positions[3*idx+1]);
+ } else {
+ fprintf(fp, "v %f %f %f\n",
+ shapes[i].mesh.positions[3*idx+0],
+ shapes[i].mesh.positions[3*idx+1],
+ shapes[i].mesh.positions[3*idx+2]);
+ }
+ }
+ }
+
+ // facevarying normal
+ if (shapes[i].mesh.normals.size() > 0) {
+ for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
+ for (int j = 0; j < 3; j++) {
+ int idx = shapes[i].mesh.indices[3*k+j];
+ if (coordTransform) {
+ fprintf(fp, "vn %f %f %f\n",
+ shapes[i].mesh.normals[3*idx+0],
+ shapes[i].mesh.normals[3*idx+2],
+ -shapes[i].mesh.normals[3*idx+1]);
+ } else {
+ fprintf(fp, "vn %f %f %f\n",
+ shapes[i].mesh.normals[3*idx+0],
+ shapes[i].mesh.normals[3*idx+1],
+ shapes[i].mesh.normals[3*idx+2]);
+ }
+ }
+ }
+ }
+ if (shapes[i].mesh.normals.size() > 0) has_vn = true;
+
+ // facevarying texcoord
+ if (shapes[i].mesh.texcoords.size() > 0) {
+ for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
+ for (int j = 0; j < 3; j++) {
+ int idx = shapes[i].mesh.indices[3*k+j];
+ fprintf(fp, "vt %f %f\n",
+ shapes[i].mesh.texcoords[2*idx+0],
+ shapes[i].mesh.texcoords[2*idx+1]);
+ }
+ }
+ }
+ if (shapes[i].mesh.texcoords.size() > 0) has_vt = true;
+
+ // face
+ for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
+
+ // Face index is 1-base.
+ //int v0 = shapes[i].mesh.indices[3*k+0] + 1 + v_offset;
+ //int v1 = shapes[i].mesh.indices[3*k+1] + 1 + v_offset;
+ //int v2 = shapes[i].mesh.indices[3*k+2] + 1 + v_offset;
+ int v0 = (3*k + 0) + 1 + v_offset;
+ int v1 = (3*k + 1) + 1 + v_offset;
+ int v2 = (3*k + 2) + 1 + v_offset;
+
+ int vt0 = (3*k + 0) + 1 + vt_offset;
+ int vt1 = (3*k + 1) + 1 + vt_offset;
+ int vt2 = (3*k + 2) + 1 + vt_offset;
+
+ int material_id = shapes[i].mesh.material_ids[k];
+ if (material_id != prev_material_id) {
+ std::string material_name = materials[material_id].name;
+ fprintf(fp, "usemtl %s\n", material_name.c_str());
+ prev_material_id = material_id;
+ }
+
+ if (has_vn && has_vt) {
+ fprintf(fp, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
+ v0, vt0, v0, v1, vt1, v1, v2, vt2, v2);
+ } else if (has_vn && !has_vt) {
+ fprintf(fp, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
+ } else if (!has_vn && has_vt) {
+ fprintf(fp, "f %d/%d %d/%d %d/%d\n", v0, v0, v1, v1, v2, v2);
+ } else {
+ fprintf(fp, "f %d %d %d\n", v0, v1, v2);
+ }
+
+ }
+
+ v_offset += shapes[i].mesh.indices.size();
+ //vn_offset += shapes[i].mesh.normals.size() / 3;
+ vt_offset += shapes[i].mesh.texcoords.size() / 2;
+
+ }
+
+ fclose(fp);
+
+ //
+ // Write material file
+ //
+ bool ret = WriteMat(material_filename, materials);
+
+ return ret;
+}
+
+
diff --git a/examples/obj_sticher/obj_writer.h b/examples/obj_sticher/obj_writer.h
new file mode 100644
index 0000000..bb367b6
--- /dev/null
+++ b/examples/obj_sticher/obj_writer.h
@@ -0,0 +1,9 @@
+#ifndef __OBJ_WRITER_H__
+#define __OBJ_WRITER_H__
+
+#include "../../tiny_obj_loader.h"
+
+extern bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform = false);
+
+
+#endif // __OBJ_WRITER_H__
diff --git a/examples/obj_sticher/premake4.lua b/examples/obj_sticher/premake4.lua
new file mode 100644
index 0000000..9c2deb6
--- /dev/null
+++ b/examples/obj_sticher/premake4.lua
@@ -0,0 +1,38 @@
+lib_sources = {
+ "../../tiny_obj_loader.cc"
+}
+
+sources = {
+ "obj_sticher.cc",
+ "obj_writer.cc",
+ }
+
+-- premake4.lua
+solution "ObjStickerSolution"
+ configurations { "Release", "Debug" }
+
+ if (os.is("windows")) then
+ platforms { "x32", "x64" }
+ else
+ platforms { "native", "x32", "x64" }
+ end
+
+ includedirs {
+ "../../"
+ }
+
+ -- A project defines one build target
+ project "obj_sticher"
+ kind "ConsoleApp"
+ language "C++"
+ files { lib_sources, sources }
+
+ configuration "Debug"
+ defines { "DEBUG" } -- -DDEBUG
+ flags { "Symbols" }
+ targetname "obj_sticher_debug"
+
+ configuration "Release"
+ -- defines { "NDEBUG" } -- -NDEBUG
+ flags { "Symbols", "Optimize" }
+ targetname "obj_sticher"