44 Commits

Author SHA1 Message Date
Syoyo Fujita
d5c722125a Show parsing time. 2016-07-09 00:52:27 +09:00
Syoyo Fujita
16ed0ac129 Update README. 2016-07-06 01:36:16 +09:00
Syoyo Fujita
b69d2a2c55 Add more links. 2016-05-29 16:37:30 +09:00
Syoyo Fujita
e210379335 Add Probulator 2016-05-29 14:08:27 +09:00
Syoyo Fujita
659976b8f3 Merge branch 'master' of github.com:syoyo/tinyobjloader 2016-05-29 13:32:24 +09:00
Syoyo Fujita
96ba498d70 Add voxelizer. 2016-05-29 13:09:00 +09:00
Syoyo Fujita
7ecb0b2f37 Use sefe getline for files with different line breaks. Fixes #81. 2016-05-15 16:20:35 +09:00
Syoyo Fujita
a14bbdb065 Merge pull request #80 from Vazquinhos/master
Fixing errors normal generation no triangulation. Remove warnings. Coding Style.
2016-05-13 21:18:48 +09:00
Vazquinhos
bfedfbb1fb Merge remote-tracking branch 'refs/remotes/syoyo/master'
# Conflicts:
#	tiny_obj_loader.h
2016-05-13 14:03:03 +02:00
Vazquinhos
41f46c7fd7 Error fixed with no triangulation. Removed warnings and modified coding brace style 2016-05-13 13:54:27 +02:00
Vazquinhos
a62dd278e2 Merge remote-tracking branch 'refs/remotes/syoyo/master' 2016-05-13 13:19:09 +02:00
Syoyo Fujita
a20e4ede85 Update document and version. 2016-05-13 20:09:49 +09:00
Syoyo Fujita
1ab0d147cb Merge pull request #79 from Vazquinhos/master
Flat normals calculation of obj without normals
2016-05-13 19:46:47 +09:00
Vazquinhos
9aee576b99 Added dependencies to cmath in order to use sqrt 2016-05-13 12:37:24 +02:00
Vazquinhos
0dcc72239d Files deleted of compilation log 2016-05-13 12:29:42 +02:00
Vazquinhos
33d5e9aa07 Test.cc modified with the new flags 2016-05-13 12:28:10 +02:00
Vazquinhos
e528741a8b Flat normals calculation of objects that their normals are empty 2016-05-13 12:25:48 +02:00
Syoyo Fujita
9c81fcb4cc Merge branch 'master' of github.com:syoyo/tinyobjloader 2016-04-15 12:32:06 +09:00
Syoyo Fujita
d119dcb976 Cosmetics. 2016-04-15 12:31:47 +09:00
Syoyo Fujita
6cdb3ec832 Merge pull request #72 from jlfwong/patch-1
Fix typo in README.md
2016-04-13 01:04:59 +09:00
Jamie Wong
1b24514ed9 Fix typo in README.md 2016-04-12 22:36:56 +08:00
Syoyo Fujita
0dd90f853d Merge pull request #71 from nlguillemot/master
use sscanf_s in MSVC
2016-04-05 19:00:54 +09:00
Nicolas Guillemot
b40e8c9427 use sscanf_s in MSVC
consistent with other uses of sscanf in the library
2016-04-02 15:15:29 -07:00
Syoyo Fujita
ad9911ef1b Initialize vertex_index. Fixes #70. 2016-03-25 18:43:52 +09:00
Syoyo Fujita
d6cd178d6a Add test data for issue 68.
Deploy to Bintray only for the build with tag.
2016-03-12 17:42:31 +09:00
Syoyo Fujita
6a25058ef5 Multiple deploy target. 2016-03-12 17:38:31 +09:00
Syoyo Fujita
06acb38847 Resurrect github release deploy.
Upload to bintray on specific build(DEPLOY_BUILD=1)
2016-03-12 17:30:06 +09:00
Syoyo Fujita
d688bbd910 Create dist directory to specify uploading files. 2016-03-12 17:16:50 +09:00
Syoyo Fujita
31c6633535 Fix file patterns in bintray description. 2016-03-12 16:27:58 +09:00
Syoyo Fujita
bf131698e5 Use Bintray friendly data format. 2016-03-12 16:20:40 +09:00
Syoyo Fujita
f2db18dc53 Add bintray deploy in travis build. 2016-03-12 16:13:04 +09:00
Syoyo Fujita
bc42bc47ad Don't create new shape by usemtl. Fixes #68. 2016-03-12 02:14:52 +09:00
Syoyo Fujita
31611161df Merge pull request #67 from pra85/patch-1
Fix a typo and add syntax highlighting language
2016-02-22 13:33:00 +09:00
Prayag Verma
21c93c51ed Fix a typo and add syntax highlighting language
`poweful` → `powerful`
2016-02-22 09:38:18 +05:30
Syoyo Fujita
b48d363dd2 Merge pull request #66 from mrdoob/patch-1
Fixed links.
2016-02-22 12:30:04 +09:00
Mr.doob
0f00a3b3e8 Fixed links. 2016-02-22 10:04:33 +09:00
Syoyo Fujita
ab10b76eda Merge pull request #65 from Ambal/master
Performance tweaks
2016-02-20 19:49:12 +09:00
Ambal
cf52401ca7 Replace calls to 'isdigit', 'isSpace' and 'isNewLine' functions to macros. Other small performance tweaks. 2016-02-20 12:20:19 +02:00
Syoyo Fujita
9c1826381c Update travis script. 2016-02-19 12:25:16 +09:00
Syoyo Fujita
7eb029edaf Add link to Android Vulkan demo. 2016-02-17 16:58:05 +09:00
Syoyo Fujita
d55863ce50 Fix coverall basedir argument. 2016-02-16 16:52:00 +09:00
Syoyo Fujita
ecf1005c72 Exclude feature_tests.* from coverall. 2016-02-16 16:50:09 +09:00
Syoyo Fujita
60ba85e9cd Add all_branches: true. 2016-02-15 14:52:26 +09:00
Syoyo Fujita
45b4924c27 Fix travis script. 2016-02-14 17:03:59 +09:00
8 changed files with 1322 additions and 186 deletions

37
.bintray.in Normal file
View File

@@ -0,0 +1,37 @@
{
/* Bintray package information.
In case the package already exists on Bintray, only the name, repo and subject
fields are mandatory. */
"package": {
"name": "releases", // Bintray package name
"repo": "tinyobjloader", // Bintray repository name
"subject": "syoyo" // Bintray subject (user or organization)
},
/* Package version information.
In case the version already exists on Bintray, only the name fields is mandatory. */
"version": {
"name": "@VERSION@",
"desc": "@VERSION@",
"released": "@DATE@",
"vcs_tag": "@VERSION@",
"gpgSign": false
},
/* Configure the files you would like to upload to Bintray and their upload path.
You can define one or more groups of patterns.
Each group contains three patterns:
includePattern: Pattern in the form of Ruby regular expression, indicating the path of files to be uploaded to Bintray.
excludePattern: Optional. Pattern in the form of Ruby regular expression, indicating the path of files to be removed from the list of files specified by the includePattern.
uploadPattern: Upload path on Bintray. The path can contain symbols in the form of $1, $2,... that are replaced with capturing groups defined in the include pattern.
Note: Regular expressions defined as part of the includePattern property must be wrapped with brackets. */
"files":
[ {"includePattern": "dist/(.*)", "uploadPattern": "$1"} ],
"publish": true
}

View File

