Update obj_writer.cc

This commit is contained in:
LZaw
2018-03-08 15:48:45 +01:00
committed by GitHub
parent 12837cc8b2
commit 707014f843

View File

@@ -30,6 +30,8 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
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);
fprintf(fp, "illum %d\n", mat.illum);
fprintf(fp, "\n");
// @todo { texture }
}
@@ -38,7 +40,7 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
return true;
}
bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform) {
bool WriteObj(const std::string& filename, const tinyobj::attrib_t& attributes, 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());
@@ -48,17 +50,53 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
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<tinyobj::shape_t>&
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);