Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ca47da4

Browse files
committed
Merge branch 'vertex_weight'
2 parents 53f17f2 + c7268ca commit ca47da4

File tree

5 files changed

+233
-8
lines changed

5 files changed

+233
-8
lines changed

examples/skin_weight/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
all:
2+
clang++ -std=c++11 -o skin_weight -I../../ -g main.cc

examples/skin_weight/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
This example printf skin weight of vertex(`vw`). TinyObjLoader extension.
2+
3+
## Run example
4+
5+
```
6+
$ ./skin_weight ../../models/skin-weight.obj
7+
```

examples/skin_weight/main.cc

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// g++ -g -std=c++11 main.cc
3+
//
4+
#define TINYOBJLOADER_IMPLEMENTATION
5+
#include "tiny_obj_loader.h"
6+
7+
#include <cassert>
8+
#include <cstdio>
9+
#include <cstdlib>
10+
#include <fstream>
11+
#include <iostream>
12+
#include <sstream>
13+
14+
#include <unordered_map> // C++11
15+
16+
#ifdef __clang__
17+
#pragma clang diagnostic push
18+
#if __has_warning("-Wzero-as-null-pointer-constant")
19+
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
20+
#endif
21+
#endif
22+
23+
static void ConstructVertexWeight(
24+
const std::vector<tinyobj::real_t> &vertices,
25+
const std::vector<tinyobj::skin_weight_t> &skin_weights,
26+
std::vector<tinyobj::skin_weight_t> *vertex_skin_weights)
27+
{
28+
size_t num_vertices = vertices.size() / 3;
29+
30+
vertex_skin_weights->resize(num_vertices);
31+
32+
for (size_t i = 0; i < skin_weights.size(); i++) {
33+
const tinyobj::skin_weight_t &skin = skin_weights[i];
34+
35+
assert(skin.vertex_id >= 0);
36+
assert(skin.vertex_id < num_vertices);
37+
38+
(*vertex_skin_weights)[skin.vertex_id] = skin;
39+
}
40+
41+
// now you can lookup i'th vertex skin weight by `vertex_skin_weights[i]`
42+
43+
44+
}
45+
46+
static bool TestLoadObj(const char* filename, const char* basepath = nullptr,
47+
bool triangulate = true) {
48+
std::cout << "Loading " << filename << std::endl;
49+
50+
tinyobj::attrib_t attrib;
51+
std::vector<tinyobj::shape_t> shapes;
52+
std::vector<tinyobj::material_t> materials;
53+
54+
std::string warn;
55+
std::string err;
56+
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename,
57+
basepath, triangulate);
58+
if (!warn.empty()) {
59+
std::cout << "WARN: " << warn << std::endl;
60+
}
61+
62+
if (!err.empty()) {
63+
std::cerr << "ERR: " << err << std::endl;
64+
}
65+
66+
if (!ret) {
67+
printf("Failed to load/parse .obj.\n");
68+
return false;
69+
}
70+
71+
std::vector<tinyobj::skin_weight_t> vertex_skin_weights;
72+
73+
ConstructVertexWeight(
74+
attrib.vertices,
75+
attrib.skin_weights,
76+
&vertex_skin_weights);
77+
78+
for (size_t v = 0; v < vertex_skin_weights.size(); v++) {
79+
std::cout << "vertex[" << v << "] num_weights = " << vertex_skin_weights[v].weightValues.size() << "\n";
80+
for (size_t w = 0; w < vertex_skin_weights[v].weightValues.size(); w++) {
81+
std::cout << " w[" << w << "] joint = " << vertex_skin_weights[v].weightValues[w].joint_id
82+
<< ", weight = " << vertex_skin_weights[v].weightValues[w].weight << "\n";
83+
}
84+
}
85+
86+
return true;
87+
}
88+
89+
90+
int main(int argc, char** argv) {
91+
if (argc < 2) {
92+
std::cerr << "Need input.obj\n";
93+
return EXIT_FAILURE;
94+
}
95+
96+
const char* basepath = nullptr;
97+
if (argc > 2) {
98+
basepath = argv[2];
99+
}
100+
assert(true == TestLoadObj(argv[1], basepath));
101+
102+
return 0;
103+
}

models/skin-weight.obj

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
mtllib cube.mtl
2+
3+
v 0.000000 2.000000 2.000000
4+
v 0.000000 0.000000 2.000000
5+
v 2.000000 0.000000 2.000000
6+
v 2.000000 2.000000 2.000000
7+
v 0.000000 2.000000 0.000000
8+
v 0.000000 0.000000 0.000000
9+
v 2.000000 0.000000 0.000000
10+
v 2.000000 2.000000 0.000000
11+
# 8 vertices
12+
13+
vw 0 0 1.0
14+
vw 1 0 0.5 1 0.5
15+
vw 2 1 1.0
16+
vw 3 2 1.0
17+
vw 4 3 1.0
18+
vw 5 0 0.25 1 0.25 2 0.25 3 0.25
19+
# No weight for 6th vertex
20+
# vw 6 0 1.0
21+
vw 7 0 1.0
22+
# max 4 joints
23+
24+
g front cube
25+
usemtl white
26+
f 1 2 3 4
27+
# two white spaces between 'back' and 'cube'
28+
g back cube
29+
# expects white material
30+
f 8 7 6 5
31+
g right cube
32+
usemtl red
33+
f 4 3 7 8
34+
g top cube
35+
usemtl white
36+
f 5 1 4 8
37+
g left cube
38+
usemtl green
39+
f 5 6 2 1
40+
g bottom cube
41+
usemtl white
42+
f 2 6 7 3
43+
# 6 elements

tiny_obj_loader.h

Lines changed: 78 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -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

322323
struct 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.
332345
struct 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

634656
namespace 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;
@@ -2676,6 +2745,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26762745
attrib->texcoords.swap(vt);
26772746
attrib->texcoord_ws.swap(vt);
26782747
attrib->colors.swap(vc);
2748+
attrib->skin_weights.swap(vw);
26792749

26802750
return true;
26812751
}

0 commit comments

Comments
 (0)