@@ -27,6 +27,7 @@ THE SOFTWARE.
2727// * Support line primitive.
2828// * Support points primitive.
2929// * Support multiple search path for .mtl(v1 API).
30+ // * Support vertex weight `vw`(as an tinyobj extension)
3031// version 1.4.0 : Modifed ParseTextureNameAndOption API
3132// version 1.3.1 : Make ParseTextureNameAndOption API public
3233// version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
@@ -162,8 +163,9 @@ struct texture_option_t {
162163 real_t origin_offset[3 ]; // -o u [v [w]] (default 0 0 0)
163164 real_t scale[3 ]; // -s u [v [w]] (default 1 1 1)
164165 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)
167169 char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
168170 bool blendu; // -blendu (default on)
169171 bool blendv; // -blendv (default on)
@@ -316,7 +318,6 @@ struct material_t {
316318 }
317319
318320#endif
319-
320321};
321322
322323struct tag_t {
@@ -327,6 +328,18 @@ struct tag_t {
327328 std::vector<std::string> stringValues;
328329};
329330
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+
330343// Index struct to support different indices for vtx/normal/texcoord.
331344// -1 means not used.
332345struct index_t {
@@ -383,6 +396,16 @@ struct attrib_t {
383396 std::vector<real_t > texcoord_ws; // 'vt'(w)
384397 std::vector<real_t > colors; // extension: vertex colors
385398
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+
386409 attrib_t () {}
387410
388411 //
@@ -625,11 +648,10 @@ bool ParseTextureNameAndOption(std::string *texname, texture_option_t *texopt,
625648#include < cstddef>
626649#include < cstdlib>
627650#include < cstring>
628- #include < limits>
629- #include < utility>
630-
631651#include < fstream>
652+ #include < limits>
632653#include < sstream>
654+ #include < utility>
633655
634656namespace tinyobj {
635657
@@ -1917,8 +1939,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
19171939
19181940 // Set a decent diffuse default value if a diffuse texture is specified
19191941 // without a matching Kd value.
1920- if (!has_kd)
1921- {
1942+ if (!has_kd) {
19221943 material.diffuse [0 ] = static_cast <real_t >(0.6 );
19231944 material.diffuse [1 ] = static_cast <real_t >(0.6 );
19241945 material.diffuse [2 ] = static_cast <real_t >(0.6 );
@@ -2181,6 +2202,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
21812202 std::vector<real_t > vn;
21822203 std::vector<real_t > vt;
21832204 std::vector<real_t > vc;
2205+ std::vector<skin_weight_t > vw;
21842206 std::vector<tag_t > tags;
21852207 PrimGroup prim_group;
21862208 std::string name;
@@ -2274,6 +2296,53 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
22742296 continue ;
22752297 }
22762298
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+
22772346 // line
22782347 if (token[0 ] == ' l' && IS_SPACE ((token[1 ]))) {
22792348 token += 2 ;
@@ -2675,6 +2744,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26752744 attrib->texcoords .swap (vt);
26762745 attrib->texcoord_ws .swap (vt);
26772746 attrib->colors .swap (vc);
2747+ attrib->skin_weights .swap (vw);
26782748
26792749 return true ;
26802750}
0 commit comments