79 Commits

Author SHA1 Message Date
Syoyo Fujita
e60d33385e Bump version 1.0.6 2017-04-25 04:34:45 +09:00
Syoyo Fujita
744d2baa58 Merge pull request #125 from noma/upstream_master
Added double support for scientific applications
2017-04-25 04:22:40 +09:00
noma
d5ca258817 Renamed realValues back to flaotValues, as it is part of the external interface and renaming would break existing code. 2017-04-24 17:49:39 +02:00
noma
b1ac3a6c7e Fixed package config and cmake config templates for double variant of the library. 2017-04-24 17:41:22 +02:00
noma
69e56db124 Replaced all float types by real_t ones. Also adapted names accordingly. 2017-04-24 17:31:42 +02:00
noma
13412b0898 Added real_t, defined to float or double depending on CMake option TINYOBJLOADER_USE_DOUBLE 2017-04-24 17:25:21 +02:00
noma
9912bc5023 Added double variant of lib to CMakeLists.txt 2017-04-24 17:20:20 +02:00
Syoyo Fujita
9d9e987c47 Merge pull request #123 from nikitoz/master
Add std namespace for pow, ldexp, sscanf function calls.
2017-02-23 00:35:52 +09:00
nyatsenk
345560040b Add std namespace for pow, ldexp, sscanf function calls. 2017-02-22 11:34:39 +01:00
Syoyo Fujita
9134c1d395 Add file size check. 2017-02-10 17:19:28 +09:00
Syoyo Fujita
cc9897316f Do not exit program when there is no texture coordinate in .obj. 2017-02-09 20:13:27 +09:00
Syoyo Fujita
e43580bd9a Fix build with pre-C++11 compiler 2017-02-09 16:10:19 +09:00
Syoyo Fujita
9613108cef Cosmetics. 2017-02-08 13:58:40 +09:00
Syoyo Fujita
4b29502c82 Add data layout description to README. 2017-02-08 13:57:25 +09:00
Syoyo Fujita
156b709556 Move TINYOBJLOADER_IMPLEMENTATION outside of TINY_OBJ_LOADER_H_ ifdef guard. Fixes #122. 2017-02-02 14:11:13 +09:00
Syoyo Fujita
00f51e3603 Merge pull request #121 from ForsakenHarmony/patch-1
Grammar?
2017-01-11 12:47:13 +09:00
Ashley
da5942d652 Grammar? 2017-01-11 01:10:52 +01:00
Syoyo Fujita
7c3206f919 Ignore Tr parameter when d exists in MTL(#43) 2016-12-31 21:05:37 +09:00
Syoyo Fujita
4886eebbf4 Merge pull request #120 from dPavelDev/master
Fixed error in getting material name in LoadObjWithCallback
2016-12-30 20:17:28 +09:00
dPavelDev
91c727e204 Fixed error in getting material name in LoadObjWithCallback 2016-12-29 15:45:23 +03:00
Syoyo Fujita
26bdacedf6 Merge pull request #119 from jamiesnape/fix-cmake-dir
Add MIT license file, use GNUInstallDirs module, fix cmake directory location
2016-12-29 01:55:00 +09:00
Jamie Snape
7212ee47eb Use GNUInstallDirs module and fix cmake directory location 2016-12-28 11:11:59 -05:00
Jamie Snape
0fe1bb96c2 Add MIT license file 2016-12-28 11:10:07 -05:00
Syoyo Fujita
4bd75baaae Merge pull request #118 from jamiesnape/cleanup
Fix some formatting inconsistencies, fix typo, update minimum CMake
2016-12-21 01:00:16 +09:00
Jamie Snape
bbcfe59c0f Update minimum required version of CMake 2016-12-20 09:44:47 -05:00
Jamie Snape
38c07d34c4 Fix typo in destination of CMake export file 2016-12-20 09:44:26 -05:00
Jamie Snape
2019ace3b7 Remove excess padding around some parentheses in CMake files 2016-12-20 09:32:41 -05:00
Jamie Snape
ad96ff0769 Consistently use spaces instead of tabs in CMake files 2016-12-20 09:32:41 -05:00
Syoyo Fujita
d7f83f29f0 Fix for Windows platform. 2016-12-20 15:42:15 +09:00
Syoyo Fujita
98fad65028 Merge pull request #117 from jamiesnape/cmake-pkg-config
Write and install CMake package config and pkg-config files
2016-12-20 13:56:36 +09:00
Jamie Snape
e88016c63f Write and install pkg-config file 2016-12-19 11:45:00 -05:00
Jamie Snape
edabf19461 Write and install CMake package config files
This allows find_package(tinyobjloader) to be called.
2016-12-19 11:44:39 -05:00
Syoyo Fujita
8bed734a18 Merge branch 'master' of github.com:syoyo/tinyobjloader 2016-12-09 01:51:33 +09:00
Syoyo Fujita
60ffb3ca9a Add missing files. Fixes #115. 2016-12-09 01:51:03 +09:00
Syoyo Fujita
6507e70236 Merge pull request #113 from ReinierMaas/patch-1
Update README.md
2016-12-07 00:55:28 +09:00
Syoyo Fujita
2daec8be53 Search .mtl and texture from .obj's base dir.
Fix bad memory access.
2016-12-07 00:54:12 +09:00
Syoyo Fujita
c2ff3f12fc Support multiple filenames for mtllib line. Fixes #112. 2016-12-06 23:44:55 +09:00
Reinier Maas
a6a134a60e Update README.md
Basedline -> baseline
2016-12-06 15:38:26 +01:00
Syoyo Fujita
e0b39341fc Merge pull request #111 from longjon/python2
Support Python 2.7
2016-12-06 14:37:05 +09:00
Syoyo Fujita
947582b592 Merge pull request #110 from longjon/python-attribs
(Re-)expose attributes to Python
2016-12-06 14:36:14 +09:00
Jonathan L Long
c207ff3561 Support Python 2.7. 2016-12-05 15:24:22 -08:00
Jonathan L Long
41dd7c806e (Re-)expose attribs to Python. 2016-12-05 15:12:28 -08:00
Syoyo Fujita
aa4dabe64f Describe default behavior of mtl_basedir. 2016-11-23 17:17:35 +09:00
Syoyo Fujita
9868630d0e Fix windows build of loader_example. 2016-11-04 12:36:15 +09:00
Syoyo Fujita
f2397573f3 Merge pull request #107 from Warezovvv/master
Little intuitive improvements
2016-11-03 17:39:16 +09:00
Nikita Krupitskas
7d5699118e Little intuitive improvements 2016-11-03 11:23:21 +03:00
Syoyo Fujita
0948ca0417 Add more support for parsing texture options.
Add more unit testing for texture options.
2016-11-03 02:58:44 +09:00
Syoyo Fujita
582eb2b818 Initial support of texture options. 2016-11-02 02:11:17 +09:00
Syoyo Fujita
c2474e27ab Fix seg fault when no material assigned to object in viewer example.
Bump version v1.0.2.
2016-10-24 23:58:33 +09:00
Syoyo Fujita
6c6390f034 Fix typo. 2016-10-24 23:58:23 +09:00
Syoyo Fujita
4d6649cc6d Suppress compiler warnings. 2016-10-24 23:54:20 +09:00
Syoyo Fujita
d543b1447f Merge pull request #105 from dotdash/speedup
Improve parsing speed by about a factor of 2 for large files
2016-10-24 23:37:34 +09:00
Björn Steinbrink
d6eeb14216 Avoid unnecessary ldexp() and pow() calls
Parse times for some large .obj files (without asan):

         File A  File B  File C
Before   1239ms   294ms   271ms
After    1037ms   203ms   190ms
2016-10-24 14:47:59 +02:00
Björn Steinbrink
aa670fe91e Use a lookup table to speed up float parsing
The pow() function is pretty expensive, so creating a small lookup
table for the first few negative powers of ten provides a big speedup.

Parse times for some large .obj files (without asan):

        File A  File B  File C
Before  2500ms   573ms   545ms
After   1239ms   294ms   271ms
2016-10-24 12:15:42 +02:00
Björn Steinbrink
ebdbd8a231 Avoid unnecessary reallocations of the "linebuf" string
safeGetline() already clears the string buffer before writing to it, so
the same buffer can be used multiple times, but the loops calling
safeGetline() have the string scoped within the loop, so its
constructed and destructed in each loop iteration, causing lots of
unnecessary allocations.

Parse times for some large .obj files (without asan):

        File A  File B  File C
Before  2743ms   589ms   615ms
After   2500ms   573ms   545ms
2016-10-24 12:13:56 +02:00
Syoyo Fujita
fed4322d26 Merge branch 'master' of github.com:syoyo/tinyobjloader 2016-10-18 17:34:15 +09:00
Syoyo Fujita
039d4a6c54 Fix a shape is lost if obj ends with a 'usemtl'. Fixes #104 2016-10-18 17:33:28 +09:00
Syoyo Fujita
28ee1b42ce Merge pull request #103 from chrisliebert/master
Issue #74: Added basic diffuse texture support to examples/viewer
2016-10-08 14:02:11 +09:00
Chris Liebert
35889026d6 added additional bounds checking 2016-10-07 21:21:33 -07:00
Chris Liebert
e81ac971b0 Issue #74: Added basic diffuse texture support to examples/viewer using stb_image. The previously used color based on the normal is combined with the diffuse color from the material definition. 2016-10-07 20:58:04 -07:00
Syoyo Fujita
e05ce6aff0 Merge pull request #102 from Entalpi/master
Minor spelling fix
2016-10-07 11:40:33 +09:00
Alexander Lingtorp
e4598ba84a Minor spelling fix 2016-10-06 19:30:21 +02:00
Syoyo Fujita
79513077f3 Fix compilation on pre-C++11 compiler. 2016-10-02 17:37:02 +09:00
Syoyo Fujita
72acadca79 Merge pull request #101 from kavika13/master
Make it easier to use an existing stream reader
2016-10-02 17:35:36 +09:00
Merlyn Morgan-Graham
398e358826 Add unit tests for reading from existing file stream 2016-10-02 01:25:07 -07:00
Merlyn Morgan-Graham
7fc9b0fe97 Add stream based material reader implementation 2016-10-02 00:52:45 -07:00
Merlyn Morgan-Graham
71cc967f42 Allow skipping material reads on LoadObj istream overload 2016-10-02 00:52:19 -07:00
Syoyo Fujita
3ddad1e377 Merge pull request #97 from middlefeng/url-update
Metal viewer URL update.
2016-09-09 00:45:08 +09:00
middleware
92805d3088 Metal viewer URL update. 2016-09-07 06:31:08 -07:00
Syoyo Fujita
60acd05a03 Add brief README. 2016-09-06 02:18:24 +09:00
Syoyo Fujita
4a18e241d9 Measure zstd decompress time. 2016-09-06 02:11:23 +09:00
Syoyo Fujita
1b88a1e3c7 Support reading .obj from ZStd compressed format. 2016-09-04 19:34:05 +09:00
Syoyo Fujita
b3feefafdf Add link to MetalExamples. 2016-09-03 21:43:00 +09:00
Syoyo Fujita
a7a16db908 Add a link to GeeXLab. 2016-08-23 02:48:06 +09:00
Syoyo Fujita
9f92ba34a6 Update Feature list. 2016-08-23 02:44:32 +09:00
Syoyo Fujita
25cf039953 Add more link. 2016-08-23 02:37:47 +09:00
Syoyo Fujita
6bf145d7cf Add link to "Fast OBJ file importing and parsing in CUDA". 2016-08-23 02:35:31 +09:00
Syoyo Fujita
69240e18b4 Add link to PBGI. 2016-08-23 02:29:41 +09:00
Syoyo Fujita
5b9f431512 Update TODO list. 2016-08-20 18:16:50 +09:00
27 changed files with 9885 additions and 263 deletions

View File

@@ -2,60 +2,145 @@
#This configures the Cmake system with multiple properties, depending
#on the platform and configuration it is set to build in.
project(tinyobjloader)
cmake_minimum_required(VERSION 2.8.6)
cmake_minimum_required(VERSION 2.8.11)
set(TINYOBJLOADER_SOVERSION 1)
set(TINYOBJLOADER_VERSION 1.0.4)
#optional double precision support
option(TINYOBJLOADER_USE_DOUBLE "Build library with double precision instead of single (float)" OFF)
if(TINYOBJLOADER_USE_DOUBLE)
add_definitions(-DTINYOBJLOADER_USE_DOUBLE)
set(LIBRARY_NAME ${PROJECT_NAME}_double)
else()
set(LIBRARY_NAME ${PROJECT_NAME})
endif()
#Folder Shortcuts
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
set(tinyobjloader-Source
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
)
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
)
set(tinyobjloader-Example-Source
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
)
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
)
set(tinyobjloader-examples-objsticher
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
)
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
)
#Install destinations
include(GNUInstallDirs)
set(TINYOBJLOADER_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake)
set(TINYOBJLOADER_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
set(TINYOBJLOADER_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(TINYOBJLOADER_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR})
set(TINYOBJLOADER_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
set(TINYOBJLOADER_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR})
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Example Loader Application" OFF)
option(TINYOBJLOADER_COMPILATION_SHARED "Build as shared library" OFF)
if (TINYOBJLOADER_COMPILATION_SHARED)
add_library(tinyobjloader SHARED ${tinyobjloader-Source})
if(TINYOBJLOADER_COMPILATION_SHARED)
add_library(${LIBRARY_NAME} SHARED ${tinyobjloader-Source})
set_target_properties(${LIBRARY_NAME} PROPERTIES
SOVERSION ${TINYOBJLOADER_SOVERSION}
)
else()
add_library(tinyobjloader STATIC ${tinyobjloader-Source})
add_library(${LIBRARY_NAME} STATIC ${tinyobjloader-Source})
endif()
set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION ${TINYOBJLOADER_VERSION})
target_include_directories(${LIBRARY_NAME} INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${TINYOBJLOADER_INCLUDE_DIR}>
)
export(TARGETS ${LIBRARY_NAME} FILE ${PROJECT_NAME}-targets.cmake)
if(TINYOBJLOADER_BUILD_TEST_LOADER)
add_executable(test_loader ${tinyobjloader-Example-Source})
target_link_libraries(test_loader tinyobjloader)
target_link_libraries(test_loader ${LIBRARY_NAME})
endif()
option(TINYOBJLOADER_BUILD_OBJ_STICHER "Build OBJ Sticher Application" OFF)
if (TINYOBJLOADER_BUILD_OBJ_STICHER)
if(TINYOBJLOADER_BUILD_OBJ_STICHER)
add_executable(obj_sticher ${tinyobjloader-examples-objsticher})
target_link_libraries(obj_sticher tinyobjloader)
target_link_libraries(obj_sticher ${LIBRARY_NAME})
install ( TARGETS
install(TARGETS
obj_sticher
DESTINATION
bin
${TINYOBJLOADER_RUNTIME_DIR}
)
endif()
#Installation
install ( TARGETS
tinyobjloader
DESTINATION
lib
#Write CMake package config files
include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_NAME}-config.cmake.in
${LIBRARY_NAME}-config.cmake
INSTALL_DESTINATION
${TINYOBJLOADER_CMAKE_DIR}
PATH_VARS
TINYOBJLOADER_INCLUDE_DIR
TINYOBJLOADER_LIBRARY_DIR
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
install ( FILES
write_basic_package_version_file(${LIBRARY_NAME}-config-version.cmake
VERSION
${TINYOBJLOADER_VERSION}
COMPATIBILITY
SameMajorVersion
)
#pkg-config file
configure_file(${PROJECT_NAME}.pc.in ${LIBRARY_NAME}.pc @ONLY)
#Installation
install(TARGETS
${LIBRARY_NAME}
EXPORT ${PROJECT_NAME}-targets
DESTINATION
${TINYOBJLOADER_LIBRARY_DIR}
PUBLIC_HEADER DESTINATION
${TINYOBJLOADER_INCLUDE_DIR}
RUNTIME DESTINATION
${TINYOBJLOADER_RUNTIME_DIR}
)
install(EXPORT
${PROJECT_NAME}-targets
DESTINATION
${TINYOBJLOADER_CMAKE_DIR}
)
install(FILES
tiny_obj_loader.h
DESTINATION
include
${TINYOBJLOADER_INCLUDE_DIR}
)
install(FILES
LICENSE
DESTINATION
${TINYOBJLOADER_DOC_DIR}
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}-config-version.cmake"
DESTINATION
${TINYOBJLOADER_CMAKE_DIR}
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}.pc"
DESTINATION
${TINYOBJLOADER_PKGCONFIG_DIR}
)

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2012-2016 Syoyo Fujita and many contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -12,7 +12,7 @@
http://syoyo.github.io/tinyobjloader/
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.
Tiny but powerful single file wavefront obj loader written in C++. No dependency except for C++ STL. It can parse over 10M polygons with moderate memory and time.
`tinyobjloader` is good for embedding .obj loader to your (global illumination) renderer ;-)
@@ -52,6 +52,7 @@ TinyObjLoader is successfully used in ...
### New version(v1.0.x)
* Loading models in Vulkan Tutorial https://vulkan-tutorial.com/Loading_models
* .obj viewer with Metal https://github.com/middlefeng/NuoModelViewer/tree/master
* Your project here!
### Old version(v0.9.x)
@@ -73,6 +74,11 @@ TinyObjLoader is successfully used in ...
* 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
* Point Based Global Illumination on modern GPU https://pbgi.wordpress.com/code-source/
* Fast OBJ file importing and parsing in CUDA http://researchonline.jcu.edu.au/42515/1/2015.CVM.OBJCUDA.pdf
* Sorted Shading for Uni-Directional Pathtracing by Joshua Bainbridge https://nccastaff.bournemouth.ac.uk/jmacey/MastersProjects/MSc15/02Josh/joshua_bainbridge_thesis.pdf
* GeeXLab http://www.geeks3d.com/hacklab/20160531/geexlab-0-12-0-0-released-for-windows/
## Features
@@ -83,6 +89,7 @@ TinyObjLoader is successfully used in ...
* Material
* Unknown material attributes are returned as key-value(value is string) map.
* Crease tag('t'). This is OpenSubdiv specific(not in wavefront .obj specification)
* PBR material extension for .MTL. Its proposed here: http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
* Callback API for custom loading.
@@ -90,6 +97,9 @@ TinyObjLoader is successfully used in ...
* [ ] Fix obj_sticker example.
* [ ] More unit test codes.
* [x] Texture options
* [ ] Normal vector generation
* [ ] Support smoothing groups
## License
@@ -97,10 +107,76 @@ Licensed under MIT license.
## Usage
### Data format
`attrib_t` contains single and linear array of vertex data(position, normal and texcoord).
Each `shape_t` does not contain vertex data but contains array index to `attrib_t`.
```
attrib_t::vertices => 3 floats per vertex
v[0] v[1] v[2] v[3] v[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+-----------+-----------+-----------+-----------+ +-----------+
attrib_t::normals => 3 floats per vertex
n[0] n[1] n[2] n[3] n[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
+-----------+-----------+-----------+-----------+ +-----------+
attrib_t::texcoords => 2 floats per vertex
t[0] t[1] t[2] t[3] t[n-1]
+-----------+-----------+-----------+-----------+ +-----------+
| u | v | u | v | u | v | u | v | .... | u | v |
+-----------+-----------+-----------+-----------+ +-----------+
```
Each `shape_t::mesh_t` does not contain vertex data but contains array index to `attrib_t`.
See `loader_example.cc` for more details.
```
mesh_t::indices => array of vertex indices.
+----+----+----+----+----+----+----+----+----+----+ +--------+
| i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-1) |
+----+----+----+----+----+----+----+----+----+----+ +--------+
Each index has an array index to attrib_t::vertices, attrib_t::normals and attrib_t::texcoords.
mesh_t::num_face_vertices => array of the number of vertices per face(e.g. 3 = triangle, 4 = quad , 5 or more = N-gons).
+---+---+---+ +---+
| 3 | 4 | 3 | ...... | 3 |
+---+---+---+ +---+
| | | |
| | | +-----------------------------------------+
| | | |
| | +------------------------------+ |
| | | |
| +------------------+ | |
| | | |
|/ |/ |/ |/
mesh_t::indices
| face[0] | face[1] | face[2] | | face[n-1] |
+----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
| i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 | ... | i(n-3) | i(n-2) | i(n-1) |
+----+----+----+----+----+----+----+----+----+----+ +--------+--------+--------+
```
Note that when `triangulate` flas is true in `tinyobj::LoadObj()` argument, `num_face_vertices` are all filled with 3(triangle).
#### Example code
```c++
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
#include "tiny_obj_loader.h"
@@ -161,7 +237,7 @@ Here is some benchmark result. Time are measured on MacBook 12(Early 2016, Core
* Rungholt scene(6M triangles)
* old version(v0.9.x): 15500 msecs.
* baseline(v1.0.x): 6800 msecs(2.3x faster than old version)
* optimised: 1500 msecs(10x faster than old version, 4.5x faster than basedline)
* optimised: 1500 msecs(10x faster than old version, 4.5x faster than baseline)
## Tests

6755
examples/viewer/stb_image.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@
#include <cstdlib>
#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <vector>
@@ -26,12 +27,24 @@
#include "trackball.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#ifdef _WIN32
#ifdef __cplusplus
extern "C" {
#endif
#include <mmsystem.h>
#include <windows.h>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
#include <mmsystem.h>
#ifdef __cplusplus
}
#endif
@@ -112,6 +125,7 @@ class timerutil {
typedef struct {
GLuint vb; // vertex buffer
int numTriangles;
size_t material_id;
} DrawObject;
std::vector<DrawObject> gDrawObjects;
@@ -129,7 +143,26 @@ float eye[3], lookat[3], up[3];
GLFWwindow* window;
void CheckErrors(std::string desc) {
static std::string GetBaseDir(const std::string &filepath) {
if (filepath.find_last_of("/\\") != std::string::npos)
return filepath.substr(0, filepath.find_last_of("/\\"));
return "";
}
static bool FileExists(const std::string &abs_filename) {
bool ret;
FILE *fp = fopen(abs_filename.c_str(), "rb");
if (fp) {
ret = true;
fclose(fp);
} else {
ret = false;
}
return ret;
}
static void CheckErrors(std::string desc) {
GLenum e = glGetError();
if (e != GL_NO_ERROR) {
fprintf(stderr, "OpenGL error in \"%s\": %d (%d)\n", desc.c_str(), e, e);
@@ -137,7 +170,7 @@ void CheckErrors(std::string desc) {
}
}
void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
static void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
float v10[3];
v10[0] = v1[0] - v0[0];
v10[1] = v1[1] - v0[1];
@@ -161,20 +194,28 @@ void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
}
}
bool LoadObjAndConvert(float bmin[3], float bmax[3],
static bool LoadObjAndConvert(float bmin[3], float bmax[3],
std::vector<DrawObject>* drawObjects,
std::vector<tinyobj::material_t>& materials,
std::map<std::string, GLuint>& textures,
const char* filename) {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
timerutil tm;
tm.start();
std::string base_dir = GetBaseDir(filename);
#ifdef _WIN32
base_dir += "\\";
#else
base_dir += "/";
#endif
std::string err;
bool ret =
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, NULL);
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, base_dir.c_str());
if (!err.empty()) {
std::cerr << err << std::endl;
}
@@ -194,6 +235,54 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
printf("# of materials = %d\n", (int)materials.size());
printf("# of shapes = %d\n", (int)shapes.size());
// Append `default` material
materials.push_back(tinyobj::material_t());
// Load diffuse textures
{
for (size_t m = 0; m < materials.size(); m++) {
tinyobj::material_t* mp = &materials[m];
if (mp->diffuse_texname.length() > 0) {
// Only load the texture if it is not already loaded
if (textures.find(mp->diffuse_texname) == textures.end()) {
GLuint texture_id;
int w, h;
int comp;
std::string texture_filename = mp->diffuse_texname;
if (!FileExists(texture_filename)) {
// Append base dir.
texture_filename = base_dir + mp->diffuse_texname;
if (!FileExists(texture_filename)) {
std::cerr << "Unable to find file: " << mp->diffuse_texname << std::endl;
exit(1);
}
}
unsigned char* image = stbi_load(texture_filename.c_str(), &w, &h, &comp, STBI_default);
if (!image) {
std::cerr << "Unable to load texture: " << texture_filename << std::endl;
exit(1);
}
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
if (comp == 3) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
}
else if (comp == 4) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
}
glBindTexture(GL_TEXTURE_2D, 0);
stbi_image_free(image);
textures.insert(std::make_pair(mp->diffuse_texname, texture_id));
}
}
}
}
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
@@ -205,6 +294,40 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
tinyobj::index_t idx0 = shapes[s].mesh.indices[3 * f + 0];
tinyobj::index_t idx1 = shapes[s].mesh.indices[3 * f + 1];
tinyobj::index_t idx2 = shapes[s].mesh.indices[3 * f + 2];
int current_material_id = shapes[s].mesh.material_ids[f];
if ((current_material_id < 0) || (current_material_id >= static_cast<int>(materials.size()))) {
// Invaid material ID. Use default material.
current_material_id = materials.size() - 1; // Default material is added to the last item in `materials`.
}
//if (current_material_id >= materials.size()) {
// std::cerr << "Invalid material index: " << current_material_id << std::endl;
//}
//
float diffuse[3];
for (size_t i = 0; i < 3; i++) {
diffuse[i] = materials[current_material_id].diffuse[i];
}
float tc[3][2];
if (attrib.texcoords.size() > 0) {
assert(attrib.texcoords.size() > 2 * idx0.texcoord_index + 1);
assert(attrib.texcoords.size() > 2 * idx1.texcoord_index + 1);
assert(attrib.texcoords.size() > 2 * idx2.texcoord_index + 1);
tc[0][0] = attrib.texcoords[2 * idx0.texcoord_index];
tc[0][1] = 1.0f - attrib.texcoords[2 * idx0.texcoord_index + 1];
tc[1][0] = attrib.texcoords[2 * idx1.texcoord_index];
tc[1][1] = 1.0f - attrib.texcoords[2 * idx1.texcoord_index + 1];
tc[2][0] = attrib.texcoords[2 * idx2.texcoord_index];
tc[2][1] = 1.0f - attrib.texcoords[2 * idx2.texcoord_index + 1];
} else {
tc[0][0] = 0.0f;
tc[0][1] = 0.0f;
tc[1][0] = 0.0f;
tc[1][1] = 0.0f;
tc[2][0] = 0.0f;
tc[2][1] = 0.0f;
}
float v[3][3];
for (int k = 0; k < 3; k++) {
@@ -227,7 +350,6 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
}
float n[3][3];
if (attrib.normals.size() > 0) {
int f0 = idx0.normal_index;
int f1 = idx1.normal_index;
@@ -258,8 +380,14 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
vb.push_back(n[k][0]);
vb.push_back(n[k][1]);
vb.push_back(n[k][2]);
// Use normal as color.
float c[3] = {n[k][0], n[k][1], n[k][2]};
// Combine normal and diffuse to get color.
float normal_factor = 0.2;
float diffuse_factor = 1 - normal_factor;
float c[3] = {
n[k][0] * normal_factor + diffuse[0] * diffuse_factor,
n[k][1] * normal_factor + diffuse[1] * diffuse_factor,
n[k][2] * normal_factor + diffuse[2] * diffuse_factor
};
float len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2];
if (len2 > 0.0f) {
float len = sqrtf(len2);
@@ -271,17 +399,29 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
vb.push_back(c[0] * 0.5 + 0.5);
vb.push_back(c[1] * 0.5 + 0.5);
vb.push_back(c[2] * 0.5 + 0.5);
vb.push_back(tc[k][0]);
vb.push_back(tc[k][1]);
}
}
o.vb = 0;
o.numTriangles = 0;
// OpenGL viewer does not support texturing with per-face material.
if (shapes[s].mesh.material_ids.size() > 0 && shapes[s].mesh.material_ids.size() > s) {
// Base case
o.material_id = shapes[s].mesh.material_ids[s];
} else {
o.material_id = materials.size() - 1; // = ID for default material.
}
if (vb.size() > 0) {
glGenBuffers(1, &o.vb);
glBindBuffer(GL_ARRAY_BUFFER, o.vb);
glBufferData(GL_ARRAY_BUFFER, vb.size() * sizeof(float), &vb.at(0),
GL_STATIC_DRAW);
o.numTriangles = vb.size() / 9 / 3;
o.numTriangles = vb.size() / (3 + 3 + 3 + 2) * 3;
printf("shape[%d] # of triangles = %d\n", static_cast<int>(s),
o.numTriangles);
}
@@ -296,7 +436,7 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
return true;
}
void reshapeFunc(GLFWwindow* window, int w, int h) {
static void reshapeFunc(GLFWwindow* window, int w, int h) {
int fb_w, fb_h;
// Get actual framebuffer size.
glfwGetFramebufferSize(window, &fb_w, &fb_h);
@@ -312,7 +452,7 @@ void reshapeFunc(GLFWwindow* window, int w, int h) {
height = h;
}
void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
int mods) {
(void)window;
(void)scancode;
@@ -341,7 +481,7 @@ void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
}
}
void clickFunc(GLFWwindow* window, int button, int action, int mods) {
static void clickFunc(GLFWwindow* window, int button, int action, int mods) {
(void)window;
(void)mods;
if (button == GLFW_MOUSE_BUTTON_LEFT) {
@@ -368,7 +508,7 @@ void clickFunc(GLFWwindow* window, int button, int action, int mods) {
}
}
void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
(void)window;
float rotScale = 1.0f;
float transScale = 2.0f;
@@ -395,13 +535,13 @@ void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
prevMouseY = mouse_y;
}
void Draw(const std::vector<DrawObject>& drawObjects) {
static void Draw(const std::vector<DrawObject>& drawObjects, std::vector<tinyobj::material_t>& materials, std::map<std::string, GLuint>& textures) {
glPolygonMode(GL_FRONT, GL_FILL);
glPolygonMode(GL_BACK, GL_FILL);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
glColor3f(1.0f, 1.0f, 1.0f);
GLsizei stride = (3 + 3 + 3 + 2) * sizeof(float);
for (size_t i = 0; i < drawObjects.size(); i++) {
DrawObject o = drawObjects[i];
if (o.vb < 1) {
@@ -412,12 +552,22 @@ void Draw(const std::vector<DrawObject>& drawObjects) {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 36, (const void*)0);
glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float) * 3));
glColorPointer(3, GL_FLOAT, 36, (const void*)(sizeof(float) * 6));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
if ((o.material_id < materials.size())) {
std::string diffuse_texname = materials[o.material_id].diffuse_texname;
if (textures.find(diffuse_texname) != textures.end()) {
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]);
}
}
glVertexPointer(3, GL_FLOAT, stride, (const void*)0);
glNormalPointer(GL_FLOAT, stride, (const void*)(sizeof(float) * 3));
glColorPointer(3, GL_FLOAT, stride, (const void*)(sizeof(float) * 6));
glTexCoordPointer(2, GL_FLOAT, stride, (const void*)(sizeof(float) * 9));
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles);
CheckErrors("drawarrays");
glBindTexture(GL_TEXTURE_2D, 0);
}
// draw wireframe
@@ -436,8 +586,11 @@ void Draw(const std::vector<DrawObject>& drawObjects) {
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 36, (const void*)0);
glNormalPointer(GL_FLOAT, 36, (const void*)(sizeof(float) * 3));
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(3, GL_FLOAT, stride, (const void*)0);
glNormalPointer(GL_FLOAT, stride, (const void*)(sizeof(float) * 3));
glColorPointer(3, GL_FLOAT, stride, (const void*)(sizeof(float) * 6));
glTexCoordPointer(2, GL_FLOAT, stride, (const void*)(sizeof(float) * 9));
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles);
CheckErrors("drawarrays");
@@ -498,7 +651,9 @@ int main(int argc, char** argv) {
reshapeFunc(window, width, height);
float bmin[3], bmax[3];
if (false == LoadObjAndConvert(bmin, bmax, &gDrawObjects, argv[1])) {
std::vector<tinyobj::material_t> materials;
std::map<std::string, GLuint> textures;
if (false == LoadObjAndConvert(bmin, bmax, &gDrawObjects, materials, textures, argv[1])) {
return -1;
}
@@ -516,6 +671,7 @@ int main(int argc, char** argv) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
// camera & rotate
glMatrixMode(GL_MODELVIEW);
@@ -533,7 +689,7 @@ int main(int argc, char** argv) {
glTranslatef(-0.5 * (bmax[0] + bmin[0]), -0.5 * (bmax[1] + bmin[1]),
-0.5 * (bmax[2] + bmin[2]));
Draw(gDrawObjects);
Draw(gDrawObjects, materials, textures);
glfwSwapBuffers(window);
}

View File

@@ -0,0 +1,2 @@
all:
g++ -o voxelizer main.cc

View File

@@ -0,0 +1,5 @@
# Voxelize .obj and export it as also in .obj
## Third party library
This example uses https://github.com/karimnaaji/voxelizer, which is licensed under MIT Liense.

74
examples/voxelize/main.cc Normal file
View File

@@ -0,0 +1,74 @@
#define VOXELIZER_IMPLEMENTATION
#include "voxelizer.h"
#define TINYOBJLOADER_IMPLEMENTATION
#include "../../tiny_obj_loader.h"
bool Voxelize(const char* filename, float voxelsizex, float voxelsizey, float voxelsizez, float precision)
{
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, filename);
if (!err.empty()) {
printf("err: %s\n", err.c_str());
}
if (!ret) {
printf("failed to load : %s\n", filename);
return false;
}
if (shapes.size() == 0) {
printf("err: # of shapes are zero.\n");
return false;
}
// Only use first shape.
{
vx_mesh_t* mesh;
vx_mesh_t* result;
mesh = vx_mesh_alloc(attrib.vertices.size(), shapes[0].mesh.indices.size());
for (size_t f = 0; f < shapes[0].mesh.indices.size(); f++) {
mesh->indices[f] = shapes[0].mesh.indices[f].vertex_index;
}
for (size_t v = 0; v < attrib.vertices.size() / 3; v++) {
mesh->vertices[v].x = attrib.vertices[3*v+0];
mesh->vertices[v].y = attrib.vertices[3*v+1];
mesh->vertices[v].z = attrib.vertices[3*v+2];
}
result = vx_voxelize(mesh, voxelsizex, voxelsizey, voxelsizez, precision);
printf("Number of vertices: %ld\n", result->nvertices);
printf("Number of indices: %ld\n", result->nindices);
}
return true;
}
int
main(
int argc,
char** argv)
{
if (argc < 4) {
printf("Usage: voxelize input.obj voxelsizex voxelsizey voxelsizez precision\n");
exit(-1);
}
const char* filename = argv[1];
float voxelsizex = atof(argv[2]);
float voxelsizey = atof(argv[3]);
float voxelsizez = atof(argv[4]);
float prec = atof(argv[5]);
bool ret = Voxelize(filename, voxelsizex, voxelsizey, voxelsizez, prec);
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -0,0 +1,764 @@
//
// LICENCE:
// The MIT License (MIT)
//
// Copyright (c) 2016 Karim Naaji, karim.naaji@gmail.com
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE
//
// REFERENCES:
// http://matthias-mueller-fischer.ch/publications/tetraederCollision.pdf
// http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/tribox2.txt
//
// HOWTO:
// #define VOXELIZER_IMPLEMENTATION
// #define VOXELIZER_DEBUG // Only if assertions need to be checked
// #include "voxelizer.h"
//
// HISTORY:
// - version 0.9.0: Initial
//
// TODO:
// - Triangle face merging
// - Add colors from input mesh
// - Potential issue with voxel bigger than triangle
//
#ifndef VOXELIZER_H
#define VOXELIZER_H
// ------------------------------------------------------------------------------------------------
// VOXELIZER PUBLIC API
//
#ifndef VOXELIZER_HELPERS
#include <stdlib.h> // malloc, calloc, free
#endif
typedef struct vx_vertex {
union {
float v[3];
struct {
float x;
float y;
float z;
};
};
} vx_vertex_t;
typedef struct vx_mesh {
vx_vertex_t* vertices; // Contiguous mesh vertices
vx_vertex_t* normals; // Contiguous mesh normals
unsigned int* indices; // Mesh indices
unsigned int* normalindices; // Mesh normal indices
size_t nindices; // The number of normal indices
size_t nvertices; // The number of vertices
size_t nnormals; // The number of normals
} vx_mesh_t;
vx_mesh_t* vx_voxelize(vx_mesh_t* _mesh, // The input mesh
float voxelsizex, // Voxel size on X-axis
float voxelsizey, // Voxel size on Y-axis
float voxelsizez, // Voxel size on Z-axis
float precision); // A precision factor that reduces "holes" artifact
// usually a precision = voxelsize / 10. works ok.
void vx_mesh_free(vx_mesh_t* _mesh);
vx_mesh_t* vx_mesh_alloc(int nindices, int nvertices);
// Voxelizer Helpers, define your own if needed
#ifndef VOXELIZER_HELPERS
#define VOXELIZER_HELPERS 1
#define VX_MIN(a, b) (a > b ? b : a)
#define VX_MAX(a, b) (a > b ? a : b)
#define VX_FINDMINMAX(x0, x1, x2, min, max) \
min = max = x0; \
if (x1 < min) min = x1; \
if (x1 > max) max = x1; \
if (x2 < min) min = x2; \
if (x2 > max) max = x2;
#define VX_CLAMP(v, lo, hi) VX_MAX(lo, VX_MIN(hi, v))
#define VX_MALLOC(T, N) ((T*) malloc(N * sizeof(T)))
#define VX_FREE(T) free(T)
#define VX_CALLOC(T, N) ((T*) calloc(N * sizeof(T), 1))
#define VX_SWAP(T, A, B) { T tmp = B; B = A; A = tmp; }
#ifdef VOXELIZER_DEBUG
#define VX_ASSERT(STMT) if (!(STMT)) { *(int *)0 = 0; }
#else
#define VX_ASSERT(STMT)
#endif // VOXELIZER_DEBUG
#endif // VOXELIZER_HELPERS
//
// END VOXELIZER PUBLIC API
// ------------------------------------------------------------------------------------------------
#endif // VOXELIZER_H
#ifdef VOXELIZER_IMPLEMENTATION
#include <math.h> // ceil, fabs & al.
#include <stdbool.h> // hughh
#include <string.h> // memcpy
#define VOXELIZER_EPSILON (0.0000001)
#define VOXELIZER_NORMAL_INDICES_SIZE (6)
#define VOXELIZER_INDICES_SIZE (36)
#define VOXELIZER_HASH_TABLE_SIZE (4096)
unsigned int vx_voxel_indices[VOXELIZER_INDICES_SIZE] = {
0, 1, 2,
0, 2, 3,
3, 2, 6,
3, 6, 7,
0, 7, 4,
0, 3, 7,
4, 7, 5,
7, 6, 5,
0, 4, 5,
0, 5, 1,
1, 5, 6,
1, 6, 2,
};
float vx_normals[18] = {
0.0, -1.0, 0.0,
0.0, 1.0, 0.0,
1.0, 0.0, 0.0,
0.0, 0.0, 1.0,
-1.0, 0.0, 0.0,
0.0, 0.0, -1.0,
};
unsigned int vx_normal_indices[VOXELIZER_NORMAL_INDICES_SIZE] = {
3, 2, 1, 5, 4, 0,
};
typedef struct vx_aabb {
vx_vertex_t min;
vx_vertex_t max;
} vx_aabb_t;
typedef struct vx_edge {
vx_vertex_t p1;
vx_vertex_t p2;
} vx_edge_t;
typedef struct vx_triangle {
vx_vertex_t p1;
vx_vertex_t p2;
vx_vertex_t p3;
} vx_triangle_t;
typedef struct vx_hash_table_node {
struct vx_hash_table_node* next;
struct vx_hash_table_node* prev;
void* data;
} vx_hash_table_node_t;
typedef struct vx_hash_table {
vx_hash_table_node_t** elements;
size_t size;
} vx_hash_table_t;
vx_hash_table_t* vx__hash_table_alloc(size_t size)
{
vx_hash_table_t* table = VX_MALLOC(vx_hash_table_t, 1);
if (!table) { return NULL; }
table->size = size;
table->elements = VX_MALLOC(vx_hash_table_node_t*, size);
if (!table->elements) { return NULL; }
for (size_t i = 0; i < table->size; ++i) {
table->elements[i] = NULL;
}
return table;
}
void vx__hash_table_free(vx_hash_table_t* table, bool freedata)
{
for (size_t i = 0; i < table->size; ++i) {
vx_hash_table_node_t* node = table->elements[i];
if (node) {
if (node->next) {
while (node->next) {
node = node->next;
if (freedata) {
VX_FREE(node->prev->data);
}
VX_FREE(node->prev);
}
VX_FREE(node);
} else {
VX_FREE(node->data);
VX_FREE(node);
}
}
}
VX_FREE(table->elements);
VX_FREE(table);
}
bool vx__hash_table_insert(vx_hash_table_t* table,
size_t hash,
void* data,
bool (*compfunc)(void* d1, void* d2))
{
if (!table->elements[hash]) {
table->elements[hash] = VX_MALLOC(vx_hash_table_node_t, 1);
table->elements[hash]->prev = NULL;
table->elements[hash]->next = NULL;
table->elements[hash]->data = data;
} else {
vx_hash_table_node_t* node = table->elements[hash];
if (compfunc && compfunc(node->data, data)) {
return false;
}
while (node->next) {
node = node->next;
if (compfunc && compfunc(node->data, data)) {
return false;
}
}
vx_hash_table_node_t* nnode = VX_MALLOC(vx_hash_table_node_t, 1);
nnode->prev = node;
nnode->next = NULL;
nnode->data = data;
node->next = nnode;
}
return true;
}
void vx_mesh_free(vx_mesh_t* m)
{
VX_FREE(m->vertices);
m->vertices = NULL;
m->nvertices = 0;
VX_FREE(m->indices);
m->indices = NULL;
m->nindices = 0;
if (m->normals) { VX_FREE(m->normals); }
VX_FREE(m);
}
vx_mesh_t* vx_mesh_alloc(int nvertices, int nindices)
{
vx_mesh_t* m = VX_MALLOC(vx_mesh_t, 1);
if (!m) { return NULL; }
m->indices = VX_CALLOC(unsigned int, nindices);
if (!m->indices) { return NULL; }
m->vertices = VX_CALLOC(vx_vertex_t, nvertices);
if (!m->vertices) { return NULL; }
m->normals = NULL;
m->nindices = nindices;
m->nvertices = nvertices;
return m;
}
float vx__map_to_voxel(float position, float voxelSize, bool min)
{
float vox = (position + (position < 0.f ? -1.f : 1.f) * voxelSize * 0.5f) / voxelSize;
return (min ? floor(vox) : ceil(vox)) * voxelSize;
}
vx_vertex_t vx__vertex_cross(vx_vertex_t* v1, vx_vertex_t* v2)
{
vx_vertex_t cross;
cross.x = v1->y * v2->z - v1->z * v2->y;
cross.y = v1->z * v2->x - v1->x * v2->z;
cross.z = v1->x * v2->y - v1->y * v2->x;
return cross;
}
bool vx__vertex_equals(vx_vertex_t* v1, vx_vertex_t* v2) {
return fabs(v1->x - v2->x) < VOXELIZER_EPSILON &&
fabs(v1->y - v2->y) < VOXELIZER_EPSILON &&
fabs(v1->z - v2->z) < VOXELIZER_EPSILON;
}
bool vx__vertex_comp_func(void* a, void* b)
{
return vx__vertex_equals((vx_vertex_t*) a, (vx_vertex_t*) b);
}
void vx__vertex_sub(vx_vertex_t* a, vx_vertex_t* b)
{
a->x -= b->x;
a->y -= b->y;
a->z -= b->z;
}
void vx__vertex_add(vx_vertex_t* a, vx_vertex_t* b)
{
a->x += b->x;
a->y += b->y;
a->z += b->z;
}
void vx__vertex_multiply(vx_vertex_t* a, float v)
{
a->x *= v;
a->y *= v;
a->z *= v;
}
float vx__vertex_dot(vx_vertex_t* v1, vx_vertex_t* v2)
{
return v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
}
int vx__plane_box_overlap(vx_vertex_t* normal,
float d,
vx_vertex_t* halfboxsize)
{
vx_vertex_t vmin, vmax;
for (int dim = 0; dim <= 2; dim++) {
if (normal->v[dim] > 0.0f) {
vmin.v[dim] = -halfboxsize->v[dim];
vmax.v[dim] = halfboxsize->v[dim];
} else {
vmin.v[dim] = halfboxsize->v[dim];
vmax.v[dim] = -halfboxsize->v[dim];
}
}
if (vx__vertex_dot(normal, &vmin) + d > 0.0f) {
return false;
}
if (vx__vertex_dot(normal, &vmax) + d >= 0.0f) {
return true;
}
return false;
}
#define AXISTEST_X01(a, b, fa, fb) \
p1 = a * v1.y - b * v1.z; \
p3 = a * v3.y - b * v3.z; \
if (p1 < p3) { \
min = p1; max = p3; \
} else { \
min = p3; max = p1; \
} \
rad = fa * halfboxsize.y + fb * halfboxsize.z; \
if (min > rad || max < -rad) { \
return false; \
} \
#define AXISTEST_X2(a, b, fa, fb) \
p1 = a * v1.y - b * v1.z; \
p2 = a * v2.y - b * v2.z; \
if (p1 < p2) { \
min = p1; max = p2; \
} else { \
min = p2; max = p1; \
} \
rad = fa * halfboxsize.y + fb * halfboxsize.z; \
if (min > rad || max < -rad) { \
return false; \
} \
#define AXISTEST_Y02(a, b, fa, fb) \
p1 = -a * v1.x + b * v1.z; \
p3 = -a * v3.x + b * v3.z; \
if (p1 < p3) { \
min = p1; max = p3; \
} else { \
min = p3; max = p1; \
} \
rad = fa * halfboxsize.x + fb * halfboxsize.z; \
if (min > rad || max < -rad) { \
return false; \
} \
#define AXISTEST_Y1(a, b, fa, fb) \
p1 = -a * v1.x + b * v1.z; \
p2 = -a * v2.x + b * v2.z; \
if (p1 < p2) { \
min = p1; max = p2; \
} else { \
min = p2; max = p1; \
} \
rad = fa * halfboxsize.x + fb * halfboxsize.z; \
if (min > rad || max < -rad) { \
return false; \
}
#define AXISTEST_Z12(a, b, fa, fb) \
p2 = a * v2.x - b * v2.y; \
p3 = a * v3.x - b * v3.y; \
if (p3 < p2) { \
min = p3; max = p2; \
} else { \
min = p2; max = p3; \
} \
rad = fa * halfboxsize.x + fb * halfboxsize.y; \
if (min > rad || max < -rad) { \
return false; \
}
#define AXISTEST_Z0(a, b, fa, fb) \
p1 = a * v1.x - b * v1.y; \
p2 = a * v2.x - b * v2.y; \
if (p1 < p2) { \
min = p1; max = p2; \
} else { \
min = p2; max = p1; \
} \
rad = fa * halfboxsize.x + fb * halfboxsize.y; \
if (min > rad || max < -rad) { \
return false; \
}
int vx__triangle_box_overlap(vx_vertex_t boxcenter,
vx_vertex_t halfboxsize,
vx_triangle_t triangle)
{
vx_vertex_t v1, v2, v3, normal, e1, e2, e3;
float min, max, d, p1, p2, p3, rad, fex, fey, fez;
v1 = triangle.p1;
v2 = triangle.p2;
v3 = triangle.p3;
vx__vertex_sub(&v1, &boxcenter);
vx__vertex_sub(&v2, &boxcenter);
vx__vertex_sub(&v3, &boxcenter);
e1 = v2;
e2 = v3;
e3 = v1;
vx__vertex_sub(&e1, &v1);
vx__vertex_sub(&e2, &v2);
vx__vertex_sub(&e3, &v3);
fex = fabs(e1.x);
fey = fabs(e1.y);
fez = fabs(e1.z);
AXISTEST_X01(e1.z, e1.y, fez, fey);
AXISTEST_Y02(e1.z, e1.x, fez, fex);
AXISTEST_Z12(e1.y, e1.x, fey, fex);
fex = fabs(e2.x);
fey = fabs(e2.y);
fez = fabs(e2.z);
AXISTEST_X01(e2.z, e2.y, fez, fey);
AXISTEST_Y02(e2.z, e2.x, fez, fex);
AXISTEST_Z0(e2.y, e2.x, fey, fex);
fex = fabs(e3.x);
fey = fabs(e3.y);
fez = fabs(e3.z);
AXISTEST_X2(e3.z, e3.y, fez, fey);
AXISTEST_Y1(e3.z, e3.x, fez, fex);
AXISTEST_Z12(e3.y, e3.x, fey, fex);
VX_FINDMINMAX(v1.x, v2.x, v3.x, min, max);
if (min > halfboxsize.x || max < -halfboxsize.x) {
return false;
}
VX_FINDMINMAX(v1.y, v2.y, v3.y, min, max);
if (min > halfboxsize.y || max < -halfboxsize.y) {
return false;
}
VX_FINDMINMAX(v1.z, v2.z, v3.z, min, max);
if (min > halfboxsize.z || max < -halfboxsize.z) {
return false;
}
normal = vx__vertex_cross(&e1, &e2);
d = -vx__vertex_dot(&normal, &v1);
if (!vx__plane_box_overlap(&normal, d, &halfboxsize)) {
return false;
}
return true;
}
#undef AXISTEST_X2
#undef AXISTEST_X01
#undef AXISTEST_Y1
#undef AXISTEST_Y02
#undef AXISTEST_Z0
#undef AXISTEST_Z12
float vx__triangle_area(vx_triangle_t* triangle) {
vx_vertex_t ab = triangle->p2;
vx_vertex_t ac = triangle->p3;
vx__vertex_sub(&ab, &triangle->p1);
vx__vertex_sub(&ac, &triangle->p1);
float a0 = ab.y * ac.z - ab.z * ac.y;
float a1 = ab.z * ac.x - ab.x * ac.z;
float a2 = ab.x * ac.y - ab.y * ac.x;
return sqrtf(powf(a0, 2.f) + powf(a1, 2.f) + powf(a2, 2.f)) * 0.5f;
}
void vx__aabb_init(vx_aabb_t* aabb)
{
aabb->max.x = aabb->max.y = aabb->max.z = -INFINITY;
aabb->min.x = aabb->min.y = aabb->min.z = INFINITY;
}
vx_aabb_t vx__triangle_aabb(vx_triangle_t* triangle)
{
vx_aabb_t aabb;
vx__aabb_init(&aabb);
aabb.max.x = VX_MAX(aabb.max.x, triangle->p1.x); aabb.max.x = VX_MAX(aabb.max.x,
triangle->p2.x); aabb.max.x = VX_MAX(aabb.max.x, triangle->p3.x);
aabb.max.y = VX_MAX(aabb.max.y, triangle->p1.y); aabb.max.y = VX_MAX(aabb.max.y,
triangle->p2.y); aabb.max.y = VX_MAX(aabb.max.y, triangle->p3.y);
aabb.max.z = VX_MAX(aabb.max.z, triangle->p1.z); aabb.max.z = VX_MAX(aabb.max.z,
triangle->p2.z); aabb.max.z = VX_MAX(aabb.max.z, triangle->p3.z);
aabb.min.x = VX_MIN(aabb.min.x, triangle->p1.x); aabb.min.x = VX_MIN(aabb.min.x,
triangle->p2.x); aabb.min.x = VX_MIN(aabb.min.x, triangle->p3.x);
aabb.min.y = VX_MIN(aabb.min.y, triangle->p1.y); aabb.min.y = VX_MIN(aabb.min.y,
triangle->p2.y); aabb.min.y = VX_MIN(aabb.min.y, triangle->p3.y);
aabb.min.z = VX_MIN(aabb.min.z, triangle->p1.z); aabb.min.z = VX_MIN(aabb.min.z,
triangle->p2.z); aabb.min.z = VX_MIN(aabb.min.z, triangle->p3.z);
return aabb;
}
vx_vertex_t vx__aabb_center(vx_aabb_t* a)
{
vx_vertex_t boxcenter = a->min;
vx__vertex_add(&boxcenter, &a->max);
vx__vertex_multiply(&boxcenter, 0.5f);
return boxcenter;
}
vx_vertex_t vx__aabb_half_size(vx_aabb_t* a)
{
vx_vertex_t size;
size.x = fabs(a->max.x - a->min.x) * 0.5f;
size.y = fabs(a->max.y - a->min.y) * 0.5f;
size.z = fabs(a->max.z - a->min.z) * 0.5f;
return size;
}
vx_aabb_t vx__aabb_merge(vx_aabb_t* a, vx_aabb_t* b)
{
vx_aabb_t merge;
merge.min.x = VX_MIN(a->min.x, b->min.x);
merge.min.y = VX_MIN(a->min.y, b->min.y);
merge.min.z = VX_MIN(a->min.z, b->min.z);
merge.max.x = VX_MAX(a->max.x, b->max.x);
merge.max.y = VX_MAX(a->max.y, b->max.y);
merge.max.z = VX_MAX(a->max.z, b->max.z);
return merge;
}
size_t vx__vertex_hash(vx_vertex_t pos, size_t n)
{
size_t a = (size_t)(pos.x * 73856093);
size_t b = (size_t)(pos.y * 19349663);
size_t c = (size_t)(pos.z * 83492791);
return (a ^ b ^ c) % n;
}
void vx__add_voxel(vx_mesh_t* mesh,
vx_vertex_t* pos,
float* vertices)
{
for (size_t i = 0; i < 8; ++i) {
size_t index = i+mesh->nvertices;
mesh->vertices[index].x = vertices[i*3+0] + pos->x;
mesh->vertices[index].y = vertices[i*3+1] + pos->y;
mesh->vertices[index].z = vertices[i*3+2] + pos->z;
}
int j = -1;
for (size_t i = 0; i < VOXELIZER_INDICES_SIZE; ++i) {
if (i % 6 == 0) {
j++;
}
mesh->normalindices[i+mesh->nindices] = vx_normal_indices[j];
}
for (size_t i = 0; i < VOXELIZER_INDICES_SIZE; ++i) {
mesh->indices[i+mesh->nindices] = vx_voxel_indices[i] + mesh->nvertices;
}
mesh->nindices += VOXELIZER_INDICES_SIZE;
mesh->nvertices += 8;
}
vx_mesh_t* vx_voxelize(vx_mesh_t* m,
float voxelsizex,
float voxelsizey,
float voxelsizez,
float precision)
{
vx_mesh_t* outmesh = NULL;
vx_hash_table_t* table = NULL;
size_t voxels = 0;
float halfsizex = voxelsizex * 0.5f;
float halfsizey = voxelsizey * 0.5f;
float halfsizez = voxelsizez * 0.5f;
table = vx__hash_table_alloc(VOXELIZER_HASH_TABLE_SIZE);
for (int i = 0; i < m->nindices; i += 3) {
vx_triangle_t triangle;
VX_ASSERT(m->indices[i+0] < m->nvertices);
VX_ASSERT(m->indices[i+1] < m->nvertices);
VX_ASSERT(m->indices[i+2] < m->nvertices);
triangle.p1 = m->vertices[m->indices[i+0]];
triangle.p2 = m->vertices[m->indices[i+1]];
triangle.p3 = m->vertices[m->indices[i+2]];
if (vx__triangle_area(&triangle) < VOXELIZER_EPSILON) {
// triangle with 0 area
continue;
}
vx_aabb_t aabb = vx__triangle_aabb(&triangle);
aabb.min.x = vx__map_to_voxel(aabb.min.x, voxelsizex, true);
aabb.min.y = vx__map_to_voxel(aabb.min.y, voxelsizey, true);
aabb.min.z = vx__map_to_voxel(aabb.min.z, voxelsizez, true);
aabb.max.x = vx__map_to_voxel(aabb.max.x, voxelsizex, false);
aabb.max.y = vx__map_to_voxel(aabb.max.y, voxelsizey, false);
aabb.max.z = vx__map_to_voxel(aabb.max.z, voxelsizez, false);
for (float x = aabb.min.x; x < aabb.max.x; x += voxelsizex) {
for (float y = aabb.min.y; y < aabb.max.y; y += voxelsizey) {
for (float z = aabb.min.z; z < aabb.max.z; z += voxelsizez) {
vx_aabb_t saabb;
saabb.min.x = x - halfsizex;
saabb.min.y = y - halfsizey;
saabb.min.z = z - halfsizez;
saabb.max.x = x + halfsizex;
saabb.max.y = y + halfsizey;
saabb.max.z = z + halfsizez;
vx_vertex_t boxcenter = vx__aabb_center(&saabb);
vx_vertex_t halfsize = vx__aabb_half_size(&saabb);
// HACK: some holes might appear, this
// precision factor reduces the artifact
halfsize.x += precision;
halfsize.y += precision;
halfsize.z += precision;
if (vx__triangle_box_overlap(boxcenter, halfsize, triangle)) {
vx_vertex_t* nodedata = VX_MALLOC(vx_vertex_t, 1);
*nodedata = boxcenter;
size_t hash = vx__vertex_hash(boxcenter, VOXELIZER_HASH_TABLE_SIZE);
bool insert = vx__hash_table_insert(table,
hash,
nodedata,
vx__vertex_comp_func);
if (insert) {
voxels++;
}
}
}
}
}
}
outmesh = VX_MALLOC(vx_mesh_t, 1);
size_t nvertices = voxels * 8;
size_t nindices = voxels * VOXELIZER_INDICES_SIZE;
outmesh->nnormals = VOXELIZER_NORMAL_INDICES_SIZE;
outmesh->vertices = VX_CALLOC(vx_vertex_t, nvertices);
outmesh->normals = VX_CALLOC(vx_vertex_t, 6);
outmesh->indices = VX_CALLOC(unsigned int, nindices);
outmesh->normalindices = VX_CALLOC(unsigned int, nindices);
outmesh->nindices = 0;
outmesh->nvertices = 0;
memcpy(outmesh->normals, vx_normals, 18 * sizeof(float));
float vertices[24] = {
-halfsizex, halfsizey, halfsizez,
-halfsizex, -halfsizey, halfsizez,
halfsizex, -halfsizey, halfsizez,
halfsizex, halfsizey, halfsizez,
-halfsizex, halfsizey, -halfsizez,
-halfsizex, -halfsizey, -halfsizez,
halfsizex, -halfsizey, -halfsizez,
halfsizex, halfsizey, -halfsizez,
};
for (size_t i = 0; i < table->size; ++i) {
if (table->elements[i] != NULL) {
vx_hash_table_node_t* node = table->elements[i];
if (!node) {
continue;
}
vx_vertex_t* p = (vx_vertex_t*) node->data;
vx__add_voxel(outmesh, p, vertices);
while (node->next) {
node = node->next;
p = (vx_vertex_t*) node->data;
vx__add_voxel(outmesh, p, vertices);
}
}
}
vx__hash_table_free(table, true);
return outmesh;
}
#undef VOXELIZER_EPSILON
#undef VOXELIZER_INDICES_SIZE
#undef VOXELIZER_HASH_TABLE_SIZE
#endif // VX_VOXELIZER_IMPLEMENTATION

5
experimental/README.md Normal file
View File

@@ -0,0 +1,5 @@
Experimental code for .obj loader.
* Multi-threaded optimized parser : tinyobj_loader_opt.h
* zstd compressed .obj support. `--with-zstd` premake option.
* gzip compressed .obj support. `--with-zlib` premake option.

View File

@@ -3,6 +3,21 @@ newoption {
description = "Build with zlib."
}
newoption {
trigger = "with-zstd",
description = "Build with ZStandard compression."
}
newoption {
trigger = "clang",
description = "Use clang compiler."
}
newoption {
trigger = "asan",
description = "Enable AddressSanitizer(gcc or clang only)."
}
solution "objview"
-- location ( "build" )
configurations { "Release", "Debug" }
@@ -16,13 +31,32 @@ solution "objview"
includedirs { "./" }
includedirs { "../../" }
buildoptions { "-std=c++11" }
flags { "c++11" }
--buildoptions { "-std=c++11" }
if _OPTIONS['clang'] then
toolset "clang"
end
if _OPTIONS['with-zlib'] then
defines { 'ENABLE_ZLIB' }
links { 'z' }
end
if _OPTIONS['asan'] then
buildoptions { '-fsanitize=address' }
linkoptions { '-fsanitize=address' }
end
if _OPTIONS['with-zstd'] then
print("with-zstd")
defines { 'ENABLE_ZSTD' }
-- Set path to zstd installed dir.
includedirs { '$$HOME/local/include' }
libdirs { '$$HOME/local/lib' }
links { 'zstd' }
end
-- Uncomment if you want address sanitizer(gcc/clang only)
--buildoptions { "-fsanitize=address" }
--linkoptions { "-fsanitize=address" }
@@ -34,14 +68,15 @@ solution "objview"
configuration { "windows" }
-- Path to GLFW3
includedirs { '../../../../local/glfw-3.1.2.bin.WIN64/include' }
libdirs { '../../../../local/glfw-3.1.2.bin.WIN64/lib-vc2013' }
includedirs { '../../../local/glfw-3.2.bin.WIN64/include' }
libdirs { '../../../local/glfw-3.2.bin.WIN64/lib-vc2015' }
-- Path to GLEW
includedirs { '../../../../local/glew-1.13.0/include' }
libdirs { '../../../../local/glew-1.13.0/lib/Release/x64' }
includedirs { '../../../local/glew-1.13.0/include' }
libdirs { '../../../local/glew-1.13.0/lib/Release/x64' }
links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
defines { "_CRT_SECURE_NO_WARNINGS" }
defines { "NOMINMAX" }
configuration { "macosx" }
includedirs { "/usr/local/include" }

View File

@@ -29,7 +29,7 @@ THE SOFTWARE.
#ifndef TINOBJ_LOADER_OPT_H_
#define TINOBJ_LOADER_OPT_H_
#ifdef _WIN64
#ifdef _WIN32
#define atoll(S) _atoi64(S)
#include <windows.h>
#else
@@ -1263,7 +1263,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
? std::thread::hardware_concurrency()
: option.req_num_threads;
num_threads =
std::max(1, std::min(static_cast<int>(num_threads), kMaxThreads));
(std::max)(1, (std::min)(static_cast<int>(num_threads), kMaxThreads));
if (option.verbose) {
std::cout << "# of threads = " << num_threads << std::endl;
@@ -1295,7 +1295,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
for (size_t t = 0; t < static_cast<size_t>(num_threads); t++) {
workers->push_back(std::thread([&, t]() {
auto start_idx = (t + 0) * chunk_size;
auto end_idx = std::min((t + 1) * chunk_size, len - 1);
auto end_idx = (std::min)((t + 1) * chunk_size, len - 1);
if (t == static_cast<size_t>((num_threads - 1))) {
end_idx = len - 1;
}
@@ -1325,7 +1325,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
// Find extra line which spand across chunk boundary.
if ((t < num_threads) && (buf[end_idx - 1] != '\n')) {
auto extra_span_idx = std::min(end_idx - 1 + chunk_size, len - 1);
auto extra_span_idx = (std::min)(end_idx - 1 + chunk_size, len - 1);
for (size_t i = end_idx; i < extra_span_idx; i++) {
if (is_line_ending(buf, i, extra_span_idx)) {
LineInfo info;

View File

@@ -16,6 +16,10 @@
#include <zlib.h>
#endif
#if defined(ENABLE_ZSTD)
#include <zstd.h>
#endif
#include <GL/glew.h>
#ifdef __APPLE__
@@ -86,23 +90,40 @@ void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
const char *mmap_file(size_t *len, const char* filename)
{
(*len) = 0;
#ifdef _WIN64
#ifdef _WIN32
HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
assert(file != INVALID_HANDLE_VALUE);
assert(file != INVALID_HANDLE_VALUE);
HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
assert(fileMapping != INVALID_HANDLE_VALUE);
HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
assert(fileMapping != INVALID_HANDLE_VALUE);
LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0);
auto fileMapViewChar = (const char*)fileMapView;
assert(fileMapView != NULL);
LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0);
auto fileMapViewChar = (const char*)fileMapView;
assert(fileMapView != NULL);
LARGE_INTEGER fileSize;
fileSize.QuadPart = 0;
GetFileSizeEx(file, &fileSize);
(*len) = static_cast<size_t>(fileSize.QuadPart);
return fileMapViewChar;
#else
FILE* f = fopen(filename, "r" );
FILE* f = fopen(filename, "rb" );
if (!f) {
fprintf(stderr, "Failed to open file : %s\n", filename);
return nullptr;
}
fseek(f, 0, SEEK_END);
long fileSize = ftell(f);
fclose(f);
if (fileSize < 16) {
fprintf(stderr, "Empty or invalid .obj : %s\n", filename);
return nullptr;
}
struct stat sb;
char *p;
int fd;
@@ -110,29 +131,29 @@ const char *mmap_file(size_t *len, const char* filename)
fd = open (filename, O_RDONLY);
if (fd == -1) {
perror ("open");
return NULL;
return nullptr;
}
if (fstat (fd, &sb) == -1) {
perror ("fstat");
return NULL;
return nullptr;
}
if (!S_ISREG (sb.st_mode)) {
fprintf (stderr, "%s is not a file\n", "lineitem.tbl");
return NULL;
return nullptr;
}
p = (char*)mmap (0, fileSize, PROT_READ, MAP_SHARED, fd, 0);
if (p == MAP_FAILED) {
perror ("mmap");
return NULL;
return nullptr;
}
if (close (fd) == -1) {
perror ("close");
return NULL;
return nullptr;
}
(*len) = fileSize;
@@ -182,6 +203,71 @@ bool gz_load(std::vector<char>* buf, const char* filename)
#endif
}
#ifdef ENABLE_ZSTD
static off_t fsize_X(const char *filename)
{
struct stat st;
if (stat(filename, &st) == 0) return st.st_size;
/* error */
printf("stat: %s : %s \n", filename, strerror(errno));
exit(1);
}
static FILE* fopen_X(const char *filename, const char *instruction)
{
FILE* const inFile = fopen(filename, instruction);
if (inFile) return inFile;
/* error */
printf("fopen: %s : %s \n", filename, strerror(errno));
exit(2);
}
static void* malloc_X(size_t size)
{
void* const buff = malloc(size);
if (buff) return buff;
/* error */
printf("malloc: %s \n", strerror(errno));
exit(3);
}
#endif
bool zstd_load(std::vector<char>* buf, const char* filename)
{
#ifdef ENABLE_ZSTD
off_t const buffSize = fsize_X(filename);
FILE* const inFile = fopen_X(filename, "rb");
void* const buffer = malloc_X(buffSize);
size_t const readSize = fread(buffer, 1, buffSize, inFile);
if (readSize != (size_t)buffSize) {
printf("fread: %s : %s \n", filename, strerror(errno));
exit(4);
}
fclose(inFile);
unsigned long long const rSize = ZSTD_getDecompressedSize(buffer, buffSize);
if (rSize==0) {
printf("%s : original size unknown \n", filename);
exit(5);
}
buf->resize(rSize);
size_t const dSize = ZSTD_decompress(buf->data(), rSize, buffer, buffSize);
if (dSize != rSize) {
printf("error decoding %s : %s \n", filename, ZSTD_getErrorName(dSize));
exit(7);
}
free(buffer);
return true;
#else
return false;
#endif
}
const char* get_file_data(size_t *len, const char* filename)
{
@@ -204,9 +290,24 @@ const char* get_file_data(size_t *len, const char* filename)
data_len = buf.size();
}
} else if (strcmp(ext, ".zst") == 0) {
printf("zstd\n");
// Zstandard data.
std::vector<char> buf;
bool ret = zstd_load(&buf, filename);
if (ret) {
char *p = static_cast<char*>(malloc(buf.size() + 1)); // @fixme { implement deleter }
memcpy(p, &buf.at(0), buf.size());
p[buf.size()] = '\0';
data = p;
data_len = buf.size();
}
} else {
data = mmap_file(&data_len, filename);
}
(*len) = data_len;
@@ -220,18 +321,31 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename, int n
std::vector<tinyobj_opt::shape_t> shapes;
std::vector<tinyobj_opt::material_t> materials;
auto load_t_begin = std::chrono::high_resolution_clock::now();
size_t data_len = 0;
const char* data = get_file_data(&data_len, filename);
if (data == nullptr) {
printf("failed to load file\n");
exit(-1);
return false;
}
printf("filesize: %d\n", (int)data_len);
auto load_t_end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> load_ms = load_t_end - load_t_begin;
if (verbose) {
std::cout << "filesize: " << data_len << std::endl;
std::cout << "load time: " << load_ms.count() << " [msecs]" << std::endl;
}
tinyobj_opt::LoadOption option;
option.req_num_threads = num_threads;
option.verbose = verbose;
bool ret = parseObj(&attrib, &shapes, &materials, data, data_len, option);
if (!ret) {
std::cerr << "Failed to parse .obj" << std::endl;
return false;
}
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
@@ -534,6 +648,13 @@ int main(int argc, char **argv)
size_t data_len = 0;
const char* data = get_file_data(&data_len, argv[1]);
if (data == nullptr) {
printf("failed to load file\n");
exit(-1);
return false;
}
if (data_len < 4) {
printf("Empty file\n");
exit(-1);
return false;
}

View File

@@ -15,8 +15,8 @@
#ifdef __cplusplus
extern "C" {
#endif
#include <mmsystem.h>
#include <windows.h>
#include <mmsystem.h>
#ifdef __cplusplus
}
#endif
@@ -233,16 +233,17 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
printf(" material.map_Ns = %s\n",
materials[i].specular_highlight_texname.c_str());
printf(" material.map_bump = %s\n", materials[i].bump_texname.c_str());
printf(" bump_multiplier = %f\n", static_cast<const double>(materials[i].bump_texopt.bump_multiplier));
printf(" material.map_d = %s\n", materials[i].alpha_texname.c_str());
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
printf(" <<PBR>>\n");
printf(" material.Pr = %f\n", materials[i].roughness);
printf(" material.Pm = %f\n", materials[i].metallic);
printf(" material.Ps = %f\n", materials[i].sheen);
printf(" material.Pc = %f\n", materials[i].clearcoat_thickness);
printf(" material.Pcr = %f\n", materials[i].clearcoat_thickness);
printf(" material.aniso = %f\n", materials[i].anisotropy);
printf(" material.anisor = %f\n", materials[i].anisotropy_rotation);
printf(" material.Pr = %f\n", static_cast<const double>(materials[i].roughness));
printf(" material.Pm = %f\n", static_cast<const double>(materials[i].metallic));
printf(" material.Ps = %f\n", static_cast<const double>(materials[i].sheen));
printf(" material.Pc = %f\n", static_cast<const double>(materials[i].clearcoat_thickness));
printf(" material.Pcr = %f\n", static_cast<const double>(materials[i].clearcoat_thickness));
printf(" material.aniso = %f\n", static_cast<const double>(materials[i].anisotropy));
printf(" material.anisor = %f\n", static_cast<const double>(materials[i].anisotropy_rotation));
printf(" material.map_Ke = %s\n", materials[i].emissive_texname.c_str());
printf(" material.map_Pr = %s\n", materials[i].roughness_texname.c_str());
printf(" material.map_Pm = %s\n", materials[i].metallic_texname.c_str());
@@ -363,8 +364,14 @@ static bool TestStreamLoadObj() {
std::map<std::string, int>* matMap,
std::string* err) {
(void)matId;
(void)err;
LoadMtl(matMap, materials, &m_matSStream);
std::string warning;
LoadMtl(matMap, materials, &m_matSStream, &warning);
if (!warning.empty()) {
if (err) {
(*err) += warning;
}
}
return true;
}

View File

@@ -0,0 +1,6 @@
newmtl default
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
map_Kd tmp.png

View File

@@ -0,0 +1,7 @@
mtllib invalid-file-aaa.mtl invalid-file-bbb.mtl mtllib-multiple-files-issue-112.mtl
o Test
v 1.864151 -1.219172 -5.532511
v 0.575869 -0.666304 5.896140
v 0.940448 1.000000 -1.971128
usemtl default
f 1 2 3

View File

@@ -0,0 +1,36 @@
newmtl default
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
Kt 0.1 0.2 0.3
map_Ka -clamp on ambient.jpg
map_Kd -o 0.1 diffuse.jpg
map_Ks -s 0.1 0.2 specular.jpg
map_Ns -t 0.1 0.2 0.3 specular_highlight.jpg
map_bump -bm 3 bumpmap.jpg
newmtl bm2
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
Kt 0.1 0.2 0.3
# blendu
map_Kd -blendu on diffuse.jpg
map_Ks -blendv off specular.jpg
map_Ns -mm 0.1 0.3 specular_highlight.jpg
# -bm after filename
map_bump -imfchan r bumpmap2.jpg -bm 1.5
newmtl bm3
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
Kt 0.1 0.2 0.3
# type
map_Kd -type sphere diffuse.jpg
map_Ks -type cube_top specular.jpg
map_Ns -type cube_bottom specular_highlight.jpg
map_Ka -type cube_left ambient.jpg
map_d -type cube_right alpha.jpg
map_bump -type cube_front bump.jpg
disp -type cube_back displacement.jpg

View File

@@ -0,0 +1,7 @@
mtllib texture-options-issue-85.mtl
o Test
v 1.864151 -1.219172 -5.532511
v 0.575869 -0.666304 5.896140
v 0.940448 1.000000 -1.971128
usemtl default
f 1 2 3

View File

@@ -0,0 +1,13 @@
newmtl Material.001
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
d 0.75
Tr 0.5
newmtl Material.002
Ka 0 0 0
Kd 0 0 0
Ks 0 0 0
Tr 0.5
d 0.75

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 tr-and-d-issue-43.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.002
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

View File

@@ -0,0 +1,30 @@
# cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project.
# original cornell box data
# comment
# empty line including some space
mtllib cornell_box.mtl
o floor
v 552.8 0.0 0.0
v 0.0 0.0 0.0
v 0.0 0.0 559.2
v 549.6 0.0 559.2
v 130.0 0.0 65.0
v 82.0 0.0 225.0
v 240.0 0.0 272.0
v 290.0 0.0 114.0
v 423.0 0.0 247.0
v 265.0 0.0 296.0
v 314.0 0.0 456.0
v 472.0 0.0 406.0
f 1 2 3 4
f 8 7 6 5
f 12 11 10 9
usemtl white

View File

@@ -1,3 +1,2 @@
* PBR material
* Define index_t struct
* Python 2.7 binding

View File

@@ -1,4 +1,4 @@
// python3 module for tinyobjloader
// python2/3 module for tinyobjloader
//
// usage:
// import tinyobjloader as tol
@@ -172,6 +172,7 @@ static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
PyDict_SetItemString(rtndict, "shapes", pyshapes);
PyDict_SetItemString(rtndict, "materials", pymaterials);
PyDict_SetItemString(rtndict, "attribs", attribobj);
return rtndict;
}
@@ -182,10 +183,21 @@ static PyMethodDef mMethods[] = {
};
#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
NULL, -1, mMethods};
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
return PyModule_Create(&moduledef);
}
#else
PyMODINIT_FUNC inittinyobjloader(void) {
Py_InitModule3("tinyobjloader", mMethods, NULL);
}
#endif // PY_MAJOR_VERSION >= 3
}

View File

@@ -184,6 +184,48 @@ TestLoadObj(
return true;
}
static bool
TestLoadObjFromPreopenedFile(
const char* filename,
const char* basepath = NULL,
bool readMaterials = true,
bool triangulate = true)
{
std::string fullFilename = std::string(basepath) + filename;
std::cout << "Loading " << fullFilename << std::endl;
std::ifstream fileStream(fullFilename.c_str());
if (!fileStream) {
std::cerr << "Could not find specified file: " << fullFilename << std::endl;
return false;
}
tinyobj::MaterialStreamReader materialStreamReader(fileStream);
tinyobj::MaterialStreamReader* materialReader = readMaterials
? &materialStreamReader
: NULL;
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, &fileStream, materialReader);
if (!err.empty()) {
std::cerr << err << std::endl;
}
if (!ret) {
printf("Failed to load/parse .obj.\n");
return false;
}
std::cout << "Loaded material count: " << materials.size() << "\n";
return true;
}
static bool
TestStreamLoadObj()
@@ -265,7 +307,8 @@ std::string matStream(
{
(void)matId;
(void)err;
LoadMtl(matMap, materials, &m_matSStream);
std::string warning;
LoadMtl(matMap, materials, &m_matSStream, &warning);
return true;
}
@@ -351,6 +394,16 @@ TEST_CASE("stream_load", "[Stream]") {
REQUIRE(true == TestStreamLoadObj());
}
TEST_CASE("stream_load_from_file_skipping_materials", "[Stream]") {
REQUIRE(true == TestLoadObjFromPreopenedFile(
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/false, /*triangulate*/false));
}
TEST_CASE("stream_load_from_file_with_materials", "[Stream]") {
REQUIRE(true == TestLoadObjFromPreopenedFile(
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/true, /*triangulate*/false));
}
TEST_CASE("trailing_whitespace_in_mtl", "[Issue92]") {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
@@ -402,6 +455,7 @@ TEST_CASE("transmittance_filter_Tf", "[Issue95-Tf]") {
REQUIRE(0.2 == Approx(materials[0].transmittance[1]));
REQUIRE(0.3 == Approx(materials[0].transmittance[2]));
}
TEST_CASE("transmittance_filter_Kt", "[Issue95-Kt]") {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
@@ -420,6 +474,96 @@ TEST_CASE("transmittance_filter_Kt", "[Issue95-Kt]") {
REQUIRE(0.3 == Approx(materials[0].transmittance[2]));
}
TEST_CASE("usemtl_at_last_line", "[Issue104]") {
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/usemtl-issue-104.obj", gMtlBasePath);
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(1 == shapes.size());
}
TEST_CASE("texture_opts", "[Issue85]") {
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/texture-options-issue-85.obj", gMtlBasePath);
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(1 == shapes.size());
REQUIRE(3 == materials.size());
REQUIRE(0 == materials[0].name.compare("default"));
REQUIRE(0 == materials[1].name.compare("bm2"));
REQUIRE(0 == materials[2].name.compare("bm3"));
REQUIRE(true == materials[0].ambient_texopt.clamp);
REQUIRE(0.1 == Approx(materials[0].diffuse_texopt.origin_offset[0]));
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[1]));
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[2]));
REQUIRE(0.1 == Approx(materials[0].specular_texopt.scale[0]));
REQUIRE(0.2 == Approx(materials[0].specular_texopt.scale[1]));
REQUIRE(1.0 == Approx(materials[0].specular_texopt.scale[2]));
REQUIRE(0.1 == Approx(materials[0].specular_highlight_texopt.turbulence[0]));
REQUIRE(0.2 == Approx(materials[0].specular_highlight_texopt.turbulence[1]));
REQUIRE(0.3 == Approx(materials[0].specular_highlight_texopt.turbulence[2]));
REQUIRE(3.0 == Approx(materials[0].bump_texopt.bump_multiplier));
REQUIRE(0.1 == Approx(materials[1].specular_highlight_texopt.brightness));
REQUIRE(0.3 == Approx(materials[1].specular_highlight_texopt.contrast));
REQUIRE('r' == materials[1].bump_texopt.imfchan);
REQUIRE(tinyobj::TEXTURE_TYPE_SPHERE == materials[2].diffuse_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_TOP == materials[2].specular_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BOTTOM == materials[2].specular_highlight_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_LEFT == materials[2].ambient_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_RIGHT == materials[2].alpha_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_FRONT == materials[2].bump_texopt.type);
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BACK == materials[2].displacement_texopt.type);
}
TEST_CASE("mtllib_multiple_filenames", "[Issue112]") {
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/mtllib-multiple-files-issue-112.obj", gMtlBasePath);
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(1 == materials.size());
}
TEST_CASE("tr_and_d", "[Issue43]") {
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/tr-and-d-issue-43.obj", gMtlBasePath);
if (!err.empty()) {
std::cerr << err << std::endl;
}
REQUIRE(true == ret);
REQUIRE(2 == materials.size());
REQUIRE(0.75 == Approx(materials[0].dissolve));
REQUIRE(0.75 == Approx(materials[1].dissolve));
}
#if 0
int
main(

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
@PACKAGE_INIT@
set(TINYOBJLOADER_VERSION "@TINYOBJLOADER_VERSION@")
set_and_check(TINYOBJLOADER_INCLUDE_DIRS "@PACKAGE_TINYOBJLOADER_INCLUDE_DIR@")
set_and_check(TINYOBJLOADER_LIBRARY_DIRS "@PACKAGE_TINYOBJLOADER_LIBRARY_DIR@")
set(TINYOBJLOADER_LIBRARIES @LIBRARY_NAME@)
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake")

15
tinyobjloader.pc.in Normal file
View File

@@ -0,0 +1,15 @@
# Generated by CMake @CMAKE_VERSION@ for @PROJECT_NAME@. Any changes to this
# file will be overwritten by the next CMake run. The input file was
# tinyobjloader.pc.in.
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${prefix}/@TINYOBJLOADER_LIBRARY_DIR@
includedir=${prefix}/@TINYOBJLOADER_INCLUDE_DIR@
Name: @PROJECT_NAME@
Description: Tiny but powerful single file wavefront obj loader
URL: https://syoyo.github.io/tinyobjloader/
Version: @TINYOBJLOADER_VERSION@
Libs: -L${libdir} -l@LIBRARY_NAME@
Cflags: -I${includedir}