diff --git a/examples/obj_sticher/obj_writer.cc b/examples/obj_sticher/obj_writer.cc index 694ce45..9ea8d7c 100644 --- a/examples/obj_sticher/obj_writer.cc +++ b/examples/obj_sticher/obj_writer.cc @@ -30,6 +30,8 @@ bool WriteMat(const std::string& filename, const std::vector& shapes, const std::vector& materials, bool coordTransform) { +bool WriteObj(const std::string& filename, const tinyobj::attrib_t& attributes, const std::vector& shapes, const std::vector& 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()); @@ -48,17 +50,53 @@ bool WriteObj(const std::string& filename, const std::vector& 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()); + fprintf(fp, "mtllib %s\n\n", material_filename.c_str()); + + // facevarying vtx + for (size_t k = 0; k < attributes.vertices.size(); k+=3) { + if (coordTransform) { + fprintf(fp, "v %f %f %f\n", + attributes.vertices[k + 0], + attributes.vertices[k + 2], + -attributes.vertices[k + 1]); + } else { + fprintf(fp, "v %f %f %f\n", + attributes.vertices[k + 0], + attributes.vertices[k + 1], + attributes.vertices[k + 2]); + } + } + + fprintf(fp, "\n"); + + // facevarying normal + for (size_t k = 0; k < attributes.normals.size(); k += 3) { + if (coordTransform) { + fprintf(fp, "vn %f %f %f\n", + attributes.normals[k + 0], + attributes.normals[k + 2], + -attributes.normals[k + 1]); + } else { + fprintf(fp, "vn %f %f %f\n", + attributes.normals[k + 0], + attributes.normals[k + 1], + attributes.normals[k + 2]); + } + } + + fprintf(fp, "\n"); + + // facevarying texcoord + for (size_t k = 0; k < attributes.texcoords.size(); k += 2) { + fprintf(fp, "vt %f %f\n", + attributes.texcoords[k + 0], + attributes.texcoords[k + 1]); + } for (size_t i = 0; i < shapes.size(); i++) { - - bool has_vn = false; - bool has_vt = false; + fprintf(fp, "\n"); if (shapes[i].name.empty()) { fprintf(fp, "g Unknown\n"); @@ -66,101 +104,53 @@ bool WriteObj(const std::string& filename, const std::vector& 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]); - } - } + bool has_vn = false; + bool has_vt = false; + // Assumes normals and textures are set shape-wise. + if(shapes[i].mesh.indices.size() > 0){ + has_vn = shapes[i].mesh.indices[0].normal_index != -1; + has_vt = shapes[i].mesh.indices[0].texcoord_index != -1; } - // 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]; + int face_index = 0; + for (size_t k = 0; k < shapes[i].mesh.indices.size(); k += shapes[i].mesh.num_face_vertices[face_index++]) { + // Check Materials + int material_id = shapes[i].mesh.material_ids[face_index]; 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); + unsigned char v_per_f = shapes[i].mesh.num_face_vertices[face_index]; + // Imperformant, but if you want to have variable vertices per face, you need some kind of a dynamic loop. + fprintf(fp, "f"); + for(int l = 0; l < v_per_f; l++){ + const tinyobj::index_t& ref = shapes[i].mesh.indices[k + l]; + if(has_vn && has_vt){ + // v0/t0/vn0 + fprintf(fp, " %d/%d/%d", ref.vertex_index + 1, ref.texcoord_index + 1, ref.normal_index + 1); + continue; + } + if(has_vn && !has_vt){ + // v0//vn0 + fprintf(fp, " %d//%d", ref.vertex_index + 1, ref.normal_index + 1); + continue; + } + if(!has_vn && has_vt){ + // v0/vt0 + fprintf(fp, " %d/%d", ref.vertex_index + 1, ref.texcoord_index + 1); + continue; + } + if(!has_vn && !has_vt){ + // v0 v1 v2 + fprintf(fp, " %d", ref.vertex_index + 1); + continue; + } } - + fprintf(fp, "\n"); } - - 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); diff --git a/examples/obj_sticher/obj_writer.h b/examples/obj_sticher/obj_writer.h index bb367b6..262c681 100644 --- a/examples/obj_sticher/obj_writer.h +++ b/examples/obj_sticher/obj_writer.h @@ -3,7 +3,6 @@ #include "../../tiny_obj_loader.h" -extern bool WriteObj(const std::string& filename, const std::vector& shapes, const std::vector& materials, bool coordTransform = false); - +extern bool WriteObj(const std::string& filename, const tinyobj::attrib_t& attributes, const std::vector& shapes, const std::vector& materials, bool coordTransform = false); #endif // __OBJ_WRITER_H__