11//
2- // Stiches multiple .obj files into one .obj.
2+ // Stiches multiple .obj files into one .obj.
33//
4+
5+ #define TINYOBJLOADER_IMPLEMENTATION
46#include " ../../tiny_obj_loader.h"
57#include " obj_writer.h"
68
1113
1214typedef std::vector<tinyobj::shape_t > Shape;
1315typedef std::vector<tinyobj::material_t > Material;
16+ typedef tinyobj::attrib_t Attribute;
1417
1518void
1619StichObjs (
20+ tinyobj::attrib_t & out_attribute,
1721 std::vector<tinyobj::shape_t >& out_shape,
1822 std::vector<tinyobj::material_t >& out_material,
23+ const std::vector<Attribute>& attributes,
1924 const std::vector<Shape>& shapes,
2025 const std::vector<Material>& materials)
2126{
22- int numShapes = 0 ;
23- for (size_t i = 0 ; i < shapes.size (); i++) {
24- numShapes += (int )shapes[i].size ();
27+ // The amount of attributes, shape-vectors and material-vecotrs should be the same.
28+ if (attributes.size () != shapes.size () && attributes.size () != materials.size ()){
29+ std::cerr << " Size of attributes, shapes and Materials don't fit!" << attributes.size () << " " << shapes.size () <<" " << materials.size () << std::endl;;
30+ exit (1 );
31+ }
32+ int num_shapes = 0 ;
33+ // 4 values (vertices, normals, texcoords, colors)
34+ std::vector<int > num_attributes (4 , 0 );
35+ int num_materials = 0 ;
36+ for (int i = 0 ; i < shapes.size (); i++){
37+ num_shapes += shapes[i].size ();
38+ }
39+ for (int i = 0 ; i < attributes.size (); i++){
40+ num_attributes[0 ] += attributes[i].vertices .size ();
41+ num_attributes[1 ] += attributes[i].normals .size ();
42+ num_attributes[2 ] += attributes[i].texcoords .size ();
43+ num_attributes[3 ] += attributes[i].colors .size ();
44+ }
45+ for (int i = 0 ; i < materials.size (); i++){
46+ num_materials += materials[i].size ();
2547 }
2648
27- printf (" Total # of shapes = %d\n " , numShapes);
28- int materialIdOffset = 0 ;
29-
30- size_t face_offset = 0 ;
49+ // More performant, than push_back
50+ out_attribute.vertices .resize (num_attributes[0 ]);
51+ out_attribute.normals .resize (num_attributes[1 ]);
52+ out_attribute.texcoords .resize (num_attributes[2 ]);
53+ out_attribute.colors .resize (num_attributes[3 ]);
54+ out_shape.resize (num_shapes);
55+ out_material.resize (num_materials);
56+
57+ int material_id_offset = 0 ;
58+ int shape_id_offset = 0 ;
59+ int vertex_idx_offset = 0 ;
60+ int normal_idx_offset = 0 ;
61+ int texcoord_idx_offset = 0 ;
62+ int color_idx_offset = 0 ;
63+
64+ // shapes.size() = attributes.size() = materials.size()
3165 for (size_t i = 0 ; i < shapes.size (); i++) {
3266
67+ // Copy shapes
3368 for (size_t k = 0 ; k < shapes[i].size (); k++) {
34-
3569 std::string new_name = shapes[i][k].name ;
3670 // Add suffix
3771 char buf[1024 ];
3872 sprintf (buf, " _%04d" , (int )i);
3973 new_name += std::string (buf);
4074
4175 printf (" shape[%ld][%ld].name = %s\n " , i, k, shapes[i][k].name .c_str ());
42- assert ((shapes[i][k].mesh .indices .size () % 3 ) == 0 );
43- assert ((shapes[i][k].mesh .positions .size () % 3 ) == 0 );
4476
4577 tinyobj::shape_t new_shape = shapes[i][k];
46- // Add offset.
47- for (size_t f = 0 ; f < new_shape.mesh .material_ids .size (); f++) {
48- new_shape.mesh .material_ids [f] += materialIdOffset;
78+ // Add material offset.
79+ for (size_t f = 0 ; f < new_shape.mesh .material_ids .size (); f++) {
80+ new_shape.mesh .material_ids [f] += material_id_offset;
81+ }
82+ // Add indices offset.
83+ for (size_t f = 0 ; f < new_shape.mesh .indices .size (); f++){
84+ tinyobj::index_t & ref = new_shape.mesh .indices [f];
85+ if (ref.vertex_index > -1 ){
86+ ref.vertex_index += vertex_idx_offset;
87+ }
88+ if (ref.normal_index > -1 ){
89+ ref.normal_index += normal_idx_offset;
90+ }
91+ if (ref.texcoord_index > -1 ){
92+ ref.texcoord_index += texcoord_idx_offset;
93+ }
4994 }
5095
5196 new_shape.name = new_name;
5297 printf (" shape[%ld][%ld].new_name = %s\n " , i, k, new_shape.name .c_str ());
5398
54- out_shape. push_back ( new_shape) ;
99+ out_shape[shape_id_offset++] = new_shape;
55100 }
56101
57- materialIdOffset += materials[i].size ();
58- }
59-
60- for (size_t i = 0 ; i < materials.size (); i++) {
102+ // Copy materials
61103 for (size_t k = 0 ; k < materials[i].size (); k++) {
62- out_material. push_back ( materials[i][k]) ;
104+ out_material[material_id_offset++] = materials[i][k];
63105 }
64- }
65106
107+ // Copy attributes (3 floats per vertex, 3 floats per normal, 2 floats per texture-coordinate, 3 floats per color)
108+ // You could also include a check here, if the sizes are dividable by 3 (resp. 2), but it's safe to simply assume, they do.
109+ std::copy (attributes[i].vertices .begin (), attributes[i].vertices .end (), out_attribute.vertices .begin () + vertex_idx_offset * 3 );
110+ vertex_idx_offset += attributes[i].vertices .size () / 3 ;
111+ std::copy (attributes[i].normals .begin (), attributes[i].normals .end (), out_attribute.normals .begin () + normal_idx_offset * 3 );
112+ normal_idx_offset += attributes[i].normals .size () / 3 ;
113+ std::copy (attributes[i].texcoords .begin (), attributes[i].texcoords .end (), out_attribute.texcoords .begin () + texcoord_idx_offset * 2 );
114+ texcoord_idx_offset += attributes[i].texcoords .size () / 2 ;
115+ std::copy (attributes[i].colors .begin (), attributes[i].colors .end (), out_attribute.colors .begin () + color_idx_offset);
116+ color_idx_offset += attributes[i].colors .size ();
117+ }
66118}
67119
68- int
69- main (
70- int argc,
71- char **argv)
120+ int main (int argc, char **argv)
72121{
73122 if (argc < 3 ) {
74123 printf (" Usage: obj_sticher input0.obj input1.obj ... output.obj\n " );
@@ -78,16 +127,15 @@ main(
78127 int num_objfiles = argc - 2 ;
79128 std::string out_filename = std::string (argv[argc-1 ]); // last element
80129
81- std::vector<Shape> shapes;
82- std::vector<Material> materials;
83- shapes.resize (num_objfiles);
84- materials.resize (num_objfiles);
130+ std::vector<Attribute> attributes (num_objfiles);
131+ std::vector<Shape> shapes (num_objfiles);
132+ std::vector<Material> materials (num_objfiles);
85133
86134 for (int i = 0 ; i < num_objfiles; i++) {
87135 std::cout << " Loading " << argv[i+1 ] << " ... " << std::flush;
88136
89137 std::string err;
90- bool ret = tinyobj::LoadObj (shapes[i], materials[i], err, argv[i+1 ]);
138+ bool ret = tinyobj::LoadObj (&attributes[i], & shapes[i], & materials[i], & err, argv[i+1 ]);
91139 if (!err.empty ()) {
92140 std::cerr << err << std::endl;
93141 }
@@ -98,12 +146,13 @@ main(
98146 std::cout << " DONE." << std::endl;
99147 }
100148
101- std::vector<tinyobj::shape_t > out_shape;
102- std::vector<tinyobj::material_t > out_material;
103- StichObjs (out_shape, out_material, shapes, materials);
149+ Attribute out_attribute;
150+ Shape out_shape;
151+ Material out_material;
152+ StichObjs (out_attribute, out_shape, out_material, attributes, shapes, materials);
104153
105154 bool coordTransform = true ;
106- bool ret = WriteObj (out_filename, out_shape, out_material, coordTransform);
155+ bool ret = WriteObj (out_filename, out_attribute, out_shape, out_material, coordTransform);
107156 assert (ret);
108157
109158 return 0 ;
0 commit comments