@@ -15,7 +15,7 @@ matrix:
- g++-4.9 - g++-4.9
- clang-3.7 - clang-3.7
compiler: clang compiler: clang
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug env: DEPLOY_BUILD=1 COMPILER_VERSION=3.7 BUILD_TYPE=Debug
- addons: *1 - addons: *1
compiler: clang compiler: clang
env: COMPILER_VERSION=3.7 BUILD_TYPE=Release env: COMPILER_VERSION=3.7 BUILD_TYPE=Release
@@ -51,13 +51,35 @@ script:
.. ..
- ninja - ninja
- ./test_loader ../cornell_box.obj - ./test_loader ../cornell_box.obj
- if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r . -e examples -e tools -e jni - if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r .. -e examples -e tools -e
-e python -e images -E ".*CompilerId.*"; fi jni -e python -e images -E ".*CompilerId.*" -E ".*feature_tests.*" ; fi
- cd ..
- rm -rf dist
- mkdir dist
- cp tiny_obj_loader.h dist/
before_deploy:
- echo "Creating description file for bintray."
- ./tools/travis_postbuild.sh
deploy: deploy:
provider: releases - provider: bintray
file: ".bintray.json"
user: "syoyo"
key:
secure: W4F1VZcDcVOMe8Ymvo0bHery/JSmVhadl1NgAnGus6o7zVw7ChElKA1ho/NtqUbtoW8o1qUKMJdLQeh786jolocZJEJlns9JZ5FCet6H2b3kITfUa4GR5T11V/ZYwL3SajW8vZ1xu5UrpP5HHgFMYtxb1MFrNLDI60sh0RnyV/qFFBnCJGZPagF/M1mzbJeDml5xK5lShH0r8QpH+7MeQ1J8ungEyJ7UCyr1ao8gY9eq1/05IpHR9vri/d48EXQWHbqtI8EwCc7064oCYQGyYcLsD4yPEokwrdelkCvDquSpJLmbJENfZCc4vZGXsykjnQ8+gltJomBAivQFB9vc06ETEJssMzitbrfEZUrqFwZj/HZM7CYGXfGQWltL828SppCjsuWrgQ/VYXM5UgRpmhlxbqnuyxnYvKZ9EDW4+EnMkOmIl7WSDovp8E/4CZ0ghs+YyFS4SrgeqFCXS8bvxrkDUUPSipHuGBOt02fRnccKzU+3zU6Q5fghyLczz4ZtnOdk+Niz/njyF0SZfPYTUgb3GzAJ8Su6kvWJCAGdedON3n1F/TtybCE2dIdATxaO2uFQbwYjSOCiq209oCJ7MrsQZibRsa5a9YXyjlLkPxwOeVwo8wJyJclqWswIkhdSO8xvTnkwESv4yLzLutEOlBVlQbJzpyuS6vx0yHOYkwc=
all_branches: true
on:
repo: syoyo/tinyobjloader
condition: -n "$DEPLOY_BUILD"
tags: true
skip_cleanup: true
- provider: releases
api_key: api_key:
secure: AsXameK4GJn6h6wMmDrKTr7q/o9EI7hX7zWg1W6VaFBQKfkBvOmjJolWimjl6HMoRZ1NpMmK5GDm3zBlTUeABtgVBIyNWgE9vWS39ff6D5iQKcgScFsJkyILt0GikBqbN2pLGQ2t/M1Qh6n1sEIfzqekiCcF5Qvy5yYlYvHtaRGV02QeYAej/xx15/9SMuKTncHhjf63ClYPu8ODid7QUegJUvlQUeXoPsBDbaXMH2uDWoBWF7etX7G2Iob4NE8GX+ZP6dj+Ogi7p4HXThK650mzLL/pUl584EjjY/vePqx0cFhtpiRwvrW8SNPI1aJ1Phwa1enLRUgfS3bnkwQAMw/SCXSK2lnCvkUAXyTgpG03HWrZURj4vhEPXc7qHooO+dsfmi+JanYLaSDyrGpgQznLGjCMnVATimry0KxSufUY8Wt72Wh+nf7N0IgTUCjl32sWnQd/MRZPkxFuaf1h7r9RoH9KZY0yIOV09gABEFCGrOIZA2FcyhC2G26Bc4zyNrfMFpZ2DI76qdcWNdJGkRkpxtH9sGU8JgZu6Em2f1e6+SLgkBsPxbhRk5PwdhA9AXE2p9PmQqhO3jJKusGBZSoHAF7TlwagRY2J01yJxF7ge6zG9U8QuBqs1bB1zdnE34fHWOgs4st3inC+oBDOhvnEg1Nm/qeYVWMBzpwclSg= secure: AsXameK4GJn6h6wMmDrKTr7q/o9EI7hX7zWg1W6VaFBQKfkBvOmjJolWimjl6HMoRZ1NpMmK5GDm3zBlTUeABtgVBIyNWgE9vWS39ff6D5iQKcgScFsJkyILt0GikBqbN2pLGQ2t/M1Qh6n1sEIfzqekiCcF5Qvy5yYlYvHtaRGV02QeYAej/xx15/9SMuKTncHhjf63ClYPu8ODid7QUegJUvlQUeXoPsBDbaXMH2uDWoBWF7etX7G2Iob4NE8GX+ZP6dj+Ogi7p4HXThK650mzLL/pUl584EjjY/vePqx0cFhtpiRwvrW8SNPI1aJ1Phwa1enLRUgfS3bnkwQAMw/SCXSK2lnCvkUAXyTgpG03HWrZURj4vhEPXc7qHooO+dsfmi+JanYLaSDyrGpgQznLGjCMnVATimry0KxSufUY8Wt72Wh+nf7N0IgTUCjl32sWnQd/MRZPkxFuaf1h7r9RoH9KZY0yIOV09gABEFCGrOIZA2FcyhC2G26Bc4zyNrfMFpZ2DI76qdcWNdJGkRkpxtH9sGU8JgZu6Em2f1e6+SLgkBsPxbhRk5PwdhA9AXE2p9PmQqhO3jJKusGBZSoHAF7TlwagRY2J01yJxF7ge6zG9U8QuBqs1bB1zdnE34fHWOgs4st3inC+oBDOhvnEg1Nm/qeYVWMBzpwclSg=
file: tiny_obj_loader.h file: tiny_obj_loader.h
all_branches: true
on: on:
repo: syoyo/tinyobjloader repo: syoyo/tinyobjloader
tags: true tags: true
skip_cleanup: true

View File

@@ -13,14 +13,21 @@ tinyobjloader
http://syoyo.github.io/tinyobjloader/ http://syoyo.github.io/tinyobjloader/
Tiny but poweful single file wavefront obj loader written in C++. No dependency except for C++ STL. It can parse 10M over polygons with moderate memory and time. Tiny but powerful single file wavefront obj loader written in C++. No dependency except for C++ STL. It can parse 10M over polygons with moderate memory and time.
`tinyobjloader` is good for embedding .obj loader to your (global illumination) renderer ;-) `tinyobjloader` is good for embedding .obj loader to your (global illumination) renderer ;-)
Notice!
-------
`master` branch will be replaced with `develop` branch in the near future: https://github.com/syoyo/tinyobjloader/tree/develop
`develop` branch has more better support and clean API interface for loading .obj and also it has optimized multi-threaded parser(probably 10x faster than `master`). If you are new to use `TinyObjLoader`, I highly recommend to use `develop` branch.
What's new What's new
---------- ----------
* Mar 13, 2016 : Introduce `load_flag_t` and flat normal calculation flag! Thanks Vazquinhos!
* Jan 29, 2016 : Support n-polygon(no triangulation) and OpenSubdiv crease tag! Thanks dboogert! * Jan 29, 2016 : Support n-polygon(no triangulation) and OpenSubdiv crease tag! Thanks dboogert!
* Nov 26, 2015 : Now single-header only!. * Nov 26, 2015 : Now single-header only!.
* Nov 08, 2015 : Improved API. * Nov 08, 2015 : Improved API.
@@ -50,15 +57,22 @@ Use case
TinyObjLoader is successfully used in ... TinyObjLoader is successfully used in ...
* bullet3 https://github.com/erwincoumans/bullet3 * bullet3 https://github.com/erwincoumans/bullet3
* pbrt-v2 https://https://github.com/mmp/pbrt-v2 * pbrt-v2 https://github.com/mmp/pbrt-v2
* OpenGL game engine development http://swarminglogic.com/jotting/2013_10_gamedev01 * OpenGL game engine development http://swarminglogic.com/jotting/2013_10_gamedev01
* mallie https://lighttransport.github.io/mallie * mallie https://lighttransport.github.io/mallie
* IBLBaker (Image Based Lighting Baker). http://www.derkreature.com/iblbaker/ * IBLBaker (Image Based Lighting Baker). http://www.derkreature.com/iblbaker/
* Stanford CS148 http://web.stanford.edu/class/cs148/assignments/assignment3.pdf * Stanford CS148 http://web.stanford.edu/class/cs148/assignments/assignment3.pdf
* Awesome Bump http://awesomebump.besaba.com/about/ * Awesome Bump http://awesomebump.besaba.com/about/
* sdlgl3-wavefront OpenGL .obj viewer https://github.com/chrisliebert/sdlgl3-wavefront * sdlgl3-wavefront OpenGL .obj viewer https://github.com/chrisliebert/sdlgl3-wavefront
* pbrt-v3 https://https://github.com/mmp/pbrt-v3 * pbrt-v3 https://github.com/mmp/pbrt-v3
* cocos2d-x https://github.com/cocos2d/cocos2d-x/ * cocos2d-x https://github.com/cocos2d/cocos2d-x/
* Android Vulkan demo https://github.com/SaschaWillems/Vulkan
* voxelizer https://github.com/karimnaaji/voxelizer
* Probulator https://github.com/kayru/Probulator
* OptiX Prime baking https://github.com/nvpro-samples/optix_prime_baking
* FireRays SDK https://github.com/GPUOpen-LibrariesAndSDKs/FireRays_SDK
* parg, tiny C library of various graphics utilities and GL demos https://github.com/prideout/parg
* Opengl unit of ChronoEngine https://github.com/projectchrono/chrono-opengl
* Your project here! * Your project here!
Features Features
@@ -87,7 +101,7 @@ Usage
----- -----
TinyObjLoader triangulate input .obj by default. TinyObjLoader triangulate input .obj by default.
```c++
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
#include "tiny_obj_loader.h" #include "tiny_obj_loader.h"
@@ -150,10 +164,10 @@ TinyObjLoader triangulate input .obj by default.
} }
printf("\n"); printf("\n");
} }
```
Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(indices). `num_vertices[i]` stores the number of vertices for ith face. Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(indices). `num_vertices[i]` stores the number of vertices for ith face.
```c++
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc #define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
#include "tiny_obj_loader.h" #include "tiny_obj_loader.h"
@@ -162,8 +176,8 @@ Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(
std::vector<tinyobj::material_t> materials; std::vector<tinyobj::material_t> materials;
std::string err; std::string err;
bool triangulate = false; int flags = 1; // see load_flags_t enum for more information.
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), triangulate); bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), flags);
if (!err.empty()) { // `err` may contain warning message. if (!err.empty()) { // `err` may contain warning message.
std::cerr << err << std::endl; std::cerr << err << std::endl;
@@ -179,7 +193,7 @@ Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(
for (size_t n = 0; n < shapes[i].mesh.num_vertices.size(); n++) { for (size_t n = 0; n < shapes[i].mesh.num_vertices.size(); n++) {
int ngon = shapes[i].mesh.num_vertices[n]; int ngon = shapes[i].mesh.num_vertices[n];
for (size_t f = 0; f < ngon; f++) { for (size_t f = 0; f < ngon; f++) {
unsigend int v = shapes[i].mesh.indices[indexOffset + f]; unsigned int v = shapes[i].mesh.indices[indexOffset + f];
printf(" face[%ld] v[%ld] = (%f, %f, %f)\n", n, printf(" face[%ld] v[%ld] = (%f, %f, %f)\n", n,
shapes[i].mesh.positions[3*v+0], shapes[i].mesh.positions[3*v+0],
shapes[i].mesh.positions[3*v+1], shapes[i].mesh.positions[3*v+1],
@@ -190,3 +204,4 @@ Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(
} }
} }
```

View File

@@ -0,0 +1,9 @@
newmtl Material.001
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
newmtl Material.003
Ka 0 0 0
Kd 1 1 1
Ks 0 0 0

817
models/usemtl-issue-68.obj Normal file
View File

