Skip to content

Commit b205a7b

Browse files
committed
Merge branch 'release' of github.com:tinyobjloader/tinyobjloader into release
2 parents 83c96d2 + 0fd8b20 commit b205a7b

4 files changed

Lines changed: 85 additions & 37 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#Tiny Object Loader Cmake configuration file.
22
#This configures the Cmake system with multiple properties, depending
33
#on the platform and configuration it is set to build in.
4-
project(tinyobjloader)
54
cmake_minimum_required(VERSION 3.2)
5+
project(tinyobjloader)
66
set(TINYOBJLOADER_SOVERSION 2)
77
set(TINYOBJLOADER_VERSION 2.0.0-rc.10)
88

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ TinyObjLoader is successfully used in ...
7272
* liblava - A modern C++ and easy-to-use framework for the Vulkan API. [MIT]: https://github.com/liblava/liblava
7373
* rtxON - Simple Vulkan raytracing tutorials https://github.com/iOrange/rtxON
7474
* metal-ray-tracer - Writing ray-tracer using Metal Performance Shaders https://github.com/sergeyreznik/metal-ray-tracer https://sergeyreznik.github.io/metal-ray-tracer/index.html
75+
* Supernova Engine - 2D and 3D projects with Lua or C++ in data oriented design: https://github.com/supernovaengine/supernova
7576
* Your project here! (Letting us know via github issue is welcome!)
7677

7778
### Old version(v0.9.x)

python/sample.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import sys
22
import tinyobjloader
33

4+
is_numpy_available = False
5+
try:
6+
import numpy
7+
is_numpy_available = True
8+
except:
9+
print("NumPy not installed. Do not use numpy_*** API. If you encounter slow performance, see a performance tips for non-numpy API https://github.com/tinyobjloader/tinyobjloader/issues/275")
10+
411
filename = "../models/cornell_box.obj"
512

613

@@ -24,9 +31,9 @@
2431
print("Warn:", reader.Warning())
2532

2633
attrib = reader.GetAttrib()
27-
print("attrib.vertices = ", len(attrib.vertices))
28-
print("attrib.normals = ", len(attrib.normals))
29-
print("attrib.texcoords = ", len(attrib.texcoords))
34+
print("len(attrib.vertices) = ", len(attrib.vertices))
35+
print("len(attrib.normals) = ", len(attrib.normals))
36+
print("len(attrib.texcoords) = ", len(attrib.texcoords))
3037

3138
# vertex data must be `xyzxyzxyz...`
3239
assert len(attrib.vertices) % 3 == 0
@@ -37,6 +44,19 @@
3744
# texcoords data must be `uvuvuv...`
3845
assert len(attrib.texcoords) % 2 == 0
3946

47+
# Performance note
48+
# (direct?) array access through member variable is quite slow.
49+
# https://github.com/tinyobjloader/tinyobjloader/issues/275#issuecomment-753465833
50+
#
51+
# We encourage first copy(?) varible to Python world:
52+
#
53+
# vertices = attrib.vertices
54+
#
55+
# for i in range(...)
56+
# v = vertices[i]
57+
#
58+
# Or please consider using numpy_*** interface(e.g. numpy_vertices())
59+
4060
for (i, v) in enumerate(attrib.vertices):
4161
print("v[{}] = {}".format(i, v))
4262

@@ -46,7 +66,10 @@
4666
for (i, v) in enumerate(attrib.texcoords):
4767
print("vt[{}] = {}".format(i, t))
4868

49-
print("numpy_vertices = {}".format(attrib.numpy_vertices()))
69+
if is_numpy_available:
70+
print("numpy_v = {}".format(attrib.numpy_vertices()))
71+
print("numpy_vn = {}".format(attrib.numpy_normals()))
72+
print("numpy_vt = {}".format(attrib.numpy_texcoords()))
5073

