Compare commits
344 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f37fed32f3 | ||
|
|
85d92bb5cb | ||
|
|
40d00fd935 | ||
|
|
7712f1bebd | ||
|
|
e96e994355 | ||
|
|
8f16866c37 | ||
|
|
5e668b398a | ||
|
|
df3bb6f8e8 | ||
|
|
546aa09d8d | ||
|
|
aa90b5466f | ||
|
|
b404f3af67 | ||
|
|
a957ebe002 | ||
|
|
d793bfb405 | ||
|
|
0ab0146296 | ||
|
|
20d122f305 | ||
|
|
850d0ffdfa | ||
|
|
80058fdcb0 | ||
|
|
1a7aea4ac1 | ||
|
|
178ef391c7 | ||
|
|
59b4d7ccef | ||
|
|
6f990e2b6c | ||
|
|
7fb5056a53 | ||
|
|
934788785e | ||
|
|
e07a835f02 | ||
|
|
1cdfd786d8 | ||
|
|
803b65b8a0 | ||
|
|
50518a515b | ||
|
|
c9b1bccf97 | ||
|
|
1f17833657 | ||
|
|
bb58a8f8c3 | ||
|
|
b1f594d682 | ||
|
|
02df4943f9 | ||
|
|
826a892d0b | ||
|
|
68350e2fc7 | ||
|
|
7d20e9b901 | ||
|
|
fdc70abdc6 | ||
|
|
8a885e14b8 | ||
|
|
cd65de860b | ||
|
|
4924857fd3 | ||
|
|
1a7bdc6192 | ||
|
|
fd06fa49e4 | ||
|
|
0d68262246 | ||
|
|
0e950513a3 | ||
|
|
a4b115a584 | ||
|
|
bb3e27d4f3 | ||
|
|
c4e7e65acb | ||
|
|
eba327b9c0 | ||
|
|
3cbf45a572 | ||
|
|
6650dbf397 | ||
|
|
7befd59de4 | ||
|
|
c5b3139653 | ||
|
|
adb2309110 | ||
|
|
3edca81a75 | ||
|
|
7a88cddefc | ||
|
|
d541711a79 | ||
|
|
d1ce2082f6 | ||
|
|
8fd9f6e57b | ||
|
|
24bd8b49ff | ||
|
|
4a0e79985d | ||
|
|
06f6139d1f | ||
|
|
0c8db8ee23 | ||
|
|
64d1e3f883 | ||
|
|
a39a6b481c | ||
|
|
bce1bb8387 | ||
|
|
7fcfafb39a | ||
|
|
5eda671225 | ||
|
|
f95510b04b | ||
|
|
94f1dc15b3 | ||
|
|
a4eabf54b1 | ||
|
|
72c38f64d5 | ||
|
|
d174e625a2 | ||
|
|
707014f843 | ||
|
|
12837cc8b2 | ||
|
|
b85714b4cf | ||
|
|
e060b4f4aa | ||
|
|
2dca72724f | ||
|
|
72529f02fe | ||
|
|
16f3041c76 | ||
|
|
73e9b4dc3a | ||
|
|
5113cd65cf | ||
|
|
65df7c4794 | ||
|
|
eaf8623e61 | ||
|
|
dcad3e6c50 | ||
|
|
2dfc37a475 | ||
|
|
9a6390cdee | ||
|
|
78c7c9011a | ||
|
|
1754669b07 | ||
|
|
1f7b4a49c0 | ||
|
|
15f47e2e35 | ||
|
|
12bf4165be | ||
|
|
f206a56362 | ||
|
|
13951d6459 | ||
|
|
5383e3400a | ||
|
|
ac3c36ffda | ||
|
|
3b681805aa | ||
|
|
ca49183639 | ||
|
|
b29d34f2e1 | ||
|
|
cb085d1fb6 | ||
|
|
b38e97b7ec | ||
|
|
b434c2497f | ||
|
|
94fc413466 | ||
|
|
1c6dbf9bd8 | ||
|
|
88ad575f62 | ||
|
|
5cd30b70e0 | ||
|
|
eb1f395101 | ||
|
|
27bdd547f0 | ||
|
|
75a4bd1d35 | ||
|
|
7c7335c907 | ||
|
|
3a9483ca6f | ||
|
|
1065d7cfb2 | ||
|
|
303043f9ec | ||
|
|
981f7c5f99 | ||
|
|
dcbc8d51aa | ||
|
|
785af4491d | ||
|
|
be46318a52 | ||
|
|
b5961cd7b1 | ||
|
|
76632f80b3 | ||
|
|
f59f93d7dc | ||
|
|
1dfd117ccd | ||
|
|
a86b78386b | ||
|
|
e3508c3ca3 | ||
|
|
8e7da82852 | ||
|
|
6cde18eb55 | ||
|
|
2409832b24 | ||
|
|
95fba2ab32 | ||
|
|
99518b6d3e | ||
|
|
d8f702c6f7 | ||
|
|
6eca09f2bf | ||
|
|
a1324f17fd | ||
|
|
56fa047ba9 | ||
|
|
0f4a955e01 | ||
|
|
fb80e04212 | ||
|
|
cdb5c2d375 | ||
|
|
44bff466e5 | ||
|
|
47989b591f | ||
|
|
41acdc95bc | ||
|
|
cc948e4c44 | ||
|
|
889b2187c1 | ||
|
|
3e146c376c | ||
|
|
e60d33385e | ||
|
|
744d2baa58 | ||
|
|
d5ca258817 | ||
|
|
b1ac3a6c7e | ||
|
|
69e56db124 | ||
|
|
13412b0898 | ||
|
|
9912bc5023 | ||
|
|
9d9e987c47 | ||
|
|
345560040b | ||
|
|
9134c1d395 | ||
|
|
cc9897316f | ||
|
|
e43580bd9a | ||
|
|
9613108cef | ||
|
|
4b29502c82 | ||
|
|
156b709556 | ||
|
|
00f51e3603 | ||
|
|
da5942d652 | ||
|
|
7c3206f919 | ||
|
|
4886eebbf4 | ||
|
|
91c727e204 | ||
|
|
26bdacedf6 | ||
|
|
7212ee47eb | ||
|
|
0fe1bb96c2 | ||
|
|
4bd75baaae | ||
|
|
bbcfe59c0f | ||
|
|
38c07d34c4 | ||
|
|
2019ace3b7 | ||
|
|
ad96ff0769 | ||
|
|
d7f83f29f0 | ||
|
|
98fad65028 | ||
|
|
e88016c63f | ||
|
|
edabf19461 | ||
|
|
8bed734a18 | ||
|
|
60ffb3ca9a | ||
|
|
6507e70236 | ||
|
|
2daec8be53 | ||
|
|
c2ff3f12fc | ||
|
|
a6a134a60e | ||
|
|
e0b39341fc | ||
|
|
947582b592 | ||
|
|
c207ff3561 | ||
|
|
41dd7c806e | ||
|
|
aa4dabe64f | ||
|
|
9868630d0e | ||
|
|
f2397573f3 | ||
|
|
7d5699118e | ||
|
|
0948ca0417 | ||
|
|
582eb2b818 | ||
|
|
c2474e27ab | ||
|
|
6c6390f034 | ||
|
|
4d6649cc6d | ||
|
|
d543b1447f | ||
|
|
d6eeb14216 | ||
|
|
aa670fe91e | ||
|
|
ebdbd8a231 | ||
|
|
fed4322d26 | ||
|
|
039d4a6c54 | ||
|
|
28ee1b42ce | ||
|
|
35889026d6 | ||
|
|
e81ac971b0 | ||
|
|
e05ce6aff0 | ||
|
|
e4598ba84a | ||
|
|
79513077f3 | ||
|
|
72acadca79 | ||
|
|
398e358826 | ||
|
|
7fc9b0fe97 | ||
|
|
71cc967f42 | ||
|
|
3ddad1e377 | ||
|
|
92805d3088 | ||
|
|
60acd05a03 | ||
|
|
4a18e241d9 | ||
|
|
1b88a1e3c7 | ||
|
|
b3feefafdf | ||
|
|
a7a16db908 | ||
|
|
9f92ba34a6 | ||
|
|
25cf039953 | ||
|
|
6bf145d7cf | ||
|
|
69240e18b4 | ||
|
|
5b9f431512 | ||
|
|
ad79762212 | ||
|
|
64149943cc | ||
|
|
714194d353 | ||
|
|
9d81c24934 | ||
|
|
25c194bf71 | ||
|
|
5a4c5ff668 | ||
|
|
f06e814d7c | ||
|
|
5eef2b0914 | ||
|
|
49988672f4 | ||
|
|
d192402800 | ||
|
|
646f1312f1 | ||
|
|
db62a6c1cc | ||
|
|
8e53519a27 | ||
|
|
d3d6932efd | ||
|
|
dea325cdcb | ||
|
|
2b50b31657 | ||
|
|
110b49a0c8 | ||
|
|
319746d3db | ||
|
|
2cb73fa85d | ||
|
|
5a832b470a | ||
|
|
42f04024d4 | ||
|
|
07852e206d | ||
|
|
156b47760d | ||
|
|
673501749f | ||
|
|
b56fc1a0cc | ||
|
|
2ed3222bbe | ||
|
|
c7da23795d | ||
|
|
8ca2bc0de7 | ||
|
|
0a85945767 | ||
|
|
51d13700d8 | ||
|
|
1983e889dc | ||
|
|
dfe9d7bcae | ||
|
|
4dee4cc673 | ||
|
|
a7ea651bef | ||
|
|
4c2afb8814 | ||
|
|
951833812a | ||
|
|
e456cc949d | ||
|
|
75e64cd47a | ||
|
|
3736a5791f | ||
|
|
0b0bf60137 | ||
|
|
d496d8eab6 | ||
|
|
22883def8d | ||
|
|
5826f1e149 | ||
|
|
ef6560298e | ||
|
|
e3a56816d6 | ||
|
|
5ef400882a | ||
|
|
333bb55d84 | ||
|
|
7d6318c3ad | ||
|
|
d4a7eefc54 | ||
|
|
d2793bf454 | ||
|
|
d5c722125a | ||
|
|
16ed0ac129 | ||
|
|
b8c33156de | ||
|
|
0389e23847 | ||
|
|
e85155b2dd | ||
|
|
164dcb8121 | ||
|
|
5fc9842e97 | ||
|
|
831a1a4b8d | ||
|
|
4b9ef527c6 | ||
|
|
b69d2a2c55 | ||
|
|
629f1825c5 | ||
|
|
e210379335 | ||
|
|
659976b8f3 | ||
|
|
96ba498d70 | ||
|
|
5f4a557d69 | ||
|
|
2c7ba7b2ab | ||
|
|
de79540879 | ||
|
|
8880438c36 | ||
|
|
8c03771aac | ||
|
|
fc42eb8232 | ||
|
|
da5d9b1e1c | ||
|
|
64164b3a82 | ||
|
|
8205067928 | ||
|
|
660cc22b74 | ||
|
|
00251e9a5b | ||
|
|
54c28bd05f | ||
|
|
d392282f02 | ||
|
|
88fe2421d9 | ||
|
|
7ecb0b2f37 | ||
|
|
566d259df2 | ||
|
|
654e686079 | ||
|
|
bf626b5809 | ||
|
|
db62284cef | ||
|
|
109090e5b8 | ||
|
|
73d823ba77 | ||
|
|
2d16510c15 | ||
|
|
a58a804850 | ||
|
|
93c495eca8 | ||
|
|
1a4e018053 | ||
|
|
d3fbf6bb7b | ||
|
|
0a3d47fdad | ||
|
|
73af05bc23 | ||
|
|
bbb6aeff6a | ||
|
|
48839e3b07 | ||
|
|
e9a7c76c23 | ||
|
|
b90f767367 | ||
|
|
368312cb4b | ||
|
|
be1ba58aec | ||
|
|
8d60b4963a | ||
|
|
5c121140e6 | ||
|
|
7dc1418e2b | ||
|
|
9d6b58b90e | ||
|
|
58fa260605 | ||
|
|
7399aedfdd | ||
|
|
28fc3523d4 | ||
|
|
a608c3b5b1 | ||
|
|
2e6cccbfe4 | ||
|
|
a66eab0f75 | ||
|
|
170cb86870 | ||
|
|
016362234b | ||
|
|
28d1bb5521 | ||
|
|
045d31eb7a | ||
|
|
9eecb4634d | ||
|
|
6b41e68bbc | ||
|
|
a55247574c | ||
|
|
f4695de408 | ||
|
|
00ed158a8e | ||
|
|
ec5df8a48f | ||
|
|
1703ab087d | ||
|
|
153de2b3f0 | ||
|
|
90d33c33c0 | ||
|
|
1e663342bf | ||
|
|
93acf63157 | ||
|
|
72ef6cbb76 | ||
|
|
54bd46014c | ||
|
|
ee7d6cc0fd |
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
BasedOnStyle: LLVM
|
BasedOnStyle: Google
|
||||||
IndentWidth: 2
|
IndentWidth: 2
|
||||||
TabWidth: 2
|
TabWidth: 2
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
|||||||
22
.travis.yml
22
.travis.yml
@@ -1,5 +1,5 @@
|
|||||||
language: cpp
|
language: cpp
|
||||||
sudo: false
|
sudo: required
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- addons: &1
|
- addons: &1
|
||||||
@@ -36,21 +36,17 @@ matrix:
|
|||||||
env: COMPILER_VERSION=4.9 BUILD_TYPE=Release
|
env: COMPILER_VERSION=4.9 BUILD_TYPE=Release
|
||||||
- addons: *1
|
- addons: *1
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug CFLAGS="-O0 --coverage" CXXFLAGS="-O0
|
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug
|
||||||
--coverage" REPORT_COVERAGE=1
|
|
||||||
before_install:
|
before_install:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew upgrade; fi
|
||||||
- if [ -n "$REPORT_COVERAGE" ]; then pip install --user cpp-coveralls; fi
|
- if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get update python; fi
|
||||||
|
- if [ -n "$REPORT_COVERAGE" ]; then sudo apt-get install python-dev libffi-dev libssl-dev; fi
|
||||||
|
- if [ -n "$REPORT_COVERAGE" ]; then sudo pip install --upgrade pip; fi
|
||||||
|
- if [ -n "$REPORT_COVERAGE" ]; then CXX=g++ pip install --user requests[security]; fi
|
||||||
|
- if [ -n "$REPORT_COVERAGE" ]; then CXX=g++ pip install --user cpp-coveralls; fi
|
||||||
script:
|
script:
|
||||||
- mkdir build && cd build
|
- cd tests
|
||||||
- export CC="${CC}-${COMPILER_VERSION}"
|
- make check
|
||||||
- export CXX="${CXX}-${COMPILER_VERSION}"
|
|
||||||
- ${CC} -v
|
|
||||||
- cmake --version
|
|
||||||
- cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DTINYOBJLOADER_BUILD_TEST_LOADER=On -G Ninja
|
|
||||||
..
|
|
||||||
- ninja
|
|
||||||
- ./test_loader ../cornell_box.obj
|
|
||||||
- if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r .. -e examples -e tools -e
|
- if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r .. -e examples -e tools -e
|
||||||
jni -e python -e images -E ".*CompilerId.*" -E ".*feature_tests.*" ; fi
|
jni -e python -e images -E ".*CompilerId.*" -E ".*feature_tests.*" ; fi
|
||||||
- cd ..
|
- cd ..
|
||||||
|
|||||||
114
CMakeLists.txt
114
CMakeLists.txt
@@ -2,7 +2,20 @@
|
|||||||
#This configures the Cmake system with multiple properties, depending
|
#This configures the Cmake system with multiple properties, depending
|
||||||
#on the platform and configuration it is set to build in.
|
#on the platform and configuration it is set to build in.
|
||||||
project(tinyobjloader)
|
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
|
#Folder Shortcuts
|
||||||
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
||||||
@@ -12,8 +25,8 @@ set(tinyobjloader-Source
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(tinyobjloader-Test-Source
|
set(tinyobjloader-Example-Source
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/test.cc
|
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(tinyobjloader-examples-objsticher
|
set(tinyobjloader-examples-objsticher
|
||||||
@@ -22,37 +35,112 @@ set(tinyobjloader-examples-objsticher
|
|||||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(tinyobjloader
|
#Install destinations
|
||||||
${tinyobjloader-Source}
|
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)
|
||||||
|
|
||||||
|
add_library(${LIBRARY_NAME} ${tinyobjloader-Source})
|
||||||
|
|
||||||
|
if(BUILD_SHARED_LIBS)
|
||||||
|
set_target_properties(${LIBRARY_NAME} PROPERTIES
|
||||||
|
SOVERSION ${TINYOBJLOADER_SOVERSION}
|
||||||
|
)
|
||||||
|
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}>
|
||||||
)
|
)
|
||||||
|
|
||||||
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Test Loader Application" OFF)
|
export(TARGETS ${LIBRARY_NAME} FILE ${PROJECT_NAME}-targets.cmake)
|
||||||
|
|
||||||
if(TINYOBJLOADER_BUILD_TEST_LOADER)
|
if(TINYOBJLOADER_BUILD_TEST_LOADER)
|
||||||
add_executable(test_loader ${tinyobjloader-Test-Source})
|
add_executable(test_loader ${tinyobjloader-Example-Source})
|
||||||
target_link_libraries(test_loader tinyobjloader)
|
target_link_libraries(test_loader ${LIBRARY_NAME})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(TINYOBJLOADER_BUILD_OBJ_STICHER "Build OBJ Sticher Application" OFF)
|
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})
|
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
|
obj_sticher
|
||||||
DESTINATION
|
DESTINATION
|
||||||
bin
|
${TINYOBJLOADER_RUNTIME_DIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#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
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
#Installation
|
||||||
install(TARGETS
|
install(TARGETS
|
||||||
tinyobjloader
|
${LIBRARY_NAME}
|
||||||
|
EXPORT ${PROJECT_NAME}-targets
|
||||||
DESTINATION
|
DESTINATION
|
||||||
lib
|
${TINYOBJLOADER_LIBRARY_DIR}
|
||||||
|
PUBLIC_HEADER DESTINATION
|
||||||
|
${TINYOBJLOADER_INCLUDE_DIR}
|
||||||
|
RUNTIME DESTINATION
|
||||||
|
${TINYOBJLOADER_RUNTIME_DIR}
|
||||||
|
)
|
||||||
|
install(EXPORT
|
||||||
|
${PROJECT_NAME}-targets
|
||||||
|
NAMESPACE
|
||||||
|
tinyobjloader::
|
||||||
|
DESTINATION
|
||||||
|
${TINYOBJLOADER_CMAKE_DIR}
|
||||||
)
|
)
|
||||||
install(FILES
|
install(FILES
|
||||||
tiny_obj_loader.h
|
tiny_obj_loader.h
|
||||||
DESTINATION
|
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
21
LICENSE
Normal 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.
|
||||||
298
README.md
298
README.md
@@ -1,5 +1,4 @@
|
|||||||
tinyobjloader
|
# tinyobjloader
|
||||||
=============
|
|
||||||
|
|
||||||
[](https://gitter.im/syoyo/tinyobjloader?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/syoyo/tinyobjloader?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
|
||||||
@@ -11,45 +10,58 @@ tinyobjloader
|
|||||||
|
|
||||||
[](https://coveralls.io/github/syoyo/tinyobjloader?branch=master)
|
[](https://coveralls.io/github/syoyo/tinyobjloader?branch=master)
|
||||||
|
|
||||||
http://syoyo.github.io/tinyobjloader/
|
[https://github.com/syoyo/tinyobjloader](https://github.com/syoyo/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 ;-)
|
`tinyobjloader` is good for embedding .obj loader to your (global illumination) renderer ;-)
|
||||||
|
|
||||||
|
If you are looking for C89 version, please see https://github.com/syoyo/tinyobjloader-c .
|
||||||
|
|
||||||
What's new
|
Notice!
|
||||||
----------
|
|
||||||
|
|
||||||
* Mar 13, 2016 : Introduce `load_flag_t` and flat normal calculation flag! Thanks Vazquinhos!
|
|
||||||
* Jan 29, 2016 : Support n-polygon(no triangulation) and OpenSubdiv crease tag! Thanks dboogert!
|
|
||||||
* Nov 26, 2015 : Now single-header only!.
|
|
||||||
* Nov 08, 2015 : Improved API.
|
|
||||||
* Jun 23, 2015 : Various fixes and added more projects using tinyobjloader. Thanks many contributors!
|
|
||||||
* Mar 03, 2015 : Replace atof() with hand-written parser for robust reading of numeric value. Thanks skurmedel!
|
|
||||||
* Feb 06, 2015 : Fix parsing multi-material object
|
|
||||||
* Sep 14, 2014 : Add support for multi-material per object/group. Thanks Mykhailo!
|
|
||||||
* Mar 17, 2014 : Fixed trim newline bugs. Thanks ardneran!
|
|
||||||
* Apr 29, 2014 : Add API to read .obj from std::istream. Good for reading compressed .obj or connecting to procedural primitive generator. Thanks burnse!
|
|
||||||
* Apr 21, 2014 : Define default material if no material definition exists in .obj. Thanks YarmUI!
|
|
||||||
* Apr 10, 2014 : Add support for parsing 'illum' and 'd'/'Tr' statements. Thanks mmp!
|
|
||||||
* Jan 27, 2014 : Added CMake project. Thanks bradc6!
|
|
||||||
* Nov 26, 2013 : Performance optimization by NeuralSandwich. 9% improvement in his project, thanks!
|
|
||||||
* Sep 12, 2013 : Added multiple .obj sticher example.
|
|
||||||
|
|
||||||
Example
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||

|
We have released new version v1.0.0 on 20 Aug, 2016.
|
||||||
|
Old version is available `v0.9.x` branch https://github.com/syoyo/tinyobjloader/tree/v0.9.x
|
||||||
|
|
||||||
|
## What's new
|
||||||
|
|
||||||
|
* 20 Aug, 2016 : Bump version v1.0.0. New data structure and API!
|
||||||
|
|
||||||
|
### Old version
|
||||||
|
|
||||||
|
Previous old version is avaiable in `v0.9.x` branch.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
tinyobjloader can successfully load 6M triangles Rungholt scene.
|
tinyobjloader can successfully load 6M triangles Rungholt scene.
|
||||||
http://graphics.cs.williams.edu/data/meshes.xml
|
http://casual-effects.com/data/index.html
|
||||||
|
|
||||||
Use case
|

|
||||||
--------
|
|
||||||
|
* [examples/viewer/](examples/viewer) OpenGL .obj viewer
|
||||||
|
* [examples/callback_api/](examples/callback_api/) Callback API example
|
||||||
|
* [examples/voxelize/](examples/voxelize/) Voxelizer example
|
||||||
|
|
||||||
|
## Use case
|
||||||
|
|
||||||
TinyObjLoader is successfully used in ...
|
TinyObjLoader is successfully used in ...
|
||||||
|
|
||||||
|
### New version(v1.0.x)
|
||||||
|
|
||||||
|
* Double precision support through `TINYOBJLOADER_USE_DOUBLE` thanks to noma
|
||||||
|
* Loading models in Vulkan Tutorial https://vulkan-tutorial.com/Loading_models
|
||||||
|
* .obj viewer with Metal https://github.com/middlefeng/NuoModelViewer/tree/master
|
||||||
|
* Vulkan Cookbook https://github.com/PacktPublishing/Vulkan-Cookbook
|
||||||
|
* cudabox: CUDA Solid Voxelizer Engine https://github.com/gaspardzoss/cudavox
|
||||||
|
* Drake: A planning, control, and analysis toolbox for nonlinear dynamical systems https://github.com/RobotLocomotion/drake
|
||||||
|
* VFPR - a Vulkan Forward Plus Renderer : https://github.com/WindyDarian/Vulkan-Forward-Plus-Renderer
|
||||||
|
* Your project here! (Letting us know via github issue is welcome!)
|
||||||
|
|
||||||
|
### Old version(v0.9.x)
|
||||||
|
|
||||||
* bullet3 https://github.com/erwincoumans/bullet3
|
* bullet3 https://github.com/erwincoumans/bullet3
|
||||||
* pbrt-v2 https://github.com/mmp/pbrt-v2
|
* pbrt-v2 https://github.com/mmp/pbrt-v2
|
||||||
* OpenGL game engine development http://swarminglogic.com/jotting/2013_10_gamedev01
|
* OpenGL game engine development http://swarminglogic.com/jotting/2013_10_gamedev01
|
||||||
@@ -61,44 +73,141 @@ TinyObjLoader is successfully used in ...
|
|||||||
* pbrt-v3 https://github.com/mmp/pbrt-v3
|
* pbrt-v3 https://github.com/mmp/pbrt-v3
|
||||||
* cocos2d-x https://github.com/cocos2d/cocos2d-x/
|
* cocos2d-x https://github.com/cocos2d/cocos2d-x/
|
||||||
* Android Vulkan demo https://github.com/SaschaWillems/Vulkan
|
* Android Vulkan demo https://github.com/SaschaWillems/Vulkan
|
||||||
* Your project here!
|
* voxelizer https://github.com/karimnaaji/voxelizer
|
||||||
|
* Probulator https://github.com/kayru/Probulator
|
||||||
|
* OptiX Prime baking https://github.com/nvpro-samples/optix_prime_baking
|
||||||
|
* FireRays SDK https://github.com/GPUOpen-LibrariesAndSDKs/FireRays_SDK
|
||||||
|
* parg, tiny C library of various graphics utilities and GL demos https://github.com/prideout/parg
|
||||||
|
* Opengl unit of ChronoEngine https://github.com/projectchrono/chrono-opengl
|
||||||
|
* 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
|
|
||||||
--------
|
## Features
|
||||||
|
|
||||||
* Group(parse multiple group name)
|
* Group(parse multiple group name)
|
||||||
* Vertex
|
* Vertex
|
||||||
|
* Vertex color(as an extension: https://blender.stackexchange.com/questions/31997/how-can-i-get-vertex-painted-obj-files-to-import-into-blender)
|
||||||
* Texcoord
|
* Texcoord
|
||||||
* Normal
|
* Normal
|
||||||
* Material
|
* Material
|
||||||
* Unknown material attributes are returned as key-value(value is string) map.
|
* Unknown material attributes are returned as key-value(value is string) map.
|
||||||
* Crease tag('t'). This is OpenSubdiv specific(not in wavefront .obj specification)
|
* 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.
|
||||||
|
* Double precision support(for HPC application).
|
||||||
|
* Smoothing group
|
||||||
|
|
||||||
|
|
||||||
TODO
|
## TODO
|
||||||
----
|
|
||||||
|
|
||||||
* [ ] Support different indices for vertex/normal/texcoord
|
* [ ] Fix obj_sticker example.
|
||||||
|
* [ ] More unit test codes.
|
||||||
|
* [x] Texture options
|
||||||
|
|
||||||
License
|
## License
|
||||||
-------
|
|
||||||
|
|
||||||
Licensed under 2 clause BSD.
|
Licensed under MIT license.
|
||||||
|
|
||||||
Usage
|
## Usage
|
||||||
-----
|
|
||||||
|
### Data format
|
||||||
|
|
||||||
|
`attrib_t` contains single and linear array of vertex data(position, normal and texcoord).
|
||||||
|
|
||||||
|
```
|
||||||
|
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 |
|
||||||
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
|
||||||
|
attrib_t::colors => 3 floats per vertex(vertex color. optional)
|
||||||
|
|
||||||
|
c[0] c[1] c[2] c[3] c[n-1]
|
||||||
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
| x | y | z | x | y | z | x | y | z | x | y | z | .... | x | y | z |
|
||||||
|
+-----------+-----------+-----------+-----------+ +-----------+
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
Each `shape_t::mesh_t` does not contain vertex data but contains array index to `attrib_t`.
|
||||||
|
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).
|
||||||
|
|
||||||
|
### float data type
|
||||||
|
|
||||||
|
TinyObjLoader now use `real_t` for floating point data type.
|
||||||
|
Default is `float(32bit)`.
|
||||||
|
You can enable `double(64bit)` precision by using `TINYOBJLOADER_USE_DOUBLE` define.
|
||||||
|
|
||||||
|
#### Example code
|
||||||
|
|
||||||
TinyObjLoader triangulate input .obj by default.
|
|
||||||
```c++
|
```c++
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
||||||
#include "tiny_obj_loader.h"
|
#include "tiny_obj_loader.h"
|
||||||
|
|
||||||
std::string inputfile = "cornell_box.obj";
|
std::string inputfile = "cornell_box.obj";
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
std::vector<tinyobj::material_t> materials;
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string warn;
|
||||||
std::string err;
|
std::string err;
|
||||||
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str());
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, inputfile.c_str());
|
||||||
|
|
||||||
if (!err.empty()) { // `err` may contain warning message.
|
if (!err.empty()) { // `err` may contain warning message.
|
||||||
std::cerr << err << std::endl;
|
std::cerr << err << std::endl;
|
||||||
@@ -108,88 +217,53 @@ if (!ret) {
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
// Loop over shapes
|
||||||
std::cout << "# of materials : " << materials.size() << std::endl;
|
for (size_t s = 0; s < shapes.size(); s++) {
|
||||||
|
// Loop over faces(polygon)
|
||||||
|
size_t index_offset = 0;
|
||||||
|
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
|
||||||
|
int fv = shapes[s].mesh.num_face_vertices[f];
|
||||||
|
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
// Loop over vertices in the face.
|
||||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
for (size_t v = 0; v < fv; v++) {
|
||||||
printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
// access to vertex
|
||||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
|
||||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
tinyobj::real_t vx = attrib.vertices[3*idx.vertex_index+0];
|
||||||
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
|
tinyobj::real_t vy = attrib.vertices[3*idx.vertex_index+1];
|
||||||
printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]);
|
tinyobj::real_t vz = attrib.vertices[3*idx.vertex_index+2];
|
||||||
|
tinyobj::real_t nx = attrib.normals[3*idx.normal_index+0];
|
||||||
|
tinyobj::real_t ny = attrib.normals[3*idx.normal_index+1];
|
||||||
|
tinyobj::real_t nz = attrib.normals[3*idx.normal_index+2];
|
||||||
|
tinyobj::real_t tx = attrib.texcoords[2*idx.texcoord_index+0];
|
||||||
|
tinyobj::real_t ty = attrib.texcoords[2*idx.texcoord_index+1];
|
||||||
|
// Optional: vertex colors
|
||||||
|
// tinyobj::real_t red = attrib.colors[3*idx.vertex_index+0];
|
||||||
|
// tinyobj::real_t green = attrib.colors[3*idx.vertex_index+1];
|
||||||
|
// tinyobj::real_t blue = attrib.colors[3*idx.vertex_index+2];
|
||||||
}
|
}
|
||||||
|
index_offset += fv;
|
||||||
|
|
||||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
// per-face material
|
||||||
assert((shapes[i].mesh.positions.size() % 3) == 0);
|
shapes[s].mesh.material_ids[f];
|
||||||
for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
|
|
||||||
printf(" v[%ld] = (%f, %f, %f)\n", v,
|
|
||||||
shapes[i].mesh.positions[3*v+0],
|
|
||||||
shapes[i].mesh.positions[3*v+1],
|
|
||||||
shapes[i].mesh.positions[3*v+2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < materials.size(); i++) {
|
|
||||||
printf("material[%ld].name = %s\n", i, materials[i].name.c_str());
|
|
||||||
printf(" material.Ka = (%f, %f ,%f)\n", materials[i].ambient[0], materials[i].ambient[1], materials[i].ambient[2]);
|
|
||||||
printf(" material.Kd = (%f, %f ,%f)\n", materials[i].diffuse[0], materials[i].diffuse[1], materials[i].diffuse[2]);
|
|
||||||
printf(" material.Ks = (%f, %f ,%f)\n", materials[i].specular[0], materials[i].specular[1], materials[i].specular[2]);
|
|
||||||
printf(" material.Tr = (%f, %f ,%f)\n", materials[i].transmittance[0], materials[i].transmittance[1], materials[i].transmittance[2]);
|
|
||||||
printf(" material.Ke = (%f, %f ,%f)\n", materials[i].emission[0], materials[i].emission[1], materials[i].emission[2]);
|
|
||||||
printf(" material.Ns = %f\n", materials[i].shininess);
|
|
||||||
printf(" material.Ni = %f\n", materials[i].ior);
|
|
||||||
printf(" material.dissolve = %f\n", materials[i].dissolve);
|
|
||||||
printf(" material.illum = %d\n", materials[i].illum);
|
|
||||||
printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str());
|
|
||||||
printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str());
|
|
||||||
printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str());
|
|
||||||
printf(" material.map_Ns = %s\n", materials[i].specular_highlight_texname.c_str());
|
|
||||||
std::map<std::string, std::string>::const_iterator it(materials[i].unknown_parameter.begin());
|
|
||||||
std::map<std::string, std::string>::const_iterator itEnd(materials[i].unknown_parameter.end());
|
|
||||||
for (; it != itEnd; it++) {
|
|
||||||
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(indices). `num_vertices[i]` stores the number of vertices for ith face.
|
## Optimized loader
|
||||||
```c++
|
|
||||||
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
|
||||||
#include "tiny_obj_loader.h"
|
|
||||||
|
|
||||||
std::string inputfile = "cornell_box.obj";
|
Optimized multi-threaded .obj loader is available at `experimental/` directory.
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
If you want absolute performance to load .obj data, this optimized loader will fit your purpose.
|
||||||
std::vector<tinyobj::material_t> materials;
|
Note that the optimized loader uses C++11 thread and it does less error checks but may work most .obj data.
|
||||||
|
|
||||||
std::string err;
|
Here is some benchmark result. Time are measured on MacBook 12(Early 2016, Core m5 1.2GHz).
|
||||||
int flags = 1; // see load_flags_t enum for more information.
|
|
||||||
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), flags);
|
|
||||||
|
|
||||||
if (!err.empty()) { // `err` may contain warning message.
|
* Rungholt scene(6M triangles)
|
||||||
std::cerr << err << std::endl;
|
* 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 baseline)
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
## Tests
|
||||||
|
|
||||||
size_t indexOffset = 0;
|
Unit tests are provided in `tests` directory. See `tests/README.md` for details.
|
||||||
for (size_t n = 0; n < shapes[i].mesh.num_vertices.size(); n++) {
|
|
||||||
int ngon = shapes[i].mesh.num_vertices[n];
|
|
||||||
for (size_t f = 0; f < ngon; f++) {
|
|
||||||
unsigned int v = shapes[i].mesh.indices[indexOffset + f];
|
|
||||||
printf(" face[%ld] v[%ld] = (%f, %f, %f)\n", n,
|
|
||||||
shapes[i].mesh.positions[3*v+0],
|
|
||||||
shapes[i].mesh.positions[3*v+1],
|
|
||||||
shapes[i].mesh.positions[3*v+2]);
|
|
||||||
|
|
||||||
}
|
|
||||||
indexOffset += ngon;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|||||||
28
appveyor.yml
28
appveyor.yml
@@ -1,12 +1,22 @@
|
|||||||
version: 0.9.{build}
|
version: 1.0.{build}
|
||||||
|
|
||||||
# scripts that runs after repo cloning.
|
|
||||||
install:
|
|
||||||
- vcsetup.bat
|
|
||||||
|
|
||||||
platform: x64
|
platform: x64
|
||||||
configuration: Release
|
|
||||||
|
|
||||||
build:
|
install:
|
||||||
parallel: true
|
#######################################################################################
|
||||||
project: TinyObjLoaderSolution.sln
|
# All external dependencies are installed in C:\projects\deps
|
||||||
|
#######################################################################################
|
||||||
|
- mkdir C:\projects\deps
|
||||||
|
|
||||||
|
#######################################################################################
|
||||||
|
# Install Ninja
|
||||||
|
#######################################################################################
|
||||||
|
- set NINJA_URL="https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip"
|
||||||
|
- appveyor DownloadFile %NINJA_URL% -FileName ninja.zip
|
||||||
|
- 7z x ninja.zip -oC:\projects\deps\ninja > nul
|
||||||
|
- set PATH=C:\projects\deps\ninja;%PATH%
|
||||||
|
- ninja --version
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- cd tests
|
||||||
|
- vcbuild.bat
|
||||||
|
|||||||
61
build.ninja
61
build.ninja
@@ -1,16 +1,53 @@
|
|||||||
# build.ninja
|
ninja_required_version = 1.4
|
||||||
cc = clang
|
|
||||||
cxx = clang++
|
|
||||||
cflags = -Werror -Weverything
|
|
||||||
cxxflags = -Werror -Weverything
|
|
||||||
|
|
||||||
rule compile
|
gnubuilddir = build
|
||||||
command = $cxx $cxxflags -c $in -o $out
|
gnudefines =
|
||||||
|
gnuincludes = -I.
|
||||||
|
gnucflags = -O2 -g
|
||||||
|
gnucxxflags = -O2 -g -pedantic -Wall -Wextra -Wcast-align -Wcast-qual $
|
||||||
|
-Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self $
|
||||||
|
-Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast $
|
||||||
|
-Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion $
|
||||||
|
-Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror $
|
||||||
|
-Wno-unused -fsanitize=address
|
||||||
|
gnuldflags = -fsanitize=address
|
||||||
|
|
||||||
rule link
|
pool link_pool
|
||||||
command = $cxx $in -o $out
|
depth = 1
|
||||||
|
|
||||||
build test.o: compile test.cc
|
rule gnucxx
|
||||||
build test: link test.o
|
command = $gnucxx -MMD -MF $out.d $gnudefines $gnuincludes $gnucxxflags $
|
||||||
|
-c $in -o $out
|
||||||
|
description = CXX $out
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
rule gnucc
|
||||||
|
command = $gnucc -MMD -MF $out.d $gnudefines $gnuincludes $gnucflags -c $
|
||||||
|
$in -o $out
|
||||||
|
description = CC $out
|
||||||
|
depfile = $out.d
|
||||||
|
deps = gcc
|
||||||
|
rule gnulink
|
||||||
|
command = $gnuld -o $out $in $libs $gnuldflags
|
||||||
|
description = LINK $out
|
||||||
|
pool = link_pool
|
||||||
|
rule gnuar
|
||||||
|
command = $gnuar rsc $out $in
|
||||||
|
description = AR $out
|
||||||
|
pool = link_pool
|
||||||
|
rule gnustamp
|
||||||
|
command = touch $out
|
||||||
|
description = STAMP $out
|
||||||
|
|
||||||
default test
|
gnucxx = g++
|
||||||
|
gnucc = gcc
|
||||||
|
gnuld = $gnucxx
|
||||||
|
gnuar = ar
|
||||||
|
|
||||||
|
build loader_example.o: gnucxx loader_example.cc
|
||||||
|
|
||||||
|
|
||||||
|
build loader_example: gnulink loader_example.o
|
||||||
|
build all: phony loader_example
|
||||||
|
|
||||||
|
default all
|
||||||
|
|||||||
6323
deps/cpplint.py
vendored
Executable file
6323
deps/cpplint.py
vendored
Executable file
File diff suppressed because it is too large
Load Diff
2
examples/callback_api/Makefile
Normal file
2
examples/callback_api/Makefile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
clang++ -I../../ -Wall -g -o example main.cc
|
||||||
171
examples/callback_api/main.cc
Normal file
171
examples/callback_api/main.cc
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
//
|
||||||
|
// An example of how to use callback API.
|
||||||
|
// This example is minimum and incomplete. Just showing the usage of callback
|
||||||
|
// API.
|
||||||
|
// You need to implement your own Mesh data struct constrution based on this
|
||||||
|
// example in practical.
|
||||||
|
//
|
||||||
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
|
#include "tiny_obj_loader.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
std::vector<float> vertices;
|
||||||
|
std::vector<float> normals;
|
||||||
|
std::vector<float> texcoords;
|
||||||
|
std::vector<int> v_indices;
|
||||||
|
std::vector<int> vn_indices;
|
||||||
|
std::vector<int> vt_indices;
|
||||||
|
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
} MyMesh;
|
||||||
|
|
||||||
|
void vertex_cb(void *user_data, float x, float y, float z, float w) {
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
printf("v[%ld] = %f, %f, %f (w %f)\n", mesh->vertices.size() / 3, x, y, z, w);
|
||||||
|
|
||||||
|
mesh->vertices.push_back(x);
|
||||||
|
mesh->vertices.push_back(y);
|
||||||
|
mesh->vertices.push_back(z);
|
||||||
|
// Discard w
|
||||||
|
}
|
||||||
|
|
||||||
|
void normal_cb(void *user_data, float x, float y, float z) {
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
printf("vn[%ld] = %f, %f, %f\n", mesh->normals.size() / 3, x, y, z);
|
||||||
|
|
||||||
|
mesh->normals.push_back(x);
|
||||||
|
mesh->normals.push_back(y);
|
||||||
|
mesh->normals.push_back(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void texcoord_cb(void *user_data, float x, float y, float z) {
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
printf("vt[%ld] = %f, %f, %f\n", mesh->texcoords.size() / 3, x, y, z);
|
||||||
|
|
||||||
|
mesh->texcoords.push_back(x);
|
||||||
|
mesh->texcoords.push_back(y);
|
||||||
|
mesh->texcoords.push_back(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
void index_cb(void *user_data, tinyobj::index_t *indices, int num_indices) {
|
||||||
|
// NOTE: the value of each index is raw value.
|
||||||
|
// For example, the application must manually adjust the index with offset
|
||||||
|
// (e.g. v_indices.size()) when the value is negative(whic means relative
|
||||||
|
// index).
|
||||||
|
// Also, the first index starts with 1, not 0.
|
||||||
|
// See fixIndex() function in tiny_obj_loader.h for details.
|
||||||
|
// Also, 0 is set for the index value which
|
||||||
|
// does not exist in .obj
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_indices; i++) {
|
||||||
|
tinyobj::index_t idx = indices[i];
|
||||||
|
printf("idx[%ld] = %d, %d, %d\n", mesh->v_indices.size(), idx.vertex_index,
|
||||||
|
idx.normal_index, idx.texcoord_index);
|
||||||
|
|
||||||
|
if (idx.vertex_index != 0) {
|
||||||
|
mesh->v_indices.push_back(idx.vertex_index);
|
||||||
|
}
|
||||||
|
if (idx.normal_index != 0) {
|
||||||
|
mesh->vn_indices.push_back(idx.normal_index);
|
||||||
|
}
|
||||||
|
if (idx.texcoord_index != 0) {
|
||||||
|
mesh->vt_indices.push_back(idx.texcoord_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void usemtl_cb(void *user_data, const char *name, int material_idx) {
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
if ((material_idx > -1) && (material_idx < mesh->materials.size())) {
|
||||||
|
printf("usemtl. material id = %d(name = %s)\n", material_idx,
|
||||||
|
mesh->materials[material_idx].name.c_str());
|
||||||
|
} else {
|
||||||
|
printf("usemtl. name = %s\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtllib_cb(void *user_data, const tinyobj::material_t *materials,
|
||||||
|
int num_materials) {
|
||||||
|
MyMesh *mesh = reinterpret_cast<MyMesh *>(user_data);
|
||||||
|
printf("mtllib. # of materials = %d\n", num_materials);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_materials; i++) {
|
||||||
|
mesh->materials.push_back(materials[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void group_cb(void *user_data, const char **names, int num_names) {
|
||||||
|
// MyMesh *mesh = reinterpret_cast<MyMesh*>(user_data);
|
||||||
|
printf("group : name = \n");
|
||||||
|
|
||||||
|
for (int i = 0; i < num_names; i++) {
|
||||||
|
printf(" %s\n", names[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void object_cb(void *user_data, const char *name) {
|
||||||
|
// MyMesh *mesh = reinterpret_cast<MyMesh*>(user_data);
|
||||||
|
printf("object : name = %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
tinyobj::callback_t cb;
|
||||||
|
cb.vertex_cb = vertex_cb;
|
||||||
|
cb.normal_cb = normal_cb;
|
||||||
|
cb.texcoord_cb = texcoord_cb;
|
||||||
|
cb.index_cb = index_cb;
|
||||||
|
cb.usemtl_cb = usemtl_cb;
|
||||||
|
cb.mtllib_cb = mtllib_cb;
|
||||||
|
cb.group_cb = group_cb;
|
||||||
|
cb.object_cb = object_cb;
|
||||||
|
|
||||||
|
MyMesh mesh;
|
||||||
|
std::string warn;
|
||||||
|
std::string err;
|
||||||
|
std::string filename = "../../models/cornell_box.obj";
|
||||||
|
if (argc > 1) {
|
||||||
|
filename = std::string(argv[1]);
|
||||||
|
}
|
||||||
|
std::ifstream ifs(filename.c_str());
|
||||||
|
|
||||||
|
if (ifs.fail()) {
|
||||||
|
std::cerr << "file not found." << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyobj::MaterialFileReader mtlReader("../../models/");
|
||||||
|
|
||||||
|
bool ret = tinyobj::LoadObjWithCallback(ifs, cb, &mesh, &mtlReader, &warn, &err);
|
||||||
|
|
||||||
|
if (!warn.empty()) {
|
||||||
|
std::cout << "WARN: " << warn << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
std::cerr << "Failed to parse .obj" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("# of vertices = %ld\n", mesh.vertices.size() / 3);
|
||||||
|
printf("# of normals = %ld\n", mesh.normals.size() / 3);
|
||||||
|
printf("# of texcoords = %ld\n", mesh.texcoords.size() / 2);
|
||||||
|
printf("# of vertex indices = %ld\n", mesh.v_indices.size());
|
||||||
|
printf("# of normal indices = %ld\n", mesh.vn_indices.size());
|
||||||
|
printf("# of texcoord indices = %ld\n", mesh.vt_indices.size());
|
||||||
|
printf("# of materials = %ld\n", mesh.materials.size());
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
//
|
//
|
||||||
// Stiches multiple .obj files into one .obj.
|
// Stiches multiple .obj files into one .obj.
|
||||||
//
|
//
|
||||||
#include "../../tiny_obj_loader.h"
|
|
||||||
#include "obj_writer.h"
|
#include "obj_writer.h"
|
||||||
|
|
||||||
|
#include "../../tiny_obj_loader.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
@@ -11,27 +12,59 @@
|
|||||||
|
|
||||||
typedef std::vector<tinyobj::shape_t> Shape;
|
typedef std::vector<tinyobj::shape_t> Shape;
|
||||||
typedef std::vector<tinyobj::material_t> Material;
|
typedef std::vector<tinyobj::material_t> Material;
|
||||||
|
typedef tinyobj::attrib_t Attribute;
|
||||||
|
|
||||||
void
|
void
|
||||||
StichObjs(
|
StichObjs(
|
||||||
|
tinyobj::attrib_t& out_attribute,
|
||||||
std::vector<tinyobj::shape_t>& out_shape,
|
std::vector<tinyobj::shape_t>& out_shape,
|
||||||
std::vector<tinyobj::material_t>& out_material,
|
std::vector<tinyobj::material_t>& out_material,
|
||||||
|
const std::vector<Attribute>& attributes,
|
||||||
const std::vector<Shape>& shapes,
|
const std::vector<Shape>& shapes,
|
||||||
const std::vector<Material>& materials)
|
const std::vector<Material>& materials)
|
||||||
{
|
{
|
||||||
int numShapes = 0;
|
// The amount of attributes, shape-vectors and material-vecotrs should be the same.
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
if(attributes.size() != shapes.size() && attributes.size() != materials.size()){
|
||||||
numShapes += (int)shapes[i].size();
|
std::cerr << "Size of attributes, shapes and Materials don't fit!" << attributes.size() << " " << shapes.size() <<" " << materials.size() << std::endl;;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
int num_shapes = 0;
|
||||||
|
// 4 values (vertices, normals, texcoords, colors)
|
||||||
|
std::vector<int> num_attributes(4, 0);
|
||||||
|
int num_materials = 0;
|
||||||
|
for(int i = 0; i < shapes.size(); i++){
|
||||||
|
num_shapes += shapes[i].size();
|
||||||
|
}
|
||||||
|
for(int i = 0; i < attributes.size(); i++){
|
||||||
|
num_attributes[0] += attributes[i].vertices.size();
|
||||||
|
num_attributes[1] += attributes[i].normals.size();
|
||||||
|
num_attributes[2] += attributes[i].texcoords.size();
|
||||||
|
num_attributes[3] += attributes[i].colors.size();
|
||||||
|
}
|
||||||
|
for(int i = 0; i < materials.size(); i++){
|
||||||
|
num_materials += materials[i].size();
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Total # of shapes = %d\n", numShapes);
|
// More performant, than push_back
|
||||||
int materialIdOffset = 0;
|
out_attribute.vertices.resize(num_attributes[0]);
|
||||||
|
out_attribute.normals.resize(num_attributes[1]);
|
||||||
|
out_attribute.texcoords.resize(num_attributes[2]);
|
||||||
|
out_attribute.colors.resize(num_attributes[3]);
|
||||||
|
out_shape.resize(num_shapes);
|
||||||
|
out_material.resize(num_materials);
|
||||||
|
|
||||||
size_t face_offset = 0;
|
int material_id_offset = 0;
|
||||||
|
int shape_id_offset = 0;
|
||||||
|
int vertex_idx_offset = 0;
|
||||||
|
int normal_idx_offset = 0;
|
||||||
|
int texcoord_idx_offset = 0;
|
||||||
|
int color_idx_offset = 0;
|
||||||
|
|
||||||
|
// shapes.size() = attributes.size() = materials.size()
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
for (size_t i = 0; i < shapes.size(); i++) {
|
||||||
|
|
||||||
|
// Copy shapes
|
||||||
for (size_t k = 0; k < shapes[i].size(); k++) {
|
for (size_t k = 0; k < shapes[i].size(); k++) {
|
||||||
|
|
||||||
std::string new_name = shapes[i][k].name;
|
std::string new_name = shapes[i][k].name;
|
||||||
// Add suffix
|
// Add suffix
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@@ -39,36 +72,51 @@ StichObjs(
|
|||||||
new_name += std::string(buf);
|
new_name += std::string(buf);
|
||||||
|
|
||||||
printf("shape[%ld][%ld].name = %s\n", i, k, shapes[i][k].name.c_str());
|
printf("shape[%ld][%ld].name = %s\n", i, k, shapes[i][k].name.c_str());
|
||||||
assert((shapes[i][k].mesh.indices.size() % 3) == 0);
|
|
||||||
assert((shapes[i][k].mesh.positions.size() % 3) == 0);
|
|
||||||
|
|
||||||
tinyobj::shape_t new_shape = shapes[i][k];
|
tinyobj::shape_t new_shape = shapes[i][k];
|
||||||
// Add offset.
|
// Add material offset.
|
||||||
for(size_t f = 0; f < new_shape.mesh.material_ids.size(); f++) {
|
for(size_t f = 0; f < new_shape.mesh.material_ids.size(); f++) {
|
||||||
new_shape.mesh.material_ids[f] += materialIdOffset;
|
new_shape.mesh.material_ids[f] += material_id_offset;
|
||||||
|
}
|
||||||
|
// Add indices offset.
|
||||||
|
for(size_t f = 0; f < new_shape.mesh.indices.size(); f++){
|
||||||
|
tinyobj::index_t& ref = new_shape.mesh.indices[f];
|
||||||
|
if(ref.vertex_index > -1){
|
||||||
|
ref.vertex_index += vertex_idx_offset;
|
||||||
|
}
|
||||||
|
if(ref.normal_index > -1){
|
||||||
|
ref.normal_index += normal_idx_offset;
|
||||||
|
}
|
||||||
|
if(ref.texcoord_index > -1){
|
||||||
|
ref.texcoord_index += texcoord_idx_offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_shape.name = new_name;
|
new_shape.name = new_name;
|
||||||
printf("shape[%ld][%ld].new_name = %s\n", i, k, new_shape.name.c_str());
|
printf("shape[%ld][%ld].new_name = %s\n", i, k, new_shape.name.c_str());
|
||||||
|
|
||||||
out_shape.push_back(new_shape);
|
out_shape[shape_id_offset++] = new_shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
materialIdOffset += materials[i].size();
|
// Copy materials
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < materials.size(); i++) {
|
|
||||||
for (size_t k = 0; k < materials[i].size(); k++) {
|
for (size_t k = 0; k < materials[i].size(); k++) {
|
||||||
out_material.push_back(materials[i][k]);
|
out_material[material_id_offset++] = materials[i][k];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy attributes (3 floats per vertex, 3 floats per normal, 2 floats per texture-coordinate, 3 floats per color)
|
||||||
|
// You could also include a check here, if the sizes are dividable by 3 (resp. 2), but it's safe to simply assume, they do.
|
||||||
|
std::copy(attributes[i].vertices.begin(), attributes[i].vertices.end(), out_attribute.vertices.begin() + vertex_idx_offset * 3);
|
||||||
|
vertex_idx_offset += attributes[i].vertices.size() / 3;
|
||||||
|
std::copy(attributes[i].normals.begin(), attributes[i].normals.end(), out_attribute.normals.begin() + normal_idx_offset * 3);
|
||||||
|
normal_idx_offset += attributes[i].normals.size() / 3;
|
||||||
|
std::copy(attributes[i].texcoords.begin(), attributes[i].texcoords.end(), out_attribute.texcoords.begin() + texcoord_idx_offset * 2);
|
||||||
|
texcoord_idx_offset += attributes[i].texcoords.size() / 2;
|
||||||
|
std::copy(attributes[i].colors.begin(), attributes[i].colors.end(), out_attribute.colors.begin() + color_idx_offset);
|
||||||
|
color_idx_offset += attributes[i].colors.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
int main(int argc, char **argv)
|
||||||
|
|
||||||
int
|
|
||||||
main(
|
|
||||||
int argc,
|
|
||||||
char **argv)
|
|
||||||
{
|
{
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
printf("Usage: obj_sticher input0.obj input1.obj ... output.obj\n");
|
printf("Usage: obj_sticher input0.obj input1.obj ... output.obj\n");
|
||||||
@@ -78,16 +126,16 @@ main(
|
|||||||
int num_objfiles = argc - 2;
|
int num_objfiles = argc - 2;
|
||||||
std::string out_filename = std::string(argv[argc-1]); // last element
|
std::string out_filename = std::string(argv[argc-1]); // last element
|
||||||
|
|
||||||
std::vector<Shape> shapes;
|
std::vector<Attribute> attributes(num_objfiles);
|
||||||
std::vector<Material> materials;
|
std::vector<Shape> shapes(num_objfiles);
|
||||||
shapes.resize(num_objfiles);
|
std::vector<Material> materials(num_objfiles);
|
||||||
materials.resize(num_objfiles);
|
|
||||||
|
|
||||||
for (int i = 0; i < num_objfiles; i++) {
|
for (int i = 0; i < num_objfiles; i++) {
|
||||||
std::cout << "Loading " << argv[i+1] << " ... " << std::flush;
|
std::cout << "Loading " << argv[i+1] << " ... " << std::flush;
|
||||||
|
|
||||||
|
std::string warn;
|
||||||
std::string err;
|
std::string err;
|
||||||
bool ret = tinyobj::LoadObj(shapes[i], materials[i], err, argv[i+1]);
|
bool ret = tinyobj::LoadObj(&attributes[i], &shapes[i], &materials[i], &warn, &err, argv[i+1]);
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
std::cerr << err << std::endl;
|
std::cerr << err << std::endl;
|
||||||
}
|
}
|
||||||
@@ -98,12 +146,13 @@ main(
|
|||||||
std::cout << "DONE." << std::endl;
|
std::cout << "DONE." << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<tinyobj::shape_t> out_shape;
|
Attribute out_attribute;
|
||||||
std::vector<tinyobj::material_t> out_material;
|
Shape out_shape;
|
||||||
StichObjs(out_shape, out_material, shapes, materials);
|
Material out_material;
|
||||||
|
StichObjs(out_attribute, out_shape, out_material, attributes, shapes, materials);
|
||||||
|
|
||||||
bool coordTransform = true;
|
bool coordTransform = true;
|
||||||
bool ret = WriteObj(out_filename, out_shape, out_material, coordTransform);
|
bool ret = WriteObj(out_filename, out_attribute, out_shape, out_material, coordTransform);
|
||||||
assert(ret);
|
assert(ret);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
|
|||||||
fprintf(fp, "Ke %f %f %f\n", mat.emission[0], mat.emission[1], mat.emission[2]);
|
fprintf(fp, "Ke %f %f %f\n", mat.emission[0], mat.emission[1], mat.emission[2]);
|
||||||
fprintf(fp, "Ns %f\n", mat.shininess);
|
fprintf(fp, "Ns %f\n", mat.shininess);
|
||||||
fprintf(fp, "Ni %f\n", mat.ior);
|
fprintf(fp, "Ni %f\n", mat.ior);
|
||||||
|
fprintf(fp, "illum %d\n", mat.illum);
|
||||||
|
fprintf(fp, "\n");
|
||||||
// @todo { texture }
|
// @todo { texture }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,7 +40,7 @@ bool WriteMat(const std::string& filename, const std::vector<tinyobj::material_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform) {
|
bool WriteObj(const std::string& filename, const tinyobj::attrib_t& attributes, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform) {
|
||||||
FILE* fp = fopen(filename.c_str(), "w");
|
FILE* fp = fopen(filename.c_str(), "w");
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
fprintf(stderr, "Failed to open file [ %s ] for write.\n", filename.c_str());
|
fprintf(stderr, "Failed to open file [ %s ] for write.\n", filename.c_str());
|
||||||
@@ -48,17 +50,53 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
|
|||||||
std::string basename = GetFileBasename(filename);
|
std::string basename = GetFileBasename(filename);
|
||||||
std::string material_filename = basename + ".mtl";
|
std::string material_filename = basename + ".mtl";
|
||||||
|
|
||||||
int v_offset = 0;
|
|
||||||
int vn_offset = 0;
|
|
||||||
int vt_offset = 0;
|
|
||||||
int prev_material_id = -1;
|
int prev_material_id = -1;
|
||||||
|
|
||||||
fprintf(fp, "mtllib %s\n", material_filename.c_str());
|
fprintf(fp, "mtllib %s\n\n", material_filename.c_str());
|
||||||
|
|
||||||
|
// facevarying vtx
|
||||||
|
for (size_t k = 0; k < attributes.vertices.size(); k+=3) {
|
||||||
|
if (coordTransform) {
|
||||||
|
fprintf(fp, "v %f %f %f\n",
|
||||||
|
attributes.vertices[k + 0],
|
||||||
|
attributes.vertices[k + 2],
|
||||||
|
-attributes.vertices[k + 1]);
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "v %f %f %f\n",
|
||||||
|
attributes.vertices[k + 0],
|
||||||
|
attributes.vertices[k + 1],
|
||||||
|
attributes.vertices[k + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
|
// facevarying normal
|
||||||
|
for (size_t k = 0; k < attributes.normals.size(); k += 3) {
|
||||||
|
if (coordTransform) {
|
||||||
|
fprintf(fp, "vn %f %f %f\n",
|
||||||
|
attributes.normals[k + 0],
|
||||||
|
attributes.normals[k + 2],
|
||||||
|
-attributes.normals[k + 1]);
|
||||||
|
} else {
|
||||||
|
fprintf(fp, "vn %f %f %f\n",
|
||||||
|
attributes.normals[k + 0],
|
||||||
|
attributes.normals[k + 1],
|
||||||
|
attributes.normals[k + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
|
// facevarying texcoord
|
||||||
|
for (size_t k = 0; k < attributes.texcoords.size(); k += 2) {
|
||||||
|
fprintf(fp, "vt %f %f\n",
|
||||||
|
attributes.texcoords[k + 0],
|
||||||
|
attributes.texcoords[k + 1]);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
for (size_t i = 0; i < shapes.size(); i++) {
|
||||||
|
fprintf(fp, "\n");
|
||||||
bool has_vn = false;
|
|
||||||
bool has_vt = false;
|
|
||||||
|
|
||||||
if (shapes[i].name.empty()) {
|
if (shapes[i].name.empty()) {
|
||||||
fprintf(fp, "g Unknown\n");
|
fprintf(fp, "g Unknown\n");
|
||||||
@@ -66,101 +104,53 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
|
|||||||
fprintf(fp, "g %s\n", shapes[i].name.c_str());
|
fprintf(fp, "g %s\n", shapes[i].name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!shapes[i].material.name.empty()) {
|
bool has_vn = false;
|
||||||
// fprintf(fp, "usemtl %s\n", shapes[i].material.name.c_str());
|
bool has_vt = false;
|
||||||
//}
|
// Assumes normals and textures are set shape-wise.
|
||||||
|
if(shapes[i].mesh.indices.size() > 0){
|
||||||
// facevarying vtx
|
has_vn = shapes[i].mesh.indices[0].normal_index != -1;
|
||||||
for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
|
has_vt = shapes[i].mesh.indices[0].texcoord_index != -1;
|
||||||
for (int j = 0; j < 3; j++) {
|
|
||||||
int idx = shapes[i].mesh.indices[3*k+j];
|
|
||||||
if (coordTransform) {
|
|
||||||
fprintf(fp, "v %f %f %f\n",
|
|
||||||
shapes[i].mesh.positions[3*idx+0],
|
|
||||||
shapes[i].mesh.positions[3*idx+2],
|
|
||||||
-shapes[i].mesh.positions[3*idx+1]);
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "v %f %f %f\n",
|
|
||||||
shapes[i].mesh.positions[3*idx+0],
|
|
||||||
shapes[i].mesh.positions[3*idx+1],
|
|
||||||
shapes[i].mesh.positions[3*idx+2]);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// facevarying normal
|
|
||||||
if (shapes[i].mesh.normals.size() > 0) {
|
|
||||||
for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
|
|
||||||
for (int j = 0; j < 3; j++) {
|
|
||||||
int idx = shapes[i].mesh.indices[3*k+j];
|
|
||||||
if (coordTransform) {
|
|
||||||
fprintf(fp, "vn %f %f %f\n",
|
|
||||||
shapes[i].mesh.normals[3*idx+0],
|
|
||||||
shapes[i].mesh.normals[3*idx+2],
|
|
||||||
-shapes[i].mesh.normals[3*idx+1]);
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "vn %f %f %f\n",
|
|
||||||
shapes[i].mesh.normals[3*idx+0],
|
|
||||||
shapes[i].mesh.normals[3*idx+1],
|
|
||||||
shapes[i].mesh.normals[3*idx+2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shapes[i].mesh.normals.size() > 0) has_vn = true;
|
|
||||||
|
|
||||||
// facevarying texcoord
|
|
||||||
if (shapes[i].mesh.texcoords.size() > 0) {
|
|
||||||
for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
|
|
||||||
for (int j = 0; j < 3; j++) {
|
|
||||||
int idx = shapes[i].mesh.indices[3*k+j];
|
|
||||||
fprintf(fp, "vt %f %f\n",
|
|
||||||
shapes[i].mesh.texcoords[2*idx+0],
|
|
||||||
shapes[i].mesh.texcoords[2*idx+1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (shapes[i].mesh.texcoords.size() > 0) has_vt = true;
|
|
||||||
|
|
||||||
// face
|
// face
|
||||||
for (size_t k = 0; k < shapes[i].mesh.indices.size() / 3; k++) {
|
int face_index = 0;
|
||||||
|
for (size_t k = 0; k < shapes[i].mesh.indices.size(); k += shapes[i].mesh.num_face_vertices[face_index++]) {
|
||||||
// Face index is 1-base.
|
// Check Materials
|
||||||
//int v0 = shapes[i].mesh.indices[3*k+0] + 1 + v_offset;
|
int material_id = shapes[i].mesh.material_ids[face_index];
|
||||||
//int v1 = shapes[i].mesh.indices[3*k+1] + 1 + v_offset;
|
|
||||||
//int v2 = shapes[i].mesh.indices[3*k+2] + 1 + v_offset;
|
|
||||||
int v0 = (3*k + 0) + 1 + v_offset;
|
|
||||||
int v1 = (3*k + 1) + 1 + v_offset;
|
|
||||||
int v2 = (3*k + 2) + 1 + v_offset;
|
|
||||||
|
|
||||||
int vt0 = (3*k + 0) + 1 + vt_offset;
|
|
||||||
int vt1 = (3*k + 1) + 1 + vt_offset;
|
|
||||||
int vt2 = (3*k + 2) + 1 + vt_offset;
|
|
||||||
|
|
||||||
int material_id = shapes[i].mesh.material_ids[k];
|
|
||||||
if (material_id != prev_material_id) {
|
if (material_id != prev_material_id) {
|
||||||
std::string material_name = materials[material_id].name;
|
std::string material_name = materials[material_id].name;
|
||||||
fprintf(fp, "usemtl %s\n", material_name.c_str());
|
fprintf(fp, "usemtl %s\n", material_name.c_str());
|
||||||
prev_material_id = material_id;
|
prev_material_id = material_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char v_per_f = shapes[i].mesh.num_face_vertices[face_index];
|
||||||
|
// Imperformant, but if you want to have variable vertices per face, you need some kind of a dynamic loop.
|
||||||
|
fprintf(fp, "f");
|
||||||
|
for(int l = 0; l < v_per_f; l++){
|
||||||
|
const tinyobj::index_t& ref = shapes[i].mesh.indices[k + l];
|
||||||
if(has_vn && has_vt){
|
if(has_vn && has_vt){
|
||||||
fprintf(fp, "f %d/%d/%d %d/%d/%d %d/%d/%d\n",
|
// v0/t0/vn0
|
||||||
v0, vt0, v0, v1, vt1, v1, v2, vt2, v2);
|
fprintf(fp, " %d/%d/%d", ref.vertex_index + 1, ref.texcoord_index + 1, ref.normal_index + 1);
|
||||||
} else if (has_vn && !has_vt) {
|
continue;
|
||||||
fprintf(fp, "f %d//%d %d//%d %d//%d\n", v0, v0, v1, v1, v2, v2);
|
|
||||||
} else if (!has_vn && has_vt) {
|
|
||||||
fprintf(fp, "f %d/%d %d/%d %d/%d\n", v0, v0, v1, v1, v2, v2);
|
|
||||||
} else {
|
|
||||||
fprintf(fp, "f %d %d %d\n", v0, v1, v2);
|
|
||||||
}
|
}
|
||||||
|
if(has_vn && !has_vt){
|
||||||
|
// v0//vn0
|
||||||
|
fprintf(fp, " %d//%d", ref.vertex_index + 1, ref.normal_index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!has_vn && has_vt){
|
||||||
|
// v0/vt0
|
||||||
|
fprintf(fp, " %d/%d", ref.vertex_index + 1, ref.texcoord_index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(!has_vn && !has_vt){
|
||||||
|
// v0 v1 v2
|
||||||
|
fprintf(fp, " %d", ref.vertex_index + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(fp, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
v_offset += shapes[i].mesh.indices.size();
|
|
||||||
//vn_offset += shapes[i].mesh.normals.size() / 3;
|
|
||||||
vt_offset += shapes[i].mesh.texcoords.size() / 2;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
@@ -172,5 +162,3 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "../../tiny_obj_loader.h"
|
#include "../../tiny_obj_loader.h"
|
||||||
|
|
||||||
extern bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform = false);
|
extern bool WriteObj(const std::string& filename, const tinyobj::attrib_t& attributes, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool coordTransform = false);
|
||||||
|
|
||||||
|
|
||||||
#endif // __OBJ_WRITER_H__
|
#endif // __OBJ_WRITER_H__
|
||||||
|
|||||||
42
examples/viewer/README.md
Normal file
42
examples/viewer/README.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# Simple .obj viewer with glew + glfw3 + OpenGL
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* premake5
|
||||||
|
* glfw3
|
||||||
|
* glew
|
||||||
|
|
||||||
|
## Build on MaCOSX
|
||||||
|
|
||||||
|
Install glfw3 and glew using brew.
|
||||||
|
Then,
|
||||||
|
|
||||||
|
$ premake5 gmake
|
||||||
|
$ make
|
||||||
|
|
||||||
|
## Build on Linux
|
||||||
|
|
||||||
|
Set `PKG_CONFIG_PATH` or Edit path to glfw3 and glew in `premake4.lua`
|
||||||
|
|
||||||
|
Then,
|
||||||
|
|
||||||
|
$ premake5 gmake
|
||||||
|
$ make
|
||||||
|
|
||||||
|
## Build on Windows.
|
||||||
|
|
||||||
|
* Visual Studio 2013
|
||||||
|
* Windows 64bit
|
||||||
|
* 32bit may work.
|
||||||
|
|
||||||
|
Put glfw3 and glew library somewhere and replace include and lib path in `premake4.lua`
|
||||||
|
|
||||||
|
Then,
|
||||||
|
|
||||||
|
> premake5.exe vs2013
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* [ ] Support per-face material.
|
||||||
|
* [ ] Use shader-based GL rendering.
|
||||||
|
* [ ] PBR shader support.
|
||||||
44
examples/viewer/premake4.lua
Normal file
44
examples/viewer/premake4.lua
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
solution "objview"
|
||||||
|
-- location ( "build" )
|
||||||
|
configurations { "Release", "Debug" }
|
||||||
|
platforms {"native", "x64", "x32"}
|
||||||
|
|
||||||
|
project "objview"
|
||||||
|
|
||||||
|
kind "ConsoleApp"
|
||||||
|
language "C++"
|
||||||
|
files { "viewer.cc", "trackball.cc" }
|
||||||
|
includedirs { "./" }
|
||||||
|
includedirs { "../../" }
|
||||||
|
|
||||||
|
configuration { "linux" }
|
||||||
|
linkoptions { "`pkg-config --libs glfw3`" }
|
||||||
|
links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
|
||||||
|
linkoptions { "-pthread" }
|
||||||
|
|
||||||
|
configuration { "windows" }
|
||||||
|
-- Path to GLFW3
|
||||||
|
includedirs { '../../../../local/glfw-3.1.2.bin.WIN64/include' }
|
||||||
|
libdirs { '../../../../local/glfw-3.1.2.bin.WIN64/lib-vc2013' }
|
||||||
|
-- Path to GLEW
|
||||||
|
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" }
|
||||||
|
|
||||||
|
configuration { "macosx" }
|
||||||
|
includedirs { "/usr/local/include" }
|
||||||
|
buildoptions { "-Wno-deprecated-declarations" }
|
||||||
|
libdirs { "/usr/local/lib" }
|
||||||
|
links { "glfw3", "GLEW" }
|
||||||
|
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
|
||||||
|
|
||||||
|
configuration "Debug"
|
||||||
|
defines { "DEBUG" }
|
||||||
|
flags { "Symbols", "ExtraWarnings"}
|
||||||
|
|
||||||
|
configuration "Release"
|
||||||
|
defines { "NDEBUG" }
|
||||||
|
flags { "Optimize", "ExtraWarnings"}
|
||||||
|
|
||||||
6755
examples/viewer/stb_image.h
Normal file
6755
examples/viewer/stb_image.h
Normal file
File diff suppressed because it is too large
Load Diff
292
examples/viewer/trackball.cc
Normal file
292
examples/viewer/trackball.cc
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
* Permission to use, copy, modify, and distribute this software for
|
||||||
|
* any purpose and without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice appear in all copies and that both the copyright notice
|
||||||
|
* and this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of Silicon Graphics, Inc. not be used in advertising
|
||||||
|
* or publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission.
|
||||||
|
*
|
||||||
|
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
||||||
|
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||||||
|
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
||||||
|
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
||||||
|
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
||||||
|
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
||||||
|
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* US Government Users Restricted Rights
|
||||||
|
* Use, duplication, or disclosure by the Government is subject to
|
||||||
|
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||||
|
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
||||||
|
* clause at DFARS 252.227-7013 and/or in similar or successor
|
||||||
|
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
||||||
|
* Unpublished-- rights reserved under the copyright laws of the
|
||||||
|
* United States. Contractor/manufacturer is Silicon Graphics,
|
||||||
|
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
||||||
|
*
|
||||||
|
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Trackball code:
|
||||||
|
*
|
||||||
|
* Implementation of a virtual trackball.
|
||||||
|
* Implemented by Gavin Bell, lots of ideas from Thant Tessman and
|
||||||
|
* the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
|
||||||
|
*
|
||||||
|
* Vector manip code:
|
||||||
|
*
|
||||||
|
* Original code from:
|
||||||
|
* David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
|
||||||
|
*
|
||||||
|
* Much mucking with by:
|
||||||
|
* Gavin Bell
|
||||||
|
*/
|
||||||
|
#include <math.h>
|
||||||
|
#include "trackball.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This size should really be based on the distance from the center of
|
||||||
|
* rotation to the point on the object underneath the mouse. That
|
||||||
|
* point would then track the mouse as closely as possible. This is a
|
||||||
|
* simple example, though, so that is left as an Exercise for the
|
||||||
|
* Programmer.
|
||||||
|
*/
|
||||||
|
#define TRACKBALLSIZE (0.8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local function prototypes (not defined in trackball.h)
|
||||||
|
*/
|
||||||
|
static float tb_project_to_sphere(float, float, float);
|
||||||
|
static void normalize_quat(float[4]);
|
||||||
|
|
||||||
|
static void vzero(float *v) {
|
||||||
|
v[0] = 0.0;
|
||||||
|
v[1] = 0.0;
|
||||||
|
v[2] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vset(float *v, float x, float y, float z) {
|
||||||
|
v[0] = x;
|
||||||
|
v[1] = y;
|
||||||
|
v[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vsub(const float *src1, const float *src2, float *dst) {
|
||||||
|
dst[0] = src1[0] - src2[0];
|
||||||
|
dst[1] = src1[1] - src2[1];
|
||||||
|
dst[2] = src1[2] - src2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcopy(const float *v1, float *v2) {
|
||||||
|
register int i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
v2[i] = v1[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcross(const float *v1, const float *v2, float *cross) {
|
||||||
|
float temp[3];
|
||||||
|
|
||||||
|
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
|
||||||
|
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
|
||||||
|
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
|
||||||
|
vcopy(temp, cross);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float vlength(const float *v) {
|
||||||
|
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vscale(float *v, float div) {
|
||||||
|
v[0] *= div;
|
||||||
|
v[1] *= div;
|
||||||
|
v[2] *= div;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); }
|
||||||
|
|
||||||
|
static float vdot(const float *v1, const float *v2) {
|
||||||
|
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vadd(const float *src1, const float *src2, float *dst) {
|
||||||
|
dst[0] = src1[0] + src2[0];
|
||||||
|
dst[1] = src1[1] + src2[1];
|
||||||
|
dst[2] = src1[2] + src2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, simulate a track-ball. Project the points onto the virtual
|
||||||
|
* trackball, then figure out the axis of rotation, which is the cross
|
||||||
|
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
|
||||||
|
* Note: This is a deformed trackball-- is a trackball in the center,
|
||||||
|
* but is deformed into a hyperbolic sheet of rotation away from the
|
||||||
|
* center. This particular function was chosen after trying out
|
||||||
|
* several variations.
|
||||||
|
*
|
||||||
|
* It is assumed that the arguments to this routine are in the range
|
||||||
|
* (-1.0 ... 1.0)
|
||||||
|
*/
|
||||||
|
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) {
|
||||||
|
float a[3]; /* Axis of rotation */
|
||||||
|
float phi; /* how much to rotate about axis */
|
||||||
|
float p1[3], p2[3], d[3];
|
||||||
|
float t;
|
||||||
|
|
||||||
|
if (p1x == p2x && p1y == p2y) {
|
||||||
|
/* Zero rotation */
|
||||||
|
vzero(q);
|
||||||
|
q[3] = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, figure out z-coordinates for projection of P1 and P2 to
|
||||||
|
* deformed sphere
|
||||||
|
*/
|
||||||
|
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
|
||||||
|
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, we want the cross product of P1 and P2
|
||||||
|
*/
|
||||||
|
vcross(p2, p1, a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure out how much to rotate around that axis.
|
||||||
|
*/
|
||||||
|
vsub(p1, p2, d);
|
||||||
|
t = vlength(d) / (2.0 * TRACKBALLSIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid problems with out-of-control values...
|
||||||
|
*/
|
||||||
|
if (t > 1.0)
|
||||||
|
t = 1.0;
|
||||||
|
if (t < -1.0)
|
||||||
|
t = -1.0;
|
||||||
|
phi = 2.0 * asin(t);
|
||||||
|
|
||||||
|
axis_to_quat(a, phi, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an axis and angle, compute quaternion.
|
||||||
|
*/
|
||||||
|
void axis_to_quat(float a[3], float phi, float q[4]) {
|
||||||
|
vnormal(a);
|
||||||
|
vcopy(a, q);
|
||||||
|
vscale(q, sin(phi / 2.0));
|
||||||
|
q[3] = cos(phi / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
|
||||||
|
* if we are away from the center of the sphere.
|
||||||
|
*/
|
||||||
|
static float tb_project_to_sphere(float r, float x, float y) {
|
||||||
|
float d, t, z;
|
||||||
|
|
||||||
|
d = sqrt(x * x + y * y);
|
||||||
|
if (d < r * 0.70710678118654752440) { /* Inside sphere */
|
||||||
|
z = sqrt(r * r - d * d);
|
||||||
|
} else { /* On hyperbola */
|
||||||
|
t = r / 1.41421356237309504880;
|
||||||
|
z = t * t / d;
|
||||||
|
}
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given two rotations, e1 and e2, expressed as quaternion rotations,
|
||||||
|
* figure out the equivalent single rotation and stuff it into dest.
|
||||||
|
*
|
||||||
|
* This routine also normalizes the result every RENORMCOUNT times it is
|
||||||
|
* called, to keep error from creeping in.
|
||||||
|
*
|
||||||
|
* NOTE: This routine is written so that q1 or q2 may be the same
|
||||||
|
* as dest (or each other).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RENORMCOUNT 97
|
||||||
|
|
||||||
|
void add_quats(float q1[4], float q2[4], float dest[4]) {
|
||||||
|
static int count = 0;
|
||||||
|
float t1[4], t2[4], t3[4];
|
||||||
|
float tf[4];
|
||||||
|
|
||||||
|
vcopy(q1, t1);
|
||||||
|
vscale(t1, q2[3]);
|
||||||
|
|
||||||
|
vcopy(q2, t2);
|
||||||
|
vscale(t2, q1[3]);
|
||||||
|
|
||||||
|
vcross(q2, q1, t3);
|
||||||
|
vadd(t1, t2, tf);
|
||||||
|
vadd(t3, tf, tf);
|
||||||
|
tf[3] = q1[3] * q2[3] - vdot(q1, q2);
|
||||||
|
|
||||||
|
dest[0] = tf[0];
|
||||||
|
dest[1] = tf[1];
|
||||||
|
dest[2] = tf[2];
|
||||||
|
dest[3] = tf[3];
|
||||||
|
|
||||||
|
if (++count > RENORMCOUNT) {
|
||||||
|
count = 0;
|
||||||
|
normalize_quat(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0
|
||||||
|
* If they don't add up to 1.0, dividing by their magnitued will
|
||||||
|
* renormalize them.
|
||||||
|
*
|
||||||
|
* Note: See the following for more information on quaternions:
|
||||||
|
*
|
||||||
|
* - Shoemake, K., Animating rotation with quaternion curves, Computer
|
||||||
|
* Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
|
||||||
|
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
|
||||||
|
* graphics, The Visual Computer 5, 2-13, 1989.
|
||||||
|
*/
|
||||||
|
static void normalize_quat(float q[4]) {
|
||||||
|
int i;
|
||||||
|
float mag;
|
||||||
|
|
||||||
|
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
q[i] /= mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a rotation matrix, given a quaternion rotation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void build_rotmatrix(float m[4][4], const float q[4]) {
|
||||||
|
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
|
||||||
|
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
|
||||||
|
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
|
||||||
|
m[0][3] = 0.0;
|
||||||
|
|
||||||
|
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
|
||||||
|
m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
|
||||||
|
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
|
||||||
|
m[1][3] = 0.0;
|
||||||
|
|
||||||
|
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
|
||||||
|
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
|
||||||
|
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
|
||||||
|
m[2][3] = 0.0;
|
||||||
|
|
||||||
|
m[3][0] = 0.0;
|
||||||
|
m[3][1] = 0.0;
|
||||||
|
m[3][2] = 0.0;
|
||||||
|
m[3][3] = 1.0;
|
||||||
|
}
|
||||||
75
examples/viewer/trackball.h
Normal file
75
examples/viewer/trackball.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
* Permission to use, copy, modify, and distribute this software for
|
||||||
|
* any purpose and without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice appear in all copies and that both the copyright notice
|
||||||
|
* and this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of Silicon Graphics, Inc. not be used in advertising
|
||||||
|
* or publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission.
|
||||||
|
*
|
||||||
|
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
||||||
|
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||||||
|
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
||||||
|
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
||||||
|
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
||||||
|
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
||||||
|
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* US Government Users Restricted Rights
|
||||||
|
* Use, duplication, or disclosure by the Government is subject to
|
||||||
|
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||||
|
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
||||||
|
* clause at DFARS 252.227-7013 and/or in similar or successor
|
||||||
|
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
||||||
|
* Unpublished-- rights reserved under the copyright laws of the
|
||||||
|
* United States. Contractor/manufacturer is Silicon Graphics,
|
||||||
|
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
||||||
|
*
|
||||||
|
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* trackball.h
|
||||||
|
* A virtual trackball implementation
|
||||||
|
* Written by Gavin Bell for Silicon Graphics, November 1988.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass the x and y coordinates of the last and current positions of
|
||||||
|
* the mouse, scaled so they are from (-1.0 ... 1.0).
|
||||||
|
*
|
||||||
|
* The resulting rotation is returned as a quaternion rotation in the
|
||||||
|
* first paramater.
|
||||||
|
*/
|
||||||
|
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
|
||||||
|
|
||||||
|
void negate_quat(float *q, float *qn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given two quaternions, add them together to get a third quaternion.
|
||||||
|
* Adding quaternions to get a compound rotation is analagous to adding
|
||||||
|
* translations to get a compound translation. When incrementally
|
||||||
|
* adding rotations, the first argument here should be the new
|
||||||
|
* rotation, the second and third the total rotation (which will be
|
||||||
|
* over-written with the resulting new total rotation).
|
||||||
|
*/
|
||||||
|
void add_quats(float *q1, float *q2, float *dest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A useful function, builds a rotation matrix in Matrix based on
|
||||||
|
* given quaternion.
|
||||||
|
*/
|
||||||
|
void build_rotmatrix(float m[4][4], const float q[4]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function computes a quaternion based on an axis (defined by
|
||||||
|
* the given vector) and an angle about which to rotate. The angle is
|
||||||
|
* expressed in radians. The result is put into the third argument.
|
||||||
|
*/
|
||||||
|
void axis_to_quat(float a[3], float phi, float q[4]);
|
||||||
881
examples/viewer/viewer.cc
Normal file
881
examples/viewer/viewer.cc
Normal file
@@ -0,0 +1,881 @@
|
|||||||
|
//
|
||||||
|
// Simple .obj viewer(vertex only)
|
||||||
|
//
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/glu.h>
|
||||||
|
#else
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
|
#include "../../tiny_obj_loader.h"
|
||||||
|
|
||||||
|
#include "trackball.h"
|
||||||
|
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
#include <ctime>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class timerutil {
|
||||||
|
public:
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef DWORD time_t;
|
||||||
|
|
||||||
|
timerutil() { ::timeBeginPeriod(1); }
|
||||||
|
~timerutil() { ::timeEndPeriod(1); }
|
||||||
|
|
||||||
|
void start() { t_[0] = ::timeGetTime(); }
|
||||||
|
void end() { t_[1] = ::timeGetTime(); }
|
||||||
|
|
||||||
|
time_t sec() { return (time_t)((t_[1] - t_[0]) / 1000); }
|
||||||
|
time_t msec() { return (time_t)((t_[1] - t_[0])); }
|
||||||
|
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000); }
|
||||||
|
time_t current() { return ::timeGetTime(); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
typedef unsigned long int time_t;
|
||||||
|
|
||||||
|
void start() { gettimeofday(tv + 0, &tz); }
|
||||||
|
void end() { gettimeofday(tv + 1, &tz); }
|
||||||
|
|
||||||
|
time_t sec() { return (time_t)(tv[1].tv_sec - tv[0].tv_sec); }
|
||||||
|
time_t msec() {
|
||||||
|
return this->sec() * 1000 +
|
||||||
|
(time_t)((tv[1].tv_usec - tv[0].tv_usec) / 1000);
|
||||||
|
}
|
||||||
|
time_t usec() {
|
||||||
|
return this->sec() * 1000000 + (time_t)(tv[1].tv_usec - tv[0].tv_usec);
|
||||||
|
}
|
||||||
|
time_t current() {
|
||||||
|
struct timeval t;
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
return (time_t)(t.tv_sec * 1000 + t.tv_usec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // C timer
|
||||||
|
// using namespace std;
|
||||||
|
typedef clock_t time_t;
|
||||||
|
|
||||||
|
void start() { t_[0] = clock(); }
|
||||||
|
void end() { t_[1] = clock(); }
|
||||||
|
|
||||||
|
time_t sec() { return (time_t)((t_[1] - t_[0]) / CLOCKS_PER_SEC); }
|
||||||
|
time_t msec() { return (time_t)((t_[1] - t_[0]) * 1000 / CLOCKS_PER_SEC); }
|
||||||
|
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000000 / CLOCKS_PER_SEC); }
|
||||||
|
time_t current() { return (time_t)clock(); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD t_[2];
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
struct timeval tv[2];
|
||||||
|
struct timezone tz;
|
||||||
|
#else
|
||||||
|
time_t t_[2];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint vb_id; // vertex buffer id
|
||||||
|
int numTriangles;
|
||||||
|
size_t material_id;
|
||||||
|
} DrawObject;
|
||||||
|
|
||||||
|
std::vector<DrawObject> gDrawObjects;
|
||||||
|
|
||||||
|
int width = 768;
|
||||||
|
int height = 768;
|
||||||
|
|
||||||
|
double prevMouseX, prevMouseY;
|
||||||
|
bool mouseLeftPressed;
|
||||||
|
bool mouseMiddlePressed;
|
||||||
|
bool mouseRightPressed;
|
||||||
|
float curr_quat[4];
|
||||||
|
float prev_quat[4];
|
||||||
|
float eye[3], lookat[3], up[3];
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
|
|
||||||
|
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);
|
||||||
|
exit(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
v10[2] = v1[2] - v0[2];
|
||||||
|
|
||||||
|
float v20[3];
|
||||||
|
v20[0] = v2[0] - v0[0];
|
||||||
|
v20[1] = v2[1] - v0[1];
|
||||||
|
v20[2] = v2[2] - v0[2];
|
||||||
|
|
||||||
|
N[0] = v20[1] * v10[2] - v20[2] * v10[1];
|
||||||
|
N[1] = v20[2] * v10[0] - v20[0] * v10[2];
|
||||||
|
N[2] = v20[0] * v10[1] - v20[1] * v10[0];
|
||||||
|
|
||||||
|
float len2 = N[0] * N[0] + N[1] * N[1] + N[2] * N[2];
|
||||||
|
if (len2 > 0.0f) {
|
||||||
|
float len = sqrtf(len2);
|
||||||
|
|
||||||
|
N[0] /= len;
|
||||||
|
N[1] /= len;
|
||||||
|
N[2] /= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace // Local utility functions
|
||||||
|
{
|
||||||
|
struct vec3 {
|
||||||
|
float v[3];
|
||||||
|
vec3() {
|
||||||
|
v[0] = 0.0f;
|
||||||
|
v[1] = 0.0f;
|
||||||
|
v[2] = 0.0f;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void normalizeVector(vec3 &v) {
|
||||||
|
float len2 = v.v[0] * v.v[0] + v.v[1] * v.v[1] + v.v[2] * v.v[2];
|
||||||
|
if (len2 > 0.0f) {
|
||||||
|
float len = sqrtf(len2);
|
||||||
|
|
||||||
|
v.v[0] /= len;
|
||||||
|
v.v[1] /= len;
|
||||||
|
v.v[2] /= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if `mesh_t` contains smoothing group id.
|
||||||
|
bool hasSmoothingGroup(const tinyobj::shape_t& shape)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < shape.mesh.smoothing_group_ids.size(); i++) {
|
||||||
|
if (shape.mesh.smoothing_group_ids[i] > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void computeSmoothingNormals(const tinyobj::attrib_t& attrib, const tinyobj::shape_t& shape,
|
||||||
|
std::map<int, vec3>& smoothVertexNormals) {
|
||||||
|
smoothVertexNormals.clear();
|
||||||
|
std::map<int, vec3>::iterator iter;
|
||||||
|
|
||||||
|
for (size_t f = 0; f < shape.mesh.indices.size() / 3; f++) {
|
||||||
|
// Get the three indexes of the face (all faces are triangular)
|
||||||
|
tinyobj::index_t idx0 = shape.mesh.indices[3 * f + 0];
|
||||||
|
tinyobj::index_t idx1 = shape.mesh.indices[3 * f + 1];
|
||||||
|
tinyobj::index_t idx2 = shape.mesh.indices[3 * f + 2];
|
||||||
|
|
||||||
|
// Get the three vertex indexes and coordinates
|
||||||
|
int vi[3]; // indexes
|
||||||
|
float v[3][3]; // coordinates
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
vi[0] = idx0.vertex_index;
|
||||||
|
vi[1] = idx1.vertex_index;
|
||||||
|
vi[2] = idx2.vertex_index;
|
||||||
|
assert(vi[0] >= 0);
|
||||||
|
assert(vi[1] >= 0);
|
||||||
|
assert(vi[2] >= 0);
|
||||||
|
|
||||||
|
v[0][k] = attrib.vertices[3 * vi[0] + k];
|
||||||
|
v[1][k] = attrib.vertices[3 * vi[1] + k];
|
||||||
|
v[2][k] = attrib.vertices[3 * vi[2] + k];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the normal of the face
|
||||||
|
float normal[3];
|
||||||
|
CalcNormal(normal, v[0], v[1], v[2]);
|
||||||
|
|
||||||
|
// Add the normal to the three vertexes
|
||||||
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
|
iter = smoothVertexNormals.find(vi[i]);
|
||||||
|
if (iter != smoothVertexNormals.end()) {
|
||||||
|
// add
|
||||||
|
iter->second.v[0] += normal[0];
|
||||||
|
iter->second.v[1] += normal[1];
|
||||||
|
iter->second.v[2] += normal[2];
|
||||||
|
} else {
|
||||||
|
smoothVertexNormals[vi[i]].v[0] = normal[0];
|
||||||
|
smoothVertexNormals[vi[i]].v[1] = normal[1];
|
||||||
|
smoothVertexNormals[vi[i]].v[2] = normal[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // f
|
||||||
|
|
||||||
|
// Normalize the normals, that is, make them unit vectors
|
||||||
|
for (iter = smoothVertexNormals.begin(); iter != smoothVertexNormals.end();
|
||||||
|
iter++) {
|
||||||
|
normalizeVector(iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // computeSmoothingNormals
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
timerutil tm;
|
||||||
|
|
||||||
|
tm.start();
|
||||||
|
|
||||||
|
std::string base_dir = GetBaseDir(filename);
|
||||||
|
if (base_dir.empty()) {
|
||||||
|
base_dir = ".";
|
||||||
|
}
|
||||||
|
#ifdef _WIN32
|
||||||
|
base_dir += "\\";
|
||||||
|
#else
|
||||||
|
base_dir += "/";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string warn;
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename,
|
||||||
|
base_dir.c_str());
|
||||||
|
if (!warn.empty()) {
|
||||||
|
std::cout << "WARN: " << warn << std::endl;
|
||||||
|
}
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
tm.end();
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
std::cerr << "Failed to load " << filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Parsing time: %d [ms]\n", (int)tm.msec());
|
||||||
|
|
||||||
|
printf("# of vertices = %d\n", (int)(attrib.vertices.size()) / 3);
|
||||||
|
printf("# of normals = %d\n", (int)(attrib.normals.size()) / 3);
|
||||||
|
printf("# of texcoords = %d\n", (int)(attrib.texcoords.size()) / 2);
|
||||||
|
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());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < materials.size(); i++) {
|
||||||
|
printf("material[%d].diffuse_texname = %s\n", int(i),
|
||||||
|
materials[i].diffuse_texname.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
std::cout << "Loaded texture: " << texture_filename << ", w = " << w
|
||||||
|
<< ", h = " << h << ", comp = " << comp << std::endl;
|
||||||
|
|
||||||
|
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_LINEAR);
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
assert(0); // TODO
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
|
||||||
|
{
|
||||||
|
for (size_t s = 0; s < shapes.size(); s++) {
|
||||||
|
DrawObject o;
|
||||||
|
std::vector<float> buffer; // pos(3float), normal(3float), color(3float)
|
||||||
|
|
||||||
|
// Check for smoothing group and compute smoothing normals
|
||||||
|
std::map<int, vec3> smoothVertexNormals;
|
||||||
|
if (hasSmoothingGroup(shapes[s]) > 0) {
|
||||||
|
std::cout << "Compute smoothingNormal for shape [" << s << "]" << std::endl;
|
||||||
|
computeSmoothingNormals(attrib, shapes[s], smoothVertexNormals);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t f = 0; f < shapes[s].mesh.indices.size() / 3; f++) {
|
||||||
|
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) {
|
||||||
|
if ((idx0.texcoord_index < 0) || (idx1.texcoord_index < 0) ||
|
||||||
|
(idx2.texcoord_index < 0)) {
|
||||||
|
// face does not contain valid uv index.
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
assert(attrib.texcoords.size() >
|
||||||
|
size_t(2 * idx0.texcoord_index + 1));
|
||||||
|
assert(attrib.texcoords.size() >
|
||||||
|
size_t(2 * idx1.texcoord_index + 1));
|
||||||
|
assert(attrib.texcoords.size() >
|
||||||
|
size_t(2 * idx2.texcoord_index + 1));
|
||||||
|
|
||||||
|
// Flip Y coord.
|
||||||
|
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++) {
|
||||||
|
int f0 = idx0.vertex_index;
|
||||||
|
int f1 = idx1.vertex_index;
|
||||||
|
int f2 = idx2.vertex_index;
|
||||||
|
assert(f0 >= 0);
|
||||||
|
assert(f1 >= 0);
|
||||||
|
assert(f2 >= 0);
|
||||||
|
|
||||||
|
v[0][k] = attrib.vertices[3 * f0 + k];
|
||||||
|
v[1][k] = attrib.vertices[3 * f1 + k];
|
||||||
|
v[2][k] = attrib.vertices[3 * f2 + k];
|
||||||
|
bmin[k] = std::min(v[0][k], bmin[k]);
|
||||||
|
bmin[k] = std::min(v[1][k], bmin[k]);
|
||||||
|
bmin[k] = std::min(v[2][k], bmin[k]);
|
||||||
|
bmax[k] = std::max(v[0][k], bmax[k]);
|
||||||
|
bmax[k] = std::max(v[1][k], bmax[k]);
|
||||||
|
bmax[k] = std::max(v[2][k], bmax[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float n[3][3];
|
||||||
|
{
|
||||||
|
bool invalid_normal_index = false;
|
||||||
|
if (attrib.normals.size() > 0) {
|
||||||
|
int nf0 = idx0.normal_index;
|
||||||
|
int nf1 = idx1.normal_index;
|
||||||
|
int nf2 = idx2.normal_index;
|
||||||
|
|
||||||
|
if ((nf0 < 0) || (nf1 < 0) || (nf2 < 0)) {
|
||||||
|
// normal index is missing from this face.
|
||||||
|
invalid_normal_index = true;
|
||||||
|
} else {
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
assert(size_t(3 * nf0 + k) < attrib.normals.size());
|
||||||
|
assert(size_t(3 * nf1 + k) < attrib.normals.size());
|
||||||
|
assert(size_t(3 * nf2 + k) < attrib.normals.size());
|
||||||
|
n[0][k] = attrib.normals[3 * nf0 + k];
|
||||||
|
n[1][k] = attrib.normals[3 * nf1 + k];
|
||||||
|
n[2][k] = attrib.normals[3 * nf2 + k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
invalid_normal_index = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalid_normal_index && !smoothVertexNormals.empty()) {
|
||||||
|
// Use smoothing normals
|
||||||
|
int f0 = idx0.vertex_index;
|
||||||
|
int f1 = idx1.vertex_index;
|
||||||
|
int f2 = idx2.vertex_index;
|
||||||
|
|
||||||
|
if (f0 >= 0 && f1 >= 0 && f2 >= 0) {
|
||||||
|
n[0][0] = smoothVertexNormals[f0].v[0];
|
||||||
|
n[0][1] = smoothVertexNormals[f0].v[1];
|
||||||
|
n[0][2] = smoothVertexNormals[f0].v[2];
|
||||||
|
|
||||||
|
n[1][0] = smoothVertexNormals[f1].v[0];
|
||||||
|
n[1][1] = smoothVertexNormals[f1].v[1];
|
||||||
|
n[1][2] = smoothVertexNormals[f1].v[2];
|
||||||
|
|
||||||
|
n[2][0] = smoothVertexNormals[f2].v[0];
|
||||||
|
n[2][1] = smoothVertexNormals[f2].v[1];
|
||||||
|
n[2][2] = smoothVertexNormals[f2].v[2];
|
||||||
|
|
||||||
|
invalid_normal_index = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalid_normal_index) {
|
||||||
|
// compute geometric normal
|
||||||
|
CalcNormal(n[0], v[0], v[1], v[2]);
|
||||||
|
n[1][0] = n[0][0];
|
||||||
|
n[1][1] = n[0][1];
|
||||||
|
n[1][2] = n[0][2];
|
||||||
|
n[2][0] = n[0][0];
|
||||||
|
n[2][1] = n[0][1];
|
||||||
|
n[2][2] = n[0][2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
buffer.push_back(v[k][0]);
|
||||||
|
buffer.push_back(v[k][1]);
|
||||||
|
buffer.push_back(v[k][2]);
|
||||||
|
buffer.push_back(n[k][0]);
|
||||||
|
buffer.push_back(n[k][1]);
|
||||||
|
buffer.push_back(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);
|
||||||
|
|
||||||
|
c[0] /= len;
|
||||||
|
c[1] /= len;
|
||||||
|
c[2] /= len;
|
||||||
|
}
|
||||||
|
buffer.push_back(c[0] * 0.5 + 0.5);
|
||||||
|
buffer.push_back(c[1] * 0.5 + 0.5);
|
||||||
|
buffer.push_back(c[2] * 0.5 + 0.5);
|
||||||
|
|
||||||
|
buffer.push_back(tc[k][0]);
|
||||||
|
buffer.push_back(tc[k][1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
o.vb_id = 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) {
|
||||||
|
o.material_id = shapes[s].mesh.material_ids[0]; // use the material ID
|
||||||
|
// of the first face.
|
||||||
|
} else {
|
||||||
|
o.material_id = materials.size() - 1; // = ID for default material.
|
||||||
|
}
|
||||||
|
printf("shape[%d] material_id %d\n", int(s), int(o.material_id));
|
||||||
|
|
||||||
|
if (buffer.size() > 0) {
|
||||||
|
glGenBuffers(1, &o.vb_id);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, buffer.size() * sizeof(float),
|
||||||
|
&buffer.at(0), GL_STATIC_DRAW);
|
||||||
|
o.numTriangles = buffer.size() / (3 + 3 + 3 + 2) /
|
||||||
|
3; // 3:vtx, 3:normal, 3:col, 2:texcoord
|
||||||
|
|
||||||
|
printf("shape[%d] # of triangles = %d\n", static_cast<int>(s),
|
||||||
|
o.numTriangles);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawObjects->push_back(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("bmin = %f, %f, %f\n", bmin[0], bmin[1], bmin[2]);
|
||||||
|
printf("bmax = %f, %f, %f\n", bmax[0], bmax[1], bmax[2]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reshapeFunc(GLFWwindow* window, int w, int h) {
|
||||||
|
int fb_w, fb_h;
|
||||||
|
// Get actual framebuffer size.
|
||||||
|
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
||||||
|
|
||||||
|
glViewport(0, 0, fb_w, fb_h);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective(45.0, (float)w / (float)h, 0.01f, 100.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
|
||||||
|
int mods) {
|
||||||
|
(void)window;
|
||||||
|
(void)scancode;
|
||||||
|
(void)mods;
|
||||||
|
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
|
||||||
|
// Move camera
|
||||||
|
float mv_x = 0, mv_y = 0, mv_z = 0;
|
||||||
|
if (key == GLFW_KEY_K)
|
||||||
|
mv_x += 1;
|
||||||
|
else if (key == GLFW_KEY_J)
|
||||||
|
mv_x += -1;
|
||||||
|
else if (key == GLFW_KEY_L)
|
||||||
|
mv_y += 1;
|
||||||
|
else if (key == GLFW_KEY_H)
|
||||||
|
mv_y += -1;
|
||||||
|
else if (key == GLFW_KEY_P)
|
||||||
|
mv_z += 1;
|
||||||
|
else if (key == GLFW_KEY_N)
|
||||||
|
mv_z += -1;
|
||||||
|
// camera.move(mv_x * 0.05, mv_y * 0.05, mv_z * 0.05);
|
||||||
|
// Close window
|
||||||
|
if (key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE)
|
||||||
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
|
||||||
|
// init_frame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clickFunc(GLFWwindow* window, int button, int action, int mods) {
|
||||||
|
(void)window;
|
||||||
|
(void)mods;
|
||||||
|
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
mouseLeftPressed = true;
|
||||||
|
trackball(prev_quat, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
mouseLeftPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
mouseRightPressed = true;
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
mouseRightPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
|
||||||
|
if (action == GLFW_PRESS) {
|
||||||
|
mouseMiddlePressed = true;
|
||||||
|
} else if (action == GLFW_RELEASE) {
|
||||||
|
mouseMiddlePressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
|
||||||
|
(void)window;
|
||||||
|
float rotScale = 1.0f;
|
||||||
|
float transScale = 2.0f;
|
||||||
|
|
||||||
|
if (mouseLeftPressed) {
|
||||||
|
trackball(prev_quat, rotScale * (2.0f * prevMouseX - width) / (float)width,
|
||||||
|
rotScale * (height - 2.0f * prevMouseY) / (float)height,
|
||||||
|
rotScale * (2.0f * mouse_x - width) / (float)width,
|
||||||
|
rotScale * (height - 2.0f * mouse_y) / (float)height);
|
||||||
|
|
||||||
|
add_quats(prev_quat, curr_quat, curr_quat);
|
||||||
|
} else if (mouseMiddlePressed) {
|
||||||
|
eye[0] -= transScale * (mouse_x - prevMouseX) / (float)width;
|
||||||
|
lookat[0] -= transScale * (mouse_x - prevMouseX) / (float)width;
|
||||||
|
eye[1] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
} else if (mouseRightPressed) {
|
||||||
|
eye[2] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
lookat[2] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mouse point
|
||||||
|
prevMouseX = mouse_x;
|
||||||
|
prevMouseY = mouse_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
GLsizei stride = (3 + 3 + 3 + 2) * sizeof(float);
|
||||||
|
for (size_t i = 0; i < drawObjects.size(); i++) {
|
||||||
|
DrawObject o = drawObjects[i];
|
||||||
|
if (o.vb_id < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
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
|
||||||
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glPolygonMode(GL_FRONT, GL_LINE);
|
||||||
|
glPolygonMode(GL_BACK, GL_LINE);
|
||||||
|
|
||||||
|
glColor3f(0.0f, 0.0f, 0.4f);
|
||||||
|
for (size_t i = 0; i < drawObjects.size(); i++) {
|
||||||
|
DrawObject o = drawObjects[i];
|
||||||
|
if (o.vb_id < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id);
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glDisableClientState(GL_COLOR_ARRAY);
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Init() {
|
||||||
|
trackball(curr_quat, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
eye[0] = 0.0f;
|
||||||
|
eye[1] = 0.0f;
|
||||||
|
eye[2] = 3.0f;
|
||||||
|
|
||||||
|
lookat[0] = 0.0f;
|
||||||
|
lookat[1] = 0.0f;
|
||||||
|
lookat[2] = 0.0f;
|
||||||
|
|
||||||
|
up[0] = 0.0f;
|
||||||
|
up[1] = 1.0f;
|
||||||
|
up[2] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
std::cout << "Needs input.obj\n" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init();
|
||||||
|
|
||||||
|
if (!glfwInit()) {
|
||||||
|
std::cerr << "Failed to initialize GLFW." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
window = glfwCreateWindow(width, height, "Obj viewer", NULL, NULL);
|
||||||
|
if (window == NULL) {
|
||||||
|
std::cerr << "Failed to open GLFW window. " << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
// Callback
|
||||||
|
glfwSetWindowSizeCallback(window, reshapeFunc);
|
||||||
|
glfwSetKeyCallback(window, keyboardFunc);
|
||||||
|
glfwSetMouseButtonCallback(window, clickFunc);
|
||||||
|
glfwSetCursorPosCallback(window, motionFunc);
|
||||||
|
|
||||||
|
glewExperimental = true;
|
||||||
|
if (glewInit() != GLEW_OK) {
|
||||||
|
std::cerr << "Failed to initialize GLEW." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reshapeFunc(window, width, height);
|
||||||
|
|
||||||
|
float bmin[3], bmax[3];
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
std::map<std::string, GLuint> textures;
|
||||||
|
if (false == LoadObjAndConvert(bmin, bmax, &gDrawObjects, materials, textures,
|
||||||
|
argv[1])) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float maxExtent = 0.5f * (bmax[0] - bmin[0]);
|
||||||
|
if (maxExtent < 0.5f * (bmax[1] - bmin[1])) {
|
||||||
|
maxExtent = 0.5f * (bmax[1] - bmin[1]);
|
||||||
|
}
|
||||||
|
if (maxExtent < 0.5f * (bmax[2] - bmin[2])) {
|
||||||
|
maxExtent = 0.5f * (bmax[2] - bmin[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (glfwWindowShouldClose(window) == GL_FALSE) {
|
||||||
|
glfwPollEvents();
|
||||||
|
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
// camera & rotate
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
GLfloat mat[4][4];
|
||||||
|
gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0],
|
||||||
|
up[1], up[2]);
|
||||||
|
build_rotmatrix(mat, curr_quat);
|
||||||
|
glMultMatrixf(&mat[0][0]);
|
||||||
|
|
||||||
|
// Fit to -1, 1
|
||||||
|
glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent);
|
||||||
|
|
||||||
|
// Centerize object.
|
||||||
|
glTranslatef(-0.5 * (bmax[0] + bmin[0]), -0.5 * (bmax[1] + bmin[1]),
|
||||||
|
-0.5 * (bmax[2] + bmin[2]));
|
||||||
|
|
||||||
|
Draw(gDrawObjects, materials, textures);
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
2
examples/voxelize/Makefile
Normal file
2
examples/voxelize/Makefile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
all:
|
||||||
|
g++ -o voxelizer main.cc
|
||||||
5
examples/voxelize/README.md
Normal file
5
examples/voxelize/README.md
Normal 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.
|
||||||
75
examples/voxelize/main.cc
Normal file
75
examples/voxelize/main.cc
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
#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 warn;
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &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;
|
||||||
|
}
|
||||||
|
|
||||||
764
examples/voxelize/voxelizer.h
Normal file
764
examples/voxelize/voxelizer.h
Normal 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
|
||||||
26
experimental/README.md
Normal file
26
experimental/README.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# Experimental code for .obj loader.
|
||||||
|
|
||||||
|
* Multi-threaded optimized parser : tinyobj_loader_opt.h
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* C++-11 compiler
|
||||||
|
|
||||||
|
## How to build
|
||||||
|
|
||||||
|
```
|
||||||
|
$ premak5 gmake
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compile options
|
||||||
|
|
||||||
|
* zstd compressed .obj support. `--with-zstd` premake option.
|
||||||
|
* gzip compressed .obj support. `--with-zlib` premake option.
|
||||||
|
|
||||||
|
## Notes on AMD GPU + Linux
|
||||||
|
|
||||||
|
You may need to link with libdrm(`-ldrm`).
|
||||||
|
|
||||||
|
## Licenses
|
||||||
|
|
||||||
|
* lfpAlloc : MIT license.
|
||||||
89
experimental/lfpAlloc/Allocator.hpp
Normal file
89
experimental/lfpAlloc/Allocator.hpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#ifndef LF_POOL_ALLOCATOR
|
||||||
|
#define LF_POOL_ALLOCATOR
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <lfpAlloc/PoolDispatcher.hpp>
|
||||||
|
|
||||||
|
namespace lfpAlloc {
|
||||||
|
template <typename T, std::size_t NumPools = 70>
|
||||||
|
class lfpAllocator {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = T const&;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
struct rebind {
|
||||||
|
typedef lfpAllocator<U, NumPools> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
lfpAllocator() {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
lfpAllocator(lfpAllocator<U, NumPools>&&) noexcept {}
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
lfpAllocator(const lfpAllocator<U, NumPools>&) noexcept {}
|
||||||
|
|
||||||
|
T* allocate(std::size_t count) {
|
||||||
|
if (sizeof(T) * count <=
|
||||||
|
alignof(std::max_align_t) * NumPools - sizeof(void*)) {
|
||||||
|
return reinterpret_cast<T*>(
|
||||||
|
dispatcher_.allocate(sizeof(T) * count));
|
||||||
|
} else {
|
||||||
|
return new T[count];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T* p, std::size_t count) noexcept {
|
||||||
|
if (sizeof(T) * count <=
|
||||||
|
alignof(std::max_align_t) * NumPools - sizeof(void*)) {
|
||||||
|
dispatcher_.deallocate(p, sizeof(T) * count);
|
||||||
|
} else {
|
||||||
|
delete[] p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should not be required, but allocator_traits is not complete in
|
||||||
|
// gcc 4.9.1
|
||||||
|
template <typename U>
|
||||||
|
void destroy(U* p) {
|
||||||
|
p->~U();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename U, typename... Args>
|
||||||
|
void construct(U* p, Args&&... args) {
|
||||||
|
new (p) U(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Ty, typename U, std::size_t N, std::size_t M>
|
||||||
|
friend bool operator==(const lfpAllocator<Ty, N>&,
|
||||||
|
const lfpAllocator<U, M>&) noexcept;
|
||||||
|
|
||||||
|
template <typename U, std::size_t M>
|
||||||
|
friend class lfpAllocator;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PoolDispatcher<NumPools> dispatcher_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, std::size_t N>
|
||||||
|
PoolDispatcher<N> lfpAllocator<T, N>::dispatcher_;
|
||||||
|
|
||||||
|
template <typename T, typename U, std::size_t N, std::size_t M>
|
||||||
|
inline bool operator==(const lfpAllocator<T, N>&,
|
||||||
|
const lfpAllocator<U, M>&) noexcept {
|
||||||
|
return N == M;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename U, std::size_t N, std::size_t M>
|
||||||
|
inline bool operator!=(const lfpAllocator<T, N>& left,
|
||||||
|
const lfpAllocator<U, M>& right) noexcept {
|
||||||
|
return !(left == right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
116
experimental/lfpAlloc/ChunkList.hpp
Normal file
116
experimental/lfpAlloc/ChunkList.hpp
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#ifndef LF_POOL_ALLOC_CHUNK_LIST
|
||||||
|
#define LF_POOL_ALLOC_CHUNK_LIST
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <atomic>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
#ifndef LFP_ALLOW_BLOCKING
|
||||||
|
static_assert(ATOMIC_POINTER_LOCK_FREE == 2,
|
||||||
|
"Atomic pointer is not lock-free.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace lfpAlloc {
|
||||||
|
|
||||||
|
template <std::size_t Size>
|
||||||
|
struct Cell {
|
||||||
|
uint8_t val_[Size];
|
||||||
|
Cell* next_ = this + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// For small types (less than the size of void*), no additional
|
||||||
|
// space is needed, so union val_ with next_ to avoid overhead.
|
||||||
|
template <>
|
||||||
|
struct Cell<0> {
|
||||||
|
Cell() : next_{this + 1} {}
|
||||||
|
union {
|
||||||
|
uint8_t val_[sizeof(Cell*)];
|
||||||
|
Cell* next_;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t Size, std::size_t AllocationsPerChunk>
|
||||||
|
struct Chunk {
|
||||||
|
Chunk() noexcept {
|
||||||
|
auto& last = memBlock_[AllocationsPerChunk - 1];
|
||||||
|
last.next_ = nullptr;
|
||||||
|
}
|
||||||
|
Cell<Size> memBlock_[AllocationsPerChunk];
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Node {
|
||||||
|
Node() : val_(), next_(nullptr) {}
|
||||||
|
Node(const T& val) : val_(val), next_(nullptr) {}
|
||||||
|
T val_;
|
||||||
|
std::atomic<Node<T>*> next_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t Size, std::size_t AllocationsPerChunk>
|
||||||
|
class ChunkList {
|
||||||
|
static constexpr auto CellSize =
|
||||||
|
(Size > sizeof(void*)) ? Size - sizeof(void*) : 0;
|
||||||
|
using Chunk_t = Chunk<CellSize, AllocationsPerChunk>;
|
||||||
|
using Cell_t = Cell<CellSize>;
|
||||||
|
|
||||||
|
using ChunkNode = Node<Chunk_t>;
|
||||||
|
using CellNode = Node<Cell_t*>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static ChunkList& getInstance() {
|
||||||
|
static ChunkList c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Cell_t* allocateChain() {
|
||||||
|
CellNode* recentHead = head_.load();
|
||||||
|
CellNode* currentNext = nullptr;
|
||||||
|
do {
|
||||||
|
// If there are no available chains, allocate a new chunk
|
||||||
|
if (!recentHead) {
|
||||||
|
ChunkNode* currentHandle;
|
||||||
|
|
||||||
|
// Make a new node
|
||||||
|
auto newChunk = new ChunkNode();
|
||||||
|
|
||||||
|
// Add the chunk to the chain
|
||||||
|
do {
|
||||||
|
currentHandle = handle_.load();
|
||||||
|
newChunk->next_ = currentHandle;
|
||||||
|
} while (
|
||||||
|
!handle_.compare_exchange_weak(currentHandle, newChunk));
|
||||||
|
return &newChunk->val_.memBlock_[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
currentNext = recentHead->next_;
|
||||||
|
} while (!head_.compare_exchange_weak(recentHead, currentNext));
|
||||||
|
|
||||||
|
auto retnValue = recentHead->val_;
|
||||||
|
delete recentHead;
|
||||||
|
return retnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocateChain(Cell_t* newCell) {
|
||||||
|
if (!newCell) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CellNode* currentHead = head_.load();
|
||||||
|
|
||||||
|
// Construct a new node to be added to the linked list
|
||||||
|
CellNode* newHead = new CellNode(newCell);
|
||||||
|
|
||||||
|
// Add the chain to the linked list
|
||||||
|
do {
|
||||||
|
newHead->next_.store(currentHead, std::memory_order_release);
|
||||||
|
} while (!head_.compare_exchange_weak(currentHead, newHead));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ChunkList() : handle_(nullptr), head_(nullptr) {}
|
||||||
|
|
||||||
|
std::atomic<ChunkNode*> handle_;
|
||||||
|
std::atomic<CellNode*> head_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
21
experimental/lfpAlloc/LICENSE
Normal file
21
experimental/lfpAlloc/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Adam Schwalm
|
||||||
|
|
||||||
|
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.
|
||||||
48
experimental/lfpAlloc/Pool.hpp
Normal file
48
experimental/lfpAlloc/Pool.hpp
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef LF_POOL_ALLOC_POOL
|
||||||
|
#define LF_POOL_ALLOC_POOL
|
||||||
|
|
||||||
|
#include <lfpAlloc/Utils.hpp>
|
||||||
|
#include <lfpAlloc/ChunkList.hpp>
|
||||||
|
|
||||||
|
namespace lfpAlloc {
|
||||||
|
template <std::size_t Size, std::size_t AllocationsPerChunk>
|
||||||
|
class Pool {
|
||||||
|
using ChunkList_t = ChunkList<Size, AllocationsPerChunk>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto CellSize =
|
||||||
|
(Size > sizeof(void*)) ? Size - sizeof(void*) : 0;
|
||||||
|
using Cell_t = Cell<CellSize>;
|
||||||
|
|
||||||
|
Pool() : head_(nullptr) {}
|
||||||
|
|
||||||
|
~Pool() { ChunkList_t::getInstance().deallocateChain(head_); }
|
||||||
|
|
||||||
|
void* allocate() {
|
||||||
|
// Head loaded from head_
|
||||||
|
Cell_t* currentHead = head_;
|
||||||
|
Cell_t* next;
|
||||||
|
|
||||||
|
// Out of cells to allocate
|
||||||
|
if (!currentHead) {
|
||||||
|
currentHead = ChunkList_t::getInstance().allocateChain();
|
||||||
|
}
|
||||||
|
|
||||||
|
next = currentHead->next_;
|
||||||
|
head_ = next;
|
||||||
|
return ¤tHead->val_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void* p) noexcept {
|
||||||
|
auto newHead = reinterpret_cast<Cell_t*>(p);
|
||||||
|
Cell_t* currentHead = head_;
|
||||||
|
newHead->next_ = currentHead;
|
||||||
|
head_ = newHead;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cell_t* head_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
79
experimental/lfpAlloc/PoolDispatcher.hpp
Normal file
79
experimental/lfpAlloc/PoolDispatcher.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#ifndef LF_POOL_DISPATCHER
|
||||||
|
#define LF_POOL_DISPATCHER
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <lfpAlloc/Pool.hpp>
|
||||||
|
|
||||||
|
#ifndef LFP_ALLOCATIONS_PER_CHUNK
|
||||||
|
#define LFP_ALLOCATIONS_PER_CHUNK 64 * 100
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace lfpAlloc {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <std::size_t Num, uint16_t... Ts>
|
||||||
|
struct Pools : Pools<Num - 1, alignof(std::max_align_t) * Num, Ts...> {};
|
||||||
|
|
||||||
|
template <uint16_t... Size>
|
||||||
|
struct Pools<0, Size...> {
|
||||||
|
using type = std::tuple<Pool<Size, LFP_ALLOCATIONS_PER_CHUNK>...>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t NumPools>
|
||||||
|
class PoolDispatcher {
|
||||||
|
public:
|
||||||
|
void* allocate(std::size_t size) { return dispatchAllocate<0>(size); }
|
||||||
|
|
||||||
|
void deallocate(void* p, std::size_t size) noexcept {
|
||||||
|
dispatchDeallocate<0>(p, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
thread_local static typename detail::Pools<NumPools>::type pools_;
|
||||||
|
static_assert(NumPools > 0, "Invalid number of pools");
|
||||||
|
|
||||||
|
template <std::size_t Index>
|
||||||
|
typename std::enable_if <
|
||||||
|
Index<NumPools, void*>::type
|
||||||
|
dispatchAllocate(std::size_t const& requestSize) {
|
||||||
|
if (requestSize <= std::get<Index>(pools_).CellSize) {
|
||||||
|
return std::get<Index>(pools_).allocate();
|
||||||
|
} else {
|
||||||
|
return dispatchAllocate<Index + 1>(requestSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t Index>
|
||||||
|
typename std::enable_if<!(Index < NumPools), void*>::type
|
||||||
|
dispatchAllocate(std::size_t const&) {
|
||||||
|
assert(false && "Invalid allocation size.");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t Index>
|
||||||
|
typename std::enable_if <
|
||||||
|
Index<NumPools>::type
|
||||||
|
dispatchDeallocate(void* p, std::size_t const& requestSize) noexcept {
|
||||||
|
if (requestSize <= std::get<Index>(pools_).CellSize) {
|
||||||
|
std::get<Index>(pools_).deallocate(p);
|
||||||
|
} else {
|
||||||
|
dispatchDeallocate<Index + 1>(p, requestSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <std::size_t Index>
|
||||||
|
typename std::enable_if<!(Index < NumPools)>::type
|
||||||
|
dispatchDeallocate(void*, std::size_t const&) noexcept {
|
||||||
|
assert(false && "Invalid deallocation size.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t NumPools>
|
||||||
|
thread_local typename detail::Pools<NumPools>::type
|
||||||
|
PoolDispatcher<NumPools>::pools_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
20
experimental/lfpAlloc/Utils.hpp
Normal file
20
experimental/lfpAlloc/Utils.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace lfpAlloc {
|
||||||
|
namespace detail {
|
||||||
|
template <std::size_t Val, std::size_t base = 2>
|
||||||
|
struct Log {
|
||||||
|
enum { value = 1 + Log<Val / base, base>::value };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t base>
|
||||||
|
struct Log<1, base> {
|
||||||
|
enum { value = 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
template <std::size_t base>
|
||||||
|
struct Log<0, base> {
|
||||||
|
enum { value = 0 };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
94
experimental/premake5.lua
Normal file
94
experimental/premake5.lua
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
newoption {
|
||||||
|
trigger = "with-zlib",
|
||||||
|
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" }
|
||||||
|
platforms {"native", "x64", "x32"}
|
||||||
|
|
||||||
|
project "objview"
|
||||||
|
|
||||||
|
kind "ConsoleApp"
|
||||||
|
language "C++"
|
||||||
|
files { "viewer.cc", "trackball.cc" }
|
||||||
|
includedirs { "./" }
|
||||||
|
includedirs { "../../" }
|
||||||
|
|
||||||
|
flags { "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" }
|
||||||
|
|
||||||
|
configuration { "linux" }
|
||||||
|
linkoptions { "`pkg-config --libs glfw3`" }
|
||||||
|
links { "GL", "GLU", "m", "GLEW", "X11", "Xrandr", "Xinerama", "Xi", "Xxf86vm", "Xcursor", "dl" }
|
||||||
|
linkoptions { "-pthread" }
|
||||||
|
|
||||||
|
configuration { "windows" }
|
||||||
|
-- Path to GLFW3
|
||||||
|
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' }
|
||||||
|
|
||||||
|
links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
|
||||||
|
defines { "_CRT_SECURE_NO_WARNINGS" }
|
||||||
|
defines { "NOMINMAX" }
|
||||||
|
|
||||||
|
configuration { "macosx" }
|
||||||
|
includedirs { "/usr/local/include" }
|
||||||
|
buildoptions { "-Wno-deprecated-declarations" }
|
||||||
|
libdirs { "/usr/local/lib" }
|
||||||
|
links { "glfw3", "GLEW" }
|
||||||
|
linkoptions { "-framework OpenGL", "-framework Cocoa", "-framework IOKit", "-framework CoreVideo" }
|
||||||
|
|
||||||
|
configuration "Debug"
|
||||||
|
defines { "DEBUG" }
|
||||||
|
flags { "Symbols"}
|
||||||
|
|
||||||
|
configuration "Release"
|
||||||
|
defines { "NDEBUG" }
|
||||||
|
flags { "Optimize"}
|
||||||
|
|
||||||
1722
experimental/tinyobj_loader_opt.h
Normal file
1722
experimental/tinyobj_loader_opt.h
Normal file
File diff suppressed because it is too large
Load Diff
292
experimental/trackball.cc
Normal file
292
experimental/trackball.cc
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
* Permission to use, copy, modify, and distribute this software for
|
||||||
|
* any purpose and without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice appear in all copies and that both the copyright notice
|
||||||
|
* and this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of Silicon Graphics, Inc. not be used in advertising
|
||||||
|
* or publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission.
|
||||||
|
*
|
||||||
|
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
||||||
|
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||||||
|
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
||||||
|
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
||||||
|
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
||||||
|
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
||||||
|
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* US Government Users Restricted Rights
|
||||||
|
* Use, duplication, or disclosure by the Government is subject to
|
||||||
|
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||||
|
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
||||||
|
* clause at DFARS 252.227-7013 and/or in similar or successor
|
||||||
|
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
||||||
|
* Unpublished-- rights reserved under the copyright laws of the
|
||||||
|
* United States. Contractor/manufacturer is Silicon Graphics,
|
||||||
|
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
||||||
|
*
|
||||||
|
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Trackball code:
|
||||||
|
*
|
||||||
|
* Implementation of a virtual trackball.
|
||||||
|
* Implemented by Gavin Bell, lots of ideas from Thant Tessman and
|
||||||
|
* the August '88 issue of Siggraph's "Computer Graphics," pp. 121-129.
|
||||||
|
*
|
||||||
|
* Vector manip code:
|
||||||
|
*
|
||||||
|
* Original code from:
|
||||||
|
* David M. Ciemiewicz, Mark Grossman, Henry Moreton, and Paul Haeberli
|
||||||
|
*
|
||||||
|
* Much mucking with by:
|
||||||
|
* Gavin Bell
|
||||||
|
*/
|
||||||
|
#include <math.h>
|
||||||
|
#include "trackball.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This size should really be based on the distance from the center of
|
||||||
|
* rotation to the point on the object underneath the mouse. That
|
||||||
|
* point would then track the mouse as closely as possible. This is a
|
||||||
|
* simple example, though, so that is left as an Exercise for the
|
||||||
|
* Programmer.
|
||||||
|
*/
|
||||||
|
#define TRACKBALLSIZE (0.8)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local function prototypes (not defined in trackball.h)
|
||||||
|
*/
|
||||||
|
static float tb_project_to_sphere(float, float, float);
|
||||||
|
static void normalize_quat(float[4]);
|
||||||
|
|
||||||
|
static void vzero(float *v) {
|
||||||
|
v[0] = 0.0;
|
||||||
|
v[1] = 0.0;
|
||||||
|
v[2] = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vset(float *v, float x, float y, float z) {
|
||||||
|
v[0] = x;
|
||||||
|
v[1] = y;
|
||||||
|
v[2] = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vsub(const float *src1, const float *src2, float *dst) {
|
||||||
|
dst[0] = src1[0] - src2[0];
|
||||||
|
dst[1] = src1[1] - src2[1];
|
||||||
|
dst[2] = src1[2] - src2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcopy(const float *v1, float *v2) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
v2[i] = v1[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vcross(const float *v1, const float *v2, float *cross) {
|
||||||
|
float temp[3];
|
||||||
|
|
||||||
|
temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]);
|
||||||
|
temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]);
|
||||||
|
temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]);
|
||||||
|
vcopy(temp, cross);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float vlength(const float *v) {
|
||||||
|
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vscale(float *v, float div) {
|
||||||
|
v[0] *= div;
|
||||||
|
v[1] *= div;
|
||||||
|
v[2] *= div;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vnormal(float *v) { vscale(v, 1.0 / vlength(v)); }
|
||||||
|
|
||||||
|
static float vdot(const float *v1, const float *v2) {
|
||||||
|
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vadd(const float *src1, const float *src2, float *dst) {
|
||||||
|
dst[0] = src1[0] + src2[0];
|
||||||
|
dst[1] = src1[1] + src2[1];
|
||||||
|
dst[2] = src1[2] + src2[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ok, simulate a track-ball. Project the points onto the virtual
|
||||||
|
* trackball, then figure out the axis of rotation, which is the cross
|
||||||
|
* product of P1 P2 and O P1 (O is the center of the ball, 0,0,0)
|
||||||
|
* Note: This is a deformed trackball-- is a trackball in the center,
|
||||||
|
* but is deformed into a hyperbolic sheet of rotation away from the
|
||||||
|
* center. This particular function was chosen after trying out
|
||||||
|
* several variations.
|
||||||
|
*
|
||||||
|
* It is assumed that the arguments to this routine are in the range
|
||||||
|
* (-1.0 ... 1.0)
|
||||||
|
*/
|
||||||
|
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y) {
|
||||||
|
float a[3]; /* Axis of rotation */
|
||||||
|
float phi; /* how much to rotate about axis */
|
||||||
|
float p1[3], p2[3], d[3];
|
||||||
|
float t;
|
||||||
|
|
||||||
|
if (p1x == p2x && p1y == p2y) {
|
||||||
|
/* Zero rotation */
|
||||||
|
vzero(q);
|
||||||
|
q[3] = 1.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First, figure out z-coordinates for projection of P1 and P2 to
|
||||||
|
* deformed sphere
|
||||||
|
*/
|
||||||
|
vset(p1, p1x, p1y, tb_project_to_sphere(TRACKBALLSIZE, p1x, p1y));
|
||||||
|
vset(p2, p2x, p2y, tb_project_to_sphere(TRACKBALLSIZE, p2x, p2y));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now, we want the cross product of P1 and P2
|
||||||
|
*/
|
||||||
|
vcross(p2, p1, a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Figure out how much to rotate around that axis.
|
||||||
|
*/
|
||||||
|
vsub(p1, p2, d);
|
||||||
|
t = vlength(d) / (2.0 * TRACKBALLSIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid problems with out-of-control values...
|
||||||
|
*/
|
||||||
|
if (t > 1.0)
|
||||||
|
t = 1.0;
|
||||||
|
if (t < -1.0)
|
||||||
|
t = -1.0;
|
||||||
|
phi = 2.0 * asin(t);
|
||||||
|
|
||||||
|
axis_to_quat(a, phi, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given an axis and angle, compute quaternion.
|
||||||
|
*/
|
||||||
|
void axis_to_quat(float a[3], float phi, float q[4]) {
|
||||||
|
vnormal(a);
|
||||||
|
vcopy(a, q);
|
||||||
|
vscale(q, sin(phi / 2.0));
|
||||||
|
q[3] = cos(phi / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Project an x,y pair onto a sphere of radius r OR a hyperbolic sheet
|
||||||
|
* if we are away from the center of the sphere.
|
||||||
|
*/
|
||||||
|
static float tb_project_to_sphere(float r, float x, float y) {
|
||||||
|
float d, t, z;
|
||||||
|
|
||||||
|
d = sqrt(x * x + y * y);
|
||||||
|
if (d < r * 0.70710678118654752440) { /* Inside sphere */
|
||||||
|
z = sqrt(r * r - d * d);
|
||||||
|
} else { /* On hyperbola */
|
||||||
|
t = r / 1.41421356237309504880;
|
||||||
|
z = t * t / d;
|
||||||
|
}
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given two rotations, e1 and e2, expressed as quaternion rotations,
|
||||||
|
* figure out the equivalent single rotation and stuff it into dest.
|
||||||
|
*
|
||||||
|
* This routine also normalizes the result every RENORMCOUNT times it is
|
||||||
|
* called, to keep error from creeping in.
|
||||||
|
*
|
||||||
|
* NOTE: This routine is written so that q1 or q2 may be the same
|
||||||
|
* as dest (or each other).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RENORMCOUNT 97
|
||||||
|
|
||||||
|
void add_quats(float q1[4], float q2[4], float dest[4]) {
|
||||||
|
static int count = 0;
|
||||||
|
float t1[4], t2[4], t3[4];
|
||||||
|
float tf[4];
|
||||||
|
|
||||||
|
vcopy(q1, t1);
|
||||||
|
vscale(t1, q2[3]);
|
||||||
|
|
||||||
|
vcopy(q2, t2);
|
||||||
|
vscale(t2, q1[3]);
|
||||||
|
|
||||||
|
vcross(q2, q1, t3);
|
||||||
|
vadd(t1, t2, tf);
|
||||||
|
vadd(t3, tf, tf);
|
||||||
|
tf[3] = q1[3] * q2[3] - vdot(q1, q2);
|
||||||
|
|
||||||
|
dest[0] = tf[0];
|
||||||
|
dest[1] = tf[1];
|
||||||
|
dest[2] = tf[2];
|
||||||
|
dest[3] = tf[3];
|
||||||
|
|
||||||
|
if (++count > RENORMCOUNT) {
|
||||||
|
count = 0;
|
||||||
|
normalize_quat(dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quaternions always obey: a^2 + b^2 + c^2 + d^2 = 1.0
|
||||||
|
* If they don't add up to 1.0, dividing by their magnitued will
|
||||||
|
* renormalize them.
|
||||||
|
*
|
||||||
|
* Note: See the following for more information on quaternions:
|
||||||
|
*
|
||||||
|
* - Shoemake, K., Animating rotation with quaternion curves, Computer
|
||||||
|
* Graphics 19, No 3 (Proc. SIGGRAPH'85), 245-254, 1985.
|
||||||
|
* - Pletinckx, D., Quaternion calculus as a basic tool in computer
|
||||||
|
* graphics, The Visual Computer 5, 2-13, 1989.
|
||||||
|
*/
|
||||||
|
static void normalize_quat(float q[4]) {
|
||||||
|
int i;
|
||||||
|
float mag;
|
||||||
|
|
||||||
|
mag = (q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
q[i] /= mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Build a rotation matrix, given a quaternion rotation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void build_rotmatrix(float m[4][4], const float q[4]) {
|
||||||
|
m[0][0] = 1.0 - 2.0 * (q[1] * q[1] + q[2] * q[2]);
|
||||||
|
m[0][1] = 2.0 * (q[0] * q[1] - q[2] * q[3]);
|
||||||
|
m[0][2] = 2.0 * (q[2] * q[0] + q[1] * q[3]);
|
||||||
|
m[0][3] = 0.0;
|
||||||
|
|
||||||
|
m[1][0] = 2.0 * (q[0] * q[1] + q[2] * q[3]);
|
||||||
|
m[1][1] = 1.0 - 2.0 * (q[2] * q[2] + q[0] * q[0]);
|
||||||
|
m[1][2] = 2.0 * (q[1] * q[2] - q[0] * q[3]);
|
||||||
|
m[1][3] = 0.0;
|
||||||
|
|
||||||
|
m[2][0] = 2.0 * (q[2] * q[0] - q[1] * q[3]);
|
||||||
|
m[2][1] = 2.0 * (q[1] * q[2] + q[0] * q[3]);
|
||||||
|
m[2][2] = 1.0 - 2.0 * (q[1] * q[1] + q[0] * q[0]);
|
||||||
|
m[2][3] = 0.0;
|
||||||
|
|
||||||
|
m[3][0] = 0.0;
|
||||||
|
m[3][1] = 0.0;
|
||||||
|
m[3][2] = 0.0;
|
||||||
|
m[3][3] = 1.0;
|
||||||
|
}
|
||||||
75
experimental/trackball.h
Normal file
75
experimental/trackball.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 1993, 1994, Silicon Graphics, Inc.
|
||||||
|
* ALL RIGHTS RESERVED
|
||||||
|
* Permission to use, copy, modify, and distribute this software for
|
||||||
|
* any purpose and without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice appear in all copies and that both the copyright notice
|
||||||
|
* and this permission notice appear in supporting documentation, and that
|
||||||
|
* the name of Silicon Graphics, Inc. not be used in advertising
|
||||||
|
* or publicity pertaining to distribution of the software without specific,
|
||||||
|
* written prior permission.
|
||||||
|
*
|
||||||
|
* THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
|
||||||
|
* AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
|
||||||
|
* INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
|
||||||
|
* GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
|
||||||
|
* SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
|
||||||
|
* KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
|
||||||
|
* LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
|
||||||
|
* THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
|
||||||
|
* POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* US Government Users Restricted Rights
|
||||||
|
* Use, duplication, or disclosure by the Government is subject to
|
||||||
|
* restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
|
||||||
|
* (c)(1)(ii) of the Rights in Technical Data and Computer Software
|
||||||
|
* clause at DFARS 252.227-7013 and/or in similar or successor
|
||||||
|
* clauses in the FAR or the DOD or NASA FAR Supplement.
|
||||||
|
* Unpublished-- rights reserved under the copyright laws of the
|
||||||
|
* United States. Contractor/manufacturer is Silicon Graphics,
|
||||||
|
* Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
|
||||||
|
*
|
||||||
|
* OpenGL(TM) is a trademark of Silicon Graphics, Inc.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* trackball.h
|
||||||
|
* A virtual trackball implementation
|
||||||
|
* Written by Gavin Bell for Silicon Graphics, November 1988.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pass the x and y coordinates of the last and current positions of
|
||||||
|
* the mouse, scaled so they are from (-1.0 ... 1.0).
|
||||||
|
*
|
||||||
|
* The resulting rotation is returned as a quaternion rotation in the
|
||||||
|
* first paramater.
|
||||||
|
*/
|
||||||
|
void trackball(float q[4], float p1x, float p1y, float p2x, float p2y);
|
||||||
|
|
||||||
|
void negate_quat(float *q, float *qn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given two quaternions, add them together to get a third quaternion.
|
||||||
|
* Adding quaternions to get a compound rotation is analagous to adding
|
||||||
|
* translations to get a compound translation. When incrementally
|
||||||
|
* adding rotations, the first argument here should be the new
|
||||||
|
* rotation, the second and third the total rotation (which will be
|
||||||
|
* over-written with the resulting new total rotation).
|
||||||
|
*/
|
||||||
|
void add_quats(float *q1, float *q2, float *dest);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A useful function, builds a rotation matrix in Matrix based on
|
||||||
|
* given quaternion.
|
||||||
|
*/
|
||||||
|
void build_rotmatrix(float m[4][4], const float q[4]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function computes a quaternion based on an axis (defined by
|
||||||
|
* the given vector) and an angle about which to rotate. The angle is
|
||||||
|
* expressed in radians. The result is put into the third argument.
|
||||||
|
*/
|
||||||
|
void axis_to_quat(float a[3], float phi, float q[4]);
|
||||||
748
experimental/viewer.cc
Normal file
748
experimental/viewer.cc
Normal file
@@ -0,0 +1,748 @@
|
|||||||
|
//
|
||||||
|
// Simple .obj viewer(vertex only)
|
||||||
|
//
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include <limits>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstring>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#if defined(ENABLE_ZLIB)
|
||||||
|
#include <zlib.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ENABLE_ZSTD)
|
||||||
|
#include <zstd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <OpenGL/glu.h>
|
||||||
|
#else
|
||||||
|
#include <GL/glu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "trackball.h"
|
||||||
|
|
||||||
|
#define TINYOBJ_LOADER_OPT_IMPLEMENTATION
|
||||||
|
#include "tinyobj_loader_opt.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GLuint vb; // vertex buffer
|
||||||
|
int numTriangles;
|
||||||
|
} DrawObject;
|
||||||
|
|
||||||
|
std::vector<DrawObject> gDrawObjects;
|
||||||
|
|
||||||
|
int width = 768;
|
||||||
|
int height = 768;
|
||||||
|
|
||||||
|
double prevMouseX, prevMouseY;
|
||||||
|
bool mouseLeftPressed;
|
||||||
|
bool mouseMiddlePressed;
|
||||||
|
bool mouseRightPressed;
|
||||||
|
float curr_quat[4];
|
||||||
|
float prev_quat[4];
|
||||||
|
float eye[3], lookat[3], up[3];
|
||||||
|
|
||||||
|
GLFWwindow* window;
|
||||||
|
|
||||||
|
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);
|
||||||
|
exit(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
v10[2] = v1[2] - v0[2];
|
||||||
|
|
||||||
|
float v20[3];
|
||||||
|
v20[0] = v2[0] - v0[0];
|
||||||
|
v20[1] = v2[1] - v0[1];
|
||||||
|
v20[2] = v2[2] - v0[2];
|
||||||
|
|
||||||
|
N[0] = v20[1] * v10[2] - v20[2] * v10[1];
|
||||||
|
N[1] = v20[2] * v10[0] - v20[0] * v10[2];
|
||||||
|
N[2] = v20[0] * v10[1] - v20[1] * v10[0];
|
||||||
|
|
||||||
|
float len2 = N[0] * N[0] + N[1] * N[1] + N[2] * N[2];
|
||||||
|
if (len2 > 0.0f) {
|
||||||
|
float len = sqrtf(len2);
|
||||||
|
|
||||||
|
N[0] /= len;
|
||||||
|
N[1] /= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *mmap_file(size_t *len, const char* filename)
|
||||||
|
{
|
||||||
|
(*len) = 0;
|
||||||
|
#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);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
LARGE_INTEGER fileSize;
|
||||||
|
fileSize.QuadPart = 0;
|
||||||
|
GetFileSizeEx(file, &fileSize);
|
||||||
|
|
||||||
|
(*len) = static_cast<size_t>(fileSize.QuadPart);
|
||||||
|
return fileMapViewChar;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
fd = open (filename, O_RDONLY);
|
||||||
|
if (fd == -1) {
|
||||||
|
perror ("open");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fstat (fd, &sb) == -1) {
|
||||||
|
perror ("fstat");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!S_ISREG (sb.st_mode)) {
|
||||||
|
fprintf (stderr, "%s is not a file\n", "lineitem.tbl");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (char*)mmap (0, fileSize, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
|
||||||
|
if (p == MAP_FAILED) {
|
||||||
|
perror ("mmap");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close (fd) == -1) {
|
||||||
|
perror ("close");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*len) = fileSize;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gz_load(std::vector<char>* buf, const char* filename)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_ZLIB
|
||||||
|
gzFile file;
|
||||||
|
file = gzopen (filename, "r");
|
||||||
|
if (! file) {
|
||||||
|
fprintf (stderr, "gzopen of '%s' failed: %s.\n", filename,
|
||||||
|
strerror (errno));
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
int err;
|
||||||
|
int bytes_read;
|
||||||
|
unsigned char buffer[1024];
|
||||||
|
bytes_read = gzread (file, buffer, 1024);
|
||||||
|
buf->insert(buf->end(), buffer, buffer + 1024);
|
||||||
|
//printf ("%s", buffer);
|
||||||
|
if (bytes_read < 1024) {
|
||||||
|
if (gzeof (file)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const char * error_string;
|
||||||
|
error_string = gzerror (file, & err);
|
||||||
|
if (err) {
|
||||||
|
fprintf (stderr, "Error: %s.\n", error_string);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gzclose (file);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
|
||||||
|
const char *ext = strrchr(filename, '.');
|
||||||
|
|
||||||
|
size_t data_len = 0;
|
||||||
|
const char* data = nullptr;
|
||||||
|
|
||||||
|
if (strcmp(ext, ".gz") == 0) {
|
||||||
|
// gzipped data.
|
||||||
|
|
||||||
|
std::vector<char> buf;
|
||||||
|
bool ret = gz_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 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;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename, int num_threads, bool verbose)
|
||||||
|
{
|
||||||
|
tinyobj_opt::attrib_t attrib;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
|
||||||
|
//std::cout << "vertices.size() = " << attrib.vertices.size() << std::endl;
|
||||||
|
//std::cout << "normals.size() = " << attrib.normals.size() << std::endl;
|
||||||
|
|
||||||
|
{
|
||||||
|
DrawObject o;
|
||||||
|
std::vector<float> vb; // pos(3float), normal(3float), color(3float)
|
||||||
|
size_t face_offset = 0;
|
||||||
|
for (size_t v = 0; v < attrib.face_num_verts.size(); v++) {
|
||||||
|
assert(attrib.face_num_verts[v] % 3 == 0); // assume all triangle face(multiple of 3).
|
||||||
|
for (size_t f = 0; f < attrib.face_num_verts[v] / 3; f++) {
|
||||||
|
tinyobj_opt::index_t idx0 = attrib.indices[face_offset+3*f+0];
|
||||||
|
tinyobj_opt::index_t idx1 = attrib.indices[face_offset+3*f+1];
|
||||||
|
tinyobj_opt::index_t idx2 = attrib.indices[face_offset+3*f+2];
|
||||||
|
|
||||||
|
float v[3][3];
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
int f0 = idx0.vertex_index;
|
||||||
|
int f1 = idx1.vertex_index;
|
||||||
|
int f2 = idx2.vertex_index;
|
||||||
|
assert(f0 >= 0);
|
||||||
|
assert(f1 >= 0);
|
||||||
|
assert(f2 >= 0);
|
||||||
|
|
||||||
|
v[0][k] = attrib.vertices[3*f0+k];
|
||||||
|
v[1][k] = attrib.vertices[3*f1+k];
|
||||||
|
v[2][k] = attrib.vertices[3*f2+k];
|
||||||
|
bmin[k] = std::min(v[0][k], bmin[k]);
|
||||||
|
bmin[k] = std::min(v[1][k], bmin[k]);
|
||||||
|
bmin[k] = std::min(v[2][k], bmin[k]);
|
||||||
|
bmax[k] = std::max(v[0][k], bmax[k]);
|
||||||
|
bmax[k] = std::max(v[1][k], bmax[k]);
|
||||||
|
bmax[k] = std::max(v[2][k], bmax[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
float n[3][3];
|
||||||
|
|
||||||
|
if (attrib.normals.size() > 0) {
|
||||||
|
int nf0 = idx0.normal_index;
|
||||||
|
int nf1 = idx1.normal_index;
|
||||||
|
int nf2 = idx2.normal_index;
|
||||||
|
|
||||||
|
if (nf0 >= 0 && nf1 >= 0 && nf2 >= 0) {
|
||||||
|
assert(3*nf0+2 < attrib.normals.size());
|
||||||
|
assert(3*nf1+2 < attrib.normals.size());
|
||||||
|
assert(3*nf2+2 < attrib.normals.size());
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
n[0][k] = attrib.normals[3*nf0+k];
|
||||||
|
n[1][k] = attrib.normals[3*nf1+k];
|
||||||
|
n[2][k] = attrib.normals[3*nf2+k];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// compute geometric normal
|
||||||
|
CalcNormal(n[0], v[0], v[1], v[2]);
|
||||||
|
n[1][0] = n[0][0]; n[1][1] = n[0][1]; n[1][2] = n[0][2];
|
||||||
|
n[2][0] = n[0][0]; n[2][1] = n[0][1]; n[2][2] = n[0][2];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// compute geometric normal
|
||||||
|
CalcNormal(n[0], v[0], v[1], v[2]);
|
||||||
|
n[1][0] = n[0][0]; n[1][1] = n[0][1]; n[1][2] = n[0][2];
|
||||||
|
n[2][0] = n[0][0]; n[2][1] = n[0][1]; n[2][2] = n[0][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < 3; k++) {
|
||||||
|
vb.push_back(v[k][0]);
|
||||||
|
vb.push_back(v[k][1]);
|
||||||
|
vb.push_back(v[k][2]);
|
||||||
|
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]};
|
||||||
|
float len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2];
|
||||||
|
if (len2 > 1.0e-6f) {
|
||||||
|
float len = sqrtf(len2);
|
||||||
|
|
||||||
|
c[0] /= len;
|
||||||
|
c[1] /= len;
|
||||||
|
c[2] /= len;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
face_offset += attrib.face_num_verts[v];
|
||||||
|
}
|
||||||
|
|
||||||
|
o.vb = 0;
|
||||||
|
o.numTriangles = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gDrawObjects.push_back(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("bmin = %f, %f, %f\n", bmin[0], bmin[1], bmin[2]);
|
||||||
|
printf("bmax = %f, %f, %f\n", bmax[0], bmax[1], bmax[2]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reshapeFunc(GLFWwindow* window, int w, int h)
|
||||||
|
{
|
||||||
|
(void)window;
|
||||||
|
// for retinal display.
|
||||||
|
int fb_w, fb_h;
|
||||||
|
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
||||||
|
|
||||||
|
glViewport(0, 0, fb_w, fb_h);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective(45.0, (float)w / (float)h, 0.01f, 100.0f);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboardFunc(GLFWwindow *window, int key, int scancode, int action, int mods) {
|
||||||
|
(void)window;
|
||||||
|
(void)scancode;
|
||||||
|
(void)mods;
|
||||||
|
if(action == GLFW_PRESS || action == GLFW_REPEAT){
|
||||||
|
// Move camera
|
||||||
|
float mv_x = 0, mv_y = 0, mv_z = 0;
|
||||||
|
if(key == GLFW_KEY_K) mv_x += 1;
|
||||||
|
else if(key == GLFW_KEY_J) mv_x += -1;
|
||||||
|
else if(key == GLFW_KEY_L) mv_y += 1;
|
||||||
|
else if(key == GLFW_KEY_H) mv_y += -1;
|
||||||
|
else if(key == GLFW_KEY_P) mv_z += 1;
|
||||||
|
else if(key == GLFW_KEY_N) mv_z += -1;
|
||||||
|
//camera.move(mv_x * 0.05, mv_y * 0.05, mv_z * 0.05);
|
||||||
|
// Close window
|
||||||
|
if(key == GLFW_KEY_Q || key == GLFW_KEY_ESCAPE) glfwSetWindowShouldClose(window, GL_TRUE);
|
||||||
|
|
||||||
|
//init_frame = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clickFunc(GLFWwindow* window, int button, int action, int mods){
|
||||||
|
(void)window;
|
||||||
|
(void)mods;
|
||||||
|
if(button == GLFW_MOUSE_BUTTON_LEFT){
|
||||||
|
if(action == GLFW_PRESS){
|
||||||
|
mouseLeftPressed = true;
|
||||||
|
trackball(prev_quat, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
} else if(action == GLFW_RELEASE){
|
||||||
|
mouseLeftPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(button == GLFW_MOUSE_BUTTON_RIGHT){
|
||||||
|
if(action == GLFW_PRESS){
|
||||||
|
mouseRightPressed = true;
|
||||||
|
} else if(action == GLFW_RELEASE){
|
||||||
|
mouseRightPressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(button == GLFW_MOUSE_BUTTON_MIDDLE){
|
||||||
|
if(action == GLFW_PRESS){
|
||||||
|
mouseMiddlePressed = true;
|
||||||
|
} else if(action == GLFW_RELEASE){
|
||||||
|
mouseMiddlePressed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y){
|
||||||
|
(void)window;
|
||||||
|
float rotScale = 1.0f;
|
||||||
|
float transScale = 2.0f;
|
||||||
|
|
||||||
|
if(mouseLeftPressed){
|
||||||
|
trackball(prev_quat,
|
||||||
|
rotScale * (2.0f * prevMouseX - width) / (float)width,
|
||||||
|
rotScale * (height - 2.0f * prevMouseY) / (float)height,
|
||||||
|
rotScale * (2.0f * mouse_x - width) / (float)width,
|
||||||
|
rotScale * (height - 2.0f * mouse_y) / (float)height);
|
||||||
|
|
||||||
|
add_quats(prev_quat, curr_quat, curr_quat);
|
||||||
|
} else if (mouseMiddlePressed) {
|
||||||
|
eye[0] -= transScale * (mouse_x - prevMouseX) / (float)width;
|
||||||
|
lookat[0] -= transScale * (mouse_x - prevMouseX) / (float)width;
|
||||||
|
eye[1] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
lookat[1] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
} else if (mouseRightPressed) {
|
||||||
|
eye[2] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
lookat[2] += transScale * (mouse_y - prevMouseY) / (float)height;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update mouse point
|
||||||
|
prevMouseX = mouse_x;
|
||||||
|
prevMouseY = mouse_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Draw(const std::vector<DrawObject>& drawObjects)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
for (size_t i = 0; i < drawObjects.size(); i++) {
|
||||||
|
DrawObject o = drawObjects[i];
|
||||||
|
if (o.vb < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, o.vb);
|
||||||
|
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));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles);
|
||||||
|
CheckErrors("drawarrays");
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw wireframe
|
||||||
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
glPolygonMode(GL_FRONT, GL_LINE);
|
||||||
|
glPolygonMode(GL_BACK, GL_LINE);
|
||||||
|
|
||||||
|
glColor3f(0.0f, 0.0f, 0.4f);
|
||||||
|
for (size_t i = 0; i < drawObjects.size(); i++) {
|
||||||
|
DrawObject o = drawObjects[i];
|
||||||
|
if (o.vb < 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, o.vb);
|
||||||
|
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));
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, 3 * o.numTriangles);
|
||||||
|
CheckErrors("drawarrays");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Init() {
|
||||||
|
trackball(curr_quat, 0, 0, 0, 0);
|
||||||
|
|
||||||
|
eye[0] = 0.0f;
|
||||||
|
eye[1] = 0.0f;
|
||||||
|
eye[2] = 3.0f;
|
||||||
|
|
||||||
|
lookat[0] = 0.0f;
|
||||||
|
lookat[1] = 0.0f;
|
||||||
|
lookat[2] = 0.0f;
|
||||||
|
|
||||||
|
up[0] = 0.0f;
|
||||||
|
up[1] = 1.0f;
|
||||||
|
up[2] = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
std::cout << "view input.obj <num_threads> <benchark_only> <verbose>" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool benchmark_only = false;
|
||||||
|
int num_threads = -1;
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
num_threads = atoi(argv[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 3) {
|
||||||
|
benchmark_only = (atoi(argv[3]) > 0) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc > 4) {
|
||||||
|
verbose = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (benchmark_only) {
|
||||||
|
|
||||||
|
tinyobj_opt::attrib_t attrib;
|
||||||
|
std::vector<tinyobj_opt::shape_t> shapes;
|
||||||
|
std::vector<tinyobj_opt::material_t> materials;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
printf("filesize: %d\n", (int)data_len);
|
||||||
|
tinyobj_opt::LoadOption option;
|
||||||
|
option.req_num_threads = num_threads;
|
||||||
|
option.verbose = true;
|
||||||
|
|
||||||
|
bool ret = parseObj(&attrib, &shapes, &materials, data, data_len, option);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Init();
|
||||||
|
|
||||||
|
std::cout << "Initialize GLFW..." << std::endl;
|
||||||
|
|
||||||
|
if(!glfwInit()){
|
||||||
|
std::cerr << "Failed to initialize GLFW." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "GLFW OK." << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
window = glfwCreateWindow(width, height, "Obj viewer", NULL, NULL);
|
||||||
|
if(window == NULL){
|
||||||
|
std::cerr << "Failed to open GLFW window. " << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
glfwSwapInterval(1);
|
||||||
|
|
||||||
|
// Callback
|
||||||
|
glfwSetWindowSizeCallback(window, reshapeFunc);
|
||||||
|
glfwSetKeyCallback(window, keyboardFunc);
|
||||||
|
glfwSetMouseButtonCallback(window, clickFunc);
|
||||||
|
glfwSetCursorPosCallback(window, motionFunc);
|
||||||
|
|
||||||
|
glewExperimental = true;
|
||||||
|
if (glewInit() != GLEW_OK) {
|
||||||
|
std::cerr << "Failed to initialize GLEW." << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reshapeFunc(window, width, height);
|
||||||
|
|
||||||
|
float bmin[3], bmax[3];
|
||||||
|
if (false == LoadObjAndConvert(bmin, bmax, argv[1], num_threads, verbose)) {
|
||||||
|
printf("failed to load & conv\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float maxExtent = 0.5f * (bmax[0] - bmin[0]);
|
||||||
|
if (maxExtent < 0.5f * (bmax[1] - bmin[1])) {
|
||||||
|
maxExtent = 0.5f * (bmax[1] - bmin[1]);
|
||||||
|
}
|
||||||
|
if (maxExtent < 0.5f * (bmax[2] - bmin[2])) {
|
||||||
|
maxExtent = 0.5f * (bmax[2] - bmin[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(glfwWindowShouldClose(window) == GL_FALSE) {
|
||||||
|
glfwPollEvents();
|
||||||
|
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// camera & rotate
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
GLfloat mat[4][4];
|
||||||
|
gluLookAt(eye[0], eye[1], eye[2], lookat[0], lookat[1], lookat[2], up[0], up[1], up[2]);
|
||||||
|
build_rotmatrix(mat, curr_quat);
|
||||||
|
glMultMatrixf(&mat[0][0]);
|
||||||
|
|
||||||
|
// Fit to -1, 1
|
||||||
|
glScalef(1.0f / maxExtent, 1.0f / maxExtent, 1.0f / maxExtent);
|
||||||
|
|
||||||
|
// Centerize object.
|
||||||
|
glTranslatef(-0.5*(bmax[0] + bmin[0]), -0.5*(bmax[1] + bmin[1]), -0.5*(bmax[2] + bmin[2]));
|
||||||
|
|
||||||
|
Draw(gDrawObjects);
|
||||||
|
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
BIN
fuzzer/afl.tar.gz
Normal file
BIN
fuzzer/afl.tar.gz
Normal file
Binary file not shown.
20
fuzzer/runner.py
Normal file
20
fuzzer/runner.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import os, sys
|
||||||
|
import glob
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def main():
|
||||||
|
for g in glob.glob("../tests/afl/id*"):
|
||||||
|
print(g)
|
||||||
|
|
||||||
|
cmd = ["../a.out", g]
|
||||||
|
|
||||||
|
proc = subprocess.Popen(cmd)
|
||||||
|
try:
|
||||||
|
outs, errs = proc.communicate(timeout=15)
|
||||||
|
print(outs)
|
||||||
|
except TimeoutExpired:
|
||||||
|
proc.kill()
|
||||||
|
outs, errs = proc.communicate()
|
||||||
|
|
||||||
|
|
||||||
|
main()
|
||||||
BIN
images/sanmugel.png
Normal file
BIN
images/sanmugel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 188 KiB |
@@ -5,8 +5,8 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := tinyobjloader
|
LOCAL_MODULE := tinyobjloader
|
||||||
LOCAL_SRC_FILES := ../tiny_obj_loader.cc ../test.cc
|
LOCAL_SRC_FILES := ../tiny_obj_loader.cc
|
||||||
|
|
||||||
LOCAL_C_INCLUDES := ../
|
LOCAL_C_INCLUDES := ../
|
||||||
|
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|||||||
435
loader_example.cc
Normal file
435
loader_example.cc
Normal file
@@ -0,0 +1,435 @@
|
|||||||
|
//
|
||||||
|
// g++ loader_example.cc
|
||||||
|
//
|
||||||
|
#define TINYOBJLOADER_IMPLEMENTATION
|
||||||
|
#include "tiny_obj_loader.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
#include <sys/time.h>
|
||||||
|
#else
|
||||||
|
#include <ctime>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#if __has_warning("-Wzero-as-null-pointer-constant")
|
||||||
|
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class timerutil {
|
||||||
|
public:
|
||||||
|
#ifdef _WIN32
|
||||||
|
typedef DWORD time_t;
|
||||||
|
|
||||||
|
timerutil() { ::timeBeginPeriod(1); }
|
||||||
|
~timerutil() { ::timeEndPeriod(1); }
|
||||||
|
|
||||||
|
void start() { t_[0] = ::timeGetTime(); }
|
||||||
|
void end() { t_[1] = ::timeGetTime(); }
|
||||||
|
|
||||||
|
time_t sec() { return (time_t)((t_[1] - t_[0]) / 1000); }
|
||||||
|
time_t msec() { return (time_t)((t_[1] - t_[0])); }
|
||||||
|
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000); }
|
||||||
|
time_t current() { return ::timeGetTime(); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
typedef unsigned long int time_t;
|
||||||
|
|
||||||
|
void start() { gettimeofday(tv + 0, &tz); }
|
||||||
|
void end() { gettimeofday(tv + 1, &tz); }
|
||||||
|
|
||||||
|
time_t sec() { return static_cast<time_t>(tv[1].tv_sec - tv[0].tv_sec); }
|
||||||
|
time_t msec() {
|
||||||
|
return this->sec() * 1000 +
|
||||||
|
static_cast<time_t>((tv[1].tv_usec - tv[0].tv_usec) / 1000);
|
||||||
|
}
|
||||||
|
time_t usec() {
|
||||||
|
return this->sec() * 1000000 +
|
||||||
|
static_cast<time_t>(tv[1].tv_usec - tv[0].tv_usec);
|
||||||
|
}
|
||||||
|
time_t current() {
|
||||||
|
struct timeval t;
|
||||||
|
gettimeofday(&t, NULL);
|
||||||
|
return static_cast<time_t>(t.tv_sec * 1000 + t.tv_usec);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // C timer
|
||||||
|
// using namespace std;
|
||||||
|
typedef clock_t time_t;
|
||||||
|
|
||||||
|
void start() { t_[0] = clock(); }
|
||||||
|
void end() { t_[1] = clock(); }
|
||||||
|
|
||||||
|
time_t sec() { return (time_t)((t_[1] - t_[0]) / CLOCKS_PER_SEC); }
|
||||||
|
time_t msec() { return (time_t)((t_[1] - t_[0]) * 1000 / CLOCKS_PER_SEC); }
|
||||||
|
time_t usec() { return (time_t)((t_[1] - t_[0]) * 1000000 / CLOCKS_PER_SEC); }
|
||||||
|
time_t current() { return (time_t)clock(); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD t_[2];
|
||||||
|
#else
|
||||||
|
#if defined(__unix__) || defined(__APPLE__)
|
||||||
|
struct timeval tv[2];
|
||||||
|
struct timezone tz;
|
||||||
|
#else
|
||||||
|
time_t t_[2];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static void PrintInfo(const tinyobj::attrib_t& attrib,
|
||||||
|
const std::vector<tinyobj::shape_t>& shapes,
|
||||||
|
const std::vector<tinyobj::material_t>& materials) {
|
||||||
|
std::cout << "# of vertices : " << (attrib.vertices.size() / 3) << std::endl;
|
||||||
|
std::cout << "# of normals : " << (attrib.normals.size() / 3) << std::endl;
|
||||||
|
std::cout << "# of texcoords : " << (attrib.texcoords.size() / 2)
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
|
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||||
|
std::cout << "# of materials : " << materials.size() << std::endl;
|
||||||
|
|
||||||
|
for (size_t v = 0; v < attrib.vertices.size() / 3; v++) {
|
||||||
|
printf(" v[%ld] = (%f, %f, %f)\n", static_cast<long>(v),
|
||||||
|
static_cast<const double>(attrib.vertices[3 * v + 0]),
|
||||||
|
static_cast<const double>(attrib.vertices[3 * v + 1]),
|
||||||
|
static_cast<const double>(attrib.vertices[3 * v + 2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t v = 0; v < attrib.normals.size() / 3; v++) {
|
||||||
|
printf(" n[%ld] = (%f, %f, %f)\n", static_cast<long>(v),
|
||||||
|
static_cast<const double>(attrib.normals[3 * v + 0]),
|
||||||
|
static_cast<const double>(attrib.normals[3 * v + 1]),
|
||||||
|
static_cast<const double>(attrib.normals[3 * v + 2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) {
|
||||||
|
printf(" uv[%ld] = (%f, %f)\n", static_cast<long>(v),
|
||||||
|
static_cast<const double>(attrib.texcoords[2 * v + 0]),
|
||||||
|
static_cast<const double>(attrib.texcoords[2 * v + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each shape
|
||||||
|
for (size_t i = 0; i < shapes.size(); i++) {
|
||||||
|
printf("shape[%ld].name = %s\n", static_cast<long>(i),
|
||||||
|
shapes[i].name.c_str());
|
||||||
|
printf("Size of shape[%ld].mesh.indices: %lu\n", static_cast<long>(i),
|
||||||
|
static_cast<unsigned long>(shapes[i].mesh.indices.size()));
|
||||||
|
printf("Size of shape[%ld].path.indices: %lu\n", static_cast<long>(i),
|
||||||
|
static_cast<unsigned long>(shapes[i].path.indices.size()));
|
||||||
|
|
||||||
|
size_t index_offset = 0;
|
||||||
|
|
||||||
|
assert(shapes[i].mesh.num_face_vertices.size() ==
|
||||||
|
shapes[i].mesh.material_ids.size());
|
||||||
|
|
||||||
|
assert(shapes[i].mesh.num_face_vertices.size() ==
|
||||||
|
shapes[i].mesh.smoothing_group_ids.size());
|
||||||
|
|
||||||
|
printf("shape[%ld].num_faces: %lu\n", static_cast<long>(i),
|
||||||
|
static_cast<unsigned long>(shapes[i].mesh.num_face_vertices.size()));
|
||||||
|
|
||||||
|
// For each face
|
||||||
|
for (size_t f = 0; f < shapes[i].mesh.num_face_vertices.size(); f++) {
|
||||||
|
size_t fnum = shapes[i].mesh.num_face_vertices[f];
|
||||||
|
|
||||||
|
printf(" face[%ld].fnum = %ld\n", static_cast<long>(f),
|
||||||
|
static_cast<unsigned long>(fnum));
|
||||||
|
|
||||||
|
// For each vertex in the face
|
||||||
|
for (size_t v = 0; v < fnum; v++) {
|
||||||
|
tinyobj::index_t idx = shapes[i].mesh.indices[index_offset + v];
|
||||||
|
printf(" face[%ld].v[%ld].idx = %d/%d/%d\n", static_cast<long>(f),
|
||||||
|
static_cast<long>(v), idx.vertex_index, idx.normal_index,
|
||||||
|
idx.texcoord_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" face[%ld].material_id = %d\n", static_cast<long>(f),
|
||||||
|
shapes[i].mesh.material_ids[f]);
|
||||||
|
printf(" face[%ld].smoothing_group_id = %d\n", static_cast<long>(f),
|
||||||
|
shapes[i].mesh.smoothing_group_ids[f]);
|
||||||
|
|
||||||
|
index_offset += fnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("shape[%ld].num_tags: %lu\n", static_cast<long>(i),
|
||||||
|
static_cast<unsigned long>(shapes[i].mesh.tags.size()));
|
||||||
|
for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) {
|
||||||
|
printf(" tag[%ld] = %s ", static_cast<long>(t),
|
||||||
|
shapes[i].mesh.tags[t].name.c_str());
|
||||||
|
printf(" ints: [");
|
||||||
|
for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j) {
|
||||||
|
printf("%ld", static_cast<long>(shapes[i].mesh.tags[t].intValues[j]));
|
||||||
|
if (j < (shapes[i].mesh.tags[t].intValues.size() - 1)) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
|
||||||
|
printf(" floats: [");
|
||||||
|
for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j) {
|
||||||
|
printf("%f", static_cast<const double>(
|
||||||
|
shapes[i].mesh.tags[t].floatValues[j]));
|
||||||
|
if (j < (shapes[i].mesh.tags[t].floatValues.size() - 1)) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
|
||||||
|
printf(" strings: [");
|
||||||
|
for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j) {
|
||||||
|
printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str());
|
||||||
|
if (j < (shapes[i].mesh.tags[t].stringValues.size() - 1)) {
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < materials.size(); i++) {
|
||||||
|
printf("material[%ld].name = %s\n", static_cast<long>(i),
|
||||||
|
materials[i].name.c_str());
|
||||||
|
printf(" material.Ka = (%f, %f ,%f)\n",
|
||||||
|
static_cast<const double>(materials[i].ambient[0]),
|
||||||
|
static_cast<const double>(materials[i].ambient[1]),
|
||||||
|
static_cast<const double>(materials[i].ambient[2]));
|
||||||
|
printf(" material.Kd = (%f, %f ,%f)\n",
|
||||||
|
static_cast<const double>(materials[i].diffuse[0]),
|
||||||
|
static_cast<const double>(materials[i].diffuse[1]),
|
||||||
|
static_cast<const double>(materials[i].diffuse[2]));
|
||||||
|
printf(" material.Ks = (%f, %f ,%f)\n",
|
||||||
|
static_cast<const double>(materials[i].specular[0]),
|
||||||
|
static_cast<const double>(materials[i].specular[1]),
|
||||||
|
static_cast<const double>(materials[i].specular[2]));
|
||||||
|
printf(" material.Tr = (%f, %f ,%f)\n",
|
||||||
|
static_cast<const double>(materials[i].transmittance[0]),
|
||||||
|
static_cast<const double>(materials[i].transmittance[1]),
|
||||||
|
static_cast<const double>(materials[i].transmittance[2]));
|
||||||
|
printf(" material.Ke = (%f, %f ,%f)\n",
|
||||||
|
static_cast<const double>(materials[i].emission[0]),
|
||||||
|
static_cast<const double>(materials[i].emission[1]),
|
||||||
|
static_cast<const double>(materials[i].emission[2]));
|
||||||
|
printf(" material.Ns = %f\n",
|
||||||
|
static_cast<const double>(materials[i].shininess));
|
||||||
|
printf(" material.Ni = %f\n", static_cast<const double>(materials[i].ior));
|
||||||
|
printf(" material.dissolve = %f\n",
|
||||||
|
static_cast<const double>(materials[i].dissolve));
|
||||||
|
printf(" material.illum = %d\n", materials[i].illum);
|
||||||
|
printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str());
|
||||||
|
printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str());
|
||||||
|
printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str());
|
||||||
|
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", 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());
|
||||||
|
printf(" material.map_Ps = %s\n", materials[i].sheen_texname.c_str());
|
||||||
|
printf(" material.norm = %s\n", materials[i].normal_texname.c_str());
|
||||||
|
std::map<std::string, std::string>::const_iterator it(
|
||||||
|
materials[i].unknown_parameter.begin());
|
||||||
|
std::map<std::string, std::string>::const_iterator itEnd(
|
||||||
|
materials[i].unknown_parameter.end());
|
||||||
|
|
||||||
|
for (; it != itEnd; it++) {
|
||||||
|
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TestLoadObj(const char* filename, const char* basepath = NULL,
|
||||||
|
bool triangulate = true) {
|
||||||
|
std::cout << "Loading " << filename << std::endl;
|
||||||
|
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
timerutil t;
|
||||||
|
t.start();
|
||||||
|
std::string warn;
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename,
|
||||||
|
basepath, triangulate);
|
||||||
|
t.end();
|
||||||
|
printf("Parsing time: %lu [msecs]\n", t.msec());
|
||||||
|
|
||||||
|
if (!warn.empty()) {
|
||||||
|
std::cout << "WARN: " << warn << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << "ERR: " << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
printf("Failed to load/parse .obj.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintInfo(attrib, shapes, materials);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool TestStreamLoadObj() {
|
||||||
|
std::cout << "Stream Loading " << std::endl;
|
||||||
|
|
||||||
|
std::stringstream objStream;
|
||||||
|
objStream << "mtllib cube.mtl\n"
|
||||||
|
"\n"
|
||||||
|
"v 0.000000 2.000000 2.000000\n"
|
||||||
|
"v 0.000000 0.000000 2.000000\n"
|
||||||
|
"v 2.000000 0.000000 2.000000\n"
|
||||||
|
"v 2.000000 2.000000 2.000000\n"
|
||||||
|
"v 0.000000 2.000000 0.000000\n"
|
||||||
|
"v 0.000000 0.000000 0.000000\n"
|
||||||
|
"v 2.000000 0.000000 0.000000\n"
|
||||||
|
"v 2.000000 2.000000 0.000000\n"
|
||||||
|
"# 8 vertices\n"
|
||||||
|
"\n"
|
||||||
|
"g front cube\n"
|
||||||
|
"usemtl white\n"
|
||||||
|
"f 1 2 3 4\n"
|
||||||
|
"g back cube\n"
|
||||||
|
"# expects white material\n"
|
||||||
|
"f 8 7 6 5\n"
|
||||||
|
"g right cube\n"
|
||||||
|
"usemtl red\n"
|
||||||
|
"f 4 3 7 8\n"
|
||||||
|
"g top cube\n"
|
||||||
|
"usemtl white\n"
|
||||||
|
"f 5 1 4 8\n"
|
||||||
|
"g left cube\n"
|
||||||
|
"usemtl green\n"
|
||||||
|
"f 5 6 2 1\n"
|
||||||
|
"g bottom cube\n"
|
||||||
|
"usemtl white\n"
|
||||||
|
"f 2 6 7 3\n"
|
||||||
|
"# 6 elements";
|
||||||
|
|
||||||
|
std::string matStream(
|
||||||
|
"newmtl white\n"
|
||||||
|
"Ka 0 0 0\n"
|
||||||
|
"Kd 1 1 1\n"
|
||||||
|
"Ks 0 0 0\n"
|
||||||
|
"\n"
|
||||||
|
"newmtl red\n"
|
||||||
|
"Ka 0 0 0\n"
|
||||||
|
"Kd 1 0 0\n"
|
||||||
|
"Ks 0 0 0\n"
|
||||||
|
"\n"
|
||||||
|
"newmtl green\n"
|
||||||
|
"Ka 0 0 0\n"
|
||||||
|
"Kd 0 1 0\n"
|
||||||
|
"Ks 0 0 0\n"
|
||||||
|
"\n"
|
||||||
|
"newmtl blue\n"
|
||||||
|
"Ka 0 0 0\n"
|
||||||
|
"Kd 0 0 1\n"
|
||||||
|
"Ks 0 0 0\n"
|
||||||
|
"\n"
|
||||||
|
"newmtl light\n"
|
||||||
|
"Ka 20 20 20\n"
|
||||||
|
"Kd 1 1 1\n"
|
||||||
|
"Ks 0 0 0");
|
||||||
|
|
||||||
|
using namespace tinyobj;
|
||||||
|
class MaterialStringStreamReader : public MaterialReader {
|
||||||
|
public:
|
||||||
|
MaterialStringStreamReader(const std::string& matSStream)
|
||||||
|
: m_matSStream(matSStream) {}
|
||||||
|
virtual ~MaterialStringStreamReader() {}
|
||||||
|
virtual bool operator()(const std::string& matId,
|
||||||
|
std::vector<material_t>* materials,
|
||||||
|
std::map<std::string, int>* matMap,
|
||||||
|
std::string* warn,
|
||||||
|
std::string* err) {
|
||||||
|
(void)err;
|
||||||
|
(void)matId;
|
||||||
|
LoadMtl(matMap, materials, &m_matSStream, warn, err);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::stringstream m_matSStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
MaterialStringStreamReader matSSReader(matStream);
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
std::string warn;
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, &objStream,
|
||||||
|
&matSSReader);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintInfo(attrib, shapes, materials);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
if (argc > 1) {
|
||||||
|
const char* basepath = "models/";
|
||||||
|
if (argc > 2) {
|
||||||
|
basepath = argv[2];
|
||||||
|
}
|
||||||
|
assert(true == TestLoadObj(argv[1], basepath));
|
||||||
|
} else {
|
||||||
|
// assert(true == TestLoadObj("cornell_box.obj"));
|
||||||
|
// assert(true == TestLoadObj("cube.obj"));
|
||||||
|
assert(true == TestStreamLoadObj());
|
||||||
|
assert(true ==
|
||||||
|
TestLoadObj("models/catmark_torus_creases0.obj", "models/", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
models/colorspace-issue-184.mtl
Normal file
9
models/colorspace-issue-184.mtl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
Kt 0.1 0.2 0.3
|
||||||
|
map_Kd -colorspace sRGB -o 0.1 diffuse.jpg
|
||||||
|
map_Ks -s 0.1 0.2 specular.jpg
|
||||||
|
map_bump -colorspace linear -bm 3 bumpmap.jpg
|
||||||
|
|
||||||
7
models/colorspace-issue-184.obj
Normal file
7
models/colorspace-issue-184.obj
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mtllib colorspace-issue-184.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
|
||||||
31
models/cube-vertexcol.obj
Normal file
31
models/cube-vertexcol.obj
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000 0 0 0
|
||||||
|
v 0.000000 0.000000 2.000000 0 0 1
|
||||||
|
v 2.000000 0.000000 2.000000 0 1 0
|
||||||
|
v 2.000000 2.000000 2.000000 0 1 1
|
||||||
|
v 0.000000 2.000000 0.000000 1 0 0
|
||||||
|
v 0.000000 0.000000 0.000000 1 0 1
|
||||||
|
v 2.000000 0.000000 0.000000 1 1 0
|
||||||
|
v 2.000000 2.000000 0.000000 1 1 1
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1 2 3 4
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7 6 5
|
||||||
|
g right cube
|
||||||
|
usemtl red
|
||||||
|
f 4 3 7 8
|
||||||
|
g top cube
|
||||||
|
usemtl white
|
||||||
|
f 5 1 4 8
|
||||||
|
g left cube
|
||||||
|
usemtl green
|
||||||
|
f 5 6 2 1
|
||||||
|
g bottom cube
|
||||||
|
usemtl white
|
||||||
|
f 2 6 7 3
|
||||||
|
# 6 elements
|
||||||
@@ -13,6 +13,7 @@ v 2.000000 2.000000 0.000000
|
|||||||
g front cube
|
g front cube
|
||||||
usemtl white
|
usemtl white
|
||||||
f 1 2 3 4
|
f 1 2 3 4
|
||||||
|
# two white spaces between 'back' and 'cube'
|
||||||
g back cube
|
g back cube
|
||||||
# expects white material
|
# expects white material
|
||||||
f 8 7 6 5
|
f 8 7 6 5
|
||||||
24
models/invalid-face-definition.mtl
Normal file
24
models/invalid-face-definition.mtl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
newmtl white
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 1 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl blue
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl light
|
||||||
|
Ka 20 20 20
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
18
models/invalid-face-definition.obj
Normal file
18
models/invalid-face-definition.obj
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
mtllib invalid-face-definition.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7
|
||||||
23
models/issue-138.mtl
Normal file
23
models/issue-138.mtl
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
newmtl test1
|
||||||
|
Ns 10.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.5 0.2 0.2
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
|
|
||||||
|
newmtl test2
|
||||||
|
Ns 10.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.2 0.5 0.2
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
51
models/issue-138.obj
Normal file
51
models/issue-138.obj
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
# cube.obj
|
||||||
|
#
|
||||||
|
|
||||||
|
mtllib issue-138.mtl
|
||||||
|
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
|
||||||
|
vn 0.000000 0.000000 1.000000
|
||||||
|
vn 0.000000 1.000000 0.000000
|
||||||
|
vn 0.000000 0.000000 -1.000000
|
||||||
|
vn 0.000000 -1.000000 0.000000
|
||||||
|
vn 1.000000 0.000000 0.000000
|
||||||
|
vn -1.000000 0.000000 0.000000
|
||||||
|
|
||||||
|
usemtl test1
|
||||||
|
g test1
|
||||||
|
s 1
|
||||||
|
f 1/1/1 2/2/1 3/3/1
|
||||||
|
f 3/3/1 2/2/1 4/4/1
|
||||||
|
|
||||||
|
usemtl test2
|
||||||
|
g test2
|
||||||
|
|
||||||
|
s 2
|
||||||
|
f 3/1/2 4/2/2 5/3/2
|
||||||
|
f 5/3/2 4/2/2 6/4/2
|
||||||
|
s 3
|
||||||
|
f 5/4/3 6/3/3 7/2/3
|
||||||
|
f 7/2/3 6/3/3 8/1/3
|
||||||
|
s 4
|
||||||
|
f 7/1/4 8/2/4 1/3/4
|
||||||
|
f 1/3/4 8/2/4 2/4/4
|
||||||
|
s 5
|
||||||
|
f 2/1/5 8/2/5 4/3/5
|
||||||
|
f 4/3/5 8/2/5 6/4/5
|
||||||
|
s 6
|
||||||
|
f 7/1/6 1/2/6 5/3/6
|
||||||
|
f 5/3/6 1/2/6 3/4/6
|
||||||
2
models/issue-140-zero-face-idx.mtl
Normal file
2
models/issue-140-zero-face-idx.mtl
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
newmtl main
|
||||||
|
Kd 1 1 1
|
||||||
17
models/issue-140-zero-face-idx.obj
Normal file
17
models/issue-140-zero-face-idx.obj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
mtllib issue-140-zero-face-idx.mtl
|
||||||
|
|
||||||
|
v -0.5 -0.5 0
|
||||||
|
v 0.5 -0.5 0
|
||||||
|
v 0.5 0.5 0
|
||||||
|
v -0.5 0.5 0
|
||||||
|
|
||||||
|
vt 0 0 0
|
||||||
|
vt 1 0 0
|
||||||
|
vt 1 1 0
|
||||||
|
vt 0 1 0
|
||||||
|
|
||||||
|
vn 0 0 -1
|
||||||
|
|
||||||
|
usemtl main
|
||||||
|
f 0/0/0 1/1/0 3/3/0
|
||||||
|
f 1/1/0 3/3/0 2/2/0
|
||||||
37
models/issue-161-inconsistent-f.obj
Normal file
37
models/issue-161-inconsistent-f.obj
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
o cube
|
||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
|
||||||
|
g cube
|
||||||
|
usemtl cube
|
||||||
|
s 1
|
||||||
|
f 1/1 2/2 3/3
|
||||||
|
f 3/3 2/2 4/4
|
||||||
|
s 2
|
||||||
|
f 3/1 4/2 5/3
|
||||||
|
f 5/3 4/2 6/4
|
||||||
|
s 3
|
||||||
|
f 5/4 6/3 7/2
|
||||||
|
f 7/2 6/3 8/1
|
||||||
|
s 4
|
||||||
|
f 7/1 8/2 1/3
|
||||||
|
f 1/3 8/2 2/4
|
||||||
|
s 5
|
||||||
|
f 2/1 8/2 4/3
|
||||||
|
f 4/3 8/2 6/4
|
||||||
|
s 6
|
||||||
|
f 7/1 1/2 5/3
|
||||||
|
f 5 1 3
|
||||||
23
models/issue-162-smoothing-group.mtl
Normal file
23
models/issue-162-smoothing-group.mtl
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
newmtl test1
|
||||||
|
Ns 10.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.5 0.2 0.2
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
|
|
||||||
|
newmtl test2
|
||||||
|
Ns 10.0000
|
||||||
|
Ni 1.5000
|
||||||
|
d 1.0000
|
||||||
|
Tr 0.0000
|
||||||
|
Tf 1.0000 1.0000 1.0000
|
||||||
|
illum 2
|
||||||
|
Ka 0.0000 0.0000 0.0000
|
||||||
|
Kd 0.2 0.5 0.2
|
||||||
|
Ks 0.0000 0.0000 0.0000
|
||||||
|
Ke 0.0000 0.0000 0.0000
|
||||||
51
models/issue-162-smoothing-group.obj
Normal file
51
models/issue-162-smoothing-group.obj
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
|
||||||
|
# cube.obj
|
||||||
|
#
|
||||||
|
|
||||||
|
mtllib issue-162-smoothing-group.mtl
|
||||||
|
|
||||||
|
v -0.500000 -0.500000 0.500000
|
||||||
|
v 0.500000 -0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 0.500000
|
||||||
|
v 0.500000 0.500000 0.500000
|
||||||
|
v -0.500000 0.500000 -0.500000
|
||||||
|
v 0.500000 0.500000 -0.500000
|
||||||
|
v -0.500000 -0.500000 -0.500000
|
||||||
|
v 0.500000 -0.500000 -0.500000
|
||||||
|
|
||||||
|
vt 0.000000 0.000000
|
||||||
|
vt 1.000000 0.000000
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
|
||||||
|
vn 0.000000 0.000000 1.000000
|
||||||
|
vn 0.000000 1.000000 0.000000
|
||||||
|
vn 0.000000 0.000000 -1.000000
|
||||||
|
vn 0.000000 -1.000000 0.000000
|
||||||
|
vn 1.000000 0.000000 0.000000
|
||||||
|
vn -1.000000 0.000000 0.000000
|
||||||
|
|
||||||
|
usemtl test1
|
||||||
|
g test1
|
||||||
|
s 1
|
||||||
|
f 1/1/1 2/2/1 3/3/1
|
||||||
|
f 3/3/1 2/2/1 4/4/1
|
||||||
|
|
||||||
|
usemtl test2
|
||||||
|
g test2
|
||||||
|
|
||||||
|
s off
|
||||||
|
f 3/1/2 4/2/2 5/3/2
|
||||||
|
f 5/3/2 4/2/2 6/4/2
|
||||||
|
s 3
|
||||||
|
f 5/4/3 6/3/3 7/2/3
|
||||||
|
f 7/2/3 6/3/3 8/1/3
|
||||||
|
s 4
|
||||||
|
f 7/1/4 8/2/4 1/3/4
|
||||||
|
f 1/3/4 8/2/4 2/4/4
|
||||||
|
s 0
|
||||||
|
f 2/1/5 8/2/5 4/3/5
|
||||||
|
f 4/3/5 8/2/5 6/4/5
|
||||||
|
s 6
|
||||||
|
f 7/1/6 1/2/6 5/3/6
|
||||||
|
f 5/3/6 1/2/6 3/4/6
|
||||||
6
models/issue-92.mtl
Normal file
6
models/issue-92.mtl
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
map_Kd tmp.png
|
||||||
|
|
||||||
7
models/issue-92.obj
Normal file
7
models/issue-92.obj
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mtllib issue-92.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
|
||||||
5
models/issue-95-2.mtl
Normal file
5
models/issue-95-2.mtl
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
Tf 0.1 0.2 0.3
|
||||||
7
models/issue-95-2.obj
Normal file
7
models/issue-95-2.obj
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mtllib issue-95-2.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
|
||||||
5
models/issue-95.mtl
Normal file
5
models/issue-95.mtl
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
Kt 0.1 0.2 0.3
|
||||||
7
models/issue-95.obj
Normal file
7
models/issue-95.obj
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mtllib issue-95.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
|
||||||
16
models/line-prim.obj
Normal file
16
models/line-prim.obj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
mtllib cube.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g g0
|
||||||
|
usemtl white
|
||||||
|
l 1 2 3 4
|
||||||
|
l 5 6 7
|
||||||
10
models/map-bump.mtl
Normal file
10
models/map-bump.mtl
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
newmtl Material.001
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
map_Bump bump.jpg
|
||||||
|
|
||||||
|
newmtl Material.003
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
817
models/map-bump.obj
Normal file
817
models/map-bump.obj
Normal 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 map-bump.mtl
|
||||||
|
o Cube
|
||||||
|
v 1.864151 -1.219172 -5.532511
|
||||||
|
v 0.575869 -0.666304 5.896140
|
||||||
|
v 0.940448 1.000000 -1.971128
|
||||||
|
v 1.620345 1.000000 -5.815706
|
||||||
|
v 1.864152 1.000000 -6.334323
|
||||||
|
v 0.575869 -0.129842 5.896143
|
||||||
|
v 5.440438 -1.462153 -5.818601
|
||||||
|
v 4.896782 -1.462153 -2.744413
|
||||||
|
v 1.000825 -0.677484 1.899605
|
||||||
|
v 5.440438 -1.246362 -5.818600
|
||||||
|
v 1.000825 0.852342 1.899608
|
||||||
|
v 4.896782 -1.246362 -2.744412
|
||||||
|
v 1.160660 -0.450871 -2.356325
|
||||||
|
v 1.704316 -0.450871 -5.430513
|
||||||
|
v 1.000825 -0.351920 -1.293797
|
||||||
|
v 1.000825 1.000000 -1.293794
|
||||||
|
v 1.160660 -0.877888 -2.356326
|
||||||
|
v 1.704316 -0.877888 -5.430514
|
||||||
|
v 1.000825 -1.219172 -1.452514
|
||||||
|
v 1.000825 1.000000 -1.452511
|
||||||
|
v 1.000825 -0.351920 1.759410
|
||||||
|
v 1.000825 1.000000 1.759413
|
||||||
|
v 9.097919 1.221145 -6.212147
|
||||||
|
v 8.356775 1.221145 -2.021231
|
||||||
|
v 1.864151 -0.109586 -6.334325
|
||||||
|
v 0.575869 -0.398073 5.896141
|
||||||
|
v 9.097919 0.943958 -6.212148
|
||||||
|
v 8.356775 0.943958 -2.021233
|
||||||
|
v 1.061916 0.113661 -1.797961
|
||||||
|
v 1.000825 0.161258 1.899606
|
||||||
|
v 1.000825 0.324040 -1.293795
|
||||||
|
v 1.803060 0.113661 -5.988876
|
||||||
|
v 1.000825 -0.109586 -1.452513
|
||||||
|
v 1.061916 0.776753 -1.797960
|
||||||
|
v 1.803061 0.776753 -5.988875
|
||||||
|
v 1.000825 0.324040 1.759412
|
||||||
|
v 0.000825 -1.219172 -5.532512
|
||||||
|
v 0.000825 -0.666304 5.896139
|
||||||
|
v 0.000826 1.000000 -6.334325
|
||||||
|
v 0.000825 -0.129842 5.896140
|
||||||
|
v 0.000825 0.852342 1.899606
|
||||||
|
v 0.000825 -0.677484 1.899604
|
||||||
|
v 0.000825 -0.351920 -1.293797
|
||||||
|
v 0.000825 1.000000 -1.293796
|
||||||
|
v 0.000825 1.000000 -1.452513
|
||||||
|
v 0.000825 -1.219172 -1.452515
|
||||||
|
v 0.000825 -0.351920 1.759409
|
||||||
|
v 0.000825 1.000000 1.759411
|
||||||
|
v 0.000826 -0.109586 -6.334326
|
||||||
|
v 0.000825 -0.398073 5.896140
|
||||||
|
v 0.152918 1.000000 -5.815708
|
||||||
|
v 0.152917 1.000000 -1.971130
|
||||||
|
v 0.940448 1.168419 -1.971128
|
||||||
|
v 1.620345 1.168419 -5.815706
|
||||||
|
v 0.152918 1.168419 -5.815708
|
||||||
|
v 0.152917 1.168419 -1.971130
|
||||||
|
v 0.921118 1.091883 -1.050430
|
||||||
|
v 0.921118 1.091883 1.516050
|
||||||
|
v 0.080533 1.091883 -1.050432
|
||||||
|
v 0.080533 1.091883 1.516048
|
||||||
|
v 0.613003 -0.553430 5.546911
|
||||||
|
v 0.963691 -0.559956 2.248834
|
||||||
|
v 0.613003 -0.396857 5.546912
|
||||||
|
v 0.963691 -0.070362 2.248835
|
||||||
|
v 1.499370 -0.994317 3.966028
|
||||||
|
v 1.850058 -0.997914 0.667950
|
||||||
|
v 1.499370 -0.908021 3.966029
|
||||||
|
v 1.850058 -0.728071 0.667951
|
||||||
|
v 1.601022 0.760960 -6.334324
|
||||||
|
v 1.601021 0.129454 -6.334325
|
||||||
|
v 0.263955 0.760960 -6.334325
|
||||||
|
v 0.263955 0.129454 -6.334325
|
||||||
|
v 1.334809 0.760960 -7.515329
|
||||||
|
v 1.334809 0.129455 -7.515330
|
||||||
|
v 0.530168 0.760960 -7.515330
|
||||||
|
v 0.530168 0.129455 -7.515330
|
||||||
|
v 1.192720 0.649445 -7.515329
|
||||||
|
v 1.192720 0.240971 -7.515330
|
||||||
|
v 0.672258 0.649445 -7.515330
|
||||||
|
v 0.672258 0.240971 -7.515330
|
||||||
|
v 1.192719 0.649444 -6.524630
|
||||||
|
v 1.192719 0.240970 -6.524631
|
||||||
|
v 0.672257 0.649444 -6.524631
|
||||||
|
v 0.672257 0.240970 -6.524631
|
||||||
|
v 3.851026 0.431116 -1.883326
|
||||||
|
v 3.851026 0.946662 -1.883325
|
||||||
|
v 4.592170 0.946662 -6.074241
|
||||||
|
v 4.592169 0.431116 -6.074242
|
||||||
|
v 4.995714 0.561404 -1.918362
|
||||||
|
v 4.995714 1.016394 -1.918360
|
||||||
|
v 5.736857 1.016394 -6.109276
|
||||||
|
v 5.736857 0.561404 -6.109277
|
||||||
|
v 3.975454 0.471731 -2.162156
|
||||||
|
v 3.975454 0.919244 -2.162155
|
||||||
|
v 4.618796 0.919244 -5.800034
|
||||||
|
v 4.618795 0.471730 -5.800035
|
||||||
|
v 4.969088 0.584825 -2.192568
|
||||||
|
v 4.969088 0.979775 -2.192567
|
||||||
|
v 5.612430 0.979775 -5.830446
|
||||||
|
v 5.612429 0.584825 -5.830447
|
||||||
|
v 0.864214 -0.673890 3.184381
|
||||||
|
v 0.864213 0.489129 3.184384
|
||||||
|
v 0.864213 -0.018552 3.184383
|
||||||
|
v 0.000825 0.489129 3.184382
|
||||||
|
v 0.000825 -0.673890 3.184381
|
||||||
|
v 0.850955 -0.557858 3.309075
|
||||||
|
v 0.850955 -0.175321 3.309076
|
||||||
|
v 1.737321 -0.996758 1.728192
|
||||||
|
v 1.737321 -0.785920 1.728193
|
||||||
|
v -1.864151 -1.219172 -5.532511
|
||||||
|
v -0.575869 -0.666304 5.896140
|
||||||
|
v -0.940448 1.000000 -1.971128
|
||||||
|
v -1.620345 1.000000 -5.815706
|
||||||
|
v -1.864152 1.000000 -6.334323
|
||||||
|
v -0.575869 -0.129842 5.896143
|
||||||
|
v -5.440438 -1.462153 -5.818601
|
||||||
|
v -4.896782 -1.462153 -2.744413
|
||||||
|
v -1.000825 -0.677484 1.899605
|
||||||
|
v -5.440438 -1.246362 -5.818600
|
||||||
|
v -1.000825 0.852342 1.899608
|
||||||
|
v -4.896782 -1.246362 -2.744412
|
||||||
|
v -1.160660 -0.450871 -2.356325
|
||||||
|
v -1.704316 -0.450871 -5.430513
|
||||||
|
v -1.000825 -0.351920 -1.293797
|
||||||
|
v -1.000825 1.000000 -1.293794
|
||||||
|
v -1.160660 -0.877888 -2.356326
|
||||||
|
v -1.704316 -0.877888 -5.430514
|
||||||
|
v -1.000825 -1.219172 -1.452514
|
||||||
|
v -1.000825 1.000000 -1.452511
|
||||||
|
v -1.000825 -0.351920 1.759410
|
||||||
|
v -1.000825 1.000000 1.759413
|
||||||
|
v -9.097919 1.221145 -6.212147
|
||||||
|
v -8.356775 1.221145 -2.021231
|
||||||
|
v -1.864151 -0.109586 -6.334325
|
||||||
|
v -0.575869 -0.398073 5.896141
|
||||||
|
v -9.097919 0.943958 -6.212148
|
||||||
|
v -8.356775 0.943958 -2.021233
|
||||||
|
v -1.061916 0.113661 -1.797961
|
||||||
|
v -1.000825 0.161258 1.899606
|
||||||
|
v -1.000825 0.324040 -1.293795
|
||||||
|
v -1.803060 0.113661 -5.988876
|
||||||
|
v -1.000825 -0.109586 -1.452513
|
||||||
|
v -1.061916 0.776753 -1.797960
|
||||||
|
v -1.803061 0.776753 -5.988875
|
||||||
|
v -1.000825 0.324040 1.759412
|
||||||
|
v -0.000825 -1.219172 -5.532512
|
||||||
|
v -0.000825 -0.666304 5.896139
|
||||||
|
v -0.000826 1.000000 -6.334325
|
||||||
|
v -0.000825 -0.129842 5.896140
|
||||||
|
v -0.000825 0.852342 1.899606
|
||||||
|
v -0.000825 -0.677484 1.899604
|
||||||
|
v -0.000825 -0.351920 -1.293797
|
||||||
|
v -0.000825 1.000000 -1.293796
|
||||||
|
v -0.000825 1.000000 -1.452513
|
||||||
|
v -0.000825 -1.219172 -1.452515
|
||||||
|
v -0.000825 -0.351920 1.759409
|
||||||
|
v -0.000825 1.000000 1.759411
|
||||||
|
v -0.000826 -0.109586 -6.334326
|
||||||
|
v -0.000825 -0.398073 5.896140
|
||||||
|
v -0.152918 1.000000 -5.815708
|
||||||
|
v -0.152917 1.000000 -1.971130
|
||||||
|
v -0.940448 1.168419 -1.971128
|
||||||
|
v -1.620345 1.168419 -5.815706
|
||||||
|
v -0.152918 1.168419 -5.815708
|
||||||
|
v -0.152917 1.168419 -1.971130
|
||||||
|
v -0.921118 1.091883 -1.050430
|
||||||
|
v -0.921118 1.091883 1.516050
|
||||||
|
v -0.080533 1.091883 -1.050432
|
||||||
|
v -0.080533 1.091883 1.516048
|
||||||
|
v -0.613003 -0.553430 5.546911
|
||||||
|
v -0.963691 -0.559956 2.248834
|
||||||
|
v -0.613003 -0.396857 5.546912
|
||||||
|
v -0.963691 -0.070362 2.248835
|
||||||
|
v -1.499370 -0.994317 3.966028
|
||||||
|
v -1.850058 -0.997914 0.667950
|
||||||
|
v -1.499370 -0.908021 3.966029
|
||||||
|
v -1.850058 -0.728071 0.667951
|
||||||
|
v -1.601022 0.760960 -6.334324
|
||||||
|
v -1.601021 0.129454 -6.334325
|
||||||
|
v -0.263955 0.760960 -6.334325
|
||||||
|
v -0.263955 0.129454 -6.334325
|
||||||
|
v -1.334809 0.760960 -7.515329
|
||||||
|
v -1.334809 0.129455 -7.515330
|
||||||
|
v -0.530168 0.760960 -7.515330
|
||||||
|
v -0.530168 0.129455 -7.515330
|
||||||
|
v -1.192720 0.649445 -7.515329
|
||||||
|
v -1.192720 0.240971 -7.515330
|
||||||
|
v -0.672258 0.649445 -7.515330
|
||||||
|
v -0.672258 0.240971 -7.515330
|
||||||
|
v -1.192719 0.649444 -6.524630
|
||||||
|
v -1.192719 0.240970 -6.524631
|
||||||
|
v -0.672257 0.649444 -6.524631
|
||||||
|
v -0.672257 0.240970 -6.524631
|
||||||
|
v -3.851026 0.431116 -1.883326
|
||||||
|
v -3.851026 0.946662 -1.883325
|
||||||
|
v -4.592170 0.946662 -6.074241
|
||||||
|
v -4.592169 0.431116 -6.074242
|
||||||
|
v -4.995714 0.561404 -1.918362
|
||||||
|
v -4.995714 1.016394 -1.918360
|
||||||
|
v -5.736857 1.016394 -6.109276
|
||||||
|
v -5.736857 0.561404 -6.109277
|
||||||
|
v -3.975454 0.471731 -2.162156
|
||||||
|
v -3.975454 0.919244 -2.162155
|
||||||
|
v -4.618796 0.919244 -5.800034
|
||||||
|
v -4.618795 0.471730 -5.800035
|
||||||
|
v -4.969088 0.584825 -2.192568
|
||||||
|
v -4.969088 0.979775 -2.192567
|
||||||
|
v -5.612430 0.979775 -5.830446
|
||||||
|
v -5.612429 0.584825 -5.830447
|
||||||
|
v -0.864214 -0.673890 3.184381
|
||||||
|
v -0.864213 0.489129 3.184384
|
||||||
|
v -0.864213 -0.018552 3.184383
|
||||||
|
v -0.000825 0.489129 3.184382
|
||||||
|
v -0.000825 -0.673890 3.184381
|
||||||
|
v -0.850955 -0.557858 3.309075
|
||||||
|
v -0.850955 -0.175321 3.309076
|
||||||
|
v -1.737321 -0.996758 1.728192
|
||||||
|
v -1.737321 -0.785920 1.728193
|
||||||
|
vt 0.135351 -0.558072
|
||||||
|
vt 0.003035 -0.363507
|
||||||
|
vt 0.092282 -0.976844
|
||||||
|
vt -0.081322 0.947351
|
||||||
|
vt 0.100058 1.958891
|
||||||
|
vt 0.050091 1.852185
|
||||||
|
vt -0.092752 1.055565
|
||||||
|
vt -0.251711 1.059474
|
||||||
|
vt 0.075587 0.041384
|
||||||
|
vt -0.086008 0.279003
|
||||||
|
vt -0.086212 0.249830
|
||||||
|
vt -0.276044 1.968137
|
||||||
|
vt -0.246101 1.859467
|
||||||
|
vt 0.009828 1.911388
|
||||||
|
vt -0.133014 1.114769
|
||||||
|
vt 0.413322 1.261595
|
||||||
|
vt 0.299103 0.624605
|
||||||
|
vt 1.243955 0.407183
|
||||||
|
vt 0.515404 1.111487
|
||||||
|
vt 1.358173 1.044173
|
||||||
|
vt -0.081553 0.914324
|
||||||
|
vt 0.080042 0.676706
|
||||||
|
vt 0.401185 0.474498
|
||||||
|
vt 1.295541 0.331328
|
||||||
|
vt 0.365315 1.568841
|
||||||
|
vt 0.299111 1.575740
|
||||||
|
vt 0.143401 0.707357
|
||||||
|
vt 0.629403 1.011947
|
||||||
|
vt 0.449192 0.167251
|
||||||
|
vt 1.409760 0.968317
|
||||||
|
vt 0.986264 1.738667
|
||||||
|
vt 1.573373 1.877873
|
||||||
|
vt 1.417663 1.009490
|
||||||
|
vt 0.237182 -0.196235
|
||||||
|
vt 0.721785 1.030226
|
||||||
|
vt 0.830554 0.870285
|
||||||
|
vt 0.877494 1.898608
|
||||||
|
vt 1.351399 1.106930
|
||||||
|
vt 0.183935 0.557301
|
||||||
|
vt 1.507109 1.975312
|
||||||
|
vt 0.241636 0.439088
|
||||||
|
vt 0.114297 -0.045011
|
||||||
|
vt 0.140593 1.808834
|
||||||
|
vt -0.015118 0.940452
|
||||||
|
vt 0.156405 -1.071134
|
||||||
|
vt 0.164119 -0.998223
|
||||||
|
vt 0.040336 -1.068281
|
||||||
|
vt 0.104459 -1.162571
|
||||||
|
vt -0.165787 1.882802
|
||||||
|
vt -0.014821 1.660811
|
||||||
|
vt -0.287852 0.283965
|
||||||
|
vt -0.293374 0.366508
|
||||||
|
vt -0.289630 0.900550
|
||||||
|
vt 0.035337 -0.191272
|
||||||
|
vt 0.247348 0.172213
|
||||||
|
vt 0.253300 1.021193
|
||||||
|
vt -0.283166 0.952313
|
||||||
|
vt -0.283398 0.919286
|
||||||
|
vt 0.039792 0.444050
|
||||||
|
vt 0.314806 -0.339851
|
||||||
|
vt 0.112962 -0.334889
|
||||||
|
vt -0.288056 0.254793
|
||||||
|
vt -0.023788 -0.973990
|
||||||
|
vt -0.155922 -0.359599
|
||||||
|
vt 0.220528 -1.165425
|
||||||
|
vt 0.108710 -0.748730
|
||||||
|
vt -0.286364 1.918670
|
||||||
|
vt -0.291973 1.118678
|
||||||
|
vt -0.119962 0.896379
|
||||||
|
vt -0.123707 0.362337
|
||||||
|
vt 0.162891 -0.598569
|
||||||
|
vt 0.467532 -0.853353
|
||||||
|
vt 0.201549 -1.053262
|
||||||
|
vt 0.161663 -0.198915
|
||||||
|
vt 0.267667 -0.752638
|
||||||
|
vt 0.278705 -0.371021
|
||||||
|
vt 0.526390 -0.542053
|
||||||
|
vt 0.483821 -0.479457
|
||||||
|
vt 0.488162 -0.883689
|
||||||
|
vt 0.500110 -0.105561
|
||||||
|
vt 0.564618 -0.200418
|
||||||
|
vt -0.110331 2.127229
|
||||||
|
vt 0.040636 1.905238
|
||||||
|
vt -0.010786 1.578087
|
||||||
|
vt 0.104092 1.876168
|
||||||
|
vt 0.255058 1.654176
|
||||||
|
vt -0.054992 2.087323
|
||||||
|
vt 0.203048 1.901245
|
||||||
|
vt 0.052081 2.123235
|
||||||
|
vt 0.042658 1.943733
|
||||||
|
vt -0.056437 1.881175
|
||||||
|
vt 0.147710 1.941151
|
||||||
|
vt 0.050060 2.084741
|
||||||
|
vt 0.146264 1.735002
|
||||||
|
vt 0.041212 1.737584
|
||||||
|
vt 0.048615 1.878591
|
||||||
|
vt 0.663065 1.872485
|
||||||
|
vt 0.786311 1.691257
|
||||||
|
vt 0.507355 1.004102
|
||||||
|
vt 0.630601 0.822874
|
||||||
|
vt 0.955144 1.689498
|
||||||
|
vt 0.860727 1.828333
|
||||||
|
vt 0.725565 1.074543
|
||||||
|
vt 0.819981 0.935708
|
||||||
|
vt 0.674594 1.805657
|
||||||
|
vt 0.539432 1.051867
|
||||||
|
vt 0.646413 0.894554
|
||||||
|
vt 0.781576 1.648344
|
||||||
|
vt 0.240127 -0.712141
|
||||||
|
vn 0.994400 0.000000 0.105700
|
||||||
|
vn 0.000000 1.000000 0.000000
|
||||||
|
vn 1.000000 0.000000 0.000000
|
||||||
|
vn 0.984700 0.000000 0.174100
|
||||||
|
vn 0.211800 0.976600 0.037500
|
||||||
|
vn -0.103300 0.000000 -0.994600
|
||||||
|
vn 0.103300 -0.000000 0.994600
|
||||||
|
vn 0.911400 0.378700 0.161200
|
||||||
|
vn -0.157300 -0.987200 -0.027800
|
||||||
|
vn 0.113700 -0.993300 0.020100
|
||||||
|
vn 0.030600 -0.000000 0.999500
|
||||||
|
vn -0.061100 0.998100 -0.010800
|
||||||
|
vn -0.030600 0.000000 -0.999500
|
||||||
|
vn -0.000000 -0.000000 1.000000
|
||||||
|
vn 0.000000 0.000000 -1.000000
|
||||||
|
vn -0.755400 0.655300 0.000000
|
||||||
|
vn 0.000000 -1.000000 0.000000
|
||||||
|
vn -0.000000 -0.180000 0.983700
|
||||||
|
vn 0.000000 -0.395500 -0.918500
|
||||||
|
vn -0.000000 0.688500 0.725200
|
||||||
|
vn 0.000000 -0.585700 -0.810500
|
||||||
|
vn -0.000000 0.974900 0.222500
|
||||||
|
vn -0.000000 -1.000000 0.002800
|
||||||
|
vn -1.000000 0.000000 -0.000000
|
||||||
|
vn -0.000000 0.935500 0.353200
|
||||||
|
vn 0.755400 0.655300 0.000000
|
||||||
|
vn 0.000000 0.935500 -0.353200
|
||||||
|
vn 0.673800 0.724900 0.143400
|
||||||
|
vn 0.872300 -0.000000 0.489100
|
||||||
|
vn -0.872300 0.000000 -0.489100
|
||||||
|
vn -0.518300 -0.853500 -0.054200
|
||||||
|
vn -0.975500 0.000000 -0.219900
|
||||||
|
vn 0.975500 0.000000 -0.219900
|
||||||
|
vn -0.913200 0.000000 -0.407500
|
||||||
|
vn -0.436900 0.896200 -0.077300
|
||||||
|
vn -0.995300 -0.000000 0.096600
|
||||||
|
vn -0.297300 -0.953400 -0.052600
|
||||||
|
vn 0.473900 -0.876600 0.083800
|
||||||
|
vn 0.913200 0.000000 0.407500
|
||||||
|
vn 0.342200 0.937700 0.060500
|
||||||
|
vn 0.995300 -0.000000 -0.096600
|
||||||
|
vn -0.519200 -0.853000 -0.054300
|
||||||
|
vn 0.722400 0.676400 0.143800
|
||||||
|
vn -0.994400 0.000000 0.105700
|
||||||
|
vn -0.984700 0.000000 0.174100
|
||||||
|
vn -0.211800 0.976600 0.037500
|
||||||
|
vn 0.103300 0.000000 -0.994600
|
||||||
|
vn -0.103300 -0.000000 0.994600
|
||||||
|
vn -0.911400 0.378700 0.161200
|
||||||
|
vn 0.157300 -0.987200 -0.027800
|
||||||
|
vn -0.113700 -0.993300 0.020100
|
||||||
|
vn -0.030600 -0.000000 0.999500
|
||||||
|
vn 0.061100 0.998100 -0.010800
|
||||||
|
vn 0.030600 0.000000 -0.999500
|
||||||
|
vn -0.691900 0.713200 0.112500
|
||||||
|
vn -0.872300 -0.000000 0.489100
|
||||||
|
vn 0.872300 0.000000 -0.489100
|
||||||
|
vn 0.518300 -0.853500 -0.054200
|
||||||
|
vn 0.913200 0.000000 -0.407500
|
||||||
|
vn 0.436900 0.896200 -0.077300
|
||||||
|
vn 0.995300 0.000000 0.096600
|
||||||
|
vn 0.297300 -0.953300 -0.052600
|
||||||
|
vn -0.473900 -0.876600 0.083800
|
||||||
|
vn -0.913200 -0.000000 0.407500
|
||||||
|
vn -0.342200 0.937700 0.060500
|
||||||
|
vn -0.995300 -0.000000 -0.096600
|
||||||
|
vn 0.519200 -0.853000 -0.054300
|
||||||
|
vn -0.714800 0.690100 0.113700
|
||||||
|
vn 0.974400 0.089700 0.206200
|
||||||
|
vn 0.870400 0.288400 0.399100
|
||||||
|
vn 0.691900 0.713200 0.112500
|
||||||
|
vn -0.518000 -0.853700 -0.053400
|
||||||
|
vn -0.519700 -0.852700 -0.053600
|
||||||
|
vn 0.714800 0.690100 0.113700
|
||||||
|
vn -0.974400 0.089700 0.206200
|
||||||
|
vn -0.870400 0.288400 0.399100
|
||||||
|
vn -0.673800 0.724900 0.143400
|
||||||
|
vn 0.518000 -0.853700 -0.053400
|
||||||
|
vn 0.297300 -0.953400 -0.052600
|
||||||
|
vn 0.519700 -0.852700 -0.053600
|
||||||
|
vn -0.722400 0.676400 0.143800
|
||||||
|
vn -0.000000 0.962300 0.272000
|
||||||
|
usemtl Material.001
|
||||||
|
s off
|
||||||
|
f 103/1/1 102/2/1 6/3/1
|
||||||
|
f 20/4/2 5/5/2 4/6/2
|
||||||
|
f 20/4/2 3/7/2 52/8/2
|
||||||
|
f 36/9/3 22/10/3 11/11/3
|
||||||
|
f 39/12/2 51/13/2 4/6/2
|
||||||
|
f 4/6/4 54/14/4 53/15/4
|
||||||
|
f 14/16/5 13/17/5 12/18/5
|
||||||
|
f 18/19/6 14/16/6 10/20/6
|
||||||
|
f 20/4/3 16/21/3 31/22/3
|
||||||
|
f 17/23/7 8/24/7 12/18/7
|
||||||
|
f 25/25/4 32/26/4 29/27/4
|
||||||
|
f 10/20/4 12/18/4 8/24/4
|
||||||
|
f 1/28/8 18/19/8 17/23/8
|
||||||
|
f 19/29/4 17/23/4 13/17/4
|
||||||
|
f 25/25/4 14/16/4 18/19/4
|
||||||
|
f 18/19/9 7/30/9 8/24/9
|
||||||
|
f 92/31/10 27/32/10 28/33/10
|
||||||
|
f 16/21/3 22/10/3 36/9/3
|
||||||
|
f 31/22/3 36/9/3 21/34/3
|
||||||
|
f 90/35/11 89/36/11 28/33/11
|
||||||
|
f 91/37/12 90/35/12 24/38/12
|
||||||
|
f 33/39/4 13/17/4 14/16/4
|
||||||
|
f 23/40/4 24/38/4 28/33/4
|
||||||
|
f 33/39/3 31/22/3 15/41/3
|
||||||
|
f 21/34/3 36/9/3 30/42/3
|
||||||
|
f 5/5/4 35/43/4 32/26/4
|
||||||
|
f 5/5/4 20/4/4 34/44/4
|
||||||
|
f 33/39/4 29/27/4 34/44/4
|
||||||
|
f 91/37/13 23/40/13 27/32/13
|
||||||
|
f 103/1/1 26/45/1 63/46/1
|
||||||
|
f 26/45/14 50/47/14 38/48/14
|
||||||
|
f 39/12/15 71/49/15 72/50/15
|
||||||
|
f 48/51/16 60/52/16 59/53/16
|
||||||
|
f 15/41/17 21/34/17 47/54/17
|
||||||
|
f 19/29/17 46/55/17 37/56/17
|
||||||
|
f 39/12/2 45/57/2 52/8/2
|
||||||
|
f 20/4/2 45/57/2 44/58/2
|
||||||
|
f 19/29/18 15/41/18 43/59/18
|
||||||
|
f 9/60/19 42/61/19 47/54/19
|
||||||
|
f 22/10/20 48/51/20 41/62/20
|
||||||
|
f 25/25/21 1/28/21 37/56/21
|
||||||
|
f 6/3/14 40/63/14 50/47/14
|
||||||
|
f 104/64/22 40/63/22 6/3/22
|
||||||
|
f 2/65/23 38/48/23 105/66/23
|
||||||
|
f 55/67/2 56/68/2 53/15/2
|
||||||
|
f 3/7/14 53/15/14 56/68/14
|
||||||
|
f 51/13/15 55/67/15 54/14/15
|
||||||
|
f 52/8/24 56/68/24 55/67/24
|
||||||
|
f 57/69/2 59/53/2 60/52/2
|
||||||
|
f 48/51/25 22/10/25 58/70/25
|
||||||
|
f 16/21/26 57/69/26 58/70/26
|
||||||
|
f 16/21/27 44/58/27 59/53/27
|
||||||
|
f 107/71/28 63/46/28 67/72/28
|
||||||
|
f 26/45/1 2/65/1 61/73/1
|
||||||
|
f 9/60/1 30/42/1 64/74/1
|
||||||
|
f 101/75/1 9/60/1 62/76/1
|
||||||
|
f 108/77/1 109/78/1 67/72/1
|
||||||
|
f 61/73/29 65/79/29 67/72/29
|
||||||
|
f 62/76/30 64/74/30 68/80/30
|
||||||
|
f 62/76/31 66/81/31 108/77/31
|
||||||
|
f 71/49/32 75/82/32 76/83/32
|
||||||
|
f 25/25/15 49/84/15 72/50/15
|
||||||
|
f 5/5/15 69/85/15 71/49/15
|
||||||
|
f 25/25/15 70/86/15 69/85/15
|
||||||
|
f 76/83/15 75/82/15 79/87/15
|
||||||
|
f 72/50/17 76/83/17 74/88/17
|
||||||
|
f 71/49/2 69/85/2 73/89/2
|
||||||
|
f 70/86/33 74/88/33 73/89/33
|
||||||
|
f 80/90/3 79/87/3 83/91/3
|
||||||
|
f 76/83/15 80/90/15 78/92/15
|
||||||
|
f 75/82/15 73/89/15 77/93/15
|
||||||
|
f 74/88/15 78/92/15 77/93/15
|
||||||
|
f 82/94/15 84/95/15 83/91/15
|
||||||
|
f 80/90/2 84/95/2 82/94/2
|
||||||
|
f 77/93/17 81/96/17 83/91/17
|
||||||
|
f 77/93/24 78/92/24 82/94/24
|
||||||
|
f 35/43/13 87/97/13 88/98/13
|
||||||
|
f 35/43/12 34/44/12 86/99/12
|
||||||
|
f 34/44/11 29/27/11 85/100/11
|
||||||
|
f 32/26/10 88/98/10 85/100/10
|
||||||
|
f 92/31/34 100/101/34 99/102/34
|
||||||
|
f 90/35/35 91/37/35 99/102/35
|
||||||
|
f 89/36/36 90/35/36 98/103/36
|
||||||
|
f 89/36/37 97/104/37 100/101/37
|
||||||
|
f 95/105/13 99/102/13 100/101/13
|
||||||
|
f 95/105/12 94/106/12 98/103/12
|
||||||
|
f 94/106/11 93/107/11 97/104/11
|
||||||
|
f 96/108/10 100/101/10 97/104/10
|
||||||
|
f 88/98/38 96/108/38 93/107/38
|
||||||
|
f 86/99/39 85/100/39 93/107/39
|
||||||
|
f 87/97/40 86/99/40 94/106/40
|
||||||
|
f 87/97/41 95/105/41 96/108/41
|
||||||
|
f 106/109/42 108/77/42 65/79/42
|
||||||
|
f 66/81/1 68/80/1 109/78/1
|
||||||
|
f 101/75/1 106/109/1 61/73/1
|
||||||
|
f 64/74/43 107/71/43 109/78/43
|
||||||
|
f 101/75/23 105/66/23 42/61/23
|
||||||
|
f 103/1/1 107/71/1 64/74/1
|
||||||
|
f 30/42/1 11/11/1 102/2/1
|
||||||
|
f 212/1/44 135/45/44 115/3/44
|
||||||
|
f 129/4/2 112/7/2 113/6/2
|
||||||
|
f 161/8/2 112/7/2 129/4/2
|
||||||
|
f 145/9/24 139/42/24 120/11/24
|
||||||
|
f 113/6/2 160/13/2 148/12/2
|
||||||
|
f 162/15/45 163/14/45 113/6/45
|
||||||
|
f 123/16/46 119/20/46 121/18/46
|
||||||
|
f 127/19/47 116/30/47 119/20/47
|
||||||
|
f 140/22/24 125/21/24 129/4/24
|
||||||
|
f 121/18/48 117/24/48 126/23/48
|
||||||
|
f 138/27/45 141/26/45 134/25/45
|
||||||
|
f 117/24/45 121/18/45 119/20/45
|
||||||
|
f 126/23/49 127/19/49 110/28/49
|
||||||
|
f 122/17/45 126/23/45 128/29/45
|
||||||
|
f 127/19/45 123/16/45 134/25/45
|
||||||
|
f 117/24/50 116/30/50 127/19/50
|
||||||
|
f 137/33/51 136/32/51 201/31/51
|
||||||
|
f 145/9/24 131/10/24 125/21/24
|
||||||
|
f 130/34/24 145/9/24 140/22/24
|
||||||
|
f 199/35/52 133/38/52 137/33/52
|
||||||
|
f 200/37/53 132/40/53 133/38/53
|
||||||
|
f 123/16/45 122/17/45 142/39/45
|
||||||
|
f 137/33/45 133/38/45 132/40/45
|
||||||
|
f 124/41/24 140/22/24 142/39/24
|
||||||
|
f 130/34/24 118/60/24 139/42/24
|
||||||
|
f 141/26/45 144/43/45 114/5/45
|
||||||
|
f 114/5/45 144/43/45 143/44/45
|
||||||
|
f 143/44/45 138/27/45 142/39/45
|
||||||
|
f 136/32/54 132/40/54 200/37/54
|
||||||
|
f 212/1/44 216/71/44 172/46/44
|
||||||
|
f 147/48/14 159/47/14 135/45/14
|
||||||
|
f 181/50/15 180/49/15 148/12/15
|
||||||
|
f 168/53/26 169/52/26 157/51/26
|
||||||
|
f 124/41/17 152/59/17 156/54/17
|
||||||
|
f 146/56/17 155/55/17 128/29/17
|
||||||
|
f 148/12/2 160/13/2 161/8/2
|
||||||
|
f 129/4/2 125/21/2 153/58/2
|
||||||
|
f 155/55/18 152/59/18 124/41/18
|
||||||
|
f 130/34/19 156/54/19 151/61/19
|
||||||
|
f 131/10/20 120/11/20 150/62/20
|
||||||
|
f 134/25/21 158/84/21 146/56/21
|
||||||
|
f 159/47/14 149/63/14 115/3/14
|
||||||
|
f 115/3/22 149/63/22 213/64/22
|
||||||
|
f 214/66/23 147/48/23 111/65/23
|
||||||
|
f 162/15/2 165/68/2 164/67/2
|
||||||
|
f 165/68/14 162/15/14 112/7/14
|
||||||
|
f 163/14/15 164/67/15 160/13/15
|
||||||
|
f 164/67/3 165/68/3 161/8/3
|
||||||
|
f 166/69/2 167/70/2 169/52/2
|
||||||
|
f 157/51/25 169/52/25 167/70/25
|
||||||
|
f 167/70/16 166/69/16 125/21/16
|
||||||
|
f 125/21/27 166/69/27 168/53/27
|
||||||
|
f 216/71/55 218/78/55 176/72/55
|
||||||
|
f 135/45/44 172/46/44 170/73/44
|
||||||
|
f 118/60/44 171/76/44 173/74/44
|
||||||
|
f 210/75/44 215/109/44 171/76/44
|
||||||
|
f 217/77/44 174/79/44 176/72/44
|
||||||
|
f 176/72/56 174/79/56 170/73/56
|
||||||
|
f 171/76/57 175/81/57 177/80/57
|
||||||
|
f 217/77/58 175/81/58 171/76/58
|
||||||
|
f 185/83/33 184/82/33 180/49/33
|
||||||
|
f 134/25/15 179/86/15 181/50/15
|
||||||
|
f 180/49/15 178/85/15 114/5/15
|
||||||
|
f 178/85/15 179/86/15 134/25/15
|
||||||
|
f 189/90/15 188/87/15 184/82/15
|
||||||
|
f 183/88/17 185/83/17 181/50/17
|
||||||
|
f 180/49/2 184/82/2 182/89/2
|
||||||
|
f 182/89/32 183/88/32 179/86/32
|
||||||
|
f 189/90/24 193/95/24 192/91/24
|
||||||
|
f 187/92/15 189/90/15 185/83/15
|
||||||
|
f 184/82/15 188/87/15 186/93/15
|
||||||
|
f 186/93/15 187/92/15 183/88/15
|
||||||
|
f 192/91/15 193/95/15 191/94/15
|
||||||
|
f 191/94/2 193/95/2 189/90/2
|
||||||
|
f 192/91/17 190/96/17 186/93/17
|
||||||
|
f 186/93/3 190/96/3 191/94/3
|
||||||
|
f 197/98/54 196/97/54 144/43/54
|
||||||
|
f 144/43/53 196/97/53 195/99/53
|
||||||
|
f 143/44/52 195/99/52 194/100/52
|
||||||
|
f 194/100/51 197/98/51 141/26/51
|
||||||
|
f 208/102/59 209/101/59 201/31/59
|
||||||
|
f 199/35/60 207/103/60 208/102/60
|
||||||
|
f 198/36/61 206/104/61 207/103/61
|
||||||
|
f 209/101/62 206/104/62 198/36/62
|
||||||
|
f 209/101/54 208/102/54 204/105/54
|
||||||
|
f 204/105/53 208/102/53 207/103/53
|
||||||
|
f 203/106/52 207/103/52 206/104/52
|
||||||
|
f 206/104/51 209/101/51 205/108/51
|
||||||
|
f 202/107/63 205/108/63 197/98/63
|
||||||
|
f 195/99/64 203/106/64 202/107/64
|
||||||
|
f 196/97/65 204/105/65 203/106/65
|
||||||
|
f 205/108/66 204/105/66 196/97/66
|
||||||
|
f 174/79/67 217/77/67 215/109/67
|
||||||
|
f 175/81/44 217/77/44 218/78/44
|
||||||
|
f 170/73/44 215/109/44 210/75/44
|
||||||
|
f 173/74/68 177/80/68 218/78/68
|
||||||
|
f 151/61/23 214/66/23 210/75/23
|
||||||
|
f 173/74/44 216/71/44 212/1/44
|
||||||
|
f 139/42/44 212/1/44 211/2/44
|
||||||
|
f 26/45/1 103/1/1 6/3/1
|
||||||
|
f 3/7/2 20/4/2 4/6/2
|
||||||
|
f 45/57/2 20/4/2 52/8/2
|
||||||
|
f 30/42/3 36/9/3 11/11/3
|
||||||
|
f 5/5/2 39/12/2 4/6/2
|
||||||
|
f 3/7/4 4/6/4 53/15/4
|
||||||
|
f 10/20/5 14/16/5 12/18/5
|
||||||
|
f 7/30/6 18/19/6 10/20/6
|
||||||
|
f 33/39/3 20/4/3 31/22/3
|
||||||
|
f 13/17/7 17/23/7 12/18/7
|
||||||
|
f 33/39/4 25/25/4 29/27/4
|
||||||
|
f 7/30/4 10/20/4 8/24/4
|
||||||
|
f 19/29/69 1/28/69 17/23/69
|
||||||
|
f 33/39/4 19/29/4 13/17/4
|
||||||
|
f 1/28/70 25/25/70 18/19/70
|
||||||
|
f 17/23/9 18/19/9 8/24/9
|
||||||
|
f 89/36/10 92/31/10 28/33/10
|
||||||
|
f 31/22/3 16/21/3 36/9/3
|
||||||
|
f 15/41/3 31/22/3 21/34/3
|
||||||
|
f 24/38/11 90/35/11 28/33/11
|
||||||
|
f 23/40/12 91/37/12 24/38/12
|
||||||
|
f 25/25/4 33/39/4 14/16/4
|
||||||
|
f 27/32/4 23/40/4 28/33/4
|
||||||
|
f 19/29/3 33/39/3 15/41/3
|
||||||
|
f 9/60/3 21/34/3 30/42/3
|
||||||
|
f 25/25/4 5/5/4 32/26/4
|
||||||
|
f 35/43/4 5/5/4 34/44/4
|
||||||
|
f 20/4/4 33/39/4 34/44/4
|
||||||
|
f 92/31/13 91/37/13 27/32/13
|
||||||
|
f 107/71/1 103/1/1 63/46/1
|
||||||
|
f 2/65/14 26/45/14 38/48/14
|
||||||
|
f 49/84/15 39/12/15 72/50/15
|
||||||
|
f 44/58/16 48/51/16 59/53/16
|
||||||
|
f 43/59/17 15/41/17 47/54/17
|
||||||
|
f 1/28/17 19/29/17 37/56/17
|
||||||
|
f 51/13/2 39/12/2 52/8/2
|
||||||
|
f 16/21/2 20/4/2 44/58/2
|
||||||
|
f 46/55/18 19/29/18 43/59/18
|
||||||
|
f 21/34/19 9/60/19 47/54/19
|
||||||
|
f 11/11/20 22/10/20 41/62/20
|
||||||
|
f 49/84/21 25/25/21 37/56/21
|
||||||
|
f 26/45/14 6/3/14 50/47/14
|
||||||
|
f 102/2/22 104/64/22 6/3/22
|
||||||
|
f 101/75/23 2/65/23 105/66/23
|
||||||
|
f 54/14/2 55/67/2 53/15/2
|
||||||
|
f 52/8/14 3/7/14 56/68/14
|
||||||
|
f 4/6/15 51/13/15 54/14/15
|
||||||
|
f 51/13/24 52/8/24 55/67/24
|
||||||
|
f 58/70/2 57/69/2 60/52/2
|
||||||
|
f 60/52/25 48/51/25 58/70/25
|
||||||
|
f 22/10/26 16/21/26 58/70/26
|
||||||
|
f 57/69/27 16/21/27 59/53/27
|
||||||
|
f 109/78/71 107/71/71 67/72/71
|
||||||
|
f 63/46/1 26/45/1 61/73/1
|
||||||
|
f 62/76/1 9/60/1 64/74/1
|
||||||
|
f 106/109/1 101/75/1 62/76/1
|
||||||
|
f 65/79/1 108/77/1 67/72/1
|
||||||
|
f 63/46/29 61/73/29 67/72/29
|
||||||
|
f 66/81/30 62/76/30 68/80/30
|
||||||
|
f 106/109/72 62/76/72 108/77/72
|
||||||
|
f 72/50/32 71/49/32 76/83/32
|
||||||
|
f 70/86/15 25/25/15 72/50/15
|
||||||
|
f 39/12/15 5/5/15 71/49/15
|
||||||
|
f 5/5/15 25/25/15 69/85/15
|
||||||
|
f 80/90/15 76/83/15 79/87/15
|
||||||
|
f 70/86/17 72/50/17 74/88/17
|
||||||
|
f 75/82/2 71/49/2 73/89/2
|
||||||
|
f 69/85/33 70/86/33 73/89/33
|
||||||
|
f 84/95/3 80/90/3 83/91/3
|
||||||
|
f 74/88/15 76/83/15 78/92/15
|
||||||
|
f 79/87/15 75/82/15 77/93/15
|
||||||
|
f 73/89/15 74/88/15 77/93/15
|
||||||
|
f 81/96/15 82/94/15 83/91/15
|
||||||
|
f 78/92/2 80/90/2 82/94/2
|
||||||
|
f 79/87/17 77/93/17 83/91/17
|
||||||
|
f 81/96/24 77/93/24 82/94/24
|
||||||
|
f 32/26/13 35/43/13 88/98/13
|
||||||
|
f 87/97/12 35/43/12 86/99/12
|
||||||
|
f 86/99/11 34/44/11 85/100/11
|
||||||
|
f 29/27/10 32/26/10 85/100/10
|
||||||
|
f 91/37/34 92/31/34 99/102/34
|
||||||
|
f 98/103/35 90/35/35 99/102/35
|
||||||
|
f 97/104/36 89/36/36 98/103/36
|
||||||
|
f 92/31/37 89/36/37 100/101/37
|
||||||
|
f 96/108/13 95/105/13 100/101/13
|
||||||
|
f 99/102/12 95/105/12 98/103/12
|
||||||
|
f 98/103/11 94/106/11 97/104/11
|
||||||
|
f 93/107/10 96/108/10 97/104/10
|
||||||
|
f 85/100/38 88/98/38 93/107/38
|
||||||
|
f 94/106/39 86/99/39 93/107/39
|
||||||
|
f 95/105/40 87/97/40 94/106/40
|
||||||
|
f 88/98/41 87/97/41 96/108/41
|
||||||
|
f 61/73/73 106/109/73 65/79/73
|
||||||
|
f 108/77/1 66/81/1 109/78/1
|
||||||
|
f 2/65/1 101/75/1 61/73/1
|
||||||
|
f 68/80/74 64/74/74 109/78/74
|
||||||
|
f 9/60/23 101/75/23 42/61/23
|
||||||
|
f 30/42/1 103/1/1 64/74/1
|
||||||
|
f 103/1/1 30/42/1 102/2/1
|
||||||
|
f 211/2/44 212/1/44 115/3/44
|
||||||
|
f 114/5/2 129/4/2 113/6/2
|
||||||
|
f 154/57/2 161/8/2 129/4/2
|
||||||
|
f 131/10/24 145/9/24 120/11/24
|
||||||
|
f 114/5/2 113/6/2 148/12/2
|
||||||
|
f 112/7/45 162/15/45 113/6/45
|
||||||
|
f 122/17/46 123/16/46 121/18/46
|
||||||
|
f 123/16/47 127/19/47 119/20/47
|
||||||
|
f 142/39/24 140/22/24 129/4/24
|
||||||
|
f 122/17/48 121/18/48 126/23/48
|
||||||
|
f 142/39/45 138/27/45 134/25/45
|
||||||
|
f 116/30/45 117/24/45 119/20/45
|
||||||
|
f 128/29/75 126/23/75 110/28/75
|
||||||
|
f 142/39/45 122/17/45 128/29/45
|
||||||
|
f 110/28/76 127/19/76 134/25/76
|
||||||
|
f 126/23/50 117/24/50 127/19/50
|
||||||
|
f 198/36/51 137/33/51 201/31/51
|
||||||
|
f 140/22/24 145/9/24 125/21/24
|
||||||
|
f 124/41/24 130/34/24 140/22/24
|
||||||
|
f 198/36/52 199/35/52 137/33/52
|
||||||
|
f 199/35/53 200/37/53 133/38/53
|
||||||
|
f 134/25/45 123/16/45 142/39/45
|
||||||
|
f 136/32/45 137/33/45 132/40/45
|
||||||
|
f 128/29/24 124/41/24 142/39/24
|
||||||
|
f 145/9/24 130/34/24 139/42/24
|
||||||
|
f 134/25/45 141/26/45 114/5/45
|
||||||
|
f 129/4/45 114/5/45 143/44/45
|
||||||
|
f 129/4/45 143/44/45 142/39/45
|
||||||
|
f 201/31/54 136/32/54 200/37/54
|
||||||
|
f 135/45/44 212/1/44 172/46/44
|
||||||
|
f 111/65/14 147/48/14 135/45/14
|
||||||
|
f 158/84/15 181/50/15 148/12/15
|
||||||
|
f 153/58/26 168/53/26 157/51/26
|
||||||
|
f 130/34/17 124/41/17 156/54/17
|
||||||
|
f 110/28/17 146/56/17 128/29/17
|
||||||
|
f 154/57/2 148/12/2 161/8/2
|
||||||
|
f 154/57/2 129/4/2 153/58/2
|
||||||
|
f 128/29/18 155/55/18 124/41/18
|
||||||
|
f 118/60/19 130/34/19 151/61/19
|
||||||
|
f 157/51/20 131/10/20 150/62/20
|
||||||
|
f 110/28/21 134/25/21 146/56/21
|
||||||
|
f 135/45/14 159/47/14 115/3/14
|
||||||
|
f 211/2/22 115/3/22 213/64/22
|
||||||
|
f 210/75/23 214/66/23 111/65/23
|
||||||
|
f 163/14/2 162/15/2 164/67/2
|
||||||
|
f 161/8/14 165/68/14 112/7/14
|
||||||
|
f 113/6/15 163/14/15 160/13/15
|
||||||
|
f 160/13/3 164/67/3 161/8/3
|
||||||
|
f 168/53/2 166/69/2 169/52/2
|
||||||
|
f 131/10/25 157/51/25 167/70/25
|
||||||
|
f 131/10/16 167/70/16 125/21/16
|
||||||
|
f 153/58/27 125/21/27 168/53/27
|
||||||
|
f 172/46/77 216/71/77 176/72/77
|
||||||
|
f 111/65/44 135/45/44 170/73/44
|
||||||
|
f 139/42/44 118/60/44 173/74/44
|
||||||
|
f 118/60/44 210/75/44 171/76/44
|
||||||
|
f 218/78/44 217/77/44 176/72/44
|
||||||
|
f 172/46/56 176/72/56 170/73/56
|
||||||
|
f 173/74/57 171/76/57 177/80/57
|
||||||
|
f 215/109/78 217/77/78 171/76/78
|
||||||
|
f 181/50/33 185/83/33 180/49/33
|
||||||
|
f 158/84/15 134/25/15 181/50/15
|
||||||
|
f 148/12/15 180/49/15 114/5/15
|
||||||
|
f 114/5/15 178/85/15 134/25/15
|
||||||
|
f 185/83/15 189/90/15 184/82/15
|
||||||
|
f 179/86/17 183/88/17 181/50/17
|
||||||
|
f 178/85/2 180/49/2 182/89/2
|
||||||
|
f 178/85/32 182/89/32 179/86/32
|
||||||
|
f 188/87/24 189/90/24 192/91/24
|
||||||
|
f 183/88/15 187/92/15 185/83/15
|
||||||
|
f 182/89/15 184/82/15 186/93/15
|
||||||
|
f 182/89/15 186/93/15 183/88/15
|
||||||
|
f 190/96/15 192/91/15 191/94/15
|
||||||
|
f 187/92/2 191/94/2 189/90/2
|
||||||
|
f 188/87/17 192/91/17 186/93/17
|
||||||
|
f 187/92/3 186/93/3 191/94/3
|
||||||
|
f 141/26/54 197/98/54 144/43/54
|
||||||
|
f 143/44/53 144/43/53 195/99/53
|
||||||
|
f 138/27/52 143/44/52 194/100/52
|
||||||
|
f 138/27/51 194/100/51 141/26/51
|
||||||
|
f 200/37/59 208/102/59 201/31/59
|
||||||
|
f 200/37/60 199/35/60 208/102/60
|
||||||
|
f 199/35/61 198/36/61 207/103/61
|
||||||
|
f 201/31/79 209/101/79 198/36/79
|
||||||
|
f 205/108/54 209/101/54 204/105/54
|
||||||
|
f 203/106/53 204/105/53 207/103/53
|
||||||
|
f 202/107/52 203/106/52 206/104/52
|
||||||
|
f 202/107/51 206/104/51 205/108/51
|
||||||
|
f 194/100/63 202/107/63 197/98/63
|
||||||
|
f 194/100/64 195/99/64 202/107/64
|
||||||
|
f 195/99/65 196/97/65 203/106/65
|
||||||
|
f 197/98/66 205/108/66 196/97/66
|
||||||
|
f 170/73/80 174/79/80 215/109/80
|
||||||
|
f 177/80/44 175/81/44 218/78/44
|
||||||
|
f 111/65/44 170/73/44 210/75/44
|
||||||
|
f 216/71/81 173/74/81 218/78/81
|
||||||
|
f 118/60/23 151/61/23 210/75/23
|
||||||
|
f 139/42/44 173/74/44 212/1/44
|
||||||
|
f 120/11/44 139/42/44 211/2/44
|
||||||
|
usemtl Material.003
|
||||||
|
f 41/62/82 104/64/82 102/2/82
|
||||||
|
f 211/2/82 213/64/82 150/62/82
|
||||||
|
f 11/11/82 41/62/82 102/2/82
|
||||||
|
f 120/11/82 211/2/82 150/62/82
|
||||||
6
models/mtllib-multiple-files-issue-112.mtl
Normal file
6
models/mtllib-multiple-files-issue-112.mtl
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
map_Kd tmp.png
|
||||||
|
|
||||||
7
models/mtllib-multiple-files-issue-112.obj
Normal file
7
models/mtllib-multiple-files-issue-112.obj
Normal 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
|
||||||
7
models/norm-texopt.mtl
Normal file
7
models/norm-texopt.mtl
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
newmtl default
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
Kt 0.1 0.2 0.3
|
||||||
|
norm -bm 3 normalmap.jpg
|
||||||
|
|
||||||
7
models/norm-texopt.obj
Normal file
7
models/norm-texopt.obj
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
mtllib norm-texopt.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
|
||||||
19
models/pbr-mat-ext.mtl
Normal file
19
models/pbr-mat-ext.mtl
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# .MTL with PBR extension.
|
||||||
|
newmtl pbr
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
Ke 0.1 0.1 0.1
|
||||||
|
Pr 0.2
|
||||||
|
Pm 0.3
|
||||||
|
Ps 0.4
|
||||||
|
Pc 0.5
|
||||||
|
Pcr 0.6
|
||||||
|
aniso 0.7
|
||||||
|
anisor 0.8
|
||||||
|
map_Pr roughness.tex
|
||||||
|
map_Pm metallic.tex
|
||||||
|
map_Ps sheen.tex
|
||||||
|
map_Ke emissive.tex
|
||||||
|
norm normalmap.tex
|
||||||
|
|
||||||
10
models/pbr-mat-ext.obj
Normal file
10
models/pbr-mat-ext.obj
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
mtllib pbr-mat-ext.mtl
|
||||||
|
|
||||||
|
o floor
|
||||||
|
usemtl pbr
|
||||||
|
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
|
||||||
|
|
||||||
|
f 1 2 3 4
|
||||||
25
models/refl.mtl
Normal file
25
models/refl.mtl
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
newmtl white
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
refl reflection.tga
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 1 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl blue
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl light
|
||||||
|
Ka 20 20 20
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
32
models/refl.obj
Normal file
32
models/refl.obj
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
# Test for `refl` material parameter
|
||||||
|
mtllib refl.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1 2 3 4
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7 6 5
|
||||||
|
g right cube
|
||||||
|
usemtl red
|
||||||
|
f 4 3 7 8
|
||||||
|
g top cube
|
||||||
|
usemtl white
|
||||||
|
f 5 1 4 8
|
||||||
|
g left cube
|
||||||
|
usemtl green
|
||||||
|
f 5 6 2 1
|
||||||
|
g bottom cube
|
||||||
|
usemtl white
|
||||||
|
f 2 6 7 3
|
||||||
|
# 6 elements
|
||||||
22
models/smoothing-group-two-squares.obj
Normal file
22
models/smoothing-group-two-squares.obj
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# from tinyobjloader issue #29
|
||||||
|
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
v 4.000000 0.000000 -3.255298
|
||||||
|
v 4.000000 2.000000 -3.255298
|
||||||
|
#vn 0.000000 0.000000 1.000000
|
||||||
|
#vn 0.000000 0.000000 1.000000
|
||||||
|
#vn 0.276597 0.000000 0.960986
|
||||||
|
#vn 0.276597 0.000000 0.960986
|
||||||
|
#vn 0.531611 0.000000 0.846988
|
||||||
|
#vn 0.531611 0.000000 0.846988
|
||||||
|
# 6 vertices
|
||||||
|
|
||||||
|
# 6 normals
|
||||||
|
|
||||||
|
g all
|
||||||
|
s 1
|
||||||
|
f 1//1 2//2 3//3 4//4
|
||||||
|
f 4//4 3//3 5//5
|
||||||
24
models/smoothing-normal.mtl
Normal file
24
models/smoothing-normal.mtl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
newmtl white
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 1 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl blue
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl light
|
||||||
|
Ka 20 20 20
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
35
models/smoothing-normal.obj
Normal file
35
models/smoothing-normal.obj
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
mtllib smoothing-normal.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
s 1
|
||||||
|
f 1 2 3 4
|
||||||
|
#g bottom cube
|
||||||
|
#usemtl white
|
||||||
|
s 1
|
||||||
|
f 2 6 7 3
|
||||||
|
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
s off
|
||||||
|
f 8 7 6 5
|
||||||
|
#g right cube
|
||||||
|
#usemtl red
|
||||||
|
#f 4 3 7 8
|
||||||
|
#g top cube
|
||||||
|
#usemtl white
|
||||||
|
#f 5 1 4 8
|
||||||
|
#g left cube
|
||||||
|
#usemtl green
|
||||||
|
#f 5 6 2 1
|
||||||
|
# 6 elements
|
||||||
28
models/texture-filename-with-whitespace.mtl
Normal file
28
models/texture-filename-with-whitespace.mtl
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
newmtl white
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
# filename with white space.
|
||||||
|
map_Kd texture 01.png
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
# texture option + filename with white space.
|
||||||
|
bump -bm 2 bump 01.png
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 1 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl blue
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl light
|
||||||
|
Ka 20 20 20
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
31
models/texture-filename-with-whitespace.obj
Normal file
31
models/texture-filename-with-whitespace.obj
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
mtllib texture-filename-with-whitespace.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1 2 3 4
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7 6 5
|
||||||
|
g right cube
|
||||||
|
usemtl red
|
||||||
|
f 4 3 7 8
|
||||||
|
g top cube
|
||||||
|
usemtl white
|
||||||
|
f 5 1 4 8
|
||||||
|
g left cube
|
||||||
|
usemtl green
|
||||||
|
f 5 6 2 1
|
||||||
|
g bottom cube
|
||||||
|
usemtl white
|
||||||
|
f 2 6 7 3
|
||||||
|
# 6 elements
|
||||||
36
models/texture-options-issue-85.mtl
Normal file
36
models/texture-options-issue-85.mtl
Normal 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
|
||||||
7
models/texture-options-issue-85.obj
Normal file
7
models/texture-options-issue-85.obj
Normal 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
|
||||||
13
models/tr-and-d-issue-43.mtl
Normal file
13
models/tr-and-d-issue-43.mtl
Normal 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
|
||||||
817
models/tr-and-d-issue-43.obj
Normal file
817
models/tr-and-d-issue-43.obj
Normal 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
|
||||||
30
models/usemtl-issue-104.obj
Normal file
30
models/usemtl-issue-104.obj
Normal 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
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
sources = {
|
sources = {
|
||||||
"test.cc",
|
"loader_example.cc",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- premake4.lua
|
-- premake4.lua
|
||||||
@@ -21,9 +21,9 @@ solution "TinyObjLoaderSolution"
|
|||||||
configuration "Debug"
|
configuration "Debug"
|
||||||
defines { "DEBUG" } -- -DDEBUG
|
defines { "DEBUG" } -- -DDEBUG
|
||||||
flags { "Symbols" }
|
flags { "Symbols" }
|
||||||
targetname "test_tinyobjloader_debug"
|
targetname "loader_example_debug"
|
||||||
|
|
||||||
configuration "Release"
|
configuration "Release"
|
||||||
-- defines { "NDEBUG" } -- -NDEBUG
|
-- defines { "NDEBUG" } -- -NDEBUG
|
||||||
flags { "Symbols", "Optimize" }
|
flags { "Symbols", "Optimize" }
|
||||||
targetname "test_tinyobjloader"
|
targetname "loader_example"
|
||||||
|
|||||||
2
python/TODO.md
Normal file
2
python/TODO.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
* PBR material
|
||||||
|
* Define index_t struct
|
||||||
236
python/main.cpp
236
python/main.cpp
@@ -1,160 +1,212 @@
|
|||||||
//python3 module for tinyobjloader
|
// python2/3 module for tinyobjloader
|
||||||
//
|
//
|
||||||
// usage:
|
// usage:
|
||||||
// import tinyobjloader as tol
|
// import tinyobjloader as tol
|
||||||
// model = tol.LoadObj(name)
|
// model = tol.LoadObj(name)
|
||||||
// print(model["shapes"])
|
// print(model["shapes"])
|
||||||
// print(model["materials"]
|
// print(model["materials"]
|
||||||
|
// note:
|
||||||
|
// `shape.mesh.index_t` is represented as flattened array: (vertex_index, normal_index, texcoord_index) * num_faces
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "../tiny_obj_loader.h"
|
#include "../tiny_obj_loader.h"
|
||||||
|
|
||||||
typedef std::vector<double> vectd;
|
typedef std::vector<double> vectd;
|
||||||
|
typedef std::vector<int> vecti;
|
||||||
|
|
||||||
PyObject*
|
PyObject* pyTupleFromfloat3(float array[3]) {
|
||||||
pyTupleFromfloat3 (float array[3])
|
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
PyObject* tuple = PyTuple_New(3);
|
PyObject* tuple = PyTuple_New(3);
|
||||||
|
|
||||||
for (i = 0; i <= 2; i++) {
|
for (i = 0; i <= 2; i++) {
|
||||||
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
|
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tuple;
|
return tuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
|
||||||
|
|
||||||
static PyObject*
|
|
||||||
pyLoadObj(PyObject* self, PyObject* args)
|
|
||||||
{
|
|
||||||
PyObject *rtndict, *pyshapes, *pymaterials,
|
|
||||||
*current, *meshobj;
|
|
||||||
|
|
||||||
|
static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
|
||||||
|
PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *attribobj, *current, *meshobj;
|
||||||
|
char const* current_name;
|
||||||
char const* filename;
|
char const* filename;
|
||||||
char *current_name;
|
|
||||||
vectd vect;
|
vectd vect;
|
||||||
|
std::vector<tinyobj::index_t> indices;
|
||||||
|
std::vector<unsigned char> face_verts;
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
std::vector<tinyobj::material_t> materials;
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
if(!PyArg_ParseTuple(args, "s", &filename))
|
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
std::string err;
|
|
||||||
tinyobj::LoadObj(shapes, materials, err, filename);
|
|
||||||
|
|
||||||
|
std::string err, warn;
|
||||||
|
tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename);
|
||||||
pyshapes = PyDict_New();
|
pyshapes = PyDict_New();
|
||||||
pymaterials = PyDict_New();
|
pymaterials = PyDict_New();
|
||||||
|
pymaterial_indices = PyList_New(0);
|
||||||
rtndict = PyDict_New();
|
rtndict = PyDict_New();
|
||||||
|
attribobj = PyDict_New();
|
||||||
|
|
||||||
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin() ;
|
for (int i = 0; i <= 2; i++) {
|
||||||
shape != shapes.end(); shape++)
|
current = PyList_New(0);
|
||||||
{
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
current_name = "vertices";
|
||||||
|
vect = vectd(attrib.vertices.begin(), attrib.vertices.end());
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
current_name = "normals";
|
||||||
|
vect = vectd(attrib.normals.begin(), attrib.normals.end());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
current_name = "texcoords";
|
||||||
|
vect = vectd(attrib.texcoords.begin(), attrib.texcoords.end());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
|
||||||
|
PyObject* value = PyFloat_FromDouble(*it);
|
||||||
|
PyList_Insert(current, it - vect.begin(), value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(attribobj, current_name, current);
|
||||||
|
Py_DECREF(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin(); shape != shapes.end(); shape++) {
|
||||||
meshobj = PyDict_New();
|
meshobj = PyDict_New();
|
||||||
tinyobj::mesh_t cm = (*shape).mesh;
|
tinyobj::mesh_t cm = (*shape).mesh;
|
||||||
|
|
||||||
for (int i = 0; i <= 4; i++ )
|
|
||||||
{
|
{
|
||||||
current = PyList_New(0);
|
current = PyList_New(0);
|
||||||
|
for (size_t i = 0; i < cm.indices.size(); i++) {
|
||||||
switch(i) {
|
// Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
|
||||||
|
PyObject* value = PyLong_FromLong(cm.indices[i].vertex_index);
|
||||||
case 0:
|
PyList_Insert(current, 3 * i + 0, value);
|
||||||
current_name = "positions";
|
Py_DECREF(value);
|
||||||
vect = vectd(cm.positions.begin(), cm.positions.end()); break;
|
value = PyLong_FromLong(cm.indices[i].normal_index);
|
||||||
case 1:
|
PyList_Insert(current, 3 * i + 1, value);
|
||||||
current_name = "normals";
|
Py_DECREF(value);
|
||||||
vect = vectd(cm.normals.begin(), cm.normals.end()); break;
|
value = PyLong_FromLong(cm.indices[i].texcoord_index);
|
||||||
case 2:
|
PyList_Insert(current, 3 * i + 2, value);
|
||||||
current_name = "texcoords";
|
Py_DECREF(value);
|
||||||
vect = vectd(cm.texcoords.begin(), cm.texcoords.end()); break;
|
}
|
||||||
case 3:
|
PyDict_SetItemString(meshobj, "indices", current);
|
||||||
current_name = "indicies";
|
Py_DECREF(current);
|
||||||
vect = vectd(cm.indices.begin(), cm.indices.end()); break;
|
|
||||||
case 4:
|
|
||||||
current_name = "material_ids";
|
|
||||||
vect = vectd(cm.material_ids.begin(), cm.material_ids.end()); break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (vectd::iterator it = vect.begin() ;
|
|
||||||
it != vect.end(); it++)
|
|
||||||
{
|
{
|
||||||
PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
|
current = PyList_New(0);
|
||||||
|
for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
|
||||||
|
// Widen data type to long.
|
||||||
|
PyObject* value = PyLong_FromLong(cm.num_face_vertices[i]);
|
||||||
|
PyList_Insert(current, i, value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(meshobj, "num_face_vertices", current);
|
||||||
|
Py_DECREF(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_SetItemString(meshobj, current_name, current);
|
{
|
||||||
|
current = PyList_New(0);
|
||||||
|
for (size_t i = 0; i < cm.material_ids.size(); i++) {
|
||||||
|
PyObject* value = PyLong_FromLong(cm.material_ids[i]);
|
||||||
|
PyList_Insert(current, i, value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
}
|
||||||
|
PyDict_SetItemString(meshobj, "material_ids", current);
|
||||||
|
Py_DECREF(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
|
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
|
||||||
|
Py_DECREF(meshobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin() ;
|
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin(); mat != materials.end(); mat++) {
|
||||||
mat != materials.end(); mat++)
|
|
||||||
{
|
|
||||||
PyObject* matobj = PyDict_New();
|
PyObject* matobj = PyDict_New();
|
||||||
PyObject* unknown_parameter = PyDict_New();
|
PyObject* unknown_parameter = PyDict_New();
|
||||||
|
|
||||||
for (std::map<std::string, std::string>::iterator p = (*mat).unknown_parameter.begin() ;
|
for (std::map<std::string, std::string>::iterator p = mat->unknown_parameter.begin(); p != mat->unknown_parameter.end(); ++p) {
|
||||||
p != (*mat).unknown_parameter.end(); ++p)
|
PyObject* value = PyUnicode_FromString(p->second.c_str());
|
||||||
{
|
PyDict_SetItemString(unknown_parameter, p->first.c_str(), value);
|
||||||
PyDict_SetItemString(unknown_parameter, p->first.c_str(), PyUnicode_FromString(p->second.c_str()));
|
Py_DECREF(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_SetItemString(matobj, "shininess", PyFloat_FromDouble((*mat).shininess));
|
PyObject* value = PyFloat_FromDouble(mat->shininess);
|
||||||
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior));
|
PyDict_SetItemString(matobj, "shininess", value);
|
||||||
PyDict_SetItemString(matobj, "dissolve", PyFloat_FromDouble((*mat).dissolve));
|
Py_DECREF(value);
|
||||||
PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum));
|
value = PyFloat_FromDouble(mat->ior);
|
||||||
PyDict_SetItemString(matobj, "ambient_texname", PyUnicode_FromString((*mat).ambient_texname.c_str()));
|
PyDict_SetItemString(matobj, "ior", value);
|
||||||
PyDict_SetItemString(matobj, "diffuse_texname", PyUnicode_FromString((*mat).diffuse_texname.c_str()));
|
Py_DECREF(value);
|
||||||
PyDict_SetItemString(matobj, "specular_texname", PyUnicode_FromString((*mat).specular_texname.c_str()));
|
value = PyFloat_FromDouble(mat->dissolve);
|
||||||
PyDict_SetItemString(matobj, "specular_highlight_texname", PyUnicode_FromString((*mat).specular_highlight_texname.c_str()));
|
PyDict_SetItemString(matobj, "dissolve", value);
|
||||||
PyDict_SetItemString(matobj, "bump_texname", PyUnicode_FromString((*mat).bump_texname.c_str()));
|
Py_DECREF(value);
|
||||||
PyDict_SetItemString(matobj, "displacement_texname", PyUnicode_FromString((*mat).displacement_texname.c_str()));
|
value = PyLong_FromLong(mat->illum);
|
||||||
PyDict_SetItemString(matobj, "alpha_texname", PyUnicode_FromString((*mat).alpha_texname.c_str()));
|
PyDict_SetItemString(matobj, "illum", value);
|
||||||
PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3((*mat).ambient));
|
Py_DECREF(value);
|
||||||
PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3((*mat).diffuse));
|
value = PyUnicode_FromString(mat->ambient_texname.c_str());
|
||||||
PyDict_SetItemString(matobj, "specular", pyTupleFromfloat3((*mat).specular));
|
PyDict_SetItemString(matobj, "ambient_texname", value);
|
||||||
PyDict_SetItemString(matobj, "transmittance", pyTupleFromfloat3((*mat).transmittance));
|
Py_DECREF(value);
|
||||||
PyDict_SetItemString(matobj, "emission", pyTupleFromfloat3((*mat).emission));
|
value = PyUnicode_FromString(mat->diffuse_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "diffuse_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = PyUnicode_FromString(mat->specular_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "specular_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = PyUnicode_FromString(mat->specular_highlight_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "specular_highlight_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = PyUnicode_FromString(mat->bump_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "bump_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = PyUnicode_FromString(mat->displacement_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "displacement_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
value = PyUnicode_FromString(mat->alpha_texname.c_str());
|
||||||
|
PyDict_SetItemString(matobj, "alpha_texname", value);
|
||||||
|
Py_DECREF(value);
|
||||||
|
PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3(mat->ambient));
|
||||||
|
PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3(mat->diffuse));
|
||||||
|
PyDict_SetItemString(matobj, "specular", pyTupleFromfloat3(mat->specular));
|
||||||
|
PyDict_SetItemString(matobj, "transmittance", pyTupleFromfloat3(mat->transmittance));
|
||||||
|
PyDict_SetItemString(matobj, "emission", pyTupleFromfloat3(mat->emission));
|
||||||
PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);
|
PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);
|
||||||
|
Py_DECREF(unknown_parameter);
|
||||||
PyDict_SetItemString(pymaterials, (*mat).name.c_str(), matobj);
|
PyDict_SetItemString(pymaterials, mat->name.c_str(), matobj);
|
||||||
|
Py_DECREF(matobj);
|
||||||
|
value = PyUnicode_FromString(mat->name.c_str());
|
||||||
|
PyList_Append(pymaterial_indices, value);
|
||||||
|
Py_DECREF(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
||||||
|
Py_DECREF(pyshapes);
|
||||||
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
||||||
|
Py_DECREF(pymaterials);
|
||||||
|
PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices);
|
||||||
|
Py_DECREF(pymaterial_indices);
|
||||||
|
PyDict_SetItemString(rtndict, "attribs", attribobj);
|
||||||
|
Py_DECREF(attribobj);
|
||||||
return rtndict;
|
return rtndict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static PyMethodDef mMethods[] = {
|
static PyMethodDef mMethods[] = {
|
||||||
|
{"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL}
|
||||||
{"LoadObj", pyLoadObj, METH_VARARGS},
|
|
||||||
{NULL, NULL, 0, NULL}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
|
||||||
static struct PyModuleDef moduledef = {
|
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader", NULL, -1, mMethods};
|
||||||
PyModuleDef_HEAD_INIT,
|
|
||||||
"tinyobjloader",
|
|
||||||
NULL,
|
|
||||||
-1,
|
|
||||||
mMethods
|
|
||||||
};
|
|
||||||
|
|
||||||
|
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
|
||||||
PyMODINIT_FUNC
|
|
||||||
PyInit_tinyobjloader(void)
|
|
||||||
{
|
|
||||||
return PyModule_Create(&moduledef);
|
return PyModule_Create(&moduledef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
PyMODINIT_FUNC inittinyobjloader(void) {
|
||||||
|
Py_InitModule3("tinyobjloader", mMethods, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PY_MAJOR_VERSION >= 3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
279
test.cc
279
test.cc
@@ -1,279 +0,0 @@
|
|||||||
#define TINYOBJLOADER_IMPLEMENTATION
|
|
||||||
#include "tiny_obj_loader.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool triangulate = true)
|
|
||||||
{
|
|
||||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
|
||||||
std::cout << "# of materials : " << materials.size() << std::endl;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < shapes.size(); i++) {
|
|
||||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
|
||||||
printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
|
||||||
|
|
||||||
if (triangulate)
|
|
||||||
{
|
|
||||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
|
||||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
|
||||||
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
|
|
||||||
printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
|
||||||
printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
|
||||||
assert(shapes[i].mesh.material_ids.size() == shapes[i].mesh.num_vertices.size());
|
|
||||||
for (size_t m = 0; m < shapes[i].mesh.material_ids.size(); m++) {
|
|
||||||
printf(" material_id[%ld] = %d\n", m,
|
|
||||||
shapes[i].mesh.material_ids[m]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("shape[%ld].num_faces: %ld\n", i, shapes[i].mesh.num_vertices.size());
|
|
||||||
for (size_t v = 0; v < shapes[i].mesh.num_vertices.size(); v++) {
|
|
||||||
printf(" num_vertices[%ld] = %ld\n", v,
|
|
||||||
static_cast<long>(shapes[i].mesh.num_vertices[v]));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
|
||||||
assert((shapes[i].mesh.positions.size() % 3) == 0);
|
|
||||||
for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
|
|
||||||
printf(" v[%ld] = (%f, %f, %f)\n", v,
|
|
||||||
shapes[i].mesh.positions[3*v+0],
|
|
||||||
shapes[i].mesh.positions[3*v+1],
|
|
||||||
shapes[i].mesh.positions[3*v+2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("shape[%ld].num_tags: %ld\n", i, shapes[i].mesh.tags.size());
|
|
||||||
for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) {
|
|
||||||
printf(" tag[%ld] = %s ", t, shapes[i].mesh.tags[t].name.c_str());
|
|
||||||
printf(" ints: [");
|
|
||||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j)
|
|
||||||
{
|
|
||||||
printf("%ld", static_cast<long>(shapes[i].mesh.tags[t].intValues[j]));
|
|
||||||
if (j < (shapes[i].mesh.tags[t].intValues.size()-1))
|
|
||||||
{
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("]");
|
|
||||||
|
|
||||||
printf(" floats: [");
|
|
||||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j)
|
|
||||||
{
|
|
||||||
printf("%f", shapes[i].mesh.tags[t].floatValues[j]);
|
|
||||||
if (j < (shapes[i].mesh.tags[t].floatValues.size()-1))
|
|
||||||
{
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("]");
|
|
||||||
|
|
||||||
printf(" strings: [");
|
|
||||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j)
|
|
||||||
{
|
|
||||||
printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str());
|
|
||||||
if (j < (shapes[i].mesh.tags[t].stringValues.size()-1))
|
|
||||||
{
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("]");
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < materials.size(); i++) {
|
|
||||||
printf("material[%ld].name = %s\n", i, materials[i].name.c_str());
|
|
||||||
printf(" material.Ka = (%f, %f ,%f)\n", materials[i].ambient[0], materials[i].ambient[1], materials[i].ambient[2]);
|
|
||||||
printf(" material.Kd = (%f, %f ,%f)\n", materials[i].diffuse[0], materials[i].diffuse[1], materials[i].diffuse[2]);
|
|
||||||
printf(" material.Ks = (%f, %f ,%f)\n", materials[i].specular[0], materials[i].specular[1], materials[i].specular[2]);
|
|
||||||
printf(" material.Tr = (%f, %f ,%f)\n", materials[i].transmittance[0], materials[i].transmittance[1], materials[i].transmittance[2]);
|
|
||||||
printf(" material.Ke = (%f, %f ,%f)\n", materials[i].emission[0], materials[i].emission[1], materials[i].emission[2]);
|
|
||||||
printf(" material.Ns = %f\n", materials[i].shininess);
|
|
||||||
printf(" material.Ni = %f\n", materials[i].ior);
|
|
||||||
printf(" material.dissolve = %f\n", materials[i].dissolve);
|
|
||||||
printf(" material.illum = %d\n", materials[i].illum);
|
|
||||||
printf(" material.map_Ka = %s\n", materials[i].ambient_texname.c_str());
|
|
||||||
printf(" material.map_Kd = %s\n", materials[i].diffuse_texname.c_str());
|
|
||||||
printf(" material.map_Ks = %s\n", materials[i].specular_texname.c_str());
|
|
||||||
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(" material.map_d = %s\n", materials[i].alpha_texname.c_str());
|
|
||||||
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
|
|
||||||
std::map<std::string, std::string>::const_iterator it(materials[i].unknown_parameter.begin());
|
|
||||||
std::map<std::string, std::string>::const_iterator itEnd(materials[i].unknown_parameter.end());
|
|
||||||
|
|
||||||
for (; it != itEnd; it++) {
|
|
||||||
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
TestLoadObj(
|
|
||||||
const char* filename,
|
|
||||||
const char* basepath = NULL,
|
|
||||||
unsigned int flags = 1 )
|
|
||||||
{
|
|
||||||
std::cout << "Loading " << filename << std::endl;
|
|
||||||
|
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
|
||||||
std::vector<tinyobj::material_t> materials;
|
|
||||||
|
|
||||||
std::string err;
|
|
||||||
bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath, flags);
|
|
||||||
|
|
||||||
if (!err.empty()) {
|
|
||||||
std::cerr << err << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
printf("Failed to load/parse .obj.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool triangulate( ( flags & tinyobj::triangulation ) == tinyobj::triangulation );
|
|
||||||
PrintInfo(shapes, materials, triangulate );
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
TestStreamLoadObj()
|
|
||||||
{
|
|
||||||
std::cout << "Stream Loading " << std::endl;
|
|
||||||
|
|
||||||
std::stringstream objStream;
|
|
||||||
objStream
|
|
||||||
<< "mtllib cube.mtl\n"
|
|
||||||
"\n"
|
|
||||||
"v 0.000000 2.000000 2.000000\n"
|
|
||||||
"v 0.000000 0.000000 2.000000\n"
|
|
||||||
"v 2.000000 0.000000 2.000000\n"
|
|
||||||
"v 2.000000 2.000000 2.000000\n"
|
|
||||||
"v 0.000000 2.000000 0.000000\n"
|
|
||||||
"v 0.000000 0.000000 0.000000\n"
|
|
||||||
"v 2.000000 0.000000 0.000000\n"
|
|
||||||
"v 2.000000 2.000000 0.000000\n"
|
|
||||||
"# 8 vertices\n"
|
|
||||||
"\n"
|
|
||||||
"g front cube\n"
|
|
||||||
"usemtl white\n"
|
|
||||||
"f 1 2 3 4\n"
|
|
||||||
"g back cube\n"
|
|
||||||
"# expects white material\n"
|
|
||||||
"f 8 7 6 5\n"
|
|
||||||
"g right cube\n"
|
|
||||||
"usemtl red\n"
|
|
||||||
"f 4 3 7 8\n"
|
|
||||||
"g top cube\n"
|
|
||||||
"usemtl white\n"
|
|
||||||
"f 5 1 4 8\n"
|
|
||||||
"g left cube\n"
|
|
||||||
"usemtl green\n"
|
|
||||||
"f 5 6 2 1\n"
|
|
||||||
"g bottom cube\n"
|
|
||||||
"usemtl white\n"
|
|
||||||
"f 2 6 7 3\n"
|
|
||||||
"# 6 elements";
|
|
||||||
|
|
||||||
std::string matStream(
|
|
||||||
"newmtl white\n"
|
|
||||||
"Ka 0 0 0\n"
|
|
||||||
"Kd 1 1 1\n"
|
|
||||||
"Ks 0 0 0\n"
|
|
||||||
"\n"
|
|
||||||
"newmtl red\n"
|
|
||||||
"Ka 0 0 0\n"
|
|
||||||
"Kd 1 0 0\n"
|
|
||||||
"Ks 0 0 0\n"
|
|
||||||
"\n"
|
|
||||||
"newmtl green\n"
|
|
||||||
"Ka 0 0 0\n"
|
|
||||||
"Kd 0 1 0\n"
|
|
||||||
"Ks 0 0 0\n"
|
|
||||||
"\n"
|
|
||||||
"newmtl blue\n"
|
|
||||||
"Ka 0 0 0\n"
|
|
||||||
"Kd 0 0 1\n"
|
|
||||||
"Ks 0 0 0\n"
|
|
||||||
"\n"
|
|
||||||
"newmtl light\n"
|
|
||||||
"Ka 20 20 20\n"
|
|
||||||
"Kd 1 1 1\n"
|
|
||||||
"Ks 0 0 0");
|
|
||||||
|
|
||||||
using namespace tinyobj;
|
|
||||||
class MaterialStringStreamReader:
|
|
||||||
public MaterialReader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MaterialStringStreamReader(const std::string& matSStream): m_matSStream(matSStream) {}
|
|
||||||
virtual ~MaterialStringStreamReader() {}
|
|
||||||
virtual bool operator() (
|
|
||||||
const std::string& matId,
|
|
||||||
std::vector<material_t>& materials,
|
|
||||||
std::map<std::string, int>& matMap,
|
|
||||||
std::string& err)
|
|
||||||
{
|
|
||||||
(void)matId;
|
|
||||||
(void)err;
|
|
||||||
LoadMtl(matMap, materials, m_matSStream);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::stringstream m_matSStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
MaterialStringStreamReader matSSReader(matStream);
|
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
|
||||||
std::vector<tinyobj::material_t> materials;
|
|
||||||
std::string err;
|
|
||||||
bool ret = tinyobj::LoadObj(shapes, materials, err, objStream, matSSReader);
|
|
||||||
|
|
||||||
if (!err.empty()) {
|
|
||||||
std::cerr << err << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintInfo(shapes, materials);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(
|
|
||||||
int argc,
|
|
||||||
char **argv)
|
|
||||||
{
|
|
||||||
if (argc > 1) {
|
|
||||||
const char* basepath = NULL;
|
|
||||||
if (argc > 2) {
|
|
||||||
basepath = argv[2];
|
|
||||||
}
|
|
||||||
assert(true == TestLoadObj(argv[1], basepath));
|
|
||||||
} else {
|
|
||||||
//assert(true == TestLoadObj("cornell_box.obj"));
|
|
||||||
//assert(true == TestLoadObj("cube.obj"));
|
|
||||||
assert(true == TestStreamLoadObj());
|
|
||||||
assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
16
tests/Makefile
Normal file
16
tests/Makefile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
CXX ?= g++
|
||||||
|
CXXFLAGS ?= -g -O2
|
||||||
|
|
||||||
|
tester: tester.cc
|
||||||
|
$(CXX) $(CXXFLAGS) -o tester tester.cc
|
||||||
|
|
||||||
|
all: tester
|
||||||
|
|
||||||
|
check: tester
|
||||||
|
./tester
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf tester
|
||||||
|
|
||||||
37
tests/README.md
Normal file
37
tests/README.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Build&Test
|
||||||
|
|
||||||
|
## Use makefile
|
||||||
|
|
||||||
|
$ make check
|
||||||
|
|
||||||
|
## Use ninja + kuroga
|
||||||
|
|
||||||
|
Assume
|
||||||
|
|
||||||
|
* ninja 1.4+
|
||||||
|
* python 2.6+
|
||||||
|
|
||||||
|
Are installed.
|
||||||
|
|
||||||
|
### Linux/MacOSX
|
||||||
|
|
||||||
|
$ python kuroga.py config-posix.py
|
||||||
|
$ ninja
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
Visual Studio 2013 is required to build tester.
|
||||||
|
|
||||||
|
On Windows console.
|
||||||
|
|
||||||
|
> python kuroga.py config-msvc.py
|
||||||
|
> vcbuild.bat
|
||||||
|
|
||||||
|
|
||||||
|
Or on msys2 bash,
|
||||||
|
|
||||||
|
$ python kuroga.py config-msvc.py
|
||||||
|
$ cmd //c vcbuild.bat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
10445
tests/catch.hpp
Normal file
10445
tests/catch.hpp
Normal file
File diff suppressed because it is too large
Load Diff
52
tests/config-msvc.py
Normal file
52
tests/config-msvc.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
exe = "tester.exe"
|
||||||
|
|
||||||
|
toolchain = "msvc"
|
||||||
|
|
||||||
|
# optional
|
||||||
|
link_pool_depth = 1
|
||||||
|
|
||||||
|
# optional
|
||||||
|
builddir = {
|
||||||
|
"gnu" : "build"
|
||||||
|
, "msvc" : "build"
|
||||||
|
, "clang" : "build"
|
||||||
|
}
|
||||||
|
|
||||||
|
includes = {
|
||||||
|
"gnu" : [ "-I." ]
|
||||||
|
, "msvc" : [ "/I." ]
|
||||||
|
, "clang" : [ "-I." ]
|
||||||
|
}
|
||||||
|
|
||||||
|
defines = {
|
||||||
|
"gnu" : [ "-DEXAMPLE=1" ]
|
||||||
|
, "msvc" : [ "/DEXAMPLE=1" ]
|
||||||
|
, "clang" : [ "-DEXAMPLE=1" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
cflags = {
|
||||||
|
"gnu" : [ "-O2", "-g" ]
|
||||||
|
, "msvc" : [ "/O2" ]
|
||||||
|
, "clang" : [ "-O2", "-g" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
cxxflags = {
|
||||||
|
"gnu" : [ "-O2", "-g" ]
|
||||||
|
, "msvc" : [ "/O2", "/W4", "/EHsc"]
|
||||||
|
, "clang" : [ "-O2", "-g", "-fsanitize=address" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
ldflags = {
|
||||||
|
"gnu" : [ ]
|
||||||
|
, "msvc" : [ ]
|
||||||
|
, "clang" : [ "-fsanitize=address" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# optionsl
|
||||||
|
cxx_files = [ "tester.cc" ]
|
||||||
|
c_files = [ ]
|
||||||
|
|
||||||
|
# You can register your own toolchain through register_toolchain function
|
||||||
|
def register_toolchain(ninja):
|
||||||
|
pass
|
||||||
|
|
||||||
53
tests/config-posix.py
Normal file
53
tests/config-posix.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
exe = "tester"
|
||||||
|
|
||||||
|
# "gnu" or "clang"
|
||||||
|
toolchain = "gnu"
|
||||||
|
|
||||||
|
# optional
|
||||||
|
link_pool_depth = 1
|
||||||
|
|
||||||
|
# optional
|
||||||
|
builddir = {
|
||||||
|
"gnu" : "build"
|
||||||
|
, "msvc" : "build"
|
||||||
|
, "clang" : "build"
|
||||||
|
}
|
||||||
|
|
||||||
|
includes = {
|
||||||
|
"gnu" : [ "-I." ]
|
||||||
|
, "msvc" : [ "/I." ]
|
||||||
|
, "clang" : [ "-I." ]
|
||||||
|
}
|
||||||
|
|
||||||
|
defines = {
|
||||||
|
"gnu" : [ ]
|
||||||
|
, "msvc" : [ ]
|
||||||
|
, "clang" : [ ]
|
||||||
|
}
|
||||||
|
|
||||||
|
cflags = {
|
||||||
|
"gnu" : [ "-O2", "-g" ]
|
||||||
|
, "msvc" : [ "/O2" ]
|
||||||
|
, "clang" : [ "-O2", "-g" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Warn as much as possible: http://qiita.com/MitsutakaTakeda/items/6b9966f890cc9b944d75
|
||||||
|
cxxflags = {
|
||||||
|
"gnu" : [ "-O2", "-g", "-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused", "-fsanitize=address" ]
|
||||||
|
, "msvc" : [ "/O2", "/W4" ]
|
||||||
|
, "clang" : [ "-O2", "-g", "-Werror -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic", "-fsanitize=address" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
ldflags = {
|
||||||
|
"gnu" : [ "-fsanitize=address" ]
|
||||||
|
, "msvc" : [ ]
|
||||||
|
, "clang" : [ "-fsanitize=address" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
cxx_files = [ "tester.cc" ]
|
||||||
|
c_files = [ ]
|
||||||
|
|
||||||
|
# You can register your own toolchain through register_toolchain function
|
||||||
|
def register_toolchain(ninja):
|
||||||
|
pass
|
||||||
|
|
||||||
24
tests/issue-177.mtl
Normal file
24
tests/issue-177.mtl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
newmtl white
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl red
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 1 0 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl green
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 1 0
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl blue
|
||||||
|
Ka 0 0 0
|
||||||
|
Kd 0 0 1
|
||||||
|
Ks 0 0 0
|
||||||
|
|
||||||
|
newmtl light
|
||||||
|
Ka 20 20 20
|
||||||
|
Kd 1 1 1
|
||||||
|
Ks 0 0 0
|
||||||
31
tests/issue-177.obj
Normal file
31
tests/issue-177.obj
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
mtllib issue-177.mtl
|
||||||
|
|
||||||
|
v 0.000000 2.000000 2.000000
|
||||||
|
v 0.000000 0.000000 2.000000
|
||||||
|
v 2.000000 0.000000 2.000000
|
||||||
|
v 2.000000 2.000000 2.000000
|
||||||
|
v 0.000000 2.000000 0.000000
|
||||||
|
v 0.000000 0.000000 0.000000
|
||||||
|
v 2.000000 0.000000 0.000000
|
||||||
|
v 2.000000 2.000000 0.000000
|
||||||
|
# 8 vertices
|
||||||
|
|
||||||
|
g front cube
|
||||||
|
usemtl white
|
||||||
|
f 1 2 3 4
|
||||||
|
g back cube
|
||||||
|
# expects white material
|
||||||
|
f 8 7 6 5
|
||||||
|
g right cube
|
||||||
|
usemtl red
|
||||||
|
f 4 3 7 8
|
||||||
|
g top cube
|
||||||
|
usemtl white
|
||||||
|
f 5 1 4 8
|
||||||
|
g left cube
|
||||||
|
usemtl green
|
||||||
|
f 5 6 2 1
|
||||||
|
g bottom cube
|
||||||
|
usemtl white
|
||||||
|
f 2 6 7 3
|
||||||
|
# 6 elements
|
||||||
312
tests/kuroga.py
Executable file
312
tests/kuroga.py
Executable file
@@ -0,0 +1,312 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Kuroga, single python file meta-build system for ninja
|
||||||
|
# https://github.com/lighttransport/kuroga
|
||||||
|
#
|
||||||
|
# Requirements: python 2.6 or 2.7
|
||||||
|
#
|
||||||
|
# Usage: $ python kuroga.py input.py
|
||||||
|
#
|
||||||
|
|
||||||
|
import imp
|
||||||
|
import re
|
||||||
|
import textwrap
|
||||||
|
import glob
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# gcc preset
|
||||||
|
def add_gnu_rule(ninja):
|
||||||
|
ninja.rule('gnucxx', description='CXX $out',
|
||||||
|
command='$gnucxx -MMD -MF $out.d $gnudefines $gnuincludes $gnucxxflags -c $in -o $out',
|
||||||
|
depfile='$out.d', deps='gcc')
|
||||||
|
ninja.rule('gnucc', description='CC $out',
|
||||||
|
command='$gnucc -MMD -MF $out.d $gnudefines $gnuincludes $gnucflags -c $in -o $out',
|
||||||
|
depfile='$out.d', deps='gcc')
|
||||||
|
ninja.rule('gnulink', description='LINK $out', pool='link_pool',
|
||||||
|
command='$gnuld -o $out $in $libs $gnuldflags')
|
||||||
|
ninja.rule('gnuar', description='AR $out', pool='link_pool',
|
||||||
|
command='$gnuar rsc $out $in')
|
||||||
|
ninja.rule('gnustamp', description='STAMP $out', command='touch $out')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
ninja.variable('gnucxx', 'g++')
|
||||||
|
ninja.variable('gnucc', 'gcc')
|
||||||
|
ninja.variable('gnuld', '$gnucxx')
|
||||||
|
ninja.variable('gnuar', 'ar')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
# clang preset
|
||||||
|
def add_clang_rule(ninja):
|
||||||
|
ninja.rule('clangcxx', description='CXX $out',
|
||||||
|
command='$clangcxx -MMD -MF $out.d $clangdefines $clangincludes $clangcxxflags -c $in -o $out',
|
||||||
|
depfile='$out.d', deps='gcc')
|
||||||
|
ninja.rule('clangcc', description='CC $out',
|
||||||
|
command='$clangcc -MMD -MF $out.d $clangdefines $clangincludes $clangcflags -c $in -o $out',
|
||||||
|
depfile='$out.d', deps='gcc')
|
||||||
|
ninja.rule('clanglink', description='LINK $out', pool='link_pool',
|
||||||
|
command='$clangld -o $out $in $libs $clangldflags')
|
||||||
|
ninja.rule('clangar', description='AR $out', pool='link_pool',
|
||||||
|
command='$clangar rsc $out $in')
|
||||||
|
ninja.rule('clangstamp', description='STAMP $out', command='touch $out')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
ninja.variable('clangcxx', 'clang++')
|
||||||
|
ninja.variable('clangcc', 'clang')
|
||||||
|
ninja.variable('clangld', '$clangcxx')
|
||||||
|
ninja.variable('clangar', 'ar')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
# msvc preset
|
||||||
|
def add_msvc_rule(ninja):
|
||||||
|
ninja.rule('msvccxx', description='CXX $out',
|
||||||
|
command='$msvccxx /TP /showIncludes $msvcdefines $msvcincludes $msvccxxflags -c $in /Fo$out',
|
||||||
|
depfile='$out.d', deps='msvc')
|
||||||
|
ninja.rule('msvccc', description='CC $out',
|
||||||
|
command='$msvccc /TC /showIncludes $msvcdefines $msvcincludes $msvccflags -c $in /Fo$out',
|
||||||
|
depfile='$out.d', deps='msvc')
|
||||||
|
ninja.rule('msvclink', description='LINK $out', pool='link_pool',
|
||||||
|
command='$msvcld $msvcldflags $in $libs /OUT:$out')
|
||||||
|
ninja.rule('msvcar', description='AR $out', pool='link_pool',
|
||||||
|
command='$msvcar $in /OUT:$out')
|
||||||
|
#ninja.rule('msvcstamp', description='STAMP $out', command='touch $out')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
ninja.variable('msvccxx', 'cl.exe')
|
||||||
|
ninja.variable('msvccc', 'cl.exe')
|
||||||
|
ninja.variable('msvcld', 'link.exe')
|
||||||
|
ninja.variable('msvcar', 'lib.exe')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
# -- from ninja_syntax.py --
|
||||||
|
def escape_path(word):
|
||||||
|
return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
|
||||||
|
|
||||||
|
class Writer(object):
|
||||||
|
def __init__(self, output, width=78):
|
||||||
|
self.output = output
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
def newline(self):
|
||||||
|
self.output.write('\n')
|
||||||
|
|
||||||
|
def comment(self, text, has_path=False):
|
||||||
|
for line in textwrap.wrap(text, self.width - 2, break_long_words=False,
|
||||||
|
break_on_hyphens=False):
|
||||||
|
self.output.write('# ' + line + '\n')
|
||||||
|
|
||||||
|
def variable(self, key, value, indent=0):
|
||||||
|
if value is None:
|
||||||
|
return
|
||||||
|
if isinstance(value, list):
|
||||||
|
value = ' '.join(filter(None, value)) # Filter out empty strings.
|
||||||
|
self._line('%s = %s' % (key, value), indent)
|
||||||
|
|
||||||
|
def pool(self, name, depth):
|
||||||
|
self._line('pool %s' % name)
|
||||||
|
self.variable('depth', depth, indent=1)
|
||||||
|
|
||||||
|
def rule(self, name, command, description=None, depfile=None,
|
||||||
|
generator=False, pool=None, restat=False, rspfile=None,
|
||||||
|
rspfile_content=None, deps=None):
|
||||||
|
self._line('rule %s' % name)
|
||||||
|
self.variable('command', command, indent=1)
|
||||||
|
if description:
|
||||||
|
self.variable('description', description, indent=1)
|
||||||
|
if depfile:
|
||||||
|
self.variable('depfile', depfile, indent=1)
|
||||||
|
if generator:
|
||||||
|
self.variable('generator', '1', indent=1)
|
||||||
|
if pool:
|
||||||
|
self.variable('pool', pool, indent=1)
|
||||||
|
if restat:
|
||||||
|
self.variable('restat', '1', indent=1)
|
||||||
|
if rspfile:
|
||||||
|
self.variable('rspfile', rspfile, indent=1)
|
||||||
|
if rspfile_content:
|
||||||
|
self.variable('rspfile_content', rspfile_content, indent=1)
|
||||||
|
if deps:
|
||||||
|
self.variable('deps', deps, indent=1)
|
||||||
|
|
||||||
|
def build(self, outputs, rule, inputs=None, implicit=None, order_only=None,
|
||||||
|
variables=None):
|
||||||
|
outputs = as_list(outputs)
|
||||||
|
out_outputs = [escape_path(x) for x in outputs]
|
||||||
|
all_inputs = [escape_path(x) for x in as_list(inputs)]
|
||||||
|
|
||||||
|
if implicit:
|
||||||
|
implicit = [escape_path(x) for x in as_list(implicit)]
|
||||||
|
all_inputs.append('|')
|
||||||
|
all_inputs.extend(implicit)
|
||||||
|
if order_only:
|
||||||
|
order_only = [escape_path(x) for x in as_list(order_only)]
|
||||||
|
all_inputs.append('||')
|
||||||
|
all_inputs.extend(order_only)
|
||||||
|
|
||||||
|
self._line('build %s: %s' % (' '.join(out_outputs),
|
||||||
|
' '.join([rule] + all_inputs)))
|
||||||
|
|
||||||
|
if variables:
|
||||||
|
if isinstance(variables, dict):
|
||||||
|
iterator = iter(variables.items())
|
||||||
|
else:
|
||||||
|
iterator = iter(variables)
|
||||||
|
|
||||||
|
for key, val in iterator:
|
||||||
|
self.variable(key, val, indent=1)
|
||||||
|
|
||||||
|
return outputs
|
||||||
|
|
||||||
|
def include(self, path):
|
||||||
|
self._line('include %s' % path)
|
||||||
|
|
||||||
|
def subninja(self, path):
|
||||||
|
self._line('subninja %s' % path)
|
||||||
|
|
||||||
|
def default(self, paths):
|
||||||
|
self._line('default %s' % ' '.join(as_list(paths)))
|
||||||
|
|
||||||
|
def _count_dollars_before_index(self, s, i):
|
||||||
|
"""Returns the number of '$' characters right in front of s[i]."""
|
||||||
|
dollar_count = 0
|
||||||
|
dollar_index = i - 1
|
||||||
|
while dollar_index > 0 and s[dollar_index] == '$':
|
||||||
|
dollar_count += 1
|
||||||
|
dollar_index -= 1
|
||||||
|
return dollar_count
|
||||||
|
|
||||||
|
def _line(self, text, indent=0):
|
||||||
|
"""Write 'text' word-wrapped at self.width characters."""
|
||||||
|
leading_space = ' ' * indent
|
||||||
|
while len(leading_space) + len(text) > self.width:
|
||||||
|
# The text is too wide; wrap if possible.
|
||||||
|
|
||||||
|
# Find the rightmost space that would obey our width constraint and
|
||||||
|
# that's not an escaped space.
|
||||||
|
available_space = self.width - len(leading_space) - len(' $')
|
||||||
|
space = available_space
|
||||||
|
while True:
|
||||||
|
space = text.rfind(' ', 0, space)
|
||||||
|
if (space < 0 or
|
||||||
|
self._count_dollars_before_index(text, space) % 2 == 0):
|
||||||
|
break
|
||||||
|
|
||||||
|
if space < 0:
|
||||||
|
# No such space; just use the first unescaped space we can find.
|
||||||
|
space = available_space - 1
|
||||||
|
while True:
|
||||||
|
space = text.find(' ', space + 1)
|
||||||
|
if (space < 0 or
|
||||||
|
self._count_dollars_before_index(text, space) % 2 == 0):
|
||||||
|
break
|
||||||
|
if space < 0:
|
||||||
|
# Give up on breaking.
|
||||||
|
break
|
||||||
|
|
||||||
|
self.output.write(leading_space + text[0:space] + ' $\n')
|
||||||
|
text = text[space+1:]
|
||||||
|
|
||||||
|
# Subsequent lines are continuations, so indent them.
|
||||||
|
leading_space = ' ' * (indent+2)
|
||||||
|
|
||||||
|
self.output.write(leading_space + text + '\n')
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.output.close()
|
||||||
|
|
||||||
|
|
||||||
|
def as_list(input):
|
||||||
|
if input is None:
|
||||||
|
return []
|
||||||
|
if isinstance(input, list):
|
||||||
|
return input
|
||||||
|
return [input]
|
||||||
|
|
||||||
|
# -- end from ninja_syntax.py --
|
||||||
|
|
||||||
|
def gen(ninja, toolchain, config):
|
||||||
|
|
||||||
|
ninja.variable('ninja_required_version', '1.4')
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
if hasattr(config, "builddir"):
|
||||||
|
builddir = config.builddir[toolchain]
|
||||||
|
ninja.variable(toolchain + 'builddir', builddir)
|
||||||
|
else:
|
||||||
|
builddir = ''
|
||||||
|
|
||||||
|
ninja.variable(toolchain + 'defines', config.defines[toolchain] or [])
|
||||||
|
ninja.variable(toolchain + 'includes', config.includes[toolchain] or [])
|
||||||
|
ninja.variable(toolchain + 'cflags', config.cflags[toolchain] or [])
|
||||||
|
ninja.variable(toolchain + 'cxxflags', config.cxxflags[toolchain] or [])
|
||||||
|
ninja.variable(toolchain + 'ldflags', config.ldflags[toolchain] or [])
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
if hasattr(config, "link_pool_depth"):
|
||||||
|
ninja.pool('link_pool', depth=config.link_pool_depth)
|
||||||
|
else:
|
||||||
|
ninja.pool('link_pool', depth=4)
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
# Add default toolchain(gnu, clang and msvc)
|
||||||
|
add_gnu_rule(ninja)
|
||||||
|
add_clang_rule(ninja)
|
||||||
|
add_msvc_rule(ninja)
|
||||||
|
|
||||||
|
obj_files = []
|
||||||
|
|
||||||
|
cc = toolchain + 'cc'
|
||||||
|
cxx = toolchain + 'cxx'
|
||||||
|
link = toolchain + 'link'
|
||||||
|
ar = toolchain + 'ar'
|
||||||
|
|
||||||
|
if hasattr(config, "cxx_files"):
|
||||||
|
for src in config.cxx_files:
|
||||||
|
srcfile = src
|
||||||
|
obj = os.path.splitext(srcfile)[0] + '.o'
|
||||||
|
obj = os.path.join(builddir, obj);
|
||||||
|
obj_files.append(obj)
|
||||||
|
ninja.build(obj, cxx, srcfile)
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
if hasattr(config, "c_files"):
|
||||||
|
for src in config.c_files:
|
||||||
|
srcfile = src
|
||||||
|
obj = os.path.splitext(srcfile)[0] + '.o'
|
||||||
|
obj = os.path.join(builddir, obj);
|
||||||
|
obj_files.append(obj)
|
||||||
|
ninja.build(obj, cc, srcfile)
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
targetlist = []
|
||||||
|
if hasattr(config, "exe"):
|
||||||
|
ninja.build(config.exe, link, obj_files)
|
||||||
|
targetlist.append(config.exe)
|
||||||
|
|
||||||
|
if hasattr(config, "staticlib"):
|
||||||
|
ninja.build(config.staticlib, ar, obj_files)
|
||||||
|
targetlist.append(config.staticlib)
|
||||||
|
|
||||||
|
ninja.build('all', 'phony', targetlist)
|
||||||
|
ninja.newline()
|
||||||
|
|
||||||
|
ninja.default('all')
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python kuroga.py config.py")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
config = imp.load_source("config", sys.argv[1])
|
||||||
|
|
||||||
|
f = open('build.ninja', 'w')
|
||||||
|
ninja = Writer(f)
|
||||||
|
|
||||||
|
if hasattr(config, "register_toolchain"):
|
||||||
|
config.register_toolchain(ninja)
|
||||||
|
|
||||||
|
gen(ninja, config.toolchain, config)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
main()
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user