@@ -0,0 +1,817 @@
# https://github.com/syoyo/tinyobjloader/issues/68
# Blender v2.73 (sub 0) OBJ File: 'enemy.blend'
# www.blender.org
mtllib usemtl-issue-68.mtl
o Cube
v 1.864151 -1.219172 -5.532511
v 0.575869 -0.666304 5.896140
v 0.940448 1.000000 -1.971128
v 1.620345 1.000000 -5.815706
v 1.864152 1.000000 -6.334323
v 0.575869 -0.129842 5.896143
v 5.440438 -1.462153 -5.818601
v 4.896782 -1.462153 -2.744413
v 1.000825 -0.677484 1.899605
v 5.440438 -1.246362 -5.818600
v 1.000825 0.852342 1.899608
v 4.896782 -1.246362 -2.744412
v 1.160660 -0.450871 -2.356325
v 1.704316 -0.450871 -5.430513
v 1.000825 -0.351920 -1.293797
v 1.000825 1.000000 -1.293794
v 1.160660 -0.877888 -2.356326
v 1.704316 -0.877888 -5.430514
v 1.000825 -1.219172 -1.452514
v 1.000825 1.000000 -1.452511
v 1.000825 -0.351920 1.759410
v 1.000825 1.000000 1.759413
v 9.097919 1.221145 -6.212147
v 8.356775 1.221145 -2.021231
v 1.864151 -0.109586 -6.334325
v 0.575869 -0.398073 5.896141
v 9.097919 0.943958 -6.212148
v 8.356775 0.943958 -2.021233
v 1.061916 0.113661 -1.797961
v 1.000825 0.161258 1.899606
v 1.000825 0.324040 -1.293795
v 1.803060 0.113661 -5.988876
v 1.000825 -0.109586 -1.452513
v 1.061916 0.776753 -1.797960
v 1.803061 0.776753 -5.988875
v 1.000825 0.324040 1.759412
v 0.000825 -1.219172 -5.532512
v 0.000825 -0.666304 5.896139
v 0.000826 1.000000 -6.334325
v 0.000825 -0.129842 5.896140
v 0.000825 0.852342 1.899606
v 0.000825 -0.677484 1.899604
v 0.000825 -0.351920 -1.293797
v 0.000825 1.000000 -1.293796
v 0.000825 1.000000 -1.452513
v 0.000825 -1.219172 -1.452515
v 0.000825 -0.351920 1.759409
v 0.000825 1.000000 1.759411
v 0.000826 -0.109586 -6.334326
v 0.000825 -0.398073 5.896140
v 0.152918 1.000000 -5.815708
v 0.152917 1.000000 -1.971130
v 0.940448 1.168419 -1.971128
v 1.620345 1.168419 -5.815706
v 0.152918 1.168419 -5.815708
v 0.152917 1.168419 -1.971130
v 0.921118 1.091883 -1.050430
v 0.921118 1.091883 1.516050
v 0.080533 1.091883 -1.050432
v 0.080533 1.091883 1.516048
v 0.613003 -0.553430 5.546911
v 0.963691 -0.559956 2.248834
v 0.613003 -0.396857 5.546912
v 0.963691 -0.070362 2.248835
v 1.499370 -0.994317 3.966028
v 1.850058 -0.997914 0.667950
v 1.499370 -0.908021 3.966029
v 1.850058 -0.728071 0.667951
v 1.601022 0.760960 -6.334324
v 1.601021 0.129454 -6.334325
v 0.263955 0.760960 -6.334325
v 0.263955 0.129454 -6.334325
v 1.334809 0.760960 -7.515329
v 1.334809 0.129455 -7.515330
v 0.530168 0.760960 -7.515330
v 0.530168 0.129455 -7.515330
v 1.192720 0.649445 -7.515329
v 1.192720 0.240971 -7.515330
v 0.672258 0.649445 -7.515330
v 0.672258 0.240971 -7.515330
v 1.192719 0.649444 -6.524630
v 1.192719 0.240970 -6.524631
v 0.672257 0.649444 -6.524631
v 0.672257 0.240970 -6.524631
v 3.851026 0.431116 -1.883326
v 3.851026 0.946662 -1.883325
v 4.592170 0.946662 -6.074241
v 4.592169 0.431116 -6.074242
v 4.995714 0.561404 -1.918362
v 4.995714 1.016394 -1.918360
v 5.736857 1.016394 -6.109276
v 5.736857 0.561404 -6.109277
v 3.975454 0.471731 -2.162156
v 3.975454 0.919244 -2.162155
v 4.618796 0.919244 -5.800034
v 4.618795 0.471730 -5.800035
v 4.969088 0.584825 -2.192568
v 4.969088 0.979775 -2.192567
v 5.612430 0.979775 -5.830446
v 5.612429 0.584825 -5.830447
v 0.864214 -0.673890 3.184381
v 0.864213 0.489129 3.184384
v 0.864213 -0.018552 3.184383
v 0.000825 0.489129 3.184382
v 0.000825 -0.673890 3.184381
v 0.850955 -0.557858 3.309075
v 0.850955 -0.175321 3.309076
v 1.737321 -0.996758 1.728192
v 1.737321 -0.785920 1.728193
v -1.864151 -1.219172 -5.532511
v -0.575869 -0.666304 5.896140
v -0.940448 1.000000 -1.971128
v -1.620345 1.000000 -5.815706
v -1.864152 1.000000 -6.334323
v -0.575869 -0.129842 5.896143
v -5.440438 -1.462153 -5.818601
v -4.896782 -1.462153 -2.744413
v -1.000825 -0.677484 1.899605
v -5.440438 -1.246362 -5.818600
v -1.000825 0.852342 1.899608
v -4.896782 -1.246362 -2.744412
v -1.160660 -0.450871 -2.356325
v -1.704316 -0.450871 -5.430513
v -1.000825 -0.351920 -1.293797
v -1.000825 1.000000 -1.293794
v -1.160660 -0.877888 -2.356326
v -1.704316 -0.877888 -5.430514
v -1.000825 -1.219172 -1.452514
v -1.000825 1.000000 -1.452511
v -1.000825 -0.351920 1.759410
v -1.000825 1.000000 1.759413
v -9.097919 1.221145 -6.212147
v -8.356775 1.221145 -2.021231
v -1.864151 -0.109586 -6.334325
v -0.575869 -0.398073 5.896141
v -9.097919 0.943958 -6.212148
v -8.356775 0.943958 -2.021233
v -1.061916 0.113661 -1.797961
v -1.000825 0.161258 1.899606
v -1.000825 0.324040 -1.293795
v -1.803060 0.113661 -5.988876
v -1.000825 -0.109586 -1.452513
v -1.061916 0.776753 -1.797960
v -1.803061 0.776753 -5.988875
v -1.000825 0.324040 1.759412
v -0.000825 -1.219172 -5.532512
v -0.000825 -0.666304 5.896139
v -0.000826 1.000000 -6.334325
v -0.000825 -0.129842 5.896140
v -0.000825 0.852342 1.899606
v -0.000825 -0.677484 1.899604
v -0.000825 -0.351920 -1.293797
v -0.000825 1.000000 -1.293796
v -0.000825 1.000000 -1.452513
v -0.000825 -1.219172 -1.452515
v -0.000825 -0.351920 1.759409
v -0.000825 1.000000 1.759411
v -0.000826 -0.109586 -6.334326
v -0.000825 -0.398073 5.896140
v -0.152918 1.000000 -5.815708
v -0.152917 1.000000 -1.971130
v -0.940448 1.168419 -1.971128
v -1.620345 1.168419 -5.815706
v -0.152918 1.168419 -5.815708
v -0.152917 1.168419 -1.971130
v -0.921118 1.091883 -1.050430
v -0.921118 1.091883 1.516050
v -0.080533 1.091883 -1.050432
v -0.080533 1.091883 1.516048
v -0.613003 -0.553430 5.546911
v -0.963691 -0.559956 2.248834
v -0.613003 -0.396857 5.546912
v -0.963691 -0.070362 2.248835
v -1.499370 -0.994317 3.966028
v -1.850058 -0.997914 0.667950
v -1.499370 -0.908021 3.966029
v -1.850058 -0.728071 0.667951
v -1.601022 0.760960 -6.334324
v -1.601021 0.129454 -6.334325
v -0.263955 0.760960 -6.334325
v -0.263955 0.129454 -6.334325
v -1.334809 0.760960 -7.515329
v -1.334809 0.129455 -7.515330
v -0.530168 0.760960 -7.515330
v -0.530168 0.129455 -7.515330
v -1.192720 0.649445 -7.515329
v -1.192720 0.240971 -7.515330
v -0.672258 0.649445 -7.515330
v -0.672258 0.240971 -7.515330
v -1.192719 0.649444 -6.524630
v -1.192719 0.240970 -6.524631
v -0.672257 0.649444 -6.524631
v -0.672257 0.240970 -6.524631
v -3.851026 0.431116 -1.883326
v -3.851026 0.946662 -1.883325
v -4.592170 0.946662 -6.074241
v -4.592169 0.431116 -6.074242
v -4.995714 0.561404 -1.918362
v -4.995714 1.016394 -1.918360
v -5.736857 1.016394 -6.109276
v -5.736857 0.561404 -6.109277
v -3.975454 0.471731 -2.162156
v -3.975454 0.919244 -2.162155
v -4.618796 0.919244 -5.800034
v -4.618795 0.471730 -5.800035
v -4.969088 0.584825 -2.192568
v -4.969088 0.979775 -2.192567
v -5.612430 0.979775 -5.830446
v -5.612429 0.584825 -5.830447
v -0.864214 -0.673890 3.184381
v -0.864213 0.489129 3.184384
v -0.864213 -0.018552 3.184383
v -0.000825 0.489129 3.184382
v -0.000825 -0.673890 3.184381
v -0.850955 -0.557858 3.309075
v -0.850955 -0.175321 3.309076
v -1.737321 -0.996758 1.728192
v -1.737321 -0.785920 1.728193
vt 0.135351 -0.558072
vt 0.003035 -0.363507
vt 0.092282 -0.976844
vt -0.081322 0.947351
vt 0.100058 1.958891
vt 0.050091 1.852185
vt -0.092752 1.055565
vt -0.251711 1.059474
vt 0.075587 0.041384
vt -0.086008 0.279003
vt -0.086212 0.249830
vt -0.276044 1.968137
vt -0.246101 1.859467
vt 0.009828 1.911388
vt -0.133014 1.114769
vt 0.413322 1.261595
vt 0.299103 0.624605
vt 1.243955 0.407183
vt 0.515404 1.111487
vt 1.358173 1.044173
vt -0.081553 0.914324
vt 0.080042 0.676706
vt 0.401185 0.474498
vt 1.295541 0.331328
vt 0.365315 1.568841
vt 0.299111 1.575740
vt 0.143401 0.707357
vt 0.629403 1.011947
vt 0.449192 0.167251
vt 1.409760 0.968317
vt 0.986264 1.738667
vt 1.573373 1.877873
vt 1.417663 1.009490
vt 0.237182 -0.196235
vt 0.721785 1.030226
vt 0.830554 0.870285
vt 0.877494 1.898608
vt 1.351399 1.106930
vt 0.183935 0.557301
vt 1.507109 1.975312
vt 0.241636 0.439088
vt 0.114297 -0.045011
vt 0.140593 1.808834
vt -0.015118 0.940452
vt 0.156405 -1.071134
vt 0.164119 -0.998223
vt 0.040336 -1.068281
vt 0.104459 -1.162571
vt -0.165787 1.882802
vt -0.014821 1.660811
vt -0.287852 0.283965
vt -0.293374 0.366508
vt -0.289630 0.900550
vt 0.035337 -0.191272
vt 0.247348 0.172213
vt 0.253300 1.021193
vt -0.283166 0.952313
vt -0.283398 0.919286
vt 0.039792 0.444050
vt 0.314806 -0.339851
vt 0.112962 -0.334889
vt -0.288056 0.254793
vt -0.023788 -0.973990
vt -0.155922 -0.359599
vt 0.220528 -1.165425
vt 0.108710 -0.748730
vt -0.286364 1.918670
vt -0.291973 1.118678
vt -0.119962 0.896379
vt -0.123707 0.362337
vt 0.162891 -0.598569
vt 0.467532 -0.853353
vt 0.201549 -1.053262
vt 0.161663 -0.198915
vt 0.267667 -0.752638
vt 0.278705 -0.371021
vt 0.526390 -0.542053
vt 0.483821 -0.479457
vt 0.488162 -0.883689
vt 0.500110 -0.105561
vt 0.564618 -0.200418
vt -0.110331 2.127229
vt 0.040636 1.905238
vt -0.010786 1.578087
vt 0.104092 1.876168
vt 0.255058 1.654176
vt -0.054992 2.087323
vt 0.203048 1.901245
vt 0.052081 2.123235
vt 0.042658 1.943733
vt -0.056437 1.881175
vt 0.147710 1.941151
vt 0.050060 2.084741
vt 0.146264 1.735002
vt 0.041212 1.737584
vt 0.048615 1.878591
vt 0.663065 1.872485
vt 0.786311 1.691257
vt 0.507355 1.004102
vt 0.630601 0.822874
vt 0.955144 1.689498
vt 0.860727 1.828333
vt 0.725565 1.074543
vt 0.819981 0.935708
vt 0.674594 1.805657
vt 0.539432 1.051867
vt 0.646413 0.894554
vt 0.781576 1.648344
vt 0.240127 -0.712141
vn 0.994400 0.000000 0.105700
vn 0.000000 1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 0.984700 0.000000 0.174100
vn 0.211800 0.976600 0.037500
vn -0.103300 0.000000 -0.994600
vn 0.103300 -0.000000 0.994600
vn 0.911400 0.378700 0.161200
vn -0.157300 -0.987200 -0.027800
vn 0.113700 -0.993300 0.020100
vn 0.030600 -0.000000 0.999500
vn -0.061100 0.998100 -0.010800
vn -0.030600 0.000000 -0.999500
vn -0.000000 -0.000000 1.000000
vn 0.000000 0.000000 -1.000000
vn -0.755400 0.655300 0.000000
vn 0.000000 -1.000000 0.000000
vn -0.000000 -0.180000 0.983700
vn 0.000000 -0.395500 -0.918500
vn -0.000000 0.688500 0.725200
vn 0.000000 -0.585700 -0.810500
vn -0.000000 0.974900 0.222500
vn -0.000000 -1.000000 0.002800
vn -1.000000 0.000000 -0.000000
vn -0.000000 0.935500 0.353200
vn 0.755400 0.655300 0.000000
vn 0.000000 0.935500 -0.353200
vn 0.673800 0.724900 0.143400
vn 0.872300 -0.000000 0.489100
vn -0.872300 0.000000 -0.489100
vn -0.518300 -0.853500 -0.054200
vn -0.975500 0.000000 -0.219900
vn 0.975500 0.000000 -0.219900
vn -0.913200 0.000000 -0.407500
vn -0.436900 0.896200 -0.077300
vn -0.995300 -0.000000 0.096600
vn -0.297300 -0.953400 -0.052600
vn 0.473900 -0.876600 0.083800
vn 0.913200 0.000000 0.407500
vn 0.342200 0.937700 0.060500
vn 0.995300 -0.000000 -0.096600
vn -0.519200 -0.853000 -0.054300
vn 0.722400 0.676400 0.143800
vn -0.994400 0.000000 0.105700
vn -0.984700 0.000000 0.174100
vn -0.211800 0.976600 0.037500
vn 0.103300 0.000000 -0.994600
vn -0.103300 -0.000000 0.994600
vn -0.911400 0.378700 0.161200
vn 0.157300 -0.987200 -0.027800
vn -0.113700 -0.993300 0.020100
vn -0.030600 -0.000000 0.999500
vn 0.061100 0.998100 -0.010800
vn 0.030600 0.000000 -0.999500
vn -0.691900 0.713200 0.112500
vn -0.872300 -0.000000 0.489100
vn 0.872300 0.000000 -0.489100
vn 0.518300 -0.853500 -0.054200
vn 0.913200 0.000000 -0.407500
vn 0.436900 0.896200 -0.077300
vn 0.995300 0.000000 0.096600
vn 0.297300 -0.953300 -0.052600
vn -0.473900 -0.876600 0.083800
vn -0.913200 -0.000000 0.407500
vn -0.342200 0.937700 0.060500
vn -0.995300 -0.000000 -0.096600
vn 0.519200 -0.853000 -0.054300
vn -0.714800 0.690100 0.113700
vn 0.974400 0.089700 0.206200
vn 0.870400 0.288400 0.399100
vn 0.691900 0.713200 0.112500
vn -0.518000 -0.853700 -0.053400
vn -0.519700 -0.852700 -0.053600
vn 0.714800 0.690100 0.113700
vn -0.974400 0.089700 0.206200
vn -0.870400 0.288400 0.399100
vn -0.673800 0.724900 0.143400
vn 0.518000 -0.853700 -0.053400
vn 0.297300 -0.953400 -0.052600
vn 0.519700 -0.852700 -0.053600
vn -0.722400 0.676400 0.143800
vn -0.000000 0.962300 0.272000
usemtl Material.001
s off
f 103/1/1 102/2/1 6/3/1
f 20/4/2 5/5/2 4/6/2
f 20/4/2 3/7/2 52/8/2
f 36/9/3 22/10/3 11/11/3
f 39/12/2 51/13/2 4/6/2
f 4/6/4 54/14/4 53/15/4
f 14/16/5 13/17/5 12/18/5
f 18/19/6 14/16/6 10/20/6
f 20/4/3 16/21/3 31/22/3
f 17/23/7 8/24/7 12/18/7
f 25/25/4 32/26/4 29/27/4
f 10/20/4 12/18/4 8/24/4
f 1/28/8 18/19/8 17/23/8
f 19/29/4 17/23/4 13/17/4
f 25/25/4 14/16/4 18/19/4
f 18/19/9 7/30/9 8/24/9
f 92/31/10 27/32/10 28/33/10
f 16/21/3 22/10/3 36/9/3
f 31/22/3 36/9/3 21/34/3
f 90/35/11 89/36/11 28/33/11
f 91/37/12 90/35/12 24/38/12
f 33/39/4 13/17/4 14/16/4
f 23/40/4 24/38/4 28/33/4
f 33/39/3 31/22/3 15/41/3
f 21/34/3 36/9/3 30/42/3
f 5/5/4 35/43/4 32/26/4
f 5/5/4 20/4/4 34/44/4
f 33/39/4 29/27/4 34/44/4
f 91/37/13 23/40/13 27/32/13
f 103/1/1 26/45/1 63/46/1
f 26/45/14 50/47/14 38/48/14
f 39/12/15 71/49/15 72/50/15
f 48/51/16 60/52/16 59/53/16
f 15/41/17 21/34/17 47/54/17
f 19/29/17 46/55/17 37/56/17
f 39/12/2 45/57/2 52/8/2
f 20/4/2 45/57/2 44/58/2
f 19/29/18 15/41/18 43/59/18
f 9/60/19 42/61/19 47/54/19
f 22/10/20 48/51/20 41/62/20
f 25/25/21 1/28/21 37/56/21
f 6/3/14 40/63/14 50/47/14
f 104/64/22 40/63/22 6/3/22
f 2/65/23 38/48/23 105/66/23
f 55/67/2 56/68/2 53/15/2
f 3/7/14 53/15/14 56/68/14
f 51/13/15 55/67/15 54/14/15
f 52/8/24 56/68/24 55/67/24
f 57/69/2 59/53/2 60/52/2
f 48/51/25 22/10/25 58/70/25
f 16/21/26 57/69/26 58/70/26
f 16/21/27 44/58/27 59/53/27
f 107/71/28 63/46/28 67/72/28
f 26/45/1 2/65/1 61/73/1
f 9/60/1 30/42/1 64/74/1
f 101/75/1 9/60/1 62/76/1
f 108/77/1 109/78/1 67/72/1
f 61/73/29 65/79/29 67/72/29
f 62/76/30 64/74/30 68/80/30
f 62/76/31 66/81/31 108/77/31
f 71/49/32 75/82/32 76/83/32
f 25/25/15 49/84/15 72/50/15
f 5/5/15 69/85/15 71/49/15
f 25/25/15 70/86/15 69/85/15
f 76/83/15 75/82/15 79/87/15
f 72/50/17 76/83/17 74/88/17
f 71/49/2 69/85/2 73/89/2
f 70/86/33 74/88/33 73/89/33
f 80/90/3 79/87/3 83/91/3
f 76/83/15 80/90/15 78/92/15
f 75/82/15 73/89/15 77/93/15
f 74/88/15 78/92/15 77/93/15
f 82/94/15 84/95/15 83/91/15
f 80/90/2 84/95/2 82/94/2
f 77/93/17 81/96/17 83/91/17
f 77/93/24 78/92/24 82/94/24
f 35/43/13 87/97/13 88/98/13
f 35/43/12 34/44/12 86/99/12
f 34/44/11 29/27/11 85/100/11
f 32/26/10 88/98/10 85/100/10
f 92/31/34 100/101/34 99/102/34
f 90/35/35 91/37/35 99/102/35
f 89/36/36 90/35/36 98/103/36
f 89/36/37 97/104/37 100/101/37
f 95/105/13 99/102/13 100/101/13
f 95/105/12 94/106/12 98/103/12
f 94/106/11 93/107/11 97/104/11
f 96/108/10 100/101/10 97/104/10
f 88/98/38 96/108/38 93/107/38
f 86/99/39 85/100/39 93/107/39
f 87/97/40 86/99/40 94/106/40
f 87/97/41 95/105/41 96/108/41
f 106/109/42 108/77/42 65/79/42
f 66/81/1 68/80/1 109/78/1
f 101/75/1 106/109/1 61/73/1
f 64/74/43 107/71/43 109/78/43
f 101/75/23 105/66/23 42/61/23
f 103/1/1 107/71/1 64/74/1
f 30/42/1 11/11/1 102/2/1
f 212/1/44 135/45/44 115/3/44
f 129/4/2 112/7/2 113/6/2
f 161/8/2 112/7/2 129/4/2
f 145/9/24 139/42/24 120/11/24
f 113/6/2 160/13/2 148/12/2
f 162/15/45 163/14/45 113/6/45
f 123/16/46 119/20/46 121/18/46
f 127/19/47 116/30/47 119/20/47
f 140/22/24 125/21/24 129/4/24
f 121/18/48 117/24/48 126/23/48
f 138/27/45 141/26/45 134/25/45
f 117/24/45 121/18/45 119/20/45
f 126/23/49 127/19/49 110/28/49
f 122/17/45 126/23/45 128/29/45
f 127/19/45 123/16/45 134/25/45
f 117/24/50 116/30/50 127/19/50
f 137/33/51 136/32/51 201/31/51
f 145/9/24 131/10/24 125/21/24
f 130/34/24 145/9/24 140/22/24
f 199/35/52 133/38/52 137/33/52
f 200/37/53 132/40/53 133/38/53
f 123/16/45 122/17/45 142/39/45
f 137/33/45 133/38/45 132/40/45
f 124/41/24 140/22/24 142/39/24
f 130/34/24 118/60/24 139/42/24
f 141/26/45 144/43/45 114/5/45
f 114/5/45 144/43/45 143/44/45
f 143/44/45 138/27/45 142/39/45
f 136/32/54 132/40/54 200/37/54
f 212/1/44 216/71/44 172/46/44
f 147/48/14 159/47/14 135/45/14
f 181/50/15 180/49/15 148/12/15
f 168/53/26 169/52/26 157/51/26
f 124/41/17 152/59/17 156/54/17
f 146/56/17 155/55/17 128/29/17
f 148/12/2 160/13/2 161/8/2
f 129/4/2 125/21/2 153/58/2
f 155/55/18 152/59/18 124/41/18
f 130/34/19 156/54/19 151/61/19
f 131/10/20 120/11/20 150/62/20
f 134/25/21 158/84/21 146/56/21
f 159/47/14 149/63/14 115/3/14
f 115/3/22 149/63/22 213/64/22
f 214/66/23 147/48/23 111/65/23
f 162/15/2 165/68/2 164/67/2
f 165/68/14 162/15/14 112/7/14
f 163/14/15 164/67/15 160/13/15
f 164/67/3 165/68/3 161/8/3
f 166/69/2 167/70/2 169/52/2
f 157/51/25 169/52/25 167/70/25
f 167/70/16 166/69/16 125/21/16
f 125/21/27 166/69/27 168/53/27
f 216/71/55 218/78/55 176/72/55
f 135/45/44 172/46/44 170/73/44
f 118/60/44 171/76/44 173/74/44
f 210/75/44 215/109/44 171/76/44
f 217/77/44 174/79/44 176/72/44
f 176/72/56 174/79/56 170/73/56
f 171/76/57 175/81/57 177/80/57
f 217/77/58 175/81/58 171/76/58
f 185/83/33 184/82/33 180/49/33
f 134/25/15 179/86/15 181/50/15
f 180/49/15 178/85/15 114/5/15
f 178/85/15 179/86/15 134/25/15
f 189/90/15 188/87/15 184/82/15
f 183/88/17 185/83/17 181/50/17
f 180/49/2 184/82/2 182/89/2
f 182/89/32 183/88/32 179/86/32
f 189/90/24 193/95/24 192/91/24
f 187/92/15 189/90/15 185/83/15
f 184/82/15 188/87/15 186/93/15
f 186/93/15 187/92/15 183/88/15
f 192/91/15 193/95/15 191/94/15
f 191/94/2 193/95/2 189/90/2
f 192/91/17 190/96/17 186/93/17
f 186/93/3 190/96/3 191/94/3
f 197/98/54 196/97/54 144/43/54
f 144/43/53 196/97/53 195/99/53
f 143/44/52 195/99/52 194/100/52
f 194/100/51 197/98/51 141/26/51
f 208/102/59 209/101/59 201/31/59
f 199/35/60 207/103/60 208/102/60
f 198/36/61 206/104/61 207/103/61
f 209/101/62 206/104/62 198/36/62
f 209/101/54 208/102/54 204/105/54
f 204/105/53 208/102/53 207/103/53
f 203/106/52 207/103/52 206/104/52
f 206/104/51 209/101/51 205/108/51
f 202/107/63 205/108/63 197/98/63
f 195/99/64 203/106/64 202/107/64
f 196/97/65 204/105/65 203/106/65
f 205/108/66 204/105/66 196/97/66
f 174/79/67 217/77/67 215/109/67
f 175/81/44 217/77/44 218/78/44
f 170/73/44 215/109/44 210/75/44
f 173/74/68 177/80/68 218/78/68
f 151/61/23 214/66/23 210/75/23
f 173/74/44 216/71/44 212/1/44
f 139/42/44 212/1/44 211/2/44
f 26/45/1 103/1/1 6/3/1
f 3/7/2 20/4/2 4/6/2
f 45/57/2 20/4/2 52/8/2
f 30/42/3 36/9/3 11/11/3
f 5/5/2 39/12/2 4/6/2
f 3/7/4 4/6/4 53/15/4
f 10/20/5 14/16/5 12/18/5
f 7/30/6 18/19/6 10/20/6
f 33/39/3 20/4/3 31/22/3
f 13/17/7 17/23/7 12/18/7
f 33/39/4 25/25/4 29/27/4
f 7/30/4 10/20/4 8/24/4
f 19/29/69 1/28/69 17/23/69
f 33/39/4 19/29/4 13/17/4
f 1/28/70 25/25/70 18/19/70
f 17/23/9 18/19/9 8/24/9
f 89/36/10 92/31/10 28/33/10
f 31/22/3 16/21/3 36/9/3
f 15/41/3 31/22/3 21/34/3
f 24/38/11 90/35/11 28/33/11
f 23/40/12 91/37/12 24/38/12
f 25/25/4 33/39/4 14/16/4
f 27/32/4 23/40/4 28/33/4
f 19/29/3 33/39/3 15/41/3
f 9/60/3 21/34/3 30/42/3
f 25/25/4 5/5/4 32/26/4
f 35/43/4 5/5/4 34/44/4
f 20/4/4 33/39/4 34/44/4
f 92/31/13 91/37/13 27/32/13
f 107/71/1 103/1/1 63/46/1
f 2/65/14 26/45/14 38/48/14
f 49/84/15 39/12/15 72/50/15
f 44/58/16 48/51/16 59/53/16
f 43/59/17 15/41/17 47/54/17
f 1/28/17 19/29/17 37/56/17
f 51/13/2 39/12/2 52/8/2
f 16/21/2 20/4/2 44/58/2
f 46/55/18 19/29/18 43/59/18
f 21/34/19 9/60/19 47/54/19
f 11/11/20 22/10/20 41/62/20
f 49/84/21 25/25/21 37/56/21
f 26/45/14 6/3/14 50/47/14
f 102/2/22 104/64/22 6/3/22
f 101/75/23 2/65/23 105/66/23
f 54/14/2 55/67/2 53/15/2
f 52/8/14 3/7/14 56/68/14
f 4/6/15 51/13/15 54/14/15
f 51/13/24 52/8/24 55/67/24
f 58/70/2 57/69/2 60/52/2
f 60/52/25 48/51/25 58/70/25
f 22/10/26 16/21/26 58/70/26
f 57/69/27 16/21/27 59/53/27
f 109/78/71 107/71/71 67/72/71
f 63/46/1 26/45/1 61/73/1
f 62/76/1 9/60/1 64/74/1
f 106/109/1 101/75/1 62/76/1
f 65/79/1 108/77/1 67/72/1
f 63/46/29 61/73/29 67/72/29
f 66/81/30 62/76/30 68/80/30
f 106/109/72 62/76/72 108/77/72
f 72/50/32 71/49/32 76/83/32
f 70/86/15 25/25/15 72/50/15
f 39/12/15 5/5/15 71/49/15
f 5/5/15 25/25/15 69/85/15
f 80/90/15 76/83/15 79/87/15
f 70/86/17 72/50/17 74/88/17
f 75/82/2 71/49/2 73/89/2
f 69/85/33 70/86/33 73/89/33
f 84/95/3 80/90/3 83/91/3
f 74/88/15 76/83/15 78/92/15
f 79/87/15 75/82/15 77/93/15
f 73/89/15 74/88/15 77/93/15
f 81/96/15 82/94/15 83/91/15
f 78/92/2 80/90/2 82/94/2
f 79/87/17 77/93/17 83/91/17
f 81/96/24 77/93/24 82/94/24
f 32/26/13 35/43/13 88/98/13
f 87/97/12 35/43/12 86/99/12
f 86/99/11 34/44/11 85/100/11
f 29/27/10 32/26/10 85/100/10
f 91/37/34 92/31/34 99/102/34
f 98/103/35 90/35/35 99/102/35
f 97/104/36 89/36/36 98/103/36
f 92/31/37 89/36/37 100/101/37
f 96/108/13 95/105/13 100/101/13
f 99/102/12 95/105/12 98/103/12
f 98/103/11 94/106/11 97/104/11
f 93/107/10 96/108/10 97/104/10
f 85/100/38 88/98/38 93/107/38
f 94/106/39 86/99/39 93/107/39
f 95/105/40 87/97/40 94/106/40
f 88/98/41 87/97/41 96/108/41
f 61/73/73 106/109/73 65/79/73
f 108/77/1 66/81/1 109/78/1
f 2/65/1 101/75/1 61/73/1
f 68/80/74 64/74/74 109/78/74
f 9/60/23 101/75/23 42/61/23
f 30/42/1 103/1/1 64/74/1
f 103/1/1 30/42/1 102/2/1
f 211/2/44 212/1/44 115/3/44
f 114/5/2 129/4/2 113/6/2
f 154/57/2 161/8/2 129/4/2
f 131/10/24 145/9/24 120/11/24
f 114/5/2 113/6/2 148/12/2
f 112/7/45 162/15/45 113/6/45
f 122/17/46 123/16/46 121/18/46
f 123/16/47 127/19/47 119/20/47
f 142/39/24 140/22/24 129/4/24
f 122/17/48 121/18/48 126/23/48
f 142/39/45 138/27/45 134/25/45
f 116/30/45 117/24/45 119/20/45
f 128/29/75 126/23/75 110/28/75
f 142/39/45 122/17/45 128/29/45
f 110/28/76 127/19/76 134/25/76
f 126/23/50 117/24/50 127/19/50
f 198/36/51 137/33/51 201/31/51
f 140/22/24 145/9/24 125/21/24
f 124/41/24 130/34/24 140/22/24
f 198/36/52 199/35/52 137/33/52
f 199/35/53 200/37/53 133/38/53
f 134/25/45 123/16/45 142/39/45
f 136/32/45 137/33/45 132/40/45
f 128/29/24 124/41/24 142/39/24
f 145/9/24 130/34/24 139/42/24
f 134/25/45 141/26/45 114/5/45
f 129/4/45 114/5/45 143/44/45
f 129/4/45 143/44/45 142/39/45
f 201/31/54 136/32/54 200/37/54
f 135/45/44 212/1/44 172/46/44
f 111/65/14 147/48/14 135/45/14
f 158/84/15 181/50/15 148/12/15
f 153/58/26 168/53/26 157/51/26
f 130/34/17 124/41/17 156/54/17
f 110/28/17 146/56/17 128/29/17
f 154/57/2 148/12/2 161/8/2
f 154/57/2 129/4/2 153/58/2
f 128/29/18 155/55/18 124/41/18
f 118/60/19 130/34/19 151/61/19
f 157/51/20 131/10/20 150/62/20
f 110/28/21 134/25/21 146/56/21
f 135/45/14 159/47/14 115/3/14
f 211/2/22 115/3/22 213/64/22
f 210/75/23 214/66/23 111/65/23
f 163/14/2 162/15/2 164/67/2
f 161/8/14 165/68/14 112/7/14
f 113/6/15 163/14/15 160/13/15
f 160/13/3 164/67/3 161/8/3
f 168/53/2 166/69/2 169/52/2
f 131/10/25 157/51/25 167/70/25
f 131/10/16 167/70/16 125/21/16
f 153/58/27 125/21/27 168/53/27
f 172/46/77 216/71/77 176/72/77
f 111/65/44 135/45/44 170/73/44
f 139/42/44 118/60/44 173/74/44
f 118/60/44 210/75/44 171/76/44
f 218/78/44 217/77/44 176/72/44
f 172/46/56 176/72/56 170/73/56
f 173/74/57 171/76/57 177/80/57
f 215/109/78 217/77/78 171/76/78
f 181/50/33 185/83/33 180/49/33
f 158/84/15 134/25/15 181/50/15
f 148/12/15 180/49/15 114/5/15
f 114/5/15 178/85/15 134/25/15
f 185/83/15 189/90/15 184/82/15
f 179/86/17 183/88/17 181/50/17
f 178/85/2 180/49/2 182/89/2
f 178/85/32 182/89/32 179/86/32
f 188/87/24 189/90/24 192/91/24
f 183/88/15 187/92/15 185/83/15
f 182/89/15 184/82/15 186/93/15
f 182/89/15 186/93/15 183/88/15
f 190/96/15 192/91/15 191/94/15
f 187/92/2 191/94/2 189/90/2
f 188/87/17 192/91/17 186/93/17
f 187/92/3 186/93/3 191/94/3
f 141/26/54 197/98/54 144/43/54
f 143/44/53 144/43/53 195/99/53
f 138/27/52 143/44/52 194/100/52
f 138/27/51 194/100/51 141/26/51
f 200/37/59 208/102/59 201/31/59
f 200/37/60 199/35/60 208/102/60
f 199/35/61 198/36/61 207/103/61
f 201/31/79 209/101/79 198/36/79
f 205/108/54 209/101/54 204/105/54
f 203/106/53 204/105/53 207/103/53
f 202/107/52 203/106/52 206/104/52
f 202/107/51 206/104/51 205/108/51
f 194/100/63 202/107/63 197/98/63
f 194/100/64 195/99/64 202/107/64
f 195/99/65 196/97/65 203/106/65
f 197/98/66 205/108/66 196/97/66
f 170/73/80 174/79/80 215/109/80
f 177/80/44 175/81/44 218/78/44
f 111/65/44 170/73/44 210/75/44
f 216/71/81 173/74/81 218/78/81
f 118/60/23 151/61/23 210/75/23
f 139/42/44 173/74/44 212/1/44
f 120/11/44 139/42/44 211/2/44
usemtl Material.003
f 41/62/82 104/64/82 102/2/82
f 211/2/82 213/64/82 150/62/82
f 11/11/82 41/62/82 102/2/82
f 120/11/82 211/2/82 150/62/82