5174
materials = reader.GetMaterials()
5275
print("Num materials: ", len(materials))
@@ -73,6 +96,9 @@
7396
print("[{}] v_idx {}".format(i, idx.vertex_index))
7497
print("[{}] vn_idx {}".format(i, idx.normal_index))
7598
print("[{}] vt_idx {}".format(i, idx.texcoord_index))
76-
print("numpy_indices = {}".format(shape.mesh.numpy_indices()))
77-
print("numpy_num_face_vertices = {}".format(shape.mesh.numpy_num_face_vertices()))
78-
print("numpy_material_ids = {}".format(shape.mesh.numpy_material_ids()))
99+
print("material_ids = {}".format(shape.mesh.material_ids))
100+
101+
if is_numpy_available:
102+
print("numpy_indices = {}".format(shape.mesh.numpy_indices()))
103+
print("numpy_num_face_vertices = {}".format(shape.mesh.numpy_num_face_vertices()))
104+
print("numpy_material_ids = {}".format(shape.mesh.numpy_material_ids()))

tiny_obj_loader.h

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,8 @@ struct attrib_t {
421421
struct callback_t {
422422
// W is optional and set to 1 if there is no `w` item in `v` line
423423
void (*vertex_cb)(void *user_data, real_t x, real_t y, real_t z, real_t w);
424+
void (*vertex_color_cb)(void *user_data, real_t x, real_t y, real_t z,
425+
real_t r, real_t g, real_t b, bool has_color);
424426
void (*normal_cb)(void *user_data, real_t x, real_t y, real_t z);
425427

426428
// y and z are optional and set to 0 if there is no `y` and/or `z` item(s) in
@@ -796,8 +798,21 @@ static std::istream &safeGetline(std::istream &is, std::string &t) {
796798
(static_cast<unsigned int>((x) - '0') < static_cast<unsigned int>(10))
797799
#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0'))
798800

801+
template <typename T>
802+
static inline std::string toString(const T &t) {
803+
std::stringstream ss;
804+
ss << t;
805+
return ss.str();
806+
}
807+
808+
struct warning_context
809+
{
810+
std::string *warn;
811+
size_t line_number;
812+
};
813+
799814
// Make index zero-base, and also support relative index.
800-
static inline bool fixIndex(int idx, int n, int *ret) {
815+
static inline bool fixIndex(int idx, int n, int *ret, bool allow_zero, const warning_context &context) {
801816
if (!ret) {
802817
return false;
803818
}
@@ -809,7 +824,13 @@ static inline bool fixIndex(int idx, int n, int *ret) {
809824

810825
if (idx == 0) {
811826
// zero is not allowed according to the spec.
812-
return false;
827+
if (context.warn) {
828+
(*context.warn) += "A zero value index found (will have a value of -1 for normal and tex indices. Line "
829+
+ toString(context.line_number) + ").\n";
830+
}
831+
832+
(*ret) = idx - 1;
833+
return allow_zero;
813834
}
814835

815836
if (idx < 0) {
@@ -1134,14 +1155,14 @@ static tag_sizes parseTagTriple(const char **token) {
11341155

11351156
// Parse triples with index offsets: i, i/j/k, i//k, i/j
11361157
static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
1137-
vertex_index_t *ret) {
1158+
vertex_index_t *ret, const warning_context &context) {
11381159
if (!ret) {
11391160
return false;
11401161
}
11411162

11421163
vertex_index_t vi(-1);
11431164

1144-
if (!fixIndex(atoi((*token)), vsize, &(vi.v_idx))) {
1165+
if (!fixIndex(atoi((*token)), vsize, &vi.v_idx, false, context)) {
11451166
return false;
11461167
}
11471168

@@ -1155,7 +1176,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11551176
// i//k
11561177
if ((*token)[0] == '/') {
11571178
(*token)++;
1158-
if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx))) {
1179+
if (!fixIndex(atoi((*token)), vnsize, &vi.vn_idx, true, context)) {
11591180
return false;
11601181
}
11611182
(*token) += strcspn((*token), "/ \t\r");
@@ -1164,7 +1185,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11641185
}
11651186

11661187
// i/j/k or i/j
1167-
if (!fixIndex(atoi((*token)), vtsize, &(vi.vt_idx))) {
1188+
if (!fixIndex(atoi((*token)), vtsize, &vi.vt_idx, true, context)) {
11681189
return false;
11691190
}
11701191

@@ -1176,7 +1197,7 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
11761197

11771198
// i/j/k
11781199
(*token)++; // skip '/'
1179-
if (!fixIndex(atoi((*token)), vnsize, &(vi.vn_idx))) {
1200+
if (!fixIndex(atoi((*token)), vnsize, &vi.vn_idx, true, context)) {
11801201
return false;
11811202
}
11821203
(*token) += strcspn((*token), "/ \t\r");
@@ -1419,7 +1440,7 @@ inline real_t GetLength(TinyObjPoint &e) {
14191440
}
14201441

14211442
inline TinyObjPoint Normalize(TinyObjPoint e) {
1422-
real_t inv_length = 1.0 / GetLength(e);
1443+
real_t inv_length = real_t(1) / GetLength(e);
14231444
return TinyObjPoint(e.x * inv_length, e.y * inv_length, e.z * inv_length );
14241445
}
14251446

@@ -2678,6 +2699,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26782699
vw.push_back(sw);
26792700
}
26802701

2702+
warning_context context;
2703+
context.warn = warn;
2704+
context.line_number = line_num;
2705+
26812706
// line
26822707
if (token[0] == 'l' && IS_SPACE((token[1]))) {
26832708
token += 2;
@@ -2688,13 +2713,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
26882713
vertex_index_t vi;
26892714
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
26902715
static_cast<int>(vn.size() / 3),
2691-
static_cast<int>(vt.size() / 2), &vi)) {
2716+
static_cast<int>(vt.size() / 2), &vi, context)) {
26922717
if (err) {
2693-
std::stringstream ss;
2694-
ss << "Failed parse `l' line(e.g. zero value for vertex index. "
2695-
"line "
2696-
<< line_num << ".)\n";
2697-
(*err) += ss.str();
2718+
(*err) += "Failed to parse `l' line (e.g. a zero value for vertex index. Line " +
2719+
toString(line_num) + ").\n";
26982720
}
26992721
return false;
27002722
}
@@ -2720,13 +2742,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
27202742
vertex_index_t vi;
27212743
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
27222744
static_cast<int>(vn.size() / 3),
2723-
static_cast<int>(vt.size() / 2), &vi)) {
2745+
static_cast<int>(vt.size() / 2), &vi, context)) {
27242746
if (err) {
2725-
std::stringstream ss;
2726-
ss << "Failed parse `p' line(e.g. zero value for vertex index. "
2727-
"line "
2728-
<< line_num << ".)\n";
2729-
(*err) += ss.str();
2747+
(*err) += "Failed to parse `p' line (e.g. a zero value for vertex index. Line " +
2748+
toString(line_num) + ").\n";
27302749
}
27312750
return false;
27322751
}
@@ -2756,12 +2775,10 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
27562775
vertex_index_t vi;
27572776
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
27582777
static_cast<int>(vn.size() / 3),
2759-
static_cast<int>(vt.size() / 2), &vi)) {
2778+
static_cast<int>(vt.size() / 2), &vi, context)) {
27602779
if (err) {
2761-
std::stringstream ss;
2762-
ss << "Failed parse `f' line(e.g. zero value for face index. line "
2763-
<< line_num << ".)\n";
2764-
(*err) += ss.str();
2780+
(*err) += "Failed to parse `f' line (e.g. a zero value for vertex index. Line " +
2781+
toString(line_num) + ").\n";
27652782
}
27662783
return false;
27672784
}
@@ -3138,11 +3155,15 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
31383155
// vertex
31393156
if (token[0] == 'v' && IS_SPACE((token[1]))) {
31403157
token += 2;
3141-
// TODO(syoyo): Support parsing vertex color extension.
3142-
real_t x, y, z, w; // w is optional. default = 1.0
3143-
parseV(&x, &y, &z, &w, &token);
3158+
real_t x, y, z;
3159+
real_t r, g, b;
3160+
3161+
bool found_color = parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token);
31443162
if (callback.vertex_cb) {
3145-
callback.vertex_cb(user_data, x, y, z, w);
3163+
callback.vertex_cb(user_data, x, y, z, r); // r=w is optional
3164+
}
3165+
if (callback.vertex_color_cb) {
3166+
callback.vertex_color_cb(user_data, x, y, z, r, g, b, found_color);
31463167
}
31473168
continue;
31483169
}

0 commit comments

Comments
 (0)