1
1
//
2
- // Stiches multiple .obj files into one .obj.
2
+ // Stiches multiple .obj files into one .obj.
3
3
//
4
+
5
+ #define TINYOBJLOADER_IMPLEMENTATION
4
6
#include " ../../tiny_obj_loader.h"
5
7
#include " obj_writer.h"
6
8
11
13
12
14
typedef std::vector<tinyobj::shape_t > Shape;
13
15
typedef std::vector<tinyobj::material_t > Material;
16
+ typedef tinyobj::attrib_t Attribute;
14
17
15
18
void
16
19
StichObjs (
20
+ tinyobj::attrib_t & out_attribute,
17
21
std::vector<tinyobj::shape_t >& out_shape,
18
22
std::vector<tinyobj::material_t >& out_material,
23
+ const std::vector<Attribute>& attributes,
19
24
const std::vector<Shape>& shapes,
20
25
const std::vector<Material>& materials)
21
26
{
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 ();
25
47
}
26
48
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()
31
65
for (size_t i = 0 ; i < shapes.size (); i++) {
32
66
67
+ // Copy shapes
33
68
for (size_t k = 0 ; k < shapes[i].size (); k++) {
34
-
35
69
std::string new_name = shapes[i][k].name ;
36
70
// Add suffix
37
71
char buf[1024 ];
38
72
sprintf (buf, " _%04d" , (int )i);
39
73
new_name += std::string (buf);
40
74
41
75
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 );
44
76
45
77
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
+ }
49
94
}
50
95
51
96
new_shape.name = new_name;
52
97
printf (" shape[%ld][%ld].new_name = %s\n " , i, k, new_shape.name .c_str ());
53
98
54
- out_shape. push_back ( new_shape) ;
99
+ out_shape[shape_id_offset++] = new_shape;
55
100
}
56
101
57
- materialIdOffset += materials[i].size ();
58
- }
59
-
60
- for (size_t i = 0 ; i < materials.size (); i++) {
102
+ // Copy materials
61
103
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];
63
105
}
64
- }
65
106
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
+ }
66
118
}
67
119
68
- int
69
- main (
70
- int argc,
71
- char **argv)
120
+ int main (int argc, char **argv)
72
121
{
73
122
if (argc < 3 ) {
74
123
printf (" Usage: obj_sticher input0.obj input1.obj ... output.obj\n " );
@@ -78,16 +127,15 @@ main(
78
127
int num_objfiles = argc - 2 ;
79
128
std::string out_filename = std::string (argv[argc-1 ]); // last element
80
129
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);
85
133
86
134
for (int i = 0 ; i < num_objfiles; i++) {
87
135
std::cout << " Loading " << argv[i+1 ] << " ... " << std::flush;
88
136
89
137
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 ]);
91
139
if (!err.empty ()) {
92
140
std::cerr << err << std::endl;
93
141
}
@@ -98,12 +146,13 @@ main(
98
146
std::cout << " DONE." << std::endl;
99
147
}
100
148
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);
104
153
105
154
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);
107
156
assert (ret);
108
157
109
158
return 0 ;
0 commit comments