97
test.cc
View File

@@ -8,6 +8,90 @@
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#ifdef _WIN32
#ifdef __cplusplus
extern "C" {
#endif
#include <windows.h>
#include <mmsystem.h>
#ifdef __cplusplus
}
#endif
#pragma comment(lib, "winmm.lib")
#else
#if defined(__unix__) || defined(__APPLE__)
#include <sys/time.h>
#else
#include <ctime>
#endif
#endif
// not thread-safe
class timerutil {
public:
#ifdef _WIN32
typedef DWORD time_t;
timerutil() { ::timeBeginPeriod(1); }
~timerutil() { ::timeEndPeriod(1); }
void start() { t_[0] = ::timeGetTime(); }
void end() { t_[1] = ::timeGetTime(); }
time_t sec() { return (time_t)((t_[1] - t_[0]) / 1000); }
time_t msec() { return (time_t)((t_[1] - t_[0])); }
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000); }
time_t current() { return ::timeGetTime(); }
#else
#if defined(__unix__) || defined(__APPLE__)
typedef unsigned long int time_t;
void start() { gettimeofday(tv + 0, &tz); }
void end() { gettimeofday(tv + 1, &tz); }
time_t sec() { return (time_t)(tv[1].tv_sec - tv[0].tv_sec); }
time_t msec() {
return this->sec() * 1000 +
(time_t)((tv[1].tv_usec - tv[0].tv_usec) / 1000);
}
time_t usec() {
return this->sec() * 1000000 + (time_t)(tv[1].tv_usec - tv[0].tv_usec);
}
time_t current() {
struct timeval t;
gettimeofday(&t, NULL);
return (time_t)(t.tv_sec * 1000 + t.tv_usec);
}
#else // C timer
// using namespace std;
typedef clock_t time_t;
void start() { t_[0] = clock(); }
void end() { t_[1] = clock(); }
time_t sec() { return (time_t)((t_[1] - t_[0]) / CLOCKS_PER_SEC); }
time_t msec() { return (time_t)((t_[1] - t_[0]) * 1000 / CLOCKS_PER_SEC); }
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000000 / CLOCKS_PER_SEC); }
time_t current() { return (time_t)clock(); }
#endif
#endif
private:
#ifdef _WIN32
DWORD t_[2];
#else
#if defined(__unix__) || defined(__APPLE__)
struct timeval tv[2];
struct timezone tz;
#else
time_t t_[2];
#endif
#endif
};
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool triangulate = true) static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool triangulate = true)
{ {
std::cout << "# of shapes : " << shapes.size() << std::endl; std::cout << "# of shapes : " << shapes.size() << std::endl;
@@ -124,24 +208,31 @@ static bool
TestLoadObj( TestLoadObj(
const char* filename, const char* filename,
const char* basepath = NULL, const char* basepath = NULL,
bool triangulate = true) unsigned int flags = 1 )
{ {
std::cout << "Loading " << filename << std::endl; std::cout << "Loading " << filename << std::endl;
std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials; std::vector<tinyobj::material_t> materials;
timerutil t;
t.start();
std::string err; std::string err;
bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath, triangulate); bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath, flags);
t.end();
if (!err.empty()) { if (!err.empty()) {
std::cerr << err << std::endl; std::cerr << err << std::endl;
} }
if (!ret) { if (!ret) {
printf("Failed to load/parse .obj.\n");
return false; return false;
} }
printf("Parse time: %lu [msecs]\n", t.msec());
bool triangulate( ( flags & tinyobj::triangulation ) == tinyobj::triangulation );
PrintInfo(shapes, materials, triangulate ); PrintInfo(shapes, materials, triangulate );
return true; return true;
@@ -270,7 +361,7 @@ main(
//assert(true == TestLoadObj("cornell_box.obj")); //assert(true == TestLoadObj("cornell_box.obj"));
//assert(true == TestLoadObj("cube.obj")); //assert(true == TestLoadObj("cube.obj"));
assert(true == TestStreamLoadObj()); assert(true == TestStreamLoadObj());
assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, false)); assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, 0));
} }
return 0; return 0;

