Compare commits
1 Commits
group-fix
...
vertex-col
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88ad575f62 |
12
README.md
12
README.md
@@ -89,6 +89,7 @@ TinyObjLoader is successfully used in ...
|
|||||||
|
|
||||||
* Group(parse multiple group name)
|
* Group(parse multiple group name)
|
||||||
* Vertex
|
* Vertex
|
||||||
|
* Vertex color(as an extension: https://blender.stackexchange.com/questions/31997/how-can-i-get-vertex-painted-obj-files-to-import-into-blender)
|
||||||
* Texcoord
|
* Texcoord
|
||||||
* Normal
|
* Normal
|
||||||
* Material
|
* Material
|
||||||
@@ -139,6 +140,13 @@ attrib_t::texcoords => 2 floats per vertex
|
|||||||
| u | v | u | v | u | v | u | v | .... | u | v |
|
| u | v | u | v | u | v | u | v | .... | u | v |
|
||||||
+-----------+-----------+-----------+-----------+ +-----------+
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
|
||||||
|
attrib_t::colors => 3 floats per vertex(vertex color. optional)
|
||||||
|
|
||||||
|
c[0] c[1] c[2] c[3] c[n-1]
|
||||||
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
|
||||||
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Each `shape_t::mesh_t` does not contain vertex data but contains array index to `attrib_t`.
|
Each `shape_t::mesh_t` does not contain vertex data but contains array index to `attrib_t`.
|
||||||
@@ -228,6 +236,10 @@ for (size_t s = 0; s < shapes.size(); s++) {
|
|||||||
tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
|
tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
|
||||||
tinyobj::real_t tx = attrib.texcoords[2*idx.texcoord_index+0];
|
tinyobj::real_t tx = attrib.texcoords[2*idx.texcoord_index+0];
|
||||||
tinyobj::real_t ty = attrib.texcoords[2*idx.texcoord_index+1];
|
tinyobj::real_t ty = attrib.texcoords[2*idx.texcoord_index+1];
|
||||||
|
// Optional: vertex colors
|
||||||
|
// tinyobj::real_t red = attrib.colors[3*idx.vertex_index+0];
|
||||||
|
// tinyobj::real_t green = attrib.colors[3*idx.vertex_index+1];
|
||||||
|
// tinyobj::real_t blue = attrib.colors[3*idx.vertex_index+2];
|
||||||
}
|
}
|
||||||
index_offset += fv;
|
index_offset += fv;
|
||||||
|
|
||||||
|
|||||||
31
models/cube-vertexcol.obj
Normal file
31
models/cube-vertexcol.obj
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000 0 0 0
|
||||||
|
v 0.000000 0.000000 2.000000 0 0 1
|
||||||
|
v 2.000000 0.000000 2.000000 0 1 0
|
||||||
|
v 2.000000 2.000000 2.000000 0 1 1
|
||||||
|
v 0.000000 2.000000 0.000000 1 0 0
|
||||||
|
v 0.000000 0.000000 0.000000 1 0 1
|
||||||
|
v 2.000000 0.000000 0.000000 1 1 0
|
||||||
|
v 2.000000 2.000000 0.000000 1 1 1
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1 2 3 4
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7 6 5
|
||||||
|
g right cube
|
||||||
|
usemtl red
|
||||||
|
f 4 3 7 8
|
||||||
|
g top cube
|
||||||
|
usemtl white
|
||||||
|
f 5 1 4 8
|
||||||
|
g left cube
|
||||||
|
usemtl green
|
||||||
|
f 5 6 2 1
|
||||||
|
g bottom cube
|
||||||
|
usemtl white
|
||||||
|
f 2 6 7 3
|
||||||
|
# 6 elements
|
||||||
@@ -625,6 +625,39 @@ TEST_CASE("g_ignored", "[Issue138]") {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("vertex-col-ext", "[Issue144]") {
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/cube-vertexcol.obj", gMtlBasePath);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintInfo(attrib, shapes, materials);
|
||||||
|
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
REQUIRE((8 * 3) == attrib.colors.size());
|
||||||
|
|
||||||
|
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 0]));
|
||||||
|
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 1]));
|
||||||
|
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 2]));
|
||||||
|
|
||||||
|
REQUIRE(0 == Approx(attrib.colors[3 * 1 + 0]));
|
||||||
|
REQUIRE(0 == Approx(attrib.colors[3 * 1 + 1]));
|
||||||
|
REQUIRE(1 == Approx(attrib.colors[3 * 1 + 2]));
|
||||||
|
|
||||||
|
REQUIRE(1 == Approx(attrib.colors[3 * 4 + 0]));
|
||||||
|
|
||||||
|
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 0]));
|
||||||
|
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 1]));
|
||||||
|
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 2]));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int
|
int
|
||||||
main(
|
main(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// version 1.1.0 : Support parsing vertex color(#144)
|
||||||
// version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138)
|
// version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138)
|
||||||
// version 1.0.7 : Support multiple tex options(#126)
|
// version 1.0.7 : Support multiple tex options(#126)
|
||||||
// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124)
|
// version 1.0.6 : Add TINYOBJLOADER_USE_DOUBLE option(#124)
|
||||||
@@ -230,6 +231,7 @@ typedef struct {
|
|||||||
std::vector<real_t> vertices; // 'v'
|
std::vector<real_t> vertices; // 'v'
|
||||||
std::vector<real_t> normals; // 'vn'
|
std::vector<real_t> normals; // 'vn'
|
||||||
std::vector<real_t> texcoords; // 'vt'
|
std::vector<real_t> texcoords; // 'vt'
|
||||||
|
std::vector<real_t> colors; // extension: vertex colors
|
||||||
} attrib_t;
|
} attrib_t;
|
||||||
|
|
||||||
typedef struct callback_t_ {
|
typedef struct callback_t_ {
|
||||||
@@ -602,6 +604,19 @@ static inline real_t parseReal(const char **token, double default_value = 0.0) {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool parseReal(const char **token, real_t *out) {
|
||||||
|
(*token) += strspn((*token), " \t");
|
||||||
|
const char *end = (*token) + strcspn((*token), " \t\r");
|
||||||
|
double val;
|
||||||
|
bool ret = tryParseDouble((*token), end, &val);
|
||||||
|
if (ret) {
|
||||||
|
real_t f = static_cast<real_t>(val);
|
||||||
|
(*out) = f;
|
||||||
|
}
|
||||||
|
(*token) = end;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void parseReal2(real_t *x, real_t *y, const char **token,
|
static inline void parseReal2(real_t *x, real_t *y, const char **token,
|
||||||
const double default_x = 0.0,
|
const double default_x = 0.0,
|
||||||
const double default_y = 0.0) {
|
const double default_y = 0.0) {
|
||||||
@@ -629,6 +644,23 @@ static inline void parseV(real_t *x, real_t *y, real_t *z, real_t *w,
|
|||||||
(*w) = parseReal(token, default_w);
|
(*w) = parseReal(token, default_w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extension: parse vertex with colors(6 items)
|
||||||
|
static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z, real_t *r,
|
||||||
|
real_t *g, real_t *b,
|
||||||
|
const char **token, const double default_x = 0.0,
|
||||||
|
const double default_y = 0.0,
|
||||||
|
const double default_z = 0.0) {
|
||||||
|
(*x) = parseReal(token, default_x);
|
||||||
|
(*y) = parseReal(token, default_y);
|
||||||
|
(*z) = parseReal(token, default_z);
|
||||||
|
|
||||||
|
(*r) = parseReal(token, 1.0);
|
||||||
|
(*g) = parseReal(token, 1.0);
|
||||||
|
(*b) = parseReal(token, 1.0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool parseOnOff(const char **token, bool default_value = true) {
|
static inline bool parseOnOff(const char **token, bool default_value = true) {
|
||||||
(*token) += strspn((*token), " \t");
|
(*token) += strspn((*token), " \t");
|
||||||
const char *end = (*token) + strcspn((*token), " \t\r");
|
const char *end = (*token) + strcspn((*token), " \t\r");
|
||||||
@@ -1421,6 +1453,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
attrib->vertices.clear();
|
attrib->vertices.clear();
|
||||||
attrib->normals.clear();
|
attrib->normals.clear();
|
||||||
attrib->texcoords.clear();
|
attrib->texcoords.clear();
|
||||||
|
attrib->colors.clear();
|
||||||
shapes->clear();
|
shapes->clear();
|
||||||
|
|
||||||
std::stringstream errss;
|
std::stringstream errss;
|
||||||
@@ -1453,6 +1486,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
std::vector<real_t> v;
|
std::vector<real_t> v;
|
||||||
std::vector<real_t> vn;
|
std::vector<real_t> vn;
|
||||||
std::vector<real_t> vt;
|
std::vector<real_t> vt;
|
||||||
|
std::vector<real_t> vc;
|
||||||
std::vector<tag_t> tags;
|
std::vector<tag_t> tags;
|
||||||
std::vector<std::vector<vertex_index> > faceGroup;
|
std::vector<std::vector<vertex_index> > faceGroup;
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -1495,10 +1529,15 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
||||||
token += 2;
|
token += 2;
|
||||||
real_t x, y, z;
|
real_t x, y, z;
|
||||||
parseReal3(&x, &y, &z, &token);
|
real_t r, g, b;
|
||||||
|
parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token);
|
||||||
v.push_back(x);
|
v.push_back(x);
|
||||||
v.push_back(y);
|
v.push_back(y);
|
||||||
v.push_back(z);
|
v.push_back(z);
|
||||||
|
|
||||||
|
vc.push_back(r);
|
||||||
|
vc.push_back(g);
|
||||||
|
vc.push_back(b);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1733,6 +1772,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
attrib->vertices.swap(v);
|
attrib->vertices.swap(v);
|
||||||
attrib->normals.swap(vn);
|
attrib->normals.swap(vn);
|
||||||
attrib->texcoords.swap(vt);
|
attrib->texcoords.swap(vt);
|
||||||
|
attrib->colors.swap(vc);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1785,6 +1825,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
// vertex
|
// vertex
|
||||||
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
||||||
token += 2;
|
token += 2;
|
||||||
|
// TODO(syoyo): Support parsing vertex color extension.
|
||||||
real_t x, y, z, w; // w is optional. default = 1.0
|
real_t x, y, z, w; // w is optional. default = 1.0
|
||||||
parseV(&x, &y, &z, &w, &token);
|
parseV(&x, &y, &z, &w, &token);
|
||||||
if (callback.vertex_cb) {
|
if (callback.vertex_cb) {
|
||||||
|
|||||||
Reference in New Issue
Block a user