@@ -27,6 +27,7 @@ THE SOFTWARE.
27
27
// * Support line primitive.
28
28
// * Support points primitive.
29
29
// * Support multiple search path for .mtl(v1 API).
30
+ // * Support vertex weight `vw`(as an tinyobj extension)
30
31
// version 1.4.0 : Modifed ParseTextureNameAndOption API
31
32
// version 1.3.1 : Make ParseTextureNameAndOption API public
32
33
// version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
@@ -162,8 +163,9 @@ struct texture_option_t {
162
163
real_t origin_offset[3 ]; // -o u [v [w]] (default 0 0 0)
163
164
real_t scale[3 ]; // -s u [v [w]] (default 1 1 1)
164
165
real_t turbulence[3 ]; // -t u [v [w]] (default 0 0 0)
165
- int texture_resolution; // -texres resolution (No default value in the spec. We'll use -1)
166
- bool clamp; // -clamp (default false)
166
+ int texture_resolution; // -texres resolution (No default value in the spec.
167
+ // We'll use -1)
168
+ bool clamp; // -clamp (default false)
167
169
char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
168
170
bool blendu; // -blendu (default on)
169
171
bool blendv; // -blendv (default on)
@@ -316,7 +318,6 @@ struct material_t {
316
318
}
317
319
318
320
#endif
319
-
320
321
};
321
322
322
323
struct tag_t {
@@ -327,6 +328,18 @@ struct tag_t {
327
328
std::vector<std::string> stringValues;
328
329
};
329
330
331
+ struct joint_and_weight_t {
332
+ int joint_id;
333
+ real_t weight;
334
+ };
335
+
336
+ struct skin_weight_t {
337
+ int vertex_id; // Corresponding vertex index in `attrib_t::vertices`.
338
+ // Compared to `index_t`, this index must be positive and
339
+ // start with 0(does not allow relative indexing)
340
+ std::vector<joint_and_weight_t > weightValues;
341
+ };
342
+
330
343
// Index struct to support different indices for vtx/normal/texcoord.
331
344
// -1 means not used.
332
345
struct index_t {
@@ -383,6 +396,16 @@ struct attrib_t {
383
396
std::vector<real_t > texcoord_ws; // 'vt'(w)
384
397
std::vector<real_t > colors; // extension: vertex colors
385
398
399
+ //
400
+ // TinyObj extension.
401
+ //
402
+
403
+ // NOTE(syoyo): array index is based on the appearance order.
404
+ // To get a corresponding skin weight for a specific vertex id `vid`,
405
+ // Need to reconstruct a look up table: `skin_weight_t::vertex_id` == `vid`
406
+ // (e.g. using std::map, std::unordered_map)
407
+ std::vector<skin_weight_t > skin_weights;
408
+
386
409
attrib_t () {}
387
410
388
411
//
@@ -625,11 +648,10 @@ bool ParseTextureNameAndOption(std::string *texname, texture_option_t *texopt,
625
648
#include < cstddef>
626
649
#include < cstdlib>
627
650
#include < cstring>
628
- #include < limits>
629
- #include < utility>
630
-
631
651
#include < fstream>
652
+ #include < limits>
632
653
#include < sstream>
654
+ #include < utility>
633
655
634
656
namespace tinyobj {
635
657
@@ -1917,8 +1939,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
1917
1939
1918
1940
// Set a decent diffuse default value if a diffuse texture is specified
1919
1941
// without a matching Kd value.
1920
- if (!has_kd)
1921
- {
1942
+ if (!has_kd) {
1922
1943
material.diffuse [0 ] = static_cast <real_t >(0.6 );
1923
1944
material.diffuse [1 ] = static_cast <real_t >(0.6 );
1924
1945
material.diffuse [2 ] = static_cast <real_t >(0.6 );
@@ -2181,6 +2202,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
2181
2202
std::vector<real_t > vn;
2182
2203
std::vector<real_t > vt;
2183
2204
std::vector<real_t > vc;
2205
+ std::vector<skin_weight_t > vw;
2184
2206
std::vector<tag_t > tags;
2185
2207
PrimGroup prim_group;
2186
2208
std::string name;
@@ -2274,6 +2296,53 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
2274
2296
continue ;
2275
2297
}
2276
2298
2299
+ // skin weight. tinyobj extension
2300
+ if (token[0 ] == ' v' && token[1 ] == ' w' && IS_SPACE ((token[2 ]))) {
2301
+ token += 3 ;
2302
+
2303
+ // vw <vid> <joint_0> <weight_0> <joint_1> <weight_1> ...
2304
+ // example:
2305
+ // vw 0 0 0.25 1 0.25 2 0.5
2306
+
2307
+ // TODO(syoyo): Add syntax check
2308
+ int vid = 0 ;
2309
+ vid = parseInt (&token);
2310
+
2311
+ skin_weight_t sw;
2312
+
2313
+ sw.vertex_id = vid;
2314
+
2315
+ while (!IS_NEW_LINE (token[0 ])) {
2316
+ real_t j, w;
2317
+ // joint_id should not be negative, weight may be negative
2318
+ // TODO(syoyo): # of elements check
2319
+ parseReal2 (&j, &w, &token, -1.0 );
2320
+
2321
+ if (j < 0.0 ) {
2322
+ if (err) {
2323
+ std::stringstream ss;
2324
+ ss << " Failed parse `vw' line. joint_id is negative. "
2325
+ " line "
2326
+ << line_num << " .)\n " ;
2327
+ (*err) += ss.str ();
2328
+ }
2329
+ return false ;
2330
+ }
2331
+
2332
+ joint_and_weight_t jw;
2333
+
2334
+ jw.joint_id = int (j);
2335
+ jw.weight = w;
2336
+
2337
+ sw.weightValues .push_back (jw);
2338
+
2339
+ size_t n = strspn (token, " \t\r " );
2340
+ token += n;
2341
+ }
2342
+
2343
+ vw.push_back (sw);
2344
+ }
2345
+
2277
2346
// line
2278
2347
if (token[0 ] == ' l' && IS_SPACE ((token[1 ]))) {
2279
2348
token += 2 ;
@@ -2676,6 +2745,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
2676
2745
attrib->texcoords .swap (vt);
2677
2746
attrib->texcoord_ws .swap (vt);
2678
2747
attrib->colors .swap (vc);
2748
+ attrib->skin_weights .swap (vw);
2679
2749
2680
2750
return true ;
2681
2751
}
0 commit comments