aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSyoyo Fujita <syoyo@lighttransport.com>2017-10-12 19:04:38 +0900
committerSyoyo Fujita <syoyo@lighttransport.com>2017-10-12 19:04:38 +0900
commit88ad575f6247a215bda2a8938bc0f6e41d113ea4 (patch)
tree7db67bd5950169c0ed76746029335db31d22494a
parent3a9483ca6f06cfbf8215753981c8af2965d3afaa (diff)
downloadtinyobjloader-88ad575f6247a215bda2a8938bc0f6e41d113ea4.tar.gz
Initial support of parsing vertex color(extension format)
-rw-r--r--README.md12
-rw-r--r--models/cube-vertexcol.obj31
-rw-r--r--tests/tester.cc33
-rw-r--r--tiny_obj_loader.h43
4 files changed, 118 insertions, 1 deletions
diff --git a/README.md b/README.md
index 2737f08..8608c3b 100644
--- a/README.md
+++ b/README.md
@@ -89,6 +89,7 @@ TinyObjLoader is successfully used in ...
* Group(parse multiple group name)
* 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
* Normal
* Material
@@ -139,6 +140,13 @@ attrib_t::texcoords => 2 floats per vertex
| 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`.
@@ -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 tx = attrib.texcoords[2*idx.texcoord_index+0];
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;
diff --git a/models/cube-vertexcol.obj b/models/cube-vertexcol.obj
new file mode 100644
index 0000000..494ce21
--- /dev/null
+++ b/models/cube-vertexcol.obj
@@ -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
diff --git a/tests/tester.cc b/tests/tester.cc
index d4070c9..83b1df5 100644
--- a/tests/tester.cc
+++ b/tests/tester.cc
@@ -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
int
main(
diff --git a/tiny_obj_loader.h b/tiny_obj_loader.h
index 4e2f6b5..3d02e8d 100644
--- a/tiny_obj_loader.h
+++ b/tiny_obj_loader.h
@@ -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.7 : Support multiple tex options(#126)
// 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> normals; // 'vn'
std::vector<real_t> texcoords; // 'vt'
+ std::vector<real_t> colors; // extension: vertex colors
} attrib_t;
typedef struct callback_t_ {
@@ -602,6 +604,19 @@ static inline real_t parseReal(const char **token, double default_value = 0.0) {
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,
const double default_x = 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);
}
+// 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) {
(*token) += strspn((*token), " \t");
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->normals.clear();
attrib->texcoords.clear();
+ attrib->colors.clear();
shapes->clear();
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> vn;
std::vector<real_t> vt;
+ std::vector<real_t> vc;
std::vector<tag_t> tags;
std::vector<std::vector<vertex_index> > faceGroup;
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]))) {
token += 2;
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(y);
v.push_back(z);
+
+ vc.push_back(r);
+ vc.push_back(g);
+ vc.push_back(b);
continue;
}
@@ -1733,6 +1772,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
attrib->vertices.swap(v);
attrib->normals.swap(vn);
attrib->texcoords.swap(vt);
+ attrib->colors.swap(vc);
return true;
}
@@ -1785,6 +1825,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
// vertex
if (token[0] == 'v' && IS_SPACE((token[1]))) {
token += 2;
+ // TODO(syoyo): Support parsing vertex color extension.
real_t x, y, z, w; // w is optional. default = 1.0
parseV(&x, &y, &z, &w, &token);
if (callback.vertex_cb) {