@@ -30,6 +30,8 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
3030 fprintf (fp, " Ke %f %f %f\n " , mat.emission [0 ], mat.emission [1 ], mat.emission [2 ]);
3131 fprintf (fp, " Ns %f\n " , mat.shininess );
3232 fprintf (fp, " Ni %f\n " , mat.ior );
33+ fprintf (fp, " illum %d\n " , mat.illum );
34+ fprintf (fp, " \n " );
3335 // @todo { texture }
3436 }
3537
@@ -38,7 +40,7 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
3840 return true ;
3941}
4042
41- bool WriteObj (const std::string& filename, const std::vector<tinyobj::shape_t >& shapes, const std::vector<tinyobj::material_t >& materials, bool coordTransform) {
43+ 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) {
4244 FILE* fp = fopen (filename.c_str (), " w" );
4345 if (!fp) {
4446 fprintf (stderr, " Failed to open file [ %s ] for write.\n " , filename.c_str ());
@@ -48,119 +50,107 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
4850 std::string basename = GetFileBasename (filename);
4951 std::string material_filename = basename + " .mtl" ;
5052
51- int v_offset = 0 ;
52- int vn_offset = 0 ;
53- int vt_offset = 0 ;
5453 int prev_material_id = -1 ;
5554
56- fprintf (fp, " mtllib %s\n " , material_filename.c_str ());
55+ fprintf (fp, " mtllib %s\n\n " , material_filename.c_str ());
5756
58- for (size_t i = 0 ; i < shapes.size (); i++) {
57+ // facevarying vtx
58+ for (size_t k = 0 ; k < attributes.vertices .size (); k+=3 ) {
59+ if (coordTransform) {
60+ fprintf (fp, " v %f %f %f\n " ,
61+ attributes.vertices [k + 0 ],
62+ attributes.vertices [k + 2 ],
63+ -attributes.vertices [k + 1 ]);
64+ } else {
65+ fprintf (fp, " v %f %f %f\n " ,
66+ attributes.vertices [k + 0 ],
67+ attributes.vertices [k + 1 ],
68+ attributes.vertices [k + 2 ]);
69+ }
70+ }
5971
60- bool has_vn = false ;
61- bool has_vt = false ;
72+ fprintf (fp, " \n " );
73+
74+ // facevarying normal
75+ for (size_t k = 0 ; k < attributes.normals .size (); k += 3 ) {
76+ if (coordTransform) {
77+ fprintf (fp, " vn %f %f %f\n " ,
78+ attributes.normals [k + 0 ],
79+ attributes.normals [k + 2 ],
80+ -attributes.normals [k + 1 ]);
81+ } else {
82+ fprintf (fp, " vn %f %f %f\n " ,
83+ attributes.normals [k + 0 ],
84+ attributes.normals [k + 1 ],
85+ attributes.normals [k + 2 ]);
86+ }
87+ }
88+
89+ fprintf (fp, " \n " );
90+
91+ // facevarying texcoord
92+ for (size_t k = 0 ; k < attributes.texcoords .size (); k += 2 ) {
93+ fprintf (fp, " vt %f %f\n " ,
94+ attributes.texcoords [k + 0 ],
95+ attributes.texcoords [k + 1 ]);
96+ }
97+
98+ for (size_t i = 0 ; i < shapes.size (); i++) {
99+ fprintf (fp, " \n " );
62100
63101 if (shapes[i].name .empty ()) {
64102 fprintf (fp, " g Unknown\n " );
65103 } else {
66104 fprintf (fp, " g %s\n " , shapes[i].name .c_str ());
67105 }
68106
69- // if (!shapes[i].material.name.empty()) {
70- // fprintf(fp, "usemtl %s\n", shapes[i].material.name.c_str());
71- // }
72-
73- // facevarying vtx
74- for (size_t k = 0 ; k < shapes[i].mesh .indices .size () / 3 ; k++) {
75- for (int j = 0 ; j < 3 ; j++) {
76- int idx = shapes[i].mesh .indices [3 *k+j];
77- if (coordTransform) {
78- fprintf (fp, " v %f %f %f\n " ,
79- shapes[i].mesh .positions [3 *idx+0 ],
80- shapes[i].mesh .positions [3 *idx+2 ],
81- -shapes[i].mesh .positions [3 *idx+1 ]);
82- } else {
83- fprintf (fp, " v %f %f %f\n " ,
84- shapes[i].mesh .positions [3 *idx+0 ],
85- shapes[i].mesh .positions [3 *idx+1 ],
86- shapes[i].mesh .positions [3 *idx+2 ]);
87- }
88- }
89- }
90-
91- // facevarying normal
92- if (shapes[i].mesh .normals .size () > 0 ) {
93- for (size_t k = 0 ; k < shapes[i].mesh .indices .size () / 3 ; k++) {
94- for (int j = 0 ; j < 3 ; j++) {
95- int idx = shapes[i].mesh .indices [3 *k+j];
96- if (coordTransform) {
97- fprintf (fp, " vn %f %f %f\n " ,
98- shapes[i].mesh .normals [3 *idx+0 ],
99- shapes[i].mesh .normals [3 *idx+2 ],
100- -shapes[i].mesh .normals [3 *idx+1 ]);
101- } else {
102- fprintf (fp, " vn %f %f %f\n " ,
103- shapes[i].mesh .normals [3 *idx+0 ],
104- shapes[i].mesh .normals [3 *idx+1 ],
105- shapes[i].mesh .normals [3 *idx+2 ]);
106- }
107- }
108- }
109- }
110- if (shapes[i].mesh .normals .size () > 0 ) has_vn = true ;
111-
112- // facevarying texcoord
113- if (shapes[i].mesh .texcoords .size () > 0 ) {
114- for (size_t k = 0 ; k < shapes[i].mesh .indices .size () / 3 ; k++) {
115- for (int j = 0 ; j < 3 ; j++) {
116- int idx = shapes[i].mesh .indices [3 *k+j];
117- fprintf (fp, " vt %f %f\n " ,
118- shapes[i].mesh .texcoords [2 *idx+0 ],
119- shapes[i].mesh .texcoords [2 *idx+1 ]);
120- }
121- }
107+ bool has_vn = false ;
108+ bool has_vt = false ;
109+ // Assumes normals and textures are set shape-wise.
110+ if (shapes[i].mesh .indices .size () > 0 ){
111+ has_vn = shapes[i].mesh .indices [0 ].normal_index != -1 ;
112+ has_vt = shapes[i].mesh .indices [0 ].texcoord_index != -1 ;
122113 }
123- if (shapes[i].mesh .texcoords .size () > 0 ) has_vt = true ;
124114
125115 // face
126- for (size_t k = 0 ; k < shapes[i].mesh .indices .size () / 3 ; k++) {
127-
128- // Face index is 1-base.
129- // int v0 = shapes[i].mesh.indices[3*k+0] + 1 + v_offset;
130- // int v1 = shapes[i].mesh.indices[3*k+1] + 1 + v_offset;
131- // int v2 = shapes[i].mesh.indices[3*k+2] + 1 + v_offset;
132- int v0 = (3 *k + 0 ) + 1 + v_offset;
133- int v1 = (3 *k + 1 ) + 1 + v_offset;
134- int v2 = (3 *k + 2 ) + 1 + v_offset;
135-
136- int vt0 = (3 *k + 0 ) + 1 + vt_offset;
137- int vt1 = (3 *k + 1 ) + 1 + vt_offset;
138- int vt2 = (3 *k + 2 ) + 1 + vt_offset;
139-
140- int material_id = shapes[i].mesh .material_ids [k];
116+ int face_index = 0 ;
117+ for (size_t k = 0 ; k < shapes[i].mesh .indices .size (); k += shapes[i].mesh .num_face_vertices [face_index++]) {
118+ // Check Materials
119+ int material_id = shapes[i].mesh .material_ids [face_index];
141120 if (material_id != prev_material_id) {
142121 std::string material_name = materials[material_id].name ;
143122 fprintf (fp, " usemtl %s\n " , material_name.c_str ());
144123 prev_material_id = material_id;
145124 }
146125
147- if (has_vn && has_vt) {
148- fprintf (fp, " f %d/%d/%d %d/%d/%d %d/%d/%d\n " ,
149- v0, vt0, v0, v1, vt1, v1, v2, vt2, v2);
150- } else if (has_vn && !has_vt) {
151- fprintf (fp, " f %d//%d %d//%d %d//%d\n " , v0, v0, v1, v1, v2, v2);
152- } else if (!has_vn && has_vt) {
153- fprintf (fp, " f %d/%d %d/%d %d/%d\n " , v0, v0, v1, v1, v2, v2);
154- } else {
155- fprintf (fp, " f %d %d %d\n " , v0, v1, v2);
126+ unsigned char v_per_f = shapes[i].mesh .num_face_vertices [face_index];
127+ // Imperformant, but if you want to have variable vertices per face, you need some kind of a dynamic loop.
128+ fprintf (fp, " f" );
129+ for (int l = 0 ; l < v_per_f; l++){
130+ const tinyobj::index_t & ref = shapes[i].mesh .indices [k + l];
131+ if (has_vn && has_vt){
132+ // v0/t0/vn0
133+ fprintf (fp, " %d/%d/%d" , ref.vertex_index + 1 , ref.texcoord_index + 1 , ref.normal_index + 1 );
134+ continue ;
135+ }
136+ if (has_vn && !has_vt){
137+ // v0//vn0
138+ fprintf (fp, " %d//%d" , ref.vertex_index + 1 , ref.normal_index + 1 );
139+ continue ;
140+ }
141+ if (!has_vn && has_vt){
142+ // v0/vt0
143+ fprintf (fp, " %d/%d" , ref.vertex_index + 1 , ref.texcoord_index + 1 );
144+ continue ;
145+ }
146+ if (!has_vn && !has_vt){
147+ // v0 v1 v2
148+ fprintf (fp, " %d" , ref.vertex_index + 1 );
149+ continue ;
150+ }
156151 }
157-
152+ fprintf (fp, " \n " );
158153 }
159-
160- v_offset += shapes[i].mesh .indices .size ();
161- // vn_offset += shapes[i].mesh.normals.size() / 3;
162- vt_offset += shapes[i].mesh .texcoords .size () / 2 ;
163-
164154 }
165155
166156 fclose (fp);
0 commit comments