View File

@@ -1,10 +1,12 @@
// //
// Copyright 2012-2015, Syoyo Fujita. // Copyright 2012-2016, Syoyo Fujita.
// //
// Licensed under 2-clause BSD license. // Licensed under 2-clause BSD license.
// //
// //
// version 0.9.22: Introduce `load_flags_t`.
// version 0.9.20: Fixes creating per-face material using `usemtl`(#68)
// version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension) // version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension)
// version 0.9.16: Make tinyobjloader header-only // version 0.9.16: Make tinyobjloader header-only
// version 0.9.15: Change API to handle no mtl file case correctly(#58) // version 0.9.15: Change API to handle no mtl file case correctly(#58)
@@ -37,12 +39,13 @@
// #include "tiny_obj_loader.h" // #include "tiny_obj_loader.h"
// //
#ifndef TINY_OBJ_LOADER_H #ifndef TINY_OBJ_LOADER_H_
#define TINY_OBJ_LOADER_H #define TINY_OBJ_LOADER_H_
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include <cmath>
namespace tinyobj { namespace tinyobj {
@@ -96,6 +99,69 @@ typedef struct {
mesh_t mesh; mesh_t mesh;
} shape_t; } shape_t;
typedef enum
{
triangulation = 1, // used whether triangulate polygon face in .obj
calculate_normals = 2, // used whether calculate the normals if the .obj normals are empty
// Some nice stuff here
} load_flags_t;
class float3
{
public:
float3()
: x( 0.0f )
, y( 0.0f )
, z( 0.0f )
{
}
float3(float coord_x, float coord_y, float coord_z)
: x( coord_x )
, y( coord_y )
, z( coord_z )
{
}
float3(const float3& from, const float3& to)
{
coord[0] = to.coord[0] - from.coord[0];
coord[1] = to.coord[1] - from.coord[1];
coord[2] = to.coord[2] - from.coord[2];
}
float3 crossproduct ( const float3 & vec )
{
float a = y * vec.z - z * vec.y ;
float b = z * vec.x - x * vec.z ;
float c = x * vec.y - y * vec.x ;
return float3( a , b , c );
}
void normalize()
{
const float length = std::sqrt( ( coord[0] * coord[0] ) +
( coord[1] * coord[1] ) +
( coord[2] * coord[2] ) );
if( length != 1 )
{
coord[0] = (coord[0] / length);
coord[1] = (coord[1] / length);
coord[2] = (coord[2] / length);
}
}
private:
union
{
float coord[3];
struct
{
float x,y,z;
};
};
};
class MaterialReader { class MaterialReader {
public: public:
MaterialReader() {} MaterialReader() {}
@@ -126,13 +192,12 @@ private:
/// Returns true when loading .obj become success. /// Returns true when loading .obj become success.
/// Returns warning and error message into `err` /// Returns warning and error message into `err`
/// 'mtl_basepath' is optional, and used for base path for .mtl file. /// 'mtl_basepath' is optional, and used for base path for .mtl file.
/// 'triangulate' is optional, and used whether triangulate polygon face in .obj /// 'optional flags
/// or not.
bool LoadObj(std::vector<shape_t> &shapes, // [output] bool LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<material_t> &materials, // [output] std::vector<material_t> &materials, // [output]
std::string &err, // [output] std::string &err, // [output]
const char *filename, const char *mtl_basepath = NULL, const char *filename, const char *mtl_basepath = NULL,
bool triangulate = true); unsigned int flags = 1 );
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve /// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
/// std::istream for materials. /// std::istream for materials.
@@ -142,7 +207,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<material_t> &materials, // [output] std::vector<material_t> &materials, // [output]
std::string &err, // [output] std::string &err, // [output]
std::istream &inStream, MaterialReader &readMatFn, std::istream &inStream, MaterialReader &readMatFn,
bool triangulate = true); unsigned int flags = 1);
/// Loads materials into std::map /// Loads materials into std::map
void LoadMtl(std::map<std::string, int> &material_map, // [output] void LoadMtl(std::map<std::string, int> &material_map, // [output]
@@ -158,9 +223,6 @@ void LoadMtl(std::map<std::string, int> &material_map, // [output]
#include <cstddef> #include <cstddef>
#include <cctype> #include <cctype>
#include <string>
#include <vector>
#include <map>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
@@ -174,8 +236,8 @@ MaterialReader::~MaterialReader() {}
struct vertex_index { struct vertex_index {
int v_idx, vt_idx, vn_idx; int v_idx, vt_idx, vn_idx;
vertex_index() {} vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {}
vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}
vertex_index(int vidx, int vtidx, int vnidx) vertex_index(int vidx, int vtidx, int vnidx)
: v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {}
}; };
@@ -205,11 +267,43 @@ struct obj_shape {
std::vector<float> vt; std::vector<float> vt;
}; };
static inline bool isSpace(const char c) { return (c == ' ') || (c == '\t'); } //See http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf
std::istream& safeGetline(std::istream& is, std::string& t)
{
t.clear();
static inline bool isNewLine(const char c) { // The characters in the stream are read one-by-one using a std::streambuf.
return (c == '\r') || (c == '\n') || (c == '\0'); // That is faster than reading them one-by-one using the std::istream.
// Code that uses streambuf this way must be guarded by a sentry object.
// The sentry object performs various tasks,
// such as thread synchronization and updating the stream state.
std::istream::sentry se(is, true);
std::streambuf* sb = is.rdbuf();
for(;;) {
int c = sb->sbumpc();
switch (c) {
case '\n':
return is;
case '\r':
if(sb->sgetc() == '\n')
sb->sbumpc();
return is;
case EOF:
// Also handle the case when the last line has no line ending
if(t.empty())
is.setstate(std::ios::eofbit);
return is;
default:
t += (char)c;
} }
}
}
#define IS_SPACE( x ) ( ( (x) == ' ') || ( (x) == '\t') )
#define IS_DIGIT( x ) ( (unsigned int)( (x) - '0' ) < (unsigned int)10 )
#define IS_NEW_LINE( x ) ( ( (x) == '\r') || ( (x) == '\n') || ( (x) == '\0') )
// Make index zero-base, and also support relative index. // Make index zero-base, and also support relative index.
static inline int fixIndex(int idx, int n) { static inline int fixIndex(int idx, int n) {
@@ -297,13 +391,13 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
if (*curr == '+' || *curr == '-') { if (*curr == '+' || *curr == '-') {
sign = *curr; sign = *curr;
curr++; curr++;
} else if (isdigit(*curr)) { /* Pass through. */ } else if (IS_DIGIT(*curr)) { /* Pass through. */
} else { } else {
goto fail; goto fail;
} }
// Read the integer part. // Read the integer part.
while ((end_not_reached = (curr != s_end)) && isdigit(*curr)) { while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) {
mantissa *= 10; mantissa *= 10;
mantissa += static_cast<int>(*curr - 0x30); mantissa += static_cast<int>(*curr - 0x30);
curr++; curr++;
@@ -321,7 +415,7 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
if (*curr == '.') { if (*curr == '.') {
curr++; curr++;
read = 1; read = 1;
while ((end_not_reached = (curr != s_end)) && isdigit(*curr)) { while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) {
// NOTE: Don't use powf here, it will absolutely murder precision. // NOTE: Don't use powf here, it will absolutely murder precision.
mantissa += static_cast<int>(*curr - 0x30) * pow(10.0, -read); mantissa += static_cast<int>(*curr - 0x30) * pow(10.0, -read);
read++; read++;
@@ -342,14 +436,14 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
if ((end_not_reached = (curr != s_end)) && (*curr == '+' || *curr == '-')) { if ((end_not_reached = (curr != s_end)) && (*curr == '+' || *curr == '-')) {
exp_sign = *curr; exp_sign = *curr;
curr++; curr++;
} else if (isdigit(*curr)) { /* Pass through. */ } else if (IS_DIGIT(*curr)) { /* Pass through. */
} else { } else {
// Empty E is not allowed. // Empty E is not allowed.
goto fail; goto fail;
} }
read = 0; read = 0;
while ((end_not_reached = (curr != s_end)) && isdigit(*curr)) { while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) {
exponent *= 10; exponent *= 10;
exponent += static_cast<int>(*curr - 0x30); exponent += static_cast<int>(*curr - 0x30);
curr++; curr++;
@@ -520,11 +614,14 @@ static bool exportFaceGroupToShape(
const std::vector<float> &in_texcoords, const std::vector<float> &in_texcoords,
const std::vector<std::vector<vertex_index> > &faceGroup, const std::vector<std::vector<vertex_index> > &faceGroup,
std::vector<tag_t> &tags, const int material_id, const std::string &name, std::vector<tag_t> &tags, const int material_id, const std::string &name,
bool clearCache, bool triangulate) { bool clearCache, unsigned int flags, std::string& err ) {
if (faceGroup.empty()) { if (faceGroup.empty()) {
return false; return false;
} }
bool triangulate( ( flags & triangulation ) == triangulation );
bool normals_calculation( ( flags & calculate_normals ) == calculate_normals );
// Flatten vertices and indices // Flatten vertices and indices
for (size_t i = 0; i < faceGroup.size(); i++) { for (size_t i = 0; i < faceGroup.size(); i++) {
const std::vector<vertex_index> &face = faceGroup[i]; const std::vector<vertex_index> &face = faceGroup[i];
@@ -575,6 +672,34 @@ static bool exportFaceGroupToShape(
} }
} }
if (normals_calculation && shape.mesh.normals.empty()) {
const size_t nIndexs = shape.mesh.indices.size();
if (nIndexs % 3 == 0) {
shape.mesh.normals.resize(shape.mesh.positions.size());
for (register size_t iIndices = 0; iIndices < nIndexs; iIndices += 3) {
float3 v1, v2, v3;
memcpy(&v1, &shape.mesh.positions[shape.mesh.indices[iIndices] * 3], sizeof(float3));
memcpy(&v2, &shape.mesh.positions[shape.mesh.indices[iIndices + 1] * 3], sizeof(float3));
memcpy(&v3, &shape.mesh.positions[shape.mesh.indices[iIndices + 2] * 3], sizeof(float3));
float3 v12(v1, v2);
float3 v13(v1, v3);
float3 normal = v12.crossproduct(v13);
normal.normalize();
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices] * 3], &normal, sizeof(float3));
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 1] * 3], &normal, sizeof(float3));
memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 2] * 3], &normal, sizeof(float3));
}
} else {
std::stringstream ss;
ss << "WARN: The shape " << name << " does not have a topology of triangles, therfore the normals calculation could not be performed. Select the tinyobj::triangulation flag for this object." << std::endl;
err += ss.str();
}
}
shape.name = name; shape.name = name;
shape.mesh.tags.swap(tags); shape.mesh.tags.swap(tags);
@@ -591,12 +716,9 @@ void LoadMtl(std::map<std::string, int> &material_map,
material_t material; material_t material;
InitMaterial(material); InitMaterial(material);
size_t maxchars = 8192; // Alloc enough size.
std::vector<char> buf(maxchars); // Alloc enough size.
while (inStream.peek() != -1) { while (inStream.peek() != -1) {
inStream.getline(&buf[0], static_cast<std::streamsize>(maxchars)); std::string linebuf;
safeGetline(inStream, linebuf);
std::string linebuf(&buf[0]);
// Trim newline '\r\n' or '\n' // Trim newline '\r\n' or '\n'
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
@@ -625,7 +747,7 @@ void LoadMtl(std::map<std::string, int> &material_map,
continue; // comment line continue; // comment line
// new mtl // new mtl
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) {
// flush previous material. // flush previous material.
if (!material.name.empty()) { if (!material.name.empty()) {
material_map.insert(std::pair<std::string, int>( material_map.insert(std::pair<std::string, int>(
@@ -649,7 +771,7 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// ambient // ambient
if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -660,7 +782,7 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// diffuse // diffuse
if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -671,7 +793,7 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// specular // specular
if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -682,7 +804,7 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// transmittance // transmittance
if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -693,14 +815,14 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// ior(index of refraction) // ior(index of refraction)
if (token[0] == 'N' && token[1] == 'i' && isSpace((token[2]))) { if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) {
token += 2; token += 2;
material.ior = parseFloat(token); material.ior = parseFloat(token);
continue; continue;
} }
// emission // emission
if (token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -711,26 +833,26 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// shininess // shininess
if (token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) {
token += 2; token += 2;
material.shininess = parseFloat(token); material.shininess = parseFloat(token);
continue; continue;
} }
// illum model // illum model
if (0 == strncmp(token, "illum", 5) && isSpace(token[5])) { if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) {
token += 6; token += 6;
material.illum = parseInt(token); material.illum = parseInt(token);
continue; continue;
} }
// dissolve // dissolve
if ((token[0] == 'd' && isSpace(token[1]))) { if ((token[0] == 'd' && IS_SPACE(token[1]))) {
token += 1; token += 1;
material.dissolve = parseFloat(token); material.dissolve = parseFloat(token);
continue; continue;
} }
if (token[0] == 'T' && token[1] == 'r' && isSpace(token[2])) { if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) {
token += 2; token += 2;
// Invert value of Tr(assume Tr is in range [0, 1]) // Invert value of Tr(assume Tr is in range [0, 1])
material.dissolve = 1.0f - parseFloat(token); material.dissolve = 1.0f - parseFloat(token);
@@ -738,56 +860,56 @@ void LoadMtl(std::map<std::string, int> &material_map,
} }
// ambient texture // ambient texture
if ((0 == strncmp(token, "map_Ka", 6)) && isSpace(token[6])) { if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
material.ambient_texname = token; material.ambient_texname = token;
continue; continue;
} }
// diffuse texture // diffuse texture
if ((0 == strncmp(token, "map_Kd", 6)) && isSpace(token[6])) { if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
material.diffuse_texname = token; material.diffuse_texname = token;
continue; continue;
} }
// specular texture // specular texture
if ((0 == strncmp(token, "map_Ks", 6)) && isSpace(token[6])) { if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
material.specular_texname = token; material.specular_texname = token;
continue; continue;
} }
// specular highlight texture // specular highlight texture
if ((0 == strncmp(token, "map_Ns", 6)) && isSpace(token[6])) { if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
material.specular_highlight_texname = token; material.specular_highlight_texname = token;
continue; continue;
} }
// bump texture // bump texture
if ((0 == strncmp(token, "map_bump", 8)) && isSpace(token[8])) { if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) {
token += 9; token += 9;
material.bump_texname = token; material.bump_texname = token;
continue; continue;
} }
// alpha texture // alpha texture
if ((0 == strncmp(token, "map_d", 5)) && isSpace(token[5])) { if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) {
token += 6; token += 6;
material.alpha_texname = token; material.alpha_texname = token;
continue; continue;
} }
// bump texture // bump texture
if ((0 == strncmp(token, "bump", 4)) && isSpace(token[4])) { if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
material.bump_texname = token; material.bump_texname = token;
continue; continue;
} }
// displacement texture // displacement texture
if ((0 == strncmp(token, "disp", 4)) && isSpace(token[4])) { if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
material.displacement_texname = token; material.displacement_texname = token;
continue; continue;
@@ -838,7 +960,7 @@ bool MaterialFileReader::operator()(const std::string &matId,
bool LoadObj(std::vector<shape_t> &shapes, // [output] bool LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<material_t> &materials, // [output] std::vector<material_t> &materials, // [output]
std::string &err, const char *filename, const char *mtl_basepath, std::string &err, const char *filename, const char *mtl_basepath,
bool trianglulate) { unsigned int flags) {
shapes.clear(); shapes.clear();
@@ -857,13 +979,14 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
MaterialFileReader matFileReader(basePath); MaterialFileReader matFileReader(basePath);
return LoadObj(shapes, materials, err, ifs, matFileReader, trianglulate); return LoadObj(shapes, materials, err, ifs, matFileReader, flags);
} }
bool LoadObj(std::vector<shape_t> &shapes, // [output] bool LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<material_t> &materials, // [output] std::vector<material_t> &materials, // [output]
std::string &err, std::istream &inStream, std::string &err, std::istream &inStream,
MaterialReader &readMatFn, bool triangulate) { MaterialReader &readMatFn, unsigned int flags) {
std::stringstream errss; std::stringstream errss;
std::vector<float> v; std::vector<float> v;
@@ -880,12 +1003,9 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
shape_t shape; shape_t shape;
int maxchars = 8192; // Alloc enough size.
std::vector<char> buf(static_cast<size_t>(maxchars)); // Alloc enough size.
while (inStream.peek() != -1) { while (inStream.peek() != -1) {
inStream.getline(&buf[0], maxchars); std::string linebuf;
safeGetline(inStream, linebuf);
std::string linebuf(&buf[0]);
// Trim newline '\r\n' or '\n' // Trim newline '\r\n' or '\n'
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
@@ -914,7 +1034,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
continue; // comment line continue; // comment line
// vertex // vertex
if (token[0] == 'v' && isSpace((token[1]))) { if (token[0] == 'v' && IS_SPACE((token[1]))) {
token += 2; token += 2;
float x, y, z; float x, y, z;
parseFloat3(x, y, z, token); parseFloat3(x, y, z, token);
@@ -925,7 +1045,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
// normal // normal
if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) { if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) {
token += 3; token += 3;
float x, y, z; float x, y, z;
parseFloat3(x, y, z, token); parseFloat3(x, y, z, token);
@@ -936,7 +1056,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
// texcoord // texcoord
if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) { if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) {
token += 3; token += 3;
float x, y; float x, y;
parseFloat2(x, y, token); parseFloat2(x, y, token);
@@ -946,12 +1066,14 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
// face // face
if (token[0] == 'f' && isSpace((token[1]))) { if (token[0] == 'f' && IS_SPACE((token[1]))) {
token += 2; token += 2;
token += strspn(token, " \t"); token += strspn(token, " \t");
std::vector<vertex_index> face; std::vector<vertex_index> face;
while (!isNewLine(token[0])) { face.reserve(3);
while (!IS_NEW_LINE(token[0])) {
vertex_index vi = parseTriple(token, static_cast<int>(v.size() / 3), vertex_index vi = parseTriple(token, static_cast<int>(v.size() / 3),
static_cast<int>(vn.size() / 3), static_cast<int>(vn.size() / 3),
static_cast<int>(vt.size() / 2)); static_cast<int>(vt.size() / 2));
@@ -960,13 +1082,15 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
token += n; token += n;
} }
faceGroup.push_back(face); // replace with emplace_back + std::move on C++11
faceGroup.push_back(std::vector<vertex_index>());
faceGroup[faceGroup.size() - 1].swap(face);
continue; continue;
} }
// use mtl // use mtl
if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) { if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) {
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
token += 7; token += 7;
@@ -976,28 +1100,26 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
sscanf(token, "%s", namebuf); sscanf(token, "%s", namebuf);
#endif #endif
// Create face group per material. int newMaterialId = -1;
bool ret =
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
material, name, true, triangulate);
if (ret) {
shapes.push_back(shape);
}
shape = shape_t();
faceGroup.clear();
if (material_map.find(namebuf) != material_map.end()) { if (material_map.find(namebuf) != material_map.end()) {
material = material_map[namebuf]; newMaterialId = material_map[namebuf];
} else { } else {
// { error!! material not found } // { error!! material not found }
material = -1; }
if (newMaterialId != material) {
// Create per-face material
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
material, name, true, flags, err );
faceGroup.clear();
material = newMaterialId;
} }
continue; continue;
} }
// load mtl // load mtl
if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) { if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) {
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
token += 7; token += 7;
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -1019,12 +1141,12 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
// group name // group name
if (token[0] == 'g' && isSpace((token[1]))) { if (token[0] == 'g' && IS_SPACE((token[1]))) {
// flush previous face group. // flush previous face group.
bool ret = bool ret =
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
material, name, true, triangulate); material, name, true, flags, err );
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
@@ -1035,7 +1157,9 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
faceGroup.clear(); faceGroup.clear();
std::vector<std::string> names; std::vector<std::string> names;
while (!isNewLine(token[0])) { names.reserve(2);
while (!IS_NEW_LINE(token[0])) {
std::string str = parseString(token); std::string str = parseString(token);
names.push_back(str); names.push_back(str);
token += strspn(token, " \t\r"); // skip tag token += strspn(token, " \t\r"); // skip tag
@@ -1054,12 +1178,12 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
// object name // object name
if (token[0] == 'o' && isSpace((token[1]))) { if (token[0] == 'o' && IS_SPACE((token[1]))) {
// flush previous face group. // flush previous face group.
bool ret = bool ret =
exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
material, name, true, triangulate); material, name, true, flags, err );
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
@@ -1081,12 +1205,16 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
continue; continue;
} }
if (token[0] == 't' && isSpace(token[1])) { if (token[0] == 't' && IS_SPACE(token[1])) {
tag_t tag; tag_t tag;
char namebuf[4096]; char namebuf[4096];
token += 2; token += 2;
#ifdef _MSC_VER
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
#else
sscanf(token, "%s", namebuf); sscanf(token, "%s", namebuf);
#endif
tag.name = std::string(namebuf); tag.name = std::string(namebuf);
token += tag.name.size() + 1; token += tag.name.size() + 1;
@@ -1110,7 +1238,11 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
for (size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i) { for (size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i) {
char stringValueBuffer[4096]; char stringValueBuffer[4096];
#ifdef _MSC_VER
sscanf_s(token, "%s", stringValueBuffer, (unsigned)_countof(stringValueBuffer));
#else
sscanf(token, "%s", stringValueBuffer); sscanf(token, "%s", stringValueBuffer);
#endif
tag.stringValues[i] = stringValueBuffer; tag.stringValues[i] = stringValueBuffer;
token += tag.stringValues[i].size() + 1; token += tag.stringValues[i].size() + 1;
} }
@@ -1122,13 +1254,14 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
} }
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup,
tags, material, name, true, triangulate); tags, material, name, true, flags, err );
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
faceGroup.clear(); // for safety faceGroup.clear(); // for safety
err += errss.str(); err += errss.str();
return true; return true;
} }
@@ -1136,4 +1269,4 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
#endif #endif
#endif // TINY_OBJ_LOADER_H #endif // TINY_OBJ_LOADER_H_

12
tools/travis_postbuild.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
DATEVAL=`date +%Y-%m-%d`
VERSIONVAL=master
# Use tag as version
if [ $TRAVIS_TAG ]; then
VERSIONVAL=$TRAVIS_TAG
fi
sed -e s%@DATE@%${DATEVAL}% .bintray.in > .bintray.tmp
sed -e s%@VERSION@%${VERSIONVAL}% .bintray.tmp > .bintray.json