Compare commits
286 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
609139f370 | ||
|
|
cc73127bf0 | ||
|
|
160d6be10f | ||
|
|
583590767e | ||
|
|
dc542d6638 | ||
|
|
c5976f931b | ||
|
|
0511658e86 | ||
|
|
54851f8ac7 | ||
|
|
a6c1d07560 | ||
|
|
4fe479453b | ||
|
|
af1bcf1e11 | ||
|
|
05f06d09d8 | ||
|
|
3c0196bfb7 | ||
|
|
dc4c970262 | ||
|
|
aeb0f05c0e | ||
|
|
c016910317 | ||
|
|
5d7f6bf539 | ||
|
|
b818a34f1a | ||
|
|
baa62f4d89 | ||
|
|
b2f07d10aa | ||
|
|
ee2c734c15 | ||
|
|
6e579f027f | ||
|
|
7b6e33da52 | ||
|
|
5896933508 | ||
|
|
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 | ||
|
|
a14bbdb065 | ||
|
|
bfedfbb1fb | ||
|
|
109090e5b8 | ||
|
|
41f46c7fd7 | ||
|
|
a62dd278e2 | ||
|
|
a20e4ede85 | ||
|
|
73d823ba77 | ||
|
|
1ab0d147cb | ||
|
|
9aee576b99 | ||
|
|
0dcc72239d | ||
|
|
33d5e9aa07 | ||
|
|
e528741a8b | ||
|
|
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 | ||
|
|
9c81fcb4cc | ||
|
|
d119dcb976 | ||
|
|
6cdb3ec832 | ||
|
|
1b24514ed9 | ||
|
|
0dd90f853d | ||
|
|
b40e8c9427 | ||
|
|
ad9911ef1b |
@@ -1,5 +1,5 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
BasedOnStyle: Google
|
||||
IndentWidth: 2
|
||||
TabWidth: 2
|
||||
UseTab: Never
|
||||
|
||||
22
.travis.yml
22
.travis.yml
@@ -1,5 +1,5 @@
|
||||
language: cpp
|
||||
sudo: false
|
||||
sudo: required
|
||||
matrix:
|
||||
include:
|
||||
- addons: &1
|
||||
@@ -36,21 +36,17 @@ matrix:
|
||||
env: COMPILER_VERSION=4.9 BUILD_TYPE=Release
|
||||
- addons: *1
|
||||
compiler: clang
|
||||
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug CFLAGS="-O0 --coverage" CXXFLAGS="-O0
|
||||
--coverage" REPORT_COVERAGE=1
|
||||
env: COMPILER_VERSION=3.7 BUILD_TYPE=Debug
|
||||
before_install:
|
||||
- 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:
|
||||
- mkdir build && cd build
|
||||
- export CC="${CC}-${COMPILER_VERSION}"
|
||||
- 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
|
||||
- cd tests
|
||||
- make check
|
||||
- if [ -n "$REPORT_COVERAGE" ]; then coveralls -b . -r .. -e examples -e tools -e
|
||||
jni -e python -e images -E ".*CompilerId.*" -E ".*feature_tests.*" ; fi
|
||||
- cd ..
|
||||
|
||||
144
CMakeLists.txt
144
CMakeLists.txt
@@ -2,57 +2,145 @@
|
||||
#This configures the Cmake system with multiple properties, depending
|
||||
#on the platform and configuration it is set to build in.
|
||||
project(tinyobjloader)
|
||||
cmake_minimum_required(VERSION 2.8.6)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
set(TINYOBJLOADER_SOVERSION 1)
|
||||
set(TINYOBJLOADER_VERSION 1.0.4)
|
||||
|
||||
#optional double precision support
|
||||
option(TINYOBJLOADER_USE_DOUBLE "Build library with double precision instead of single (float)" OFF)
|
||||
|
||||
if(TINYOBJLOADER_USE_DOUBLE)
|
||||
add_definitions(-DTINYOBJLOADER_USE_DOUBLE)
|
||||
set(LIBRARY_NAME ${PROJECT_NAME}_double)
|
||||
else()
|
||||
set(LIBRARY_NAME ${PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
|
||||
#Folder Shortcuts
|
||||
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
||||
|
||||
set(tinyobjloader-Source
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
||||
)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
||||
)
|
||||
|
||||
set(tinyobjloader-Test-Source
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/test.cc
|
||||
)
|
||||
set(tinyobjloader-Example-Source
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
|
||||
)
|
||||
|
||||
set(tinyobjloader-examples-objsticher
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
||||
)
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
|
||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
||||
)
|
||||
|
||||
add_library(tinyobjloader
|
||||
${tinyobjloader-Source}
|
||||
)
|
||||
#Install destinations
|
||||
include(GNUInstallDirs)
|
||||
|
||||
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Test Loader Application" OFF)
|
||||
set(TINYOBJLOADER_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake)
|
||||
set(TINYOBJLOADER_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
|
||||
set(TINYOBJLOADER_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(TINYOBJLOADER_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR})
|
||||
set(TINYOBJLOADER_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||
set(TINYOBJLOADER_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Example Loader Application" OFF)
|
||||
option(TINYOBJLOADER_COMPILATION_SHARED "Build as shared library" OFF)
|
||||
|
||||
if(TINYOBJLOADER_COMPILATION_SHARED)
|
||||
add_library(${LIBRARY_NAME} SHARED ${tinyobjloader-Source})
|
||||
set_target_properties(${LIBRARY_NAME} PROPERTIES
|
||||
SOVERSION ${TINYOBJLOADER_SOVERSION}
|
||||
)
|
||||
else()
|
||||
add_library(${LIBRARY_NAME} STATIC ${tinyobjloader-Source})
|
||||
endif()
|
||||
|
||||
set_target_properties(${LIBRARY_NAME} PROPERTIES VERSION ${TINYOBJLOADER_VERSION})
|
||||
|
||||
target_include_directories(${LIBRARY_NAME} INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${TINYOBJLOADER_INCLUDE_DIR}>
|
||||
)
|
||||
|
||||
export(TARGETS ${LIBRARY_NAME} FILE ${PROJECT_NAME}-targets.cmake)
|
||||
|
||||
if(TINYOBJLOADER_BUILD_TEST_LOADER)
|
||||
add_executable(test_loader ${tinyobjloader-Test-Source})
|
||||
target_link_libraries(test_loader tinyobjloader)
|
||||
add_executable(test_loader ${tinyobjloader-Example-Source})
|
||||
target_link_libraries(test_loader ${LIBRARY_NAME})
|
||||
endif()
|
||||
|
||||
option(TINYOBJLOADER_BUILD_OBJ_STICHER "Build OBJ Sticher Application" OFF)
|
||||
if (TINYOBJLOADER_BUILD_OBJ_STICHER)
|
||||
if(TINYOBJLOADER_BUILD_OBJ_STICHER)
|
||||
add_executable(obj_sticher ${tinyobjloader-examples-objsticher})
|
||||
target_link_libraries(obj_sticher tinyobjloader)
|
||||
target_link_libraries(obj_sticher ${LIBRARY_NAME})
|
||||
|
||||
install ( TARGETS
|
||||
install(TARGETS
|
||||
obj_sticher
|
||||
DESTINATION
|
||||
bin
|
||||
${TINYOBJLOADER_RUNTIME_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
#Installation
|
||||
install ( TARGETS
|
||||
tinyobjloader
|
||||
DESTINATION
|
||||
lib
|
||||
#Write CMake package config files
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
||||
configure_package_config_file(
|
||||
${PROJECT_NAME}-config.cmake.in
|
||||
${LIBRARY_NAME}-config.cmake
|
||||
INSTALL_DESTINATION
|
||||
${TINYOBJLOADER_CMAKE_DIR}
|
||||
PATH_VARS
|
||||
TINYOBJLOADER_INCLUDE_DIR
|
||||
TINYOBJLOADER_LIBRARY_DIR
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||
)
|
||||
install ( FILES
|
||||
|
||||
write_basic_package_version_file(${LIBRARY_NAME}-config-version.cmake
|
||||
VERSION
|
||||
${TINYOBJLOADER_VERSION}
|
||||
COMPATIBILITY
|
||||
SameMajorVersion
|
||||
)
|
||||
|
||||
#pkg-config file
|
||||
configure_file(${PROJECT_NAME}.pc.in ${LIBRARY_NAME}.pc @ONLY)
|
||||
|
||||
#Installation
|
||||
install(TARGETS
|
||||
${LIBRARY_NAME}
|
||||
EXPORT ${PROJECT_NAME}-targets
|
||||
DESTINATION
|
||||
${TINYOBJLOADER_LIBRARY_DIR}
|
||||
PUBLIC_HEADER DESTINATION
|
||||
${TINYOBJLOADER_INCLUDE_DIR}
|
||||
RUNTIME DESTINATION
|
||||
${TINYOBJLOADER_RUNTIME_DIR}
|
||||
)
|
||||
install(EXPORT
|
||||
${PROJECT_NAME}-targets
|
||||
DESTINATION
|
||||
${TINYOBJLOADER_CMAKE_DIR}
|
||||
)
|
||||
install(FILES
|
||||
tiny_obj_loader.h
|
||||
DESTINATION
|
||||
include
|
||||
${TINYOBJLOADER_INCLUDE_DIR}
|
||||
)
|
||||
install(FILES
|
||||
LICENSE
|
||||
DESTINATION
|
||||
${TINYOBJLOADER_DOC_DIR}
|
||||
)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}-config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}-config-version.cmake"
|
||||
DESTINATION
|
||||
${TINYOBJLOADER_CMAKE_DIR}
|
||||
)
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/${LIBRARY_NAME}.pc"
|
||||
DESTINATION
|
||||
${TINYOBJLOADER_PKGCONFIG_DIR}
|
||||
)
|
||||
|
||||
21
LICENSE
Normal file
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.
|
||||
308
README.md
308
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)
|
||||
|
||||
@@ -11,44 +10,71 @@ tinyobjloader
|
||||
|
||||
[](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 ;-)
|
||||
|
||||
If you are looking for C89 version, please see https://github.com/syoyo/tinyobjloader-c .
|
||||
|
||||
What's new
|
||||
----------
|
||||
|
||||
* 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
|
||||
Notice!
|
||||
-------
|
||||
|
||||

|
||||
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
|
||||
|
||||
### Version 2.x
|
||||
|
||||
* Refactor API
|
||||
* Support triangulation for concave polygons(#151)
|
||||
|
||||
### Version 1.x
|
||||
|
||||
Avaiable in `v1.x.y` branch.
|
||||
|
||||
* 20 Aug, 2016 : Bump version v1.0.0. New data structure and API!
|
||||
|
||||
### Older version
|
||||
|
||||
Older version is avaiable in `v0.9.x` branch.
|
||||
|
||||
## Example
|
||||
|
||||

|
||||
|
||||
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 ...
|
||||
|
||||
### New version(v2.x)
|
||||
|
||||
* Your project here! (Letting us know via github issue is welcome!)
|
||||
|
||||
### Old version(v1.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!)
|
||||
|
||||
### Older version(v0.9.x)
|
||||
|
||||
* bullet3 https://github.com/erwincoumans/bullet3
|
||||
* pbrt-v2 https://github.com/mmp/pbrt-v2
|
||||
* OpenGL game engine development http://swarminglogic.com/jotting/2013_10_gamedev01
|
||||
@@ -60,111 +86,141 @@ TinyObjLoader is successfully used in ...
|
||||
* pbrt-v3 https://github.com/mmp/pbrt-v3
|
||||
* cocos2d-x https://github.com/cocos2d/cocos2d-x/
|
||||
* 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)
|
||||
* Vertex
|
||||
* Vertex color(as an extension: https://blender.stackexchange.com/questions/31997/how-can-i-get-vertex-painted-obj-files-to-import-into-blender)
|
||||
* Texcoord
|
||||
* Normal
|
||||
* Material
|
||||
* Unknown material attributes are returned as key-value(value is string) map.
|
||||
* Crease tag('t'). This is OpenSubdiv specific(not in wavefront .obj specification)
|
||||
* PBR material extension for .MTL. Its proposed here: http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
||||
* Callback API for custom loading.
|
||||
* Double precision support(for HPC application).
|
||||
|
||||
|
||||
TODO
|
||||
----
|
||||
## TODO
|
||||
|
||||
* [ ] Support different indices for vertex/normal/texcoord
|
||||
* [ ] Fix obj_sticker example.
|
||||
* [ ] More unit test codes.
|
||||
* [x] Texture options
|
||||
* [ ] Normal vector generation
|
||||
* [ ] Support smoothing groups
|
||||
|
||||
License
|
||||
-------
|
||||
## License
|
||||
|
||||
Licensed under 2 clause BSD.
|
||||
Licensed under MIT license.
|
||||
|
||||
Usage
|
||||
-----
|
||||
## Usage
|
||||
|
||||
TinyObjLoader triangulate input .obj by default.
|
||||
```c++
|
||||
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
||||
#include "tiny_obj_loader.h"
|
||||
### Data format
|
||||
|
||||
std::string inputfile = "cornell_box.obj";
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
`attrib_t` contains single and linear array of vertex data(position, normal and texcoord).
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str());
|
||||
```
|
||||
attrib_t::vertices => 3 floats per vertex
|
||||
|
||||
if (!err.empty()) { // `err` may contain warning message.
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
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 |
|
||||
+-----------+-----------+-----------+-----------+ +-----------+
|
||||
|
||||
if (!ret) {
|
||||
exit(1);
|
||||
}
|
||||
attrib_t::normals => 3 floats per vertex
|
||||
|
||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||
std::cout << "# of materials : " << materials.size() << std::endl;
|
||||
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 |
|
||||
+-----------+-----------+-----------+-----------+ +-----------+
|
||||
|
||||
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());
|
||||
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]);
|
||||
}
|
||||
attrib_t::texcoords => 2 floats per vertex
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
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 |
|
||||
+-----------+-----------+-----------+-----------+ +-----------+
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
```c++
|
||||
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
std::string inputfile = "cornell_box.obj";
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool triangulate = false;
|
||||
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), triangulate);
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, inputfile.c_str());
|
||||
|
||||
if (!err.empty()) { // `err` may contain warning message.
|
||||
std::cerr << err << std::endl;
|
||||
@@ -174,21 +230,53 @@ if (!ret) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
|
||||
size_t indexOffset = 0;
|
||||
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++) {
|
||||
unsigend 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]);
|
||||
// Loop over shapes
|
||||
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];
|
||||
|
||||
// Loop over vertices in the face.
|
||||
for (size_t v = 0; v < fv; v++) {
|
||||
// access to vertex
|
||||
tinyobj::index_t idx = shapes[s].mesh.indices[index_offset + v];
|
||||
tinyobj::real_t vx = attrib.vertices[idx.vertex_index].x;
|
||||
tinyobj::real_t vy = attrib.vertices[idx.vertex_index].y;
|
||||
tinyobj::real_t vz = attrib.vertices[idx.vertex_index].z;
|
||||
tinyobj::real_t nx = attrib.normals[idx.normal_index].x;
|
||||
tinyobj::real_t ny = attrib.normals[idx.normal_index].y;
|
||||
tinyobj::real_t nz = attrib.normals[idx.normal_index].z;
|
||||
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];
|
||||
}
|
||||
indexOffset += ngon;
|
||||
}
|
||||
index_offset += fv;
|
||||
|
||||
// per-face material
|
||||
shapes[s].mesh.material_ids[f];
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Optimized loader
|
||||
|
||||
Optimized multi-threaded .obj loader is available at `experimental/` directory.
|
||||
If you want absolute performance to load .obj data, this optimized loader will fit your purpose.
|
||||
Note that the optimized loader uses C++11 thread and it does less error checks but may work most .obj data.
|
||||
|
||||
Here is some benchmark result. Time are measured on MacBook 12(Early 2016, Core m5 1.2GHz).
|
||||
|
||||
* Rungholt scene(6M triangles)
|
||||
* old version(v0.9.x): 15500 msecs.
|
||||
* baseline(v1.0.x): 6800 msecs(2.3x faster than old version)
|
||||
* optimised: 1500 msecs(10x faster than old version, 4.5x faster than baseline)
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
Unit tests are provided in `tests` directory. See `tests/README.md` for details.
|
||||
|
||||
28
appveyor.yml
28
appveyor.yml
@@ -1,12 +1,22 @@
|
||||
version: 0.9.{build}
|
||||
|
||||
# scripts that runs after repo cloning.
|
||||
install:
|
||||
- vcsetup.bat
|
||||
version: 1.0.{build}
|
||||
|
||||
platform: x64
|
||||
configuration: Release
|
||||
|
||||
build:
|
||||
parallel: true
|
||||
project: TinyObjLoaderSolution.sln
|
||||
install:
|
||||
#######################################################################################
|
||||
# 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
|
||||
cc = clang
|
||||
cxx = clang++
|
||||
cflags = -Werror -Weverything
|
||||
cxxflags = -Werror -Weverything
|
||||
ninja_required_version = 1.4
|
||||
|
||||
rule compile
|
||||
command = $cxx $cxxflags -c $in -o $out
|
||||
gnubuilddir = build
|
||||
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
|
||||
command = $cxx $in -o $out
|
||||
pool link_pool
|
||||
depth = 1
|
||||
|
||||
build test.o: compile test.cc
|
||||
build test: link test.o
|
||||
rule gnucxx
|
||||
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
|
||||
166
examples/callback_api/main.cc
Normal file
166
examples/callback_api/main.cc
Normal file
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// 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 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, &err);
|
||||
|
||||
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;
|
||||
}
|
||||
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]);
|
||||
713
examples/viewer/viewer.cc
Normal file
713
examples/viewer/viewer.cc
Normal file
@@ -0,0 +1,713 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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 err;
|
||||
bool ret =
|
||||
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, base_dir.c_str());
|
||||
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)
|
||||
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) {
|
||||
assert(attrib.texcoords.size() > 2 * idx0.texcoord_index + 1);
|
||||
assert(attrib.texcoords.size() > 2 * idx1.texcoord_index + 1);
|
||||
assert(attrib.texcoords.size() > 2 * idx2.texcoord_index + 1);
|
||||
|
||||
// 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];
|
||||
if (attrib.normals.size() > 0) {
|
||||
int f0 = idx0.normal_index;
|
||||
int f1 = idx1.normal_index;
|
||||
int f2 = idx2.normal_index;
|
||||
assert(f0 >= 0);
|
||||
assert(f1 >= 0);
|
||||
assert(f2 >= 0);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
n[0][k] = attrib.normals[3 * f0 + k];
|
||||
n[1][k] = attrib.normals[3 * f1 + k];
|
||||
n[2][k] = attrib.normals[3 * f2 + 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];
|
||||
}
|
||||
|
||||
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.
|
||||
74
examples/voxelize/main.cc
Normal file
74
examples/voxelize/main.cc
Normal file
@@ -0,0 +1,74 @@
|
||||
#define VOXELIZER_IMPLEMENTATION
|
||||
#include "voxelizer.h"
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "../../tiny_obj_loader.h"
|
||||
|
||||
bool Voxelize(const char* filename, float voxelsizex, float voxelsizey, float voxelsizez, float precision)
|
||||
{
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename);
|
||||
|
||||
if (!err.empty()) {
|
||||
printf("err: %s\n", err.c_str());
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("failed to load : %s\n", filename);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shapes.size() == 0) {
|
||||
printf("err: # of shapes are zero.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only use first shape.
|
||||
{
|
||||
vx_mesh_t* mesh;
|
||||
vx_mesh_t* result;
|
||||
|
||||
mesh = vx_mesh_alloc(attrib.vertices.size(), shapes[0].mesh.indices.size());
|
||||
|
||||
for (size_t f = 0; f < shapes[0].mesh.indices.size(); f++) {
|
||||
mesh->indices[f] = shapes[0].mesh.indices[f].vertex_index;
|
||||
}
|
||||
|
||||
for (size_t v = 0; v < attrib.vertices.size() / 3; v++) {
|
||||
mesh->vertices[v].x = attrib.vertices[3*v+0];
|
||||
mesh->vertices[v].y = attrib.vertices[3*v+1];
|
||||
mesh->vertices[v].z = attrib.vertices[3*v+2];
|
||||
}
|
||||
|
||||
result = vx_voxelize(mesh, voxelsizex, voxelsizey, voxelsizez, precision);
|
||||
|
||||
printf("Number of vertices: %ld\n", result->nvertices);
|
||||
printf("Number of indices: %ld\n", result->nindices);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char** argv)
|
||||
{
|
||||
if (argc < 4) {
|
||||
printf("Usage: voxelize input.obj voxelsizex voxelsizey voxelsizez precision\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
const char* filename = argv[1];
|
||||
float voxelsizex = atof(argv[2]);
|
||||
float voxelsizey = atof(argv[3]);
|
||||
float voxelsizez = atof(argv[4]);
|
||||
float prec = atof(argv[5]);
|
||||
bool ret = Voxelize(filename, voxelsizex, voxelsizey, voxelsizez, prec);
|
||||
|
||||
return ret ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
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
|
||||
16
experimental/multithreaded/README.md
Normal file
16
experimental/multithreaded/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Experimental code for .obj loader.
|
||||
|
||||
* Multi-threaded optimized parser : tinyobj_loader_opt.h
|
||||
|
||||
## Requirements
|
||||
|
||||
* C++-11 compiler
|
||||
|
||||
## Compile options
|
||||
|
||||
* zstd compressed .obj support. `--with-zstd` premake option.
|
||||
* gzip compressed .obj support. `--with-zlib` premake option.
|
||||
|
||||
## Licenses
|
||||
|
||||
* lfpAlloc : MIT license.
|
||||
89
experimental/multithreaded/lfpAlloc/Allocator.hpp
Normal file
89
experimental/multithreaded/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/multithreaded/lfpAlloc/ChunkList.hpp
Normal file
116
experimental/multithreaded/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/multithreaded/lfpAlloc/LICENSE
Normal file
21
experimental/multithreaded/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/multithreaded/lfpAlloc/Pool.hpp
Normal file
48
experimental/multithreaded/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/multithreaded/lfpAlloc/PoolDispatcher.hpp
Normal file
79
experimental/multithreaded/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/multithreaded/lfpAlloc/Utils.hpp
Normal file
20
experimental/multithreaded/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/multithreaded/premake5.lua
Normal file
94
experimental/multithreaded/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"}
|
||||
|
||||
1684
experimental/multithreaded/tinyobj_loader_opt.h
Normal file
1684
experimental/multithreaded/tinyobj_loader_opt.h
Normal file
File diff suppressed because it is too large
Load Diff
292
experimental/multithreaded/trackball.cc
Normal file
292
experimental/multithreaded/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/multithreaded/trackball.h
Normal file
75
experimental/multithreaded/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/multithreaded/viewer.cc
Normal file
748
experimental/multithreaded/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.
|
||||
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
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)
|
||||
LOCAL_MODULE := tinyobjloader
|
||||
LOCAL_SRC_FILES := ../tiny_obj_loader.cc ../test.cc
|
||||
LOCAL_SRC_FILES := ../tiny_obj_loader.cc
|
||||
|
||||
LOCAL_C_INCLUDES := ../
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
425
loader_example.cc
Normal file
425
loader_example.cc
Normal file
@@ -0,0 +1,425 @@
|
||||
//
|
||||
// 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__
|
||||
#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(); v++) {
|
||||
printf(" v[%ld] = (%f, %f, %f)\n", static_cast<long>(v),
|
||||
static_cast<const double>(attrib.vertices[v].x),
|
||||
static_cast<const double>(attrib.vertices[v].y),
|
||||
static_cast<const double>(attrib.vertices[v].z));
|
||||
}
|
||||
|
||||
for (size_t v = 0; v < attrib.normals.size(); v++) {
|
||||
printf(" n[%ld] = (%f, %f, %f)\n", static_cast<long>(v),
|
||||
static_cast<const double>(attrib.normals[v].x),
|
||||
static_cast<const double>(attrib.normals[v].y),
|
||||
static_cast<const double>(attrib.normals[v].z));
|
||||
}
|
||||
|
||||
for (size_t v = 0; v < attrib.texcoords.size(); v++) {
|
||||
printf(" uv[%ld] = (%f, %f)\n", static_cast<long>(v),
|
||||
static_cast<const double>(attrib.texcoords[v].x),
|
||||
static_cast<const double>(attrib.texcoords[v].y));
|
||||
}
|
||||
|
||||
// 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].indices: %lu\n", static_cast<long>(i),
|
||||
static_cast<unsigned long>(shapes[i].mesh.indices.size()));
|
||||
|
||||
size_t index_offset = 0;
|
||||
|
||||
assert(shapes[i].mesh.num_face_vertices.size() ==
|
||||
shapes[i].mesh.material_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]);
|
||||
|
||||
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 err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename,
|
||||
basepath, triangulate);
|
||||
t.end();
|
||||
printf("Parsing time: %lu [msecs]\n", t.msec());
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << 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<unsigned int, int>* matMap,
|
||||
std::string* err) {
|
||||
(void)matId;
|
||||
std::string warning;
|
||||
LoadMtl(matMap, materials, &m_matSStream, &warning);
|
||||
|
||||
if (!warning.empty()) {
|
||||
if (err) {
|
||||
(*err) += warning;
|
||||
}
|
||||
}
|
||||
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 err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &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;
|
||||
}
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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 = {
|
||||
"test.cc",
|
||||
"loader_example.cc",
|
||||
}
|
||||
|
||||
-- premake4.lua
|
||||
@@ -21,9 +21,9 @@ solution "TinyObjLoaderSolution"
|
||||
configuration "Debug"
|
||||
defines { "DEBUG" } -- -DDEBUG
|
||||
flags { "Symbols" }
|
||||
targetname "test_tinyobjloader_debug"
|
||||
targetname "loader_example_debug"
|
||||
|
||||
configuration "Release"
|
||||
-- defines { "NDEBUG" } -- -NDEBUG
|
||||
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
|
||||
282
python/main.cpp
282
python/main.cpp
@@ -1,160 +1,206 @@
|
||||
//python3 module for tinyobjloader
|
||||
// python2/3 module for tinyobjloader
|
||||
//
|
||||
//usage:
|
||||
// usage:
|
||||
// import tinyobjloader as tol
|
||||
// model = tol.LoadObj(name)
|
||||
// print(model["shapes"])
|
||||
// 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 <vector>
|
||||
#include "../tiny_obj_loader.h"
|
||||
|
||||
typedef std::vector<double> vectd;
|
||||
typedef std::vector<int> vecti;
|
||||
|
||||
PyObject*
|
||||
pyTupleFromfloat3 (float array[3])
|
||||
{
|
||||
int i;
|
||||
PyObject* tuple = PyTuple_New(3);
|
||||
PyObject* pyTupleFromfloat3(float array[3]) {
|
||||
int i;
|
||||
PyObject* tuple = PyTuple_New(3);
|
||||
|
||||
for(i=0; i<=2 ; i++){
|
||||
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
|
||||
}
|
||||
for (i = 0; i <= 2; 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* filename;
|
||||
char *current_name;
|
||||
vectd vect;
|
||||
char const* current_name;
|
||||
char const* filename;
|
||||
vectd vect;
|
||||
std::vector<tinyobj::index_t> indices;
|
||||
std::vector<unsigned char> face_verts;
|
||||
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
if(!PyArg_ParseTuple(args, "s", &filename))
|
||||
return NULL;
|
||||
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
|
||||
|
||||
std::string err;
|
||||
tinyobj::LoadObj(shapes, materials, err, filename);
|
||||
std::string err;
|
||||
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename);
|
||||
|
||||
pyshapes = PyDict_New();
|
||||
pymaterials = PyDict_New();
|
||||
rtndict = PyDict_New();
|
||||
pyshapes = PyDict_New();
|
||||
pymaterials = PyDict_New();
|
||||
pymaterial_indices = PyList_New(0);
|
||||
rtndict = PyDict_New();
|
||||
|
||||
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin() ;
|
||||
shape != shapes.end(); shape++)
|
||||
{
|
||||
meshobj = PyDict_New();
|
||||
tinyobj::mesh_t cm = (*shape).mesh;
|
||||
attribobj = PyDict_New();
|
||||
|
||||
for (int i = 0; i <= 4; i++ )
|
||||
{
|
||||
current = PyList_New(0);
|
||||
for (int i = 0; i <= 2; i++) {
|
||||
current = PyList_New(0);
|
||||
|
||||
switch(i) {
|
||||
|
||||
case 0:
|
||||
current_name = "positions";
|
||||
vect = vectd(cm.positions.begin(), cm.positions.end()); break;
|
||||
case 1:
|
||||
current_name = "normals";
|
||||
vect = vectd(cm.normals.begin(), cm.normals.end()); break;
|
||||
case 2:
|
||||
current_name = "texcoords";
|
||||
vect = vectd(cm.texcoords.begin(), cm.texcoords.end()); break;
|
||||
case 3:
|
||||
current_name = "indicies";
|
||||
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));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(meshobj, current_name, current);
|
||||
|
||||
}
|
||||
|
||||
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
|
||||
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 (std::vector<tinyobj::material_t>::iterator mat = materials.begin() ;
|
||||
mat != materials.end(); mat++)
|
||||
{
|
||||
PyObject *matobj = PyDict_New();
|
||||
PyObject *unknown_parameter = PyDict_New();
|
||||
|
||||
for (std::map<std::string, std::string>::iterator p = (*mat).unknown_parameter.begin() ;
|
||||
p != (*mat).unknown_parameter.end(); ++p)
|
||||
{
|
||||
PyDict_SetItemString(unknown_parameter, p->first.c_str(), PyUnicode_FromString(p->second.c_str()));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(matobj, "shininess", PyFloat_FromDouble((*mat).shininess));
|
||||
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble((*mat).ior));
|
||||
PyDict_SetItemString(matobj, "dissolve", PyFloat_FromDouble((*mat).dissolve));
|
||||
PyDict_SetItemString(matobj, "illum", PyLong_FromLong((*mat).illum));
|
||||
PyDict_SetItemString(matobj, "ambient_texname", PyUnicode_FromString((*mat).ambient_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "diffuse_texname", PyUnicode_FromString((*mat).diffuse_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "specular_texname", PyUnicode_FromString((*mat).specular_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "specular_highlight_texname", PyUnicode_FromString((*mat).specular_highlight_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "bump_texname", PyUnicode_FromString((*mat).bump_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "displacement_texname", PyUnicode_FromString((*mat).displacement_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "alpha_texname", PyUnicode_FromString((*mat).alpha_texname.c_str()));
|
||||
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(pymaterials, (*mat).name.c_str(), matobj);
|
||||
for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
|
||||
PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
||||
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
||||
PyDict_SetItemString(attribobj, current_name, current);
|
||||
}
|
||||
|
||||
return rtndict;
|
||||
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin();
|
||||
shape != shapes.end(); shape++) {
|
||||
meshobj = PyDict_New();
|
||||
tinyobj::mesh_t cm = (*shape).mesh;
|
||||
|
||||
{
|
||||
current = PyList_New(0);
|
||||
|
||||
for (size_t i = 0; i < cm.indices.size(); i++) {
|
||||
// Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
|
||||
// ...
|
||||
PyList_Insert(current, 3 * i + 0,
|
||||
PyLong_FromLong(cm.indices[i].vertex_index));
|
||||
PyList_Insert(current, 3 * i + 1,
|
||||
PyLong_FromLong(cm.indices[i].normal_index));
|
||||
PyList_Insert(current, 3 * i + 2,
|
||||
PyLong_FromLong(cm.indices[i].texcoord_index));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(meshobj, "indices", current);
|
||||
}
|
||||
|
||||
{
|
||||
current = PyList_New(0);
|
||||
|
||||
for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
|
||||
// Widen data type to long.
|
||||
PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i]));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(meshobj, "num_face_vertices", current);
|
||||
}
|
||||
|
||||
{
|
||||
current = PyList_New(0);
|
||||
|
||||
for (size_t i = 0; i < cm.material_ids.size(); i++) {
|
||||
PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i]));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(meshobj, "material_ids", current);
|
||||
}
|
||||
|
||||
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
|
||||
}
|
||||
|
||||
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin();
|
||||
mat != materials.end(); mat++) {
|
||||
PyObject* matobj = PyDict_New();
|
||||
PyObject* unknown_parameter = PyDict_New();
|
||||
|
||||
for (std::map<std::string, std::string>::iterator p =
|
||||
mat->unknown_parameter.begin();
|
||||
p != mat->unknown_parameter.end(); ++p) {
|
||||
PyDict_SetItemString(unknown_parameter, p->first.c_str(),
|
||||
PyUnicode_FromString(p->second.c_str()));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(matobj, "shininess",
|
||||
PyFloat_FromDouble(mat->shininess));
|
||||
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble(mat->ior));
|
||||
PyDict_SetItemString(matobj, "dissolve",
|
||||
PyFloat_FromDouble(mat->dissolve));
|
||||
PyDict_SetItemString(matobj, "illum", PyLong_FromLong(mat->illum));
|
||||
PyDict_SetItemString(matobj, "ambient_texname",
|
||||
PyUnicode_FromString(mat->ambient_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "diffuse_texname",
|
||||
PyUnicode_FromString(mat->diffuse_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "specular_texname",
|
||||
PyUnicode_FromString(mat->specular_texname.c_str()));
|
||||
PyDict_SetItemString(
|
||||
matobj, "specular_highlight_texname",
|
||||
PyUnicode_FromString(mat->specular_highlight_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "bump_texname",
|
||||
PyUnicode_FromString(mat->bump_texname.c_str()));
|
||||
PyDict_SetItemString(
|
||||
matobj, "displacement_texname",
|
||||
PyUnicode_FromString(mat->displacement_texname.c_str()));
|
||||
PyDict_SetItemString(matobj, "alpha_texname",
|
||||
PyUnicode_FromString(mat->alpha_texname.c_str()));
|
||||
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(pymaterials, mat->name.c_str(), matobj);
|
||||
PyList_Append(pymaterial_indices, PyUnicode_FromString(mat->name.c_str()));
|
||||
}
|
||||
|
||||
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
||||
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
||||
PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices);
|
||||
PyDict_SetItemString(rtndict, "attribs", attribobj);
|
||||
|
||||
return rtndict;
|
||||
}
|
||||
|
||||
|
||||
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 = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"tinyobjloader",
|
||||
NULL,
|
||||
-1,
|
||||
mMethods
|
||||
};
|
||||
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
|
||||
NULL, -1, mMethods};
|
||||
|
||||
|
||||
PyMODINIT_FUNC
|
||||
PyInit_tinyobjloader(void)
|
||||
{
|
||||
return PyModule_Create(&moduledef);
|
||||
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
|
||||
return PyModule_Create(&moduledef);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
PyMODINIT_FUNC inittinyobjloader(void) {
|
||||
Py_InitModule3("tinyobjloader", mMethods, NULL);
|
||||
}
|
||||
|
||||
#endif // PY_MAJOR_VERSION >= 3
|
||||
|
||||
}
|
||||
|
||||
278
test.cc
278
test.cc
@@ -1,278 +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,
|
||||
bool triangulate = true)
|
||||
{
|
||||
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, triangulate);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("Failed to load/parse .obj.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
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, false));
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
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()
|
||||
742
tests/tester.cc
Normal file
742
tests/tester.cc
Normal file
@@ -0,0 +1,742 @@
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "../tiny_obj_loader.h"
|
||||
|
||||
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
static void PrintInfo(const tinyobj::attrib_t &attrib, const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool triangulate = true)
|
||||
{
|
||||
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", v,
|
||||
static_cast<const double>(attrib.vertices[v].x),
|
||||
static_cast<const double>(attrib.vertices[v].y),
|
||||
static_cast<const double>(attrib.vertices[v].z));
|
||||
}
|
||||
|
||||
for (size_t v = 0; v < attrib.normals.size() / 3; v++) {
|
||||
printf(" n[%ld] = (%f, %f, %f)\n", v,
|
||||
static_cast<const double>(attrib.normals[v].x),
|
||||
static_cast<const double>(attrib.normals[v].y),
|
||||
static_cast<const double>(attrib.normals[v].z));
|
||||
}
|
||||
|
||||
for (size_t v = 0; v < attrib.texcoords.size() / 2; v++) {
|
||||
printf(" uv[%ld] = (%f, %f)\n", v,
|
||||
static_cast<const double>(attrib.texcoords[v].x),
|
||||
static_cast<const double>(attrib.texcoords[v].y));
|
||||
}
|
||||
|
||||
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++) {
|
||||
tinyobj::index_t i0 = shapes[i].mesh.indices[3*f+0];
|
||||
tinyobj::index_t i1 = shapes[i].mesh.indices[3*f+1];
|
||||
tinyobj::index_t i2 = shapes[i].mesh.indices[3*f+2];
|
||||
printf(" idx[%ld] = %d/%d/%d, %d/%d/%d, %d/%d/%d. mat_id = %d\n", f,
|
||||
i0.vertex_index, i0.normal_index, i0.texcoord_index,
|
||||
i1.vertex_index, i1.normal_index, i1.texcoord_index,
|
||||
i2.vertex_index, i2.normal_index, i2.texcoord_index,
|
||||
shapes[i].mesh.material_ids[f]);
|
||||
}
|
||||
} else {
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
||||
tinyobj::index_t idx = shapes[i].mesh.indices[f];
|
||||
printf(" idx[%ld] = %d/%d/%d\n", f, idx.vertex_index, idx.normal_index, idx.texcoord_index);
|
||||
}
|
||||
|
||||
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_face_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_face_vertices.size());
|
||||
for (size_t v = 0; v < shapes[i].mesh.num_face_vertices.size(); v++) {
|
||||
printf(" num_vertices[%ld] = %ld\n", v,
|
||||
static_cast<long>(shapes[i].mesh.num_face_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,
|
||||
// static_cast<const double>(shapes[i].mesh.positions[3*v+0]),
|
||||
// static_cast<const double>(shapes[i].mesh.positions[3*v+1]),
|
||||
// static_cast<const double>(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", 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", 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(" material.map_d = %s\n", materials[i].alpha_texname.c_str());
|
||||
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
|
||||
printf(" material.refl = %s\n", materials[i].reflection_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;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, basepath, triangulate);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("Failed to load/parse .obj.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintInfo(attrib, shapes, materials, triangulate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TestLoadObjFromPreopenedFile(
|
||||
const char* filename,
|
||||
const char* basepath = NULL,
|
||||
bool readMaterials = true,
|
||||
bool triangulate = true)
|
||||
{
|
||||
std::string fullFilename = std::string(basepath) + filename;
|
||||
std::cout << "Loading " << fullFilename << std::endl;
|
||||
|
||||
std::ifstream fileStream(fullFilename.c_str());
|
||||
|
||||
if (!fileStream) {
|
||||
std::cerr << "Could not find specified file: " << fullFilename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
tinyobj::MaterialStreamReader materialStreamReader(fileStream);
|
||||
tinyobj::MaterialStreamReader* materialReader = readMaterials
|
||||
? &materialStreamReader
|
||||
: NULL;
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &fileStream, materialReader);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
printf("Failed to load/parse .obj.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "Loaded material count: " << materials.size() << "\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TestStreamLoadObj()
|
||||
{
|
||||
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::map<uint32_t, int>* matMap,
|
||||
std::string* err)
|
||||
{
|
||||
(void)matId;
|
||||
(void)err;
|
||||
std::string warning;
|
||||
LoadMtl(matMap, materials, &m_matSStream, &warning);
|
||||
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 err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &objStream, &matSSReader);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintInfo(attrib, shapes, materials);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* gMtlBasePath = "../models/";
|
||||
|
||||
TEST_CASE("cornell_box", "[Loader]") {
|
||||
|
||||
REQUIRE(true == TestLoadObj("../models/cornell_box.obj", gMtlBasePath));
|
||||
}
|
||||
|
||||
TEST_CASE("catmark_torus_creases0", "[Loader]") {
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/catmark_torus_creases0.obj", gMtlBasePath, /*triangulate*/false);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
REQUIRE(true == ret);
|
||||
|
||||
REQUIRE(1 == shapes.size());
|
||||
REQUIRE(8 == shapes[0].mesh.tags.size());
|
||||
}
|
||||
|
||||
TEST_CASE("pbr", "[Loader]") {
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/pbr-mat-ext.obj", gMtlBasePath, /*triangulate*/false);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(0.2 == Approx(materials[0].roughness));
|
||||
REQUIRE(0.3 == Approx(materials[0].metallic));
|
||||
REQUIRE(0.4 == Approx(materials[0].sheen));
|
||||
REQUIRE(0.5 == Approx(materials[0].clearcoat_thickness));
|
||||
REQUIRE(0.6 == Approx(materials[0].clearcoat_roughness));
|
||||
REQUIRE(0.7 == Approx(materials[0].anisotropy));
|
||||
REQUIRE(0.8 == Approx(materials[0].anisotropy_rotation));
|
||||
REQUIRE(0 == materials[0].roughness_texname.compare("roughness.tex"));
|
||||
REQUIRE(0 == materials[0].metallic_texname.compare("metallic.tex"));
|
||||
REQUIRE(0 == materials[0].sheen_texname.compare("sheen.tex"));
|
||||
REQUIRE(0 == materials[0].emissive_texname.compare("emissive.tex"));
|
||||
REQUIRE(0 == materials[0].normal_texname.compare("normalmap.tex"));
|
||||
}
|
||||
|
||||
TEST_CASE("stream_load", "[Stream]") {
|
||||
REQUIRE(true == TestStreamLoadObj());
|
||||
}
|
||||
|
||||
TEST_CASE("stream_load_from_file_skipping_materials", "[Stream]") {
|
||||
REQUIRE(true == TestLoadObjFromPreopenedFile(
|
||||
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/false, /*triangulate*/false));
|
||||
}
|
||||
|
||||
TEST_CASE("stream_load_from_file_with_materials", "[Stream]") {
|
||||
REQUIRE(true == TestLoadObjFromPreopenedFile(
|
||||
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/true, /*triangulate*/false));
|
||||
}
|
||||
|
||||
TEST_CASE("trailing_whitespace_in_mtl", "[Issue92]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-92.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(0 == materials[0].diffuse_texname.compare("tmp.png"));
|
||||
}
|
||||
|
||||
TEST_CASE("transmittance_filter", "[Issue95]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-95.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(0.1 == Approx(materials[0].transmittance[0]));
|
||||
REQUIRE(0.2 == Approx(materials[0].transmittance[1]));
|
||||
REQUIRE(0.3 == Approx(materials[0].transmittance[2]));
|
||||
}
|
||||
|
||||
TEST_CASE("transmittance_filter_Tf", "[Issue95-Tf]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-95-2.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(0.1 == Approx(materials[0].transmittance[0]));
|
||||
REQUIRE(0.2 == Approx(materials[0].transmittance[1]));
|
||||
REQUIRE(0.3 == Approx(materials[0].transmittance[2]));
|
||||
}
|
||||
|
||||
TEST_CASE("transmittance_filter_Kt", "[Issue95-Kt]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-95.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(0.1 == Approx(materials[0].transmittance[0]));
|
||||
REQUIRE(0.2 == Approx(materials[0].transmittance[1]));
|
||||
REQUIRE(0.3 == Approx(materials[0].transmittance[2]));
|
||||
}
|
||||
|
||||
TEST_CASE("usemtl_at_last_line", "[Issue104]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/usemtl-issue-104.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == shapes.size());
|
||||
}
|
||||
|
||||
TEST_CASE("texture_opts", "[Issue85]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/texture-options-issue-85.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == shapes.size());
|
||||
REQUIRE(3 == materials.size());
|
||||
REQUIRE(0 == materials[0].name.compare("default"));
|
||||
REQUIRE(0 == materials[1].name.compare("bm2"));
|
||||
REQUIRE(0 == materials[2].name.compare("bm3"));
|
||||
REQUIRE(true == materials[0].ambient_texopt.clamp);
|
||||
REQUIRE(0.1 == Approx(materials[0].diffuse_texopt.origin_offset[0]));
|
||||
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[1]));
|
||||
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[2]));
|
||||
REQUIRE(0.1 == Approx(materials[0].specular_texopt.scale[0]));
|
||||
REQUIRE(0.2 == Approx(materials[0].specular_texopt.scale[1]));
|
||||
REQUIRE(1.0 == Approx(materials[0].specular_texopt.scale[2]));
|
||||
REQUIRE(0.1 == Approx(materials[0].specular_highlight_texopt.turbulence[0]));
|
||||
REQUIRE(0.2 == Approx(materials[0].specular_highlight_texopt.turbulence[1]));
|
||||
REQUIRE(0.3 == Approx(materials[0].specular_highlight_texopt.turbulence[2]));
|
||||
REQUIRE(3.0 == Approx(materials[0].bump_texopt.bump_multiplier));
|
||||
|
||||
REQUIRE(0.1 == Approx(materials[1].specular_highlight_texopt.brightness));
|
||||
REQUIRE(0.3 == Approx(materials[1].specular_highlight_texopt.contrast));
|
||||
REQUIRE('r' == materials[1].bump_texopt.imfchan);
|
||||
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_SPHERE == materials[2].diffuse_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_TOP == materials[2].specular_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BOTTOM == materials[2].specular_highlight_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_LEFT == materials[2].ambient_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_RIGHT == materials[2].alpha_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_FRONT == materials[2].bump_texopt.type);
|
||||
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BACK == materials[2].displacement_texopt.type);
|
||||
}
|
||||
|
||||
TEST_CASE("mtllib_multiple_filenames", "[Issue112]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/mtllib-multiple-files-issue-112.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == materials.size());
|
||||
}
|
||||
|
||||
TEST_CASE("tr_and_d", "[Issue43]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/tr-and-d-issue-43.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(2 == materials.size());
|
||||
|
||||
REQUIRE(0.75 == Approx(materials[0].dissolve));
|
||||
REQUIRE(0.75 == Approx(materials[1].dissolve));
|
||||
}
|
||||
|
||||
TEST_CASE("refl", "[refl]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/refl.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
PrintInfo(attrib, shapes, materials);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(5 == materials.size());
|
||||
|
||||
REQUIRE(materials[0].reflection_texname.compare("reflection.tga") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("map_Bump", "[bump]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/map-bump.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
PrintInfo(attrib, shapes, materials);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(2 == materials.size());
|
||||
|
||||
REQUIRE(materials[0].bump_texname.compare("bump.jpg") == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("g_ignored", "[Issue138]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-138.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
PrintInfo(attrib, shapes, materials);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(2 == shapes.size());
|
||||
REQUIRE(2 == materials.size());
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("vertex-col-ext", "[Issue144]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/cube-vertexcol.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
//PrintInfo(attrib, shapes, materials);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE((8 * 3) == attrib.colors.size());
|
||||
|
||||
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 0]));
|
||||
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 1]));
|
||||
REQUIRE(0 == Approx(attrib.colors[3 * 0 + 2]));
|
||||
|
||||
REQUIRE(0 == Approx(attrib.colors[3 * 1 + 0]));
|
||||
REQUIRE(0 == Approx(attrib.colors[3 * 1 + 1]));
|
||||
REQUIRE(1 == Approx(attrib.colors[3 * 1 + 2]));
|
||||
|
||||
REQUIRE(1 == Approx(attrib.colors[3 * 4 + 0]));
|
||||
|
||||
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 0]));
|
||||
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 1]));
|
||||
REQUIRE(1 == Approx(attrib.colors[3 * 7 + 2]));
|
||||
}
|
||||
|
||||
TEST_CASE("norm_texopts", "[norm]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/norm-texopt.obj", gMtlBasePath);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(1 == shapes.size());
|
||||
REQUIRE(1 == materials.size());
|
||||
REQUIRE(3.0 == Approx(materials[0].normal_texopt.bump_multiplier));
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("zero-face-idx-value", "[Issue140]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-140-zero-face-idx.obj", gMtlBasePath);
|
||||
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
REQUIRE(false == ret);
|
||||
REQUIRE(!err.empty());
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("texture-name-whitespace", "[Issue145]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/texture-filename-with-whitespace.obj", gMtlBasePath);
|
||||
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << "[Issue145] " << err << std::endl;
|
||||
}
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(err.empty());
|
||||
REQUIRE(2 < materials.size());
|
||||
|
||||
REQUIRE(0 == materials[0].diffuse_texname.compare("texture 01.png"));
|
||||
REQUIRE(0 == materials[1].bump_texname.compare("bump 01.png"));
|
||||
REQUIRE(2 == Approx(materials[1].bump_texopt.bump_multiplier));
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
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, false));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
4
tests/vcbuild.bat
Normal file
4
tests/vcbuild.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
chcp 437
|
||||
python kuroga.py config-msvc.py
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" x86_amd64
|
||||
ninja
|
||||
2890
tiny_obj_loader.h
2890
tiny_obj_loader.h
File diff suppressed because it is too large
Load Diff
9
tinyobjloader-config.cmake.in
Normal file
9
tinyobjloader-config.cmake.in
Normal file
@@ -0,0 +1,9 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(TINYOBJLOADER_VERSION "@TINYOBJLOADER_VERSION@")
|
||||
|
||||
set_and_check(TINYOBJLOADER_INCLUDE_DIRS "@PACKAGE_TINYOBJLOADER_INCLUDE_DIR@")
|
||||
set_and_check(TINYOBJLOADER_LIBRARY_DIRS "@PACKAGE_TINYOBJLOADER_LIBRARY_DIR@")
|
||||
set(TINYOBJLOADER_LIBRARIES @LIBRARY_NAME@)
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake")
|
||||
15
tinyobjloader.pc.in
Normal file
15
tinyobjloader.pc.in
Normal file
@@ -0,0 +1,15 @@
|
||||
# Generated by CMake @CMAKE_VERSION@ for @PROJECT_NAME@. Any changes to this
|
||||
# file will be overwritten by the next CMake run. The input file was
|
||||
# tinyobjloader.pc.in.
|
||||
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${prefix}/@TINYOBJLOADER_LIBRARY_DIR@
|
||||
includedir=${prefix}/@TINYOBJLOADER_INCLUDE_DIR@
|
||||
|
||||
Name: @PROJECT_NAME@
|
||||
Description: Tiny but powerful single file wavefront obj loader
|
||||
URL: https://syoyo.github.io/tinyobjloader/
|
||||
Version: @TINYOBJLOADER_VERSION@
|
||||
Libs: -L${libdir} -l@LIBRARY_NAME@
|
||||
Cflags: -I${includedir}
|
||||
Binary file not shown.
@@ -6,7 +6,5 @@ build:
|
||||
name: build
|
||||
code: |
|
||||
git clone https://github.com/syoyo/orebuildenv.git
|
||||
chmod +x ./orebuildenv/build/linux/bin/premake4
|
||||
./orebuildenv/build/linux/bin/premake4 gmake
|
||||
make
|
||||
./test_tinyobjloader
|
||||
cd tests
|
||||
make check
|
||||
|
||||
Reference in New Issue
Block a user