Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
120
CMakeLists.txt
120
CMakeLists.txt
@@ -2,60 +2,134 @@
|
|||||||
#This configures the Cmake system with multiple properties, depending
|
#This configures the Cmake system with multiple properties, depending
|
||||||
#on the platform and configuration it is set to build in.
|
#on the platform and configuration it is set to build in.
|
||||||
project(tinyobjloader)
|
project(tinyobjloader)
|
||||||
cmake_minimum_required(VERSION 2.8.6)
|
cmake_minimum_required(VERSION 2.8.11)
|
||||||
|
set(TINYOBJLOADER_SOVERSION 1)
|
||||||
|
set(TINYOBJLOADER_VERSION 1.0.4)
|
||||||
|
|
||||||
#Folder Shortcuts
|
#Folder Shortcuts
|
||||||
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
set(TINYOBJLOADEREXAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/examples)
|
||||||
|
|
||||||
set(tinyobjloader-Source
|
set(tinyobjloader-Source
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
|
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
${CMAKE_CURRENT_SOURCE_DIR}/tiny_obj_loader.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(tinyobjloader-Example-Source
|
set(tinyobjloader-Example-Source
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
|
${CMAKE_CURRENT_SOURCE_DIR}/loader_example.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(tinyobjloader-examples-objsticher
|
set(tinyobjloader-examples-objsticher
|
||||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
|
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.h
|
||||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
|
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_writer.cc
|
||||||
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
${TINYOBJLOADEREXAMPLES_DIR}/obj_sticher/obj_sticher.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
#Install destinations
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
set(TINYOBJLOADER_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake)
|
||||||
|
set(TINYOBJLOADER_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
set(TINYOBJLOADER_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
set(TINYOBJLOADER_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
set(TINYOBJLOADER_PKGCONFIG_DIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
|
||||||
|
set(TINYOBJLOADER_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Example Loader Application" OFF)
|
option(TINYOBJLOADER_BUILD_TEST_LOADER "Build Example Loader Application" OFF)
|
||||||
option(TINYOBJLOADER_COMPILATION_SHARED "Build as shared library" OFF)
|
option(TINYOBJLOADER_COMPILATION_SHARED "Build as shared library" OFF)
|
||||||
|
|
||||||
if (TINYOBJLOADER_COMPILATION_SHARED)
|
if(TINYOBJLOADER_COMPILATION_SHARED)
|
||||||
add_library(tinyobjloader SHARED ${tinyobjloader-Source})
|
add_library(tinyobjloader SHARED ${tinyobjloader-Source})
|
||||||
|
set_target_properties(tinyobjloader PROPERTIES
|
||||||
|
SOVERSION ${TINYOBJLOADER_SOVERSION}
|
||||||
|
)
|
||||||
else()
|
else()
|
||||||
add_library(tinyobjloader STATIC ${tinyobjloader-Source})
|
add_library(tinyobjloader STATIC ${tinyobjloader-Source})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(tinyobjloader PROPERTIES VERSION ${TINYOBJLOADER_VERSION})
|
||||||
|
|
||||||
|
target_include_directories(tinyobjloader INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${TINYOBJLOADER_INCLUDE_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
export(TARGETS tinyobjloader FILE ${PROJECT_NAME}-targets.cmake)
|
||||||
|
|
||||||
if(TINYOBJLOADER_BUILD_TEST_LOADER)
|
if(TINYOBJLOADER_BUILD_TEST_LOADER)
|
||||||
add_executable(test_loader ${tinyobjloader-Example-Source})
|
add_executable(test_loader ${tinyobjloader-Example-Source})
|
||||||
target_link_libraries(test_loader tinyobjloader)
|
target_link_libraries(test_loader tinyobjloader)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(TINYOBJLOADER_BUILD_OBJ_STICHER "Build OBJ Sticher Application" OFF)
|
option(TINYOBJLOADER_BUILD_OBJ_STICHER "Build OBJ Sticher Application" OFF)
|
||||||
if (TINYOBJLOADER_BUILD_OBJ_STICHER)
|
if(TINYOBJLOADER_BUILD_OBJ_STICHER)
|
||||||
add_executable(obj_sticher ${tinyobjloader-examples-objsticher})
|
add_executable(obj_sticher ${tinyobjloader-examples-objsticher})
|
||||||
target_link_libraries(obj_sticher tinyobjloader)
|
target_link_libraries(obj_sticher tinyobjloader)
|
||||||
|
|
||||||
install ( TARGETS
|
install(TARGETS
|
||||||
obj_sticher
|
obj_sticher
|
||||||
DESTINATION
|
DESTINATION
|
||||||
bin
|
${TINYOBJLOADER_RUNTIME_DIR}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
#Installation
|
#Write CMake package config files
|
||||||
install ( TARGETS
|
include(CMakePackageConfigHelpers)
|
||||||
tinyobjloader
|
|
||||||
DESTINATION
|
configure_package_config_file(
|
||||||
lib
|
tinyobjloader-config.cmake.in
|
||||||
|
tinyobjloader-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(tinyobjloader-config-version.cmake
|
||||||
|
VERSION
|
||||||
|
${TINYOBJLOADER_VERSION}
|
||||||
|
COMPATIBILITY
|
||||||
|
SameMajorVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
#pkg-config file
|
||||||
|
configure_file(tinyobjloader.pc.in tinyobjloader.pc @ONLY)
|
||||||
|
|
||||||
|
#Installation
|
||||||
|
install(TARGETS
|
||||||
|
tinyobjloader
|
||||||
|
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
|
tiny_obj_loader.h
|
||||||
DESTINATION
|
DESTINATION
|
||||||
include
|
${TINYOBJLOADER_INCLUDE_DIR}
|
||||||
|
)
|
||||||
|
install(FILES
|
||||||
|
LICENSE
|
||||||
|
DESTINATION
|
||||||
|
${TINYOBJLOADER_DOC_DIR}
|
||||||
|
)
|
||||||
|
install(FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/tinyobjloader-config.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/tinyobjloader-config-version.cmake"
|
||||||
|
DESTINATION
|
||||||
|
${TINYOBJLOADER_CMAKE_DIR}
|
||||||
|
)
|
||||||
|
install(FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/tinyobjloader.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.
|
||||||
@@ -171,7 +171,7 @@ Here is some benchmark result. Time are measured on MacBook 12(Early 2016, Core
|
|||||||
* Rungholt scene(6M triangles)
|
* Rungholt scene(6M triangles)
|
||||||
* old version(v0.9.x): 15500 msecs.
|
* old version(v0.9.x): 15500 msecs.
|
||||||
* baseline(v1.0.x): 6800 msecs(2.3x faster than old version)
|
* baseline(v1.0.x): 6800 msecs(2.3x faster than old version)
|
||||||
* optimised: 1500 msecs(10x faster than old version, 4.5x faster than basedline)
|
* optimised: 1500 msecs(10x faster than old version, 4.5x faster than baseline)
|
||||||
|
|
||||||
|
|
||||||
## Tests
|
## Tests
|
||||||
|
|||||||
@@ -143,7 +143,26 @@ float eye[3], lookat[3], up[3];
|
|||||||
|
|
||||||
GLFWwindow* window;
|
GLFWwindow* window;
|
||||||
|
|
||||||
void CheckErrors(std::string desc) {
|
static std::string GetBaseDir(const std::string &filepath) {
|
||||||
|
if (filepath.find_last_of("/\\") != std::string::npos)
|
||||||
|
return filepath.substr(0, filepath.find_last_of("/\\"));
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool FileExists(const std::string &abs_filename) {
|
||||||
|
bool ret;
|
||||||
|
FILE *fp = fopen(abs_filename.c_str(), "rb");
|
||||||
|
if (fp) {
|
||||||
|
ret = true;
|
||||||
|
fclose(fp);
|
||||||
|
} else {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CheckErrors(std::string desc) {
|
||||||
GLenum e = glGetError();
|
GLenum e = glGetError();
|
||||||
if (e != GL_NO_ERROR) {
|
if (e != GL_NO_ERROR) {
|
||||||
fprintf(stderr, "OpenGL error in \"%s\": %d (%d)\n", desc.c_str(), e, e);
|
fprintf(stderr, "OpenGL error in \"%s\": %d (%d)\n", desc.c_str(), e, e);
|
||||||
@@ -151,7 +170,7 @@ void CheckErrors(std::string desc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
|
static void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
|
||||||
float v10[3];
|
float v10[3];
|
||||||
v10[0] = v1[0] - v0[0];
|
v10[0] = v1[0] - v0[0];
|
||||||
v10[1] = v1[1] - v0[1];
|
v10[1] = v1[1] - v0[1];
|
||||||
@@ -175,7 +194,7 @@ void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||||
std::vector<DrawObject>* drawObjects,
|
std::vector<DrawObject>* drawObjects,
|
||||||
std::vector<tinyobj::material_t>& materials,
|
std::vector<tinyobj::material_t>& materials,
|
||||||
std::map<std::string, GLuint>& textures,
|
std::map<std::string, GLuint>& textures,
|
||||||
@@ -187,9 +206,16 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
|||||||
|
|
||||||
tm.start();
|
tm.start();
|
||||||
|
|
||||||
|
std::string base_dir = GetBaseDir(filename);
|
||||||
|
#ifdef _WIN32
|
||||||
|
base_dir += "\\";
|
||||||
|
#else
|
||||||
|
base_dir += "/";
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string err;
|
std::string err;
|
||||||
bool ret =
|
bool ret =
|
||||||
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, NULL);
|
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, base_dir.c_str());
|
||||||
if (!err.empty()) {
|
if (!err.empty()) {
|
||||||
std::cerr << err << std::endl;
|
std::cerr << err << std::endl;
|
||||||
}
|
}
|
||||||
@@ -223,9 +249,20 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
|||||||
GLuint texture_id;
|
GLuint texture_id;
|
||||||
int w, h;
|
int w, h;
|
||||||
int comp;
|
int comp;
|
||||||
unsigned char* image = stbi_load(mp->diffuse_texname.c_str(), &w, &h, &comp, STBI_default);
|
|
||||||
|
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 == nullptr) {
|
if (image == nullptr) {
|
||||||
std::cerr << "Unable to load texture: " << mp->diffuse_texname << std::endl;
|
std::cerr << "Unable to load texture: " << texture_filename << std::endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
glGenTextures(1, &texture_id);
|
glGenTextures(1, &texture_id);
|
||||||
@@ -395,7 +432,7 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void reshapeFunc(GLFWwindow* window, int w, int h) {
|
static void reshapeFunc(GLFWwindow* window, int w, int h) {
|
||||||
int fb_w, fb_h;
|
int fb_w, fb_h;
|
||||||
// Get actual framebuffer size.
|
// Get actual framebuffer size.
|
||||||
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
glfwGetFramebufferSize(window, &fb_w, &fb_h);
|
||||||
@@ -411,7 +448,7 @@ void reshapeFunc(GLFWwindow* window, int w, int h) {
|
|||||||
height = h;
|
height = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
|
static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
|
||||||
int mods) {
|
int mods) {
|
||||||
(void)window;
|
(void)window;
|
||||||
(void)scancode;
|
(void)scancode;
|
||||||
@@ -440,7 +477,7 @@ void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clickFunc(GLFWwindow* window, int button, int action, int mods) {
|
static void clickFunc(GLFWwindow* window, int button, int action, int mods) {
|
||||||
(void)window;
|
(void)window;
|
||||||
(void)mods;
|
(void)mods;
|
||||||
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
if (button == GLFW_MOUSE_BUTTON_LEFT) {
|
||||||
@@ -467,7 +504,7 @@ void clickFunc(GLFWwindow* window, int button, int action, int mods) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
|
static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
|
||||||
(void)window;
|
(void)window;
|
||||||
float rotScale = 1.0f;
|
float rotScale = 1.0f;
|
||||||
float transScale = 2.0f;
|
float transScale = 2.0f;
|
||||||
@@ -494,7 +531,7 @@ void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
|
|||||||
prevMouseY = mouse_y;
|
prevMouseY = mouse_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw(const std::vector<DrawObject>& drawObjects, std::vector<tinyobj::material_t>& materials, std::map<std::string, GLuint>& textures) {
|
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_FRONT, GL_FILL);
|
||||||
glPolygonMode(GL_BACK, GL_FILL);
|
glPolygonMode(GL_BACK, GL_FILL);
|
||||||
|
|
||||||
@@ -513,9 +550,11 @@ void Draw(const std::vector<DrawObject>& drawObjects, std::vector<tinyobj::mater
|
|||||||
glEnableClientState(GL_COLOR_ARRAY);
|
glEnableClientState(GL_COLOR_ARRAY);
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
std::string diffuse_texname = materials[o.material_id].diffuse_texname;
|
if ((o.material_id < materials.size())) {
|
||||||
if (diffuse_texname.length() > 0) {
|
std::string diffuse_texname = materials[o.material_id].diffuse_texname;
|
||||||
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]);
|
if (textures.find(diffuse_texname) != textures.end()) {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glVertexPointer(3, GL_FLOAT, stride, (const void*)0);
|
glVertexPointer(3, GL_FLOAT, stride, (const void*)0);
|
||||||
glNormalPointer(GL_FLOAT, stride, (const void*)(sizeof(float) * 3));
|
glNormalPointer(GL_FLOAT, stride, (const void*)(sizeof(float) * 3));
|
||||||
|
|||||||
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.
|
||||||
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
|
||||||
@@ -21,7 +21,8 @@ solution "objview"
|
|||||||
includedirs { "./" }
|
includedirs { "./" }
|
||||||
includedirs { "../../" }
|
includedirs { "../../" }
|
||||||
|
|
||||||
buildoptions { "-std=c++11" }
|
flags { "c++11" }
|
||||||
|
--buildoptions { "-std=c++11" }
|
||||||
|
|
||||||
if _OPTIONS['with-zlib'] then
|
if _OPTIONS['with-zlib'] then
|
||||||
defines { 'ENABLE_ZLIB' }
|
defines { 'ENABLE_ZLIB' }
|
||||||
@@ -48,14 +49,15 @@ solution "objview"
|
|||||||
|
|
||||||
configuration { "windows" }
|
configuration { "windows" }
|
||||||
-- Path to GLFW3
|
-- Path to GLFW3
|
||||||
includedirs { '../../../../local/glfw-3.1.2.bin.WIN64/include' }
|
includedirs { '../../../local/glfw-3.2.bin.WIN64/include' }
|
||||||
libdirs { '../../../../local/glfw-3.1.2.bin.WIN64/lib-vc2013' }
|
libdirs { '../../../local/glfw-3.2.bin.WIN64/lib-vc2015' }
|
||||||
-- Path to GLEW
|
-- Path to GLEW
|
||||||
includedirs { '../../../../local/glew-1.13.0/include' }
|
includedirs { '../../../local/glew-1.13.0/include' }
|
||||||
libdirs { '../../../../local/glew-1.13.0/lib/Release/x64' }
|
libdirs { '../../../local/glew-1.13.0/lib/Release/x64' }
|
||||||
|
|
||||||
links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
|
links { "glfw3", "glew32", "gdi32", "winmm", "user32", "glu32","opengl32", "kernel32" }
|
||||||
defines { "_CRT_SECURE_NO_WARNINGS" }
|
defines { "_CRT_SECURE_NO_WARNINGS" }
|
||||||
|
defines { "NOMINMAX" }
|
||||||
|
|
||||||
configuration { "macosx" }
|
configuration { "macosx" }
|
||||||
includedirs { "/usr/local/include" }
|
includedirs { "/usr/local/include" }
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ THE SOFTWARE.
|
|||||||
#ifndef TINOBJ_LOADER_OPT_H_
|
#ifndef TINOBJ_LOADER_OPT_H_
|
||||||
#define TINOBJ_LOADER_OPT_H_
|
#define TINOBJ_LOADER_OPT_H_
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN32
|
||||||
#define atoll(S) _atoi64(S)
|
#define atoll(S) _atoi64(S)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
@@ -1263,7 +1263,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
? std::thread::hardware_concurrency()
|
? std::thread::hardware_concurrency()
|
||||||
: option.req_num_threads;
|
: option.req_num_threads;
|
||||||
num_threads =
|
num_threads =
|
||||||
std::max(1, std::min(static_cast<int>(num_threads), kMaxThreads));
|
(std::max)(1, (std::min)(static_cast<int>(num_threads), kMaxThreads));
|
||||||
|
|
||||||
if (option.verbose) {
|
if (option.verbose) {
|
||||||
std::cout << "# of threads = " << num_threads << std::endl;
|
std::cout << "# of threads = " << num_threads << std::endl;
|
||||||
@@ -1295,7 +1295,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
for (size_t t = 0; t < static_cast<size_t>(num_threads); t++) {
|
for (size_t t = 0; t < static_cast<size_t>(num_threads); t++) {
|
||||||
workers->push_back(std::thread([&, t]() {
|
workers->push_back(std::thread([&, t]() {
|
||||||
auto start_idx = (t + 0) * chunk_size;
|
auto start_idx = (t + 0) * chunk_size;
|
||||||
auto end_idx = std::min((t + 1) * chunk_size, len - 1);
|
auto end_idx = (std::min)((t + 1) * chunk_size, len - 1);
|
||||||
if (t == static_cast<size_t>((num_threads - 1))) {
|
if (t == static_cast<size_t>((num_threads - 1))) {
|
||||||
end_idx = len - 1;
|
end_idx = len - 1;
|
||||||
}
|
}
|
||||||
@@ -1325,7 +1325,7 @@ bool parseObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
// Find extra line which spand across chunk boundary.
|
// Find extra line which spand across chunk boundary.
|
||||||
if ((t < num_threads) && (buf[end_idx - 1] != '\n')) {
|
if ((t < num_threads) && (buf[end_idx - 1] != '\n')) {
|
||||||
auto extra_span_idx = std::min(end_idx - 1 + chunk_size, len - 1);
|
auto extra_span_idx = (std::min)(end_idx - 1 + chunk_size, len - 1);
|
||||||
for (size_t i = end_idx; i < extra_span_idx; i++) {
|
for (size_t i = end_idx; i < extra_span_idx; i++) {
|
||||||
if (is_line_ending(buf, i, extra_span_idx)) {
|
if (is_line_ending(buf, i, extra_span_idx)) {
|
||||||
LineInfo info;
|
LineInfo info;
|
||||||
|
|||||||
@@ -90,16 +90,24 @@ void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
|
|||||||
const char *mmap_file(size_t *len, const char* filename)
|
const char *mmap_file(size_t *len, const char* filename)
|
||||||
{
|
{
|
||||||
(*len) = 0;
|
(*len) = 0;
|
||||||
#ifdef _WIN64
|
#ifdef _WIN32
|
||||||
HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
HANDLE file = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||||
assert(file != INVALID_HANDLE_VALUE);
|
assert(file != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
HANDLE fileMapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
assert(fileMapping != INVALID_HANDLE_VALUE);
|
assert(fileMapping != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0);
|
LPVOID fileMapView = MapViewOfFile(fileMapping, FILE_MAP_READ, 0, 0, 0);
|
||||||
auto fileMapViewChar = (const char*)fileMapView;
|
auto fileMapViewChar = (const char*)fileMapView;
|
||||||
assert(fileMapView != NULL);
|
assert(fileMapView != NULL);
|
||||||
|
|
||||||
|
LARGE_INTEGER fileSize;
|
||||||
|
fileSize.QuadPart = 0;
|
||||||
|
GetFileSizeEx(file, &fileSize);
|
||||||
|
|
||||||
|
(*len) = static_cast<size_t>(fileSize.QuadPart);
|
||||||
|
return fileMapViewChar;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
FILE* f = fopen(filename, "r" );
|
FILE* f = fopen(filename, "r" );
|
||||||
@@ -324,6 +332,10 @@ bool LoadObjAndConvert(float bmin[3], float bmax[3], const char* filename, int n
|
|||||||
option.verbose = verbose;
|
option.verbose = verbose;
|
||||||
bool ret = parseObj(&attrib, &shapes, &materials, data, data_len, option);
|
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();
|
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
|
||||||
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
|
bmax[0] = bmax[1] = bmax[2] = -std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
#include <mmsystem.h>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -233,6 +233,7 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
|
|||||||
printf(" material.map_Ns = %s\n",
|
printf(" material.map_Ns = %s\n",
|
||||||
materials[i].specular_highlight_texname.c_str());
|
materials[i].specular_highlight_texname.c_str());
|
||||||
printf(" material.map_bump = %s\n", materials[i].bump_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.map_d = %s\n", materials[i].alpha_texname.c_str());
|
||||||
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
|
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
|
||||||
printf(" <<PBR>>\n");
|
printf(" <<PBR>>\n");
|
||||||
@@ -363,8 +364,14 @@ static bool TestStreamLoadObj() {
|
|||||||
std::map<std::string, int>* matMap,
|
std::map<std::string, int>* matMap,
|
||||||
std::string* err) {
|
std::string* err) {
|
||||||
(void)matId;
|
(void)matId;
|
||||||
(void)err;
|
std::string warning;
|
||||||
LoadMtl(matMap, materials, &m_matSStream);
|
LoadMtl(matMap, materials, &m_matSStream, &warning);
|
||||||
|
|
||||||
|
if (!warning.empty()) {
|
||||||
|
if (err) {
|
||||||
|
(*err) += warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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
|
||||||
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
|
||||||
@@ -1,3 +1,2 @@
|
|||||||
* PBR material
|
* PBR material
|
||||||
* Define index_t struct
|
* Define index_t struct
|
||||||
* Python 2.7 binding
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// python3 module for tinyobjloader
|
// python2/3 module for tinyobjloader
|
||||||
//
|
//
|
||||||
// usage:
|
// usage:
|
||||||
// import tinyobjloader as tol
|
// import tinyobjloader as tol
|
||||||
@@ -172,6 +172,7 @@ static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
|
|||||||
|
|
||||||
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
PyDict_SetItemString(rtndict, "shapes", pyshapes);
|
||||||
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
PyDict_SetItemString(rtndict, "materials", pymaterials);
|
||||||
|
PyDict_SetItemString(rtndict, "attribs", attribobj);
|
||||||
|
|
||||||
return rtndict;
|
return rtndict;
|
||||||
}
|
}
|
||||||
@@ -182,10 +183,21 @@ static PyMethodDef mMethods[] = {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
|
||||||
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
|
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader",
|
||||||
NULL, -1, mMethods};
|
NULL, -1, mMethods};
|
||||||
|
|
||||||
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
|
PyMODINIT_FUNC PyInit_tinyobjloader(void) {
|
||||||
return PyModule_Create(&moduledef);
|
return PyModule_Create(&moduledef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
PyMODINIT_FUNC inittinyobjloader(void) {
|
||||||
|
Py_InitModule3("tinyobjloader", mMethods, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PY_MAJOR_VERSION >= 3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,7 +307,8 @@ std::string matStream(
|
|||||||
{
|
{
|
||||||
(void)matId;
|
(void)matId;
|
||||||
(void)err;
|
(void)err;
|
||||||
LoadMtl(matMap, materials, &m_matSStream);
|
std::string warning;
|
||||||
|
LoadMtl(matMap, materials, &m_matSStream, &warning);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,6 +489,81 @@ TEST_CASE("usemtl_at_last_line", "[Issue104]") {
|
|||||||
REQUIRE(1 == shapes.size());
|
REQUIRE(1 == shapes.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("texture_opts", "[Issue85]") {
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/texture-options-issue-85.obj", gMtlBasePath);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
REQUIRE(1 == shapes.size());
|
||||||
|
REQUIRE(3 == materials.size());
|
||||||
|
REQUIRE(0 == materials[0].name.compare("default"));
|
||||||
|
REQUIRE(0 == materials[1].name.compare("bm2"));
|
||||||
|
REQUIRE(0 == materials[2].name.compare("bm3"));
|
||||||
|
REQUIRE(true == materials[0].ambient_texopt.clamp);
|
||||||
|
REQUIRE(0.1 == Approx(materials[0].diffuse_texopt.origin_offset[0]));
|
||||||
|
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[1]));
|
||||||
|
REQUIRE(0.0 == Approx(materials[0].diffuse_texopt.origin_offset[2]));
|
||||||
|
REQUIRE(0.1 == Approx(materials[0].specular_texopt.scale[0]));
|
||||||
|
REQUIRE(0.2 == Approx(materials[0].specular_texopt.scale[1]));
|
||||||
|
REQUIRE(1.0 == Approx(materials[0].specular_texopt.scale[2]));
|
||||||
|
REQUIRE(0.1 == Approx(materials[0].specular_highlight_texopt.turbulence[0]));
|
||||||
|
REQUIRE(0.2 == Approx(materials[0].specular_highlight_texopt.turbulence[1]));
|
||||||
|
REQUIRE(0.3 == Approx(materials[0].specular_highlight_texopt.turbulence[2]));
|
||||||
|
REQUIRE(3.0 == Approx(materials[0].bump_texopt.bump_multiplier));
|
||||||
|
|
||||||
|
REQUIRE(0.1 == Approx(materials[1].specular_highlight_texopt.brightness));
|
||||||
|
REQUIRE(0.3 == Approx(materials[1].specular_highlight_texopt.contrast));
|
||||||
|
REQUIRE('r' == materials[1].bump_texopt.imfchan);
|
||||||
|
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_SPHERE == materials[2].diffuse_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_TOP == materials[2].specular_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BOTTOM == materials[2].specular_highlight_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_LEFT == materials[2].ambient_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_RIGHT == materials[2].alpha_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_FRONT == materials[2].bump_texopt.type);
|
||||||
|
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BACK == materials[2].displacement_texopt.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("mtllib_multiple_filenames", "[Issue112]") {
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/mtllib-multiple-files-issue-112.obj", gMtlBasePath);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
REQUIRE(1 == materials.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("tr_and_d", "[Issue43]") {
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/tr-and-d-issue-43.obj", gMtlBasePath);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
REQUIRE(true == ret);
|
||||||
|
REQUIRE(2 == materials.size());
|
||||||
|
|
||||||
|
REQUIRE(0.75 == Approx(materials[0].dissolve));
|
||||||
|
REQUIRE(0.75 == Approx(materials[1].dissolve));
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int
|
int
|
||||||
main(
|
main(
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
// version 1.0.2 : Improve parsing speed by about a factor of 2 for large files(#105)
|
// version 1.0.5 : Ignore `Tr` when `d` exists in MTL(#43)
|
||||||
|
// version 1.0.4 : Support multiple filenames for 'mtllib'(#112)
|
||||||
|
// version 1.0.3 : Support parsing texture options(#85)
|
||||||
|
// version 1.0.2 : Improve parsing speed by about a factor of 2 for large
|
||||||
|
// files(#105)
|
||||||
// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104)
|
// version 1.0.1 : Fixes a shape is lost if obj ends with a 'usemtl'(#104)
|
||||||
// version 1.0.0 : Change data structure. Change license from BSD to MIT.
|
// version 1.0.0 : Change data structure. Change license from BSD to MIT.
|
||||||
//
|
//
|
||||||
@@ -43,6 +47,82 @@ THE SOFTWARE.
|
|||||||
|
|
||||||
namespace tinyobj {
|
namespace tinyobj {
|
||||||
|
|
||||||
|
// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ...
|
||||||
|
//
|
||||||
|
// -blendu on | off # set horizontal texture blending
|
||||||
|
// (default on)
|
||||||
|
// -blendv on | off # set vertical texture blending
|
||||||
|
// (default on)
|
||||||
|
// -boost float_value # boost mip-map sharpness
|
||||||
|
// -mm base_value gain_value # modify texture map values (default
|
||||||
|
// 0 1)
|
||||||
|
// # base_value = brightness,
|
||||||
|
// gain_value = contrast
|
||||||
|
// -o u [v [w]] # Origin offset (default
|
||||||
|
// 0 0 0)
|
||||||
|
// -s u [v [w]] # Scale (default
|
||||||
|
// 1 1 1)
|
||||||
|
// -t u [v [w]] # Turbulence (default
|
||||||
|
// 0 0 0)
|
||||||
|
// -texres resolution # texture resolution to create
|
||||||
|
// -clamp on | off # only render texels in the clamped
|
||||||
|
// 0-1 range (default off)
|
||||||
|
// # When unclamped, textures are
|
||||||
|
// repeated across a surface,
|
||||||
|
// # when clamped, only texels which
|
||||||
|
// fall within the 0-1
|
||||||
|
// # range are rendered.
|
||||||
|
// -bm mult_value # bump multiplier (for bump maps
|
||||||
|
// only)
|
||||||
|
//
|
||||||
|
// -imfchan r | g | b | m | l | z # specifies which channel of the file
|
||||||
|
// is used to
|
||||||
|
// # create a scalar or bump texture.
|
||||||
|
// r:red, g:green,
|
||||||
|
// # b:blue, m:matte, l:luminance,
|
||||||
|
// z:z-depth..
|
||||||
|
// # (the default for bump is 'l' and
|
||||||
|
// for decal is 'm')
|
||||||
|
// bump -imfchan r bumpmap.tga # says to use the red channel of
|
||||||
|
// bumpmap.tga as the bumpmap
|
||||||
|
//
|
||||||
|
// For reflection maps...
|
||||||
|
//
|
||||||
|
// -type sphere # specifies a sphere for a "refl"
|
||||||
|
// reflection map
|
||||||
|
// -type cube_top | cube_bottom | # when using a cube map, the texture
|
||||||
|
// file for each
|
||||||
|
// cube_front | cube_back | # side of the cube is specified
|
||||||
|
// separately
|
||||||
|
// cube_left | cube_right
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TEXTURE_TYPE_NONE, // default
|
||||||
|
TEXTURE_TYPE_SPHERE,
|
||||||
|
TEXTURE_TYPE_CUBE_TOP,
|
||||||
|
TEXTURE_TYPE_CUBE_BOTTOM,
|
||||||
|
TEXTURE_TYPE_CUBE_FRONT,
|
||||||
|
TEXTURE_TYPE_CUBE_BACK,
|
||||||
|
TEXTURE_TYPE_CUBE_LEFT,
|
||||||
|
TEXTURE_TYPE_CUBE_RIGHT
|
||||||
|
} texture_type_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
|
||||||
|
float sharpness; // -boost (default 1.0?)
|
||||||
|
float brightness; // base_value in -mm option (default 0)
|
||||||
|
float contrast; // gain_value in -mm option (default 1)
|
||||||
|
float origin_offset[3]; // -o u [v [w]] (default 0 0 0)
|
||||||
|
float scale[3]; // -s u [v [w]] (default 1 1 1)
|
||||||
|
float turbulence[3]; // -t u [v [w]] (default 0 0 0)
|
||||||
|
// int texture_resolution; // -texres resolution (default = ?) TODO
|
||||||
|
bool clamp; // -clamp (default false)
|
||||||
|
char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
|
||||||
|
bool blendu; // -blendu (default on)
|
||||||
|
bool blendv; // -blendv (default on)
|
||||||
|
float bump_multiplier; // -bm (for bump maps only, default 1.0)
|
||||||
|
} texture_option_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
@@ -67,22 +147,39 @@ typedef struct {
|
|||||||
std::string displacement_texname; // disp
|
std::string displacement_texname; // disp
|
||||||
std::string alpha_texname; // map_d
|
std::string alpha_texname; // map_d
|
||||||
|
|
||||||
|
texture_option_t ambient_texopt;
|
||||||
|
texture_option_t diffuse_texopt;
|
||||||
|
texture_option_t specular_texopt;
|
||||||
|
texture_option_t specular_highlight_texopt;
|
||||||
|
texture_option_t bump_texopt;
|
||||||
|
texture_option_t displacement_texopt;
|
||||||
|
texture_option_t alpha_texopt;
|
||||||
|
|
||||||
// PBR extension
|
// PBR extension
|
||||||
// http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
// http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
||||||
float roughness; // [0, 1] default 0
|
float roughness; // [0, 1] default 0
|
||||||
float metallic; // [0, 1] default 0
|
float metallic; // [0, 1] default 0
|
||||||
float sheen; // [0, 1] default 0
|
float sheen; // [0, 1] default 0
|
||||||
float clearcoat_thickness; // [0, 1] default 0
|
float clearcoat_thickness; // [0, 1] default 0
|
||||||
float clearcoat_roughness; // [0, 1] default 0
|
float clearcoat_roughness; // [0, 1] default 0
|
||||||
float anisotropy; // aniso. [0, 1] default 0
|
float anisotropy; // aniso. [0, 1] default 0
|
||||||
float anisotropy_rotation; // anisor. [0, 1] default 0
|
float anisotropy_rotation; // anisor. [0, 1] default 0
|
||||||
float pad0;
|
float pad0;
|
||||||
|
float pad1;
|
||||||
std::string roughness_texname; // map_Pr
|
std::string roughness_texname; // map_Pr
|
||||||
std::string metallic_texname; // map_Pm
|
std::string metallic_texname; // map_Pm
|
||||||
std::string sheen_texname; // map_Ps
|
std::string sheen_texname; // map_Ps
|
||||||
std::string emissive_texname; // map_Ke
|
std::string emissive_texname; // map_Ke
|
||||||
std::string normal_texname; // norm. For normal mapping.
|
std::string normal_texname; // norm. For normal mapping.
|
||||||
|
|
||||||
|
texture_option_t roughness_texopt;
|
||||||
|
texture_option_t metallic_texopt;
|
||||||
|
texture_option_t sheen_texopt;
|
||||||
|
texture_option_t emissive_texopt;
|
||||||
|
texture_option_t normal_texopt;
|
||||||
|
|
||||||
|
int pad2;
|
||||||
|
|
||||||
std::map<std::string, std::string> unknown_parameter;
|
std::map<std::string, std::string> unknown_parameter;
|
||||||
} material_t;
|
} material_t;
|
||||||
|
|
||||||
@@ -171,15 +268,15 @@ class MaterialReader {
|
|||||||
|
|
||||||
class MaterialFileReader : public MaterialReader {
|
class MaterialFileReader : public MaterialReader {
|
||||||
public:
|
public:
|
||||||
explicit MaterialFileReader(const std::string &mtl_basepath)
|
explicit MaterialFileReader(const std::string &mtl_basedir)
|
||||||
: m_mtlBasePath(mtl_basepath) {}
|
: m_mtlBaseDir(mtl_basedir) {}
|
||||||
virtual ~MaterialFileReader() {}
|
virtual ~MaterialFileReader() {}
|
||||||
virtual bool operator()(const std::string &matId,
|
virtual bool operator()(const std::string &matId,
|
||||||
std::vector<material_t> *materials,
|
std::vector<material_t> *materials,
|
||||||
std::map<std::string, int> *matMap, std::string *err);
|
std::map<std::string, int> *matMap, std::string *err);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_mtlBasePath;
|
std::string m_mtlBaseDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaterialStreamReader : public MaterialReader {
|
class MaterialStreamReader : public MaterialReader {
|
||||||
@@ -200,12 +297,14 @@ class MaterialStreamReader : public MaterialReader {
|
|||||||
/// 'shapes' will be filled with parsed shape data
|
/// 'shapes' will be filled with parsed shape data
|
||||||
/// Returns true when loading .obj become success.
|
/// Returns true when loading .obj become success.
|
||||||
/// Returns warning and error message into `err`
|
/// Returns warning and error message into `err`
|
||||||
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
/// 'mtl_basedir' is optional, and used for base directory for .mtl file.
|
||||||
|
/// In default(`NULL'), .mtl file is searched from an application's working
|
||||||
|
/// directory.
|
||||||
/// 'triangulate' is optional, and used whether triangulate polygon face in .obj
|
/// 'triangulate' is optional, and used whether triangulate polygon face in .obj
|
||||||
/// or not.
|
/// or not.
|
||||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||||
std::vector<material_t> *materials, std::string *err,
|
std::vector<material_t> *materials, std::string *err,
|
||||||
const char *filename, const char *mtl_basepath = NULL,
|
const char *filename, const char *mtl_basedir = NULL,
|
||||||
bool triangulate = true);
|
bool triangulate = true);
|
||||||
|
|
||||||
/// Loads .obj from a file with custom user callback.
|
/// Loads .obj from a file with custom user callback.
|
||||||
@@ -230,7 +329,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
/// Loads materials into std::map
|
/// Loads materials into std::map
|
||||||
void LoadMtl(std::map<std::string, int> *material_map,
|
void LoadMtl(std::map<std::string, int> *material_map,
|
||||||
std::vector<material_t> *materials, std::istream *inStream);
|
std::vector<material_t> *materials, std::istream *inStream,
|
||||||
|
std::string *warning);
|
||||||
|
|
||||||
} // namespace tinyobj
|
} // namespace tinyobj
|
||||||
|
|
||||||
@@ -421,20 +521,13 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
|
|||||||
end_not_reached = (curr != s_end);
|
end_not_reached = (curr != s_end);
|
||||||
while (end_not_reached && IS_DIGIT(*curr)) {
|
while (end_not_reached && IS_DIGIT(*curr)) {
|
||||||
static const double pow_lut[] = {
|
static const double pow_lut[] = {
|
||||||
1.0,
|
1.0, 0.1, 0.01, 0.001, 0.0001, 0.00001, 0.000001, 0.0000001,
|
||||||
0.1,
|
|
||||||
0.01,
|
|
||||||
0.001,
|
|
||||||
0.0001,
|
|
||||||
0.00001,
|
|
||||||
0.000001,
|
|
||||||
0.0000001,
|
|
||||||
};
|
};
|
||||||
const int lut_entries = sizeof pow_lut / sizeof pow_lut[0];
|
const int lut_entries = sizeof pow_lut / sizeof pow_lut[0];
|
||||||
|
|
||||||
// NOTE: Don't use powf here, it will absolutely murder precision.
|
// NOTE: Don't use powf here, it will absolutely murder precision.
|
||||||
mantissa += static_cast<int>(*curr - 0x30) *
|
mantissa += static_cast<int>(*curr - 0x30) *
|
||||||
(read < lut_entries ? pow_lut[read] : pow(10.0, -read));
|
(read < lut_entries ? pow_lut[read] : pow(10.0, -read));
|
||||||
read++;
|
read++;
|
||||||
curr++;
|
curr++;
|
||||||
end_not_reached = (curr != s_end);
|
end_not_reached = (curr != s_end);
|
||||||
@@ -474,8 +567,9 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assemble:
|
assemble:
|
||||||
*result = (sign == '+' ? 1 : -1) *
|
*result =
|
||||||
(exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa);
|
(sign == '+' ? 1 : -1) *
|
||||||
|
(exponent ? ldexp(mantissa * pow(5.0, exponent), exponent) : mantissa);
|
||||||
return true;
|
return true;
|
||||||
fail:
|
fail:
|
||||||
return false;
|
return false;
|
||||||
@@ -491,24 +585,72 @@ static inline float parseFloat(const char **token, double default_value = 0.0) {
|
|||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void parseFloat2(float *x, float *y, const char **token) {
|
static inline void parseFloat2(float *x, float *y, const char **token,
|
||||||
(*x) = parseFloat(token);
|
const double default_x = 0.0,
|
||||||
(*y) = parseFloat(token);
|
const double default_y = 0.0) {
|
||||||
|
(*x) = parseFloat(token, default_x);
|
||||||
|
(*y) = parseFloat(token, default_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void parseFloat3(float *x, float *y, float *z,
|
static inline void parseFloat3(float *x, float *y, float *z, const char **token,
|
||||||
const char **token) {
|
const double default_x = 0.0,
|
||||||
(*x) = parseFloat(token);
|
const double default_y = 0.0,
|
||||||
(*y) = parseFloat(token);
|
const double default_z = 0.0) {
|
||||||
(*z) = parseFloat(token);
|
(*x) = parseFloat(token, default_x);
|
||||||
|
(*y) = parseFloat(token, default_y);
|
||||||
|
(*z) = parseFloat(token, default_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void parseV(float *x, float *y, float *z, float *w,
|
static inline void parseV(float *x, float *y, float *z, float *w,
|
||||||
const char **token) {
|
const char **token, const double default_x = 0.0,
|
||||||
(*x) = parseFloat(token);
|
const double default_y = 0.0,
|
||||||
(*y) = parseFloat(token);
|
const double default_z = 0.0,
|
||||||
(*z) = parseFloat(token);
|
const double default_w = 1.0) {
|
||||||
(*w) = parseFloat(token, 1.0);
|
(*x) = parseFloat(token, default_x);
|
||||||
|
(*y) = parseFloat(token, default_y);
|
||||||
|
(*z) = parseFloat(token, default_z);
|
||||||
|
(*w) = parseFloat(token, default_w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool parseOnOff(const char **token, bool default_value = true) {
|
||||||
|
(*token) += strspn((*token), " \t");
|
||||||
|
const char *end = (*token) + strcspn((*token), " \t\r");
|
||||||
|
|
||||||
|
bool ret = default_value;
|
||||||
|
if ((0 == strncmp((*token), "on", 2))) {
|
||||||
|
ret = true;
|
||||||
|
} else if ((0 == strncmp((*token), "off", 3))) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*token) = end;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline texture_type_t parseTextureType(
|
||||||
|
const char **token, texture_type_t default_value = TEXTURE_TYPE_NONE) {
|
||||||
|
(*token) += strspn((*token), " \t");
|
||||||
|
const char *end = (*token) + strcspn((*token), " \t\r");
|
||||||
|
texture_type_t ty = default_value;
|
||||||
|
|
||||||
|
if ((0 == strncmp((*token), "cube_top", strlen("cube_top")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_TOP;
|
||||||
|
} else if ((0 == strncmp((*token), "cube_bottom", strlen("cube_bottom")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_BOTTOM;
|
||||||
|
} else if ((0 == strncmp((*token), "cube_left", strlen("cube_left")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_LEFT;
|
||||||
|
} else if ((0 == strncmp((*token), "cube_right", strlen("cube_right")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_RIGHT;
|
||||||
|
} else if ((0 == strncmp((*token), "cube_front", strlen("cube_front")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_FRONT;
|
||||||
|
} else if ((0 == strncmp((*token), "cube_back", strlen("cube_back")))) {
|
||||||
|
ty = TEXTURE_TYPE_CUBE_BACK;
|
||||||
|
} else if ((0 == strncmp((*token), "sphere", strlen("sphere")))) {
|
||||||
|
ty = TEXTURE_TYPE_SPHERE;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*token) = end;
|
||||||
|
return ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
static tag_sizes parseTagTriple(const char **token) {
|
static tag_sizes parseTagTriple(const char **token) {
|
||||||
@@ -601,6 +743,102 @@ static vertex_index parseRawTriple(const char **token) {
|
|||||||
return vi;
|
return vi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ParseTextureNameAndOption(std::string *texname,
|
||||||
|
texture_option_t *texopt,
|
||||||
|
const char *linebuf, const bool is_bump) {
|
||||||
|
// @todo { write more robust lexer and parser. }
|
||||||
|
bool found_texname = false;
|
||||||
|
std::string texture_name;
|
||||||
|
|
||||||
|
// Fill with default value for texopt.
|
||||||
|
if (is_bump) {
|
||||||
|
texopt->imfchan = 'l';
|
||||||
|
} else {
|
||||||
|
texopt->imfchan = 'm';
|
||||||
|
}
|
||||||
|
texopt->bump_multiplier = 1.0f;
|
||||||
|
texopt->clamp = false;
|
||||||
|
texopt->blendu = true;
|
||||||
|
texopt->blendv = true;
|
||||||
|
texopt->sharpness = 1.0f;
|
||||||
|
texopt->brightness = 0.0f;
|
||||||
|
texopt->contrast = 1.0f;
|
||||||
|
texopt->origin_offset[0] = 0.0f;
|
||||||
|
texopt->origin_offset[1] = 0.0f;
|
||||||
|
texopt->origin_offset[2] = 0.0f;
|
||||||
|
texopt->scale[0] = 1.0f;
|
||||||
|
texopt->scale[1] = 1.0f;
|
||||||
|
texopt->scale[2] = 1.0f;
|
||||||
|
texopt->turbulence[0] = 0.0f;
|
||||||
|
texopt->turbulence[1] = 0.0f;
|
||||||
|
texopt->turbulence[2] = 0.0f;
|
||||||
|
texopt->type = TEXTURE_TYPE_NONE;
|
||||||
|
|
||||||
|
const char *token = linebuf; // Assume line ends with NULL
|
||||||
|
|
||||||
|
while (!IS_NEW_LINE((*token))) {
|
||||||
|
if ((0 == strncmp(token, "-blendu", 7)) && IS_SPACE((token[7]))) {
|
||||||
|
token += 8;
|
||||||
|
texopt->blendu = parseOnOff(&token, /* default */ true);
|
||||||
|
} else if ((0 == strncmp(token, "-blendv", 7)) && IS_SPACE((token[7]))) {
|
||||||
|
token += 8;
|
||||||
|
texopt->blendv = parseOnOff(&token, /* default */ true);
|
||||||
|
} else if ((0 == strncmp(token, "-clamp", 6)) && IS_SPACE((token[6]))) {
|
||||||
|
token += 7;
|
||||||
|
texopt->clamp = parseOnOff(&token, /* default */ true);
|
||||||
|
} else if ((0 == strncmp(token, "-boost", 6)) && IS_SPACE((token[6]))) {
|
||||||
|
token += 7;
|
||||||
|
texopt->sharpness = parseFloat(&token, 1.0);
|
||||||
|
} else if ((0 == strncmp(token, "-bm", 3)) && IS_SPACE((token[3]))) {
|
||||||
|
token += 4;
|
||||||
|
texopt->bump_multiplier = parseFloat(&token, 1.0);
|
||||||
|
} else if ((0 == strncmp(token, "-o", 2)) && IS_SPACE((token[2]))) {
|
||||||
|
token += 3;
|
||||||
|
parseFloat3(&(texopt->origin_offset[0]), &(texopt->origin_offset[1]),
|
||||||
|
&(texopt->origin_offset[2]), &token);
|
||||||
|
} else if ((0 == strncmp(token, "-s", 2)) && IS_SPACE((token[2]))) {
|
||||||
|
token += 3;
|
||||||
|
parseFloat3(&(texopt->scale[0]), &(texopt->scale[1]), &(texopt->scale[2]),
|
||||||
|
&token, 1.0, 1.0, 1.0);
|
||||||
|
} else if ((0 == strncmp(token, "-t", 2)) && IS_SPACE((token[2]))) {
|
||||||
|
token += 3;
|
||||||
|
parseFloat3(&(texopt->turbulence[0]), &(texopt->turbulence[1]),
|
||||||
|
&(texopt->turbulence[2]), &token);
|
||||||
|
} else if ((0 == strncmp(token, "-type", 5)) && IS_SPACE((token[5]))) {
|
||||||
|
token += 5;
|
||||||
|
texopt->type = parseTextureType((&token), TEXTURE_TYPE_NONE);
|
||||||
|
} else if ((0 == strncmp(token, "-imfchan", 8)) && IS_SPACE((token[8]))) {
|
||||||
|
token += 9;
|
||||||
|
token += strspn(token, " \t");
|
||||||
|
const char *end = token + strcspn(token, " \t\r");
|
||||||
|
if ((end - token) == 1) { // Assume one char for -imfchan
|
||||||
|
texopt->imfchan = (*token);
|
||||||
|
}
|
||||||
|
token = end;
|
||||||
|
} else if ((0 == strncmp(token, "-mm", 3)) && IS_SPACE((token[3]))) {
|
||||||
|
token += 4;
|
||||||
|
parseFloat2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
|
||||||
|
} else {
|
||||||
|
// Assume texture filename
|
||||||
|
token += strspn(token, " \t"); // skip space
|
||||||
|
size_t len = strcspn(token, " \t\r"); // untile next space
|
||||||
|
texture_name = std::string(token, token + len);
|
||||||
|
token += len;
|
||||||
|
|
||||||
|
token += strspn(token, " \t"); // skip space
|
||||||
|
|
||||||
|
found_texname = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_texname) {
|
||||||
|
(*texname) = texture_name;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void InitMaterial(material_t *material) {
|
static void InitMaterial(material_t *material) {
|
||||||
material->name = "";
|
material->name = "";
|
||||||
material->ambient_texname = "";
|
material->ambient_texname = "";
|
||||||
@@ -701,12 +939,31 @@ static bool exportFaceGroupToShape(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split a string with specified delimiter character.
|
||||||
|
// http://stackoverflow.com/questions/236129/split-a-string-in-c
|
||||||
|
static void SplitString(const std::string &s, char delim,
|
||||||
|
std::vector<std::string> &elems) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.str(s);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(ss, item, delim)) {
|
||||||
|
elems.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LoadMtl(std::map<std::string, int> *material_map,
|
void LoadMtl(std::map<std::string, int> *material_map,
|
||||||
std::vector<material_t> *materials, std::istream *inStream) {
|
std::vector<material_t> *materials, std::istream *inStream,
|
||||||
|
std::string *warning) {
|
||||||
// Create a default material anyway.
|
// Create a default material anyway.
|
||||||
material_t material;
|
material_t material;
|
||||||
InitMaterial(&material);
|
InitMaterial(&material);
|
||||||
|
|
||||||
|
// Issue 43. `d` wins against `Tr` since `Tr` is not in the MTL specification.
|
||||||
|
bool has_d = false;
|
||||||
|
bool has_tr = false;
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
|
||||||
std::string linebuf;
|
std::string linebuf;
|
||||||
while (inStream->peek() != -1) {
|
while (inStream->peek() != -1) {
|
||||||
safeGetline(*inStream, linebuf);
|
safeGetline(*inStream, linebuf);
|
||||||
@@ -752,6 +1009,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
// initial temporary material
|
// initial temporary material
|
||||||
InitMaterial(&material);
|
InitMaterial(&material);
|
||||||
|
|
||||||
|
has_d = false;
|
||||||
|
has_tr = false;
|
||||||
|
|
||||||
// set new mtl name
|
// set new mtl name
|
||||||
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
||||||
token += 7;
|
token += 7;
|
||||||
@@ -845,12 +1105,29 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
if ((token[0] == 'd' && IS_SPACE(token[1]))) {
|
if ((token[0] == 'd' && IS_SPACE(token[1]))) {
|
||||||
token += 1;
|
token += 1;
|
||||||
material.dissolve = parseFloat(&token);
|
material.dissolve = parseFloat(&token);
|
||||||
|
|
||||||
|
if (has_tr) {
|
||||||
|
ss << "WARN: Both `d` and `Tr` parameters defined for \""
|
||||||
|
<< material.name << "\". Use the value of `d` for dissolve."
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
has_d = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) {
|
if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) {
|
||||||
token += 2;
|
token += 2;
|
||||||
// Invert value of Tr(assume Tr is in range [0, 1])
|
if (has_d) {
|
||||||
material.dissolve = 1.0f - parseFloat(&token);
|
// `d` wins. Ignore `Tr` value.
|
||||||
|
ss << "WARN: Both `d` and `Tr` parameters defined for \""
|
||||||
|
<< material.name << "\". Use the value of `d` for dissolve."
|
||||||
|
<< std::endl;
|
||||||
|
} else {
|
||||||
|
// We invert value of Tr(assume Tr is in range [0, 1])
|
||||||
|
// NOTE: Interpretation of Tr is application(exporter) dependent. For
|
||||||
|
// some application(e.g. 3ds max obj exporter), Tr = d(Issue 43)
|
||||||
|
material.dissolve = 1.0f - parseFloat(&token);
|
||||||
|
}
|
||||||
|
has_tr = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -906,35 +1183,54 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
// ambient texture
|
// ambient texture
|
||||||
if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.ambient_texname = token;
|
ParseTextureNameAndOption(&(material.ambient_texname),
|
||||||
|
&(material.ambient_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// diffuse texture
|
// diffuse texture
|
||||||
if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.diffuse_texname = token;
|
ParseTextureNameAndOption(&(material.diffuse_texname),
|
||||||
|
&(material.diffuse_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// specular texture
|
// specular texture
|
||||||
if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.specular_texname = token;
|
ParseTextureNameAndOption(&(material.specular_texname),
|
||||||
|
&(material.specular_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// specular highlight texture
|
// specular highlight texture
|
||||||
if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.specular_highlight_texname = token;
|
ParseTextureNameAndOption(&(material.specular_highlight_texname),
|
||||||
|
&(material.specular_highlight_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// bump texture
|
// bump texture
|
||||||
if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) {
|
if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) {
|
||||||
token += 9;
|
token += 9;
|
||||||
material.bump_texname = token;
|
ParseTextureNameAndOption(&(material.bump_texname),
|
||||||
|
&(material.bump_texopt), token,
|
||||||
|
/* is_bump */ true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bump texture
|
||||||
|
if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) {
|
||||||
|
token += 5;
|
||||||
|
ParseTextureNameAndOption(&(material.bump_texname),
|
||||||
|
&(material.bump_texopt), token,
|
||||||
|
/* is_bump */ true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -942,55 +1238,63 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) {
|
if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) {
|
||||||
token += 6;
|
token += 6;
|
||||||
material.alpha_texname = token;
|
material.alpha_texname = token;
|
||||||
continue;
|
ParseTextureNameAndOption(&(material.alpha_texname),
|
||||||
}
|
&(material.alpha_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
// bump texture
|
|
||||||
if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) {
|
|
||||||
token += 5;
|
|
||||||
material.bump_texname = token;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// displacement texture
|
// displacement texture
|
||||||
if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) {
|
if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) {
|
||||||
token += 5;
|
token += 5;
|
||||||
material.displacement_texname = token;
|
ParseTextureNameAndOption(&(material.displacement_texname),
|
||||||
|
&(material.displacement_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBR: roughness texture
|
// PBR: roughness texture
|
||||||
if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.roughness_texname = token;
|
ParseTextureNameAndOption(&(material.roughness_texname),
|
||||||
|
&(material.roughness_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBR: metallic texture
|
// PBR: metallic texture
|
||||||
if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.metallic_texname = token;
|
ParseTextureNameAndOption(&(material.metallic_texname),
|
||||||
|
&(material.metallic_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBR: sheen texture
|
// PBR: sheen texture
|
||||||
if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.sheen_texname = token;
|
ParseTextureNameAndOption(&(material.sheen_texname),
|
||||||
|
&(material.sheen_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBR: emissive texture
|
// PBR: emissive texture
|
||||||
if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) {
|
if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) {
|
||||||
token += 7;
|
token += 7;
|
||||||
material.emissive_texname = token;
|
ParseTextureNameAndOption(&(material.emissive_texname),
|
||||||
|
&(material.emissive_texopt), token,
|
||||||
|
/* is_bump */ false);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PBR: normal map texture
|
// PBR: normal map texture
|
||||||
if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) {
|
if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) {
|
||||||
token += 5;
|
token += 5;
|
||||||
material.normal_texname = token;
|
ParseTextureNameAndOption(
|
||||||
|
&(material.normal_texname), &(material.normal_texopt), token,
|
||||||
|
/* is_bump */ false); // @fixme { is_bump will be true? }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1011,6 +1315,10 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
|||||||
material_map->insert(std::pair<std::string, int>(
|
material_map->insert(std::pair<std::string, int>(
|
||||||
material.name, static_cast<int>(materials->size())));
|
material.name, static_cast<int>(materials->size())));
|
||||||
materials->push_back(material);
|
materials->push_back(material);
|
||||||
|
|
||||||
|
if (warning) {
|
||||||
|
(*warning) = ss.str();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MaterialFileReader::operator()(const std::string &matId,
|
bool MaterialFileReader::operator()(const std::string &matId,
|
||||||
@@ -1019,22 +1327,31 @@ bool MaterialFileReader::operator()(const std::string &matId,
|
|||||||
std::string *err) {
|
std::string *err) {
|
||||||
std::string filepath;
|
std::string filepath;
|
||||||
|
|
||||||
if (!m_mtlBasePath.empty()) {
|
if (!m_mtlBaseDir.empty()) {
|
||||||
filepath = std::string(m_mtlBasePath) + matId;
|
filepath = std::string(m_mtlBaseDir) + matId;
|
||||||
} else {
|
} else {
|
||||||
filepath = matId;
|
filepath = matId;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream matIStream(filepath.c_str());
|
std::ifstream matIStream(filepath.c_str());
|
||||||
LoadMtl(matMap, materials, &matIStream);
|
|
||||||
if (!matIStream) {
|
if (!matIStream) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "WARN: Material file [ " << filepath
|
ss << "WARN: Material file [ " << filepath << " ] not found." << std::endl;
|
||||||
<< " ] not found. Created a default material.";
|
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += ss.str();
|
(*err) += ss.str();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string warning;
|
||||||
|
LoadMtl(matMap, materials, &matIStream, &warning);
|
||||||
|
|
||||||
|
if (!warning.empty()) {
|
||||||
|
if (err) {
|
||||||
|
(*err) += warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1043,22 +1360,30 @@ bool MaterialStreamReader::operator()(const std::string &matId,
|
|||||||
std::map<std::string, int> *matMap,
|
std::map<std::string, int> *matMap,
|
||||||
std::string *err) {
|
std::string *err) {
|
||||||
(void)matId;
|
(void)matId;
|
||||||
LoadMtl(matMap, materials, &m_inStream);
|
|
||||||
if (!m_inStream) {
|
if (!m_inStream) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "WARN: Material stream in error state."
|
ss << "WARN: Material stream in error state. " << std::endl;
|
||||||
<< " Created a default material.";
|
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += ss.str();
|
(*err) += ss.str();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string warning;
|
||||||
|
LoadMtl(matMap, materials, &m_inStream, &warning);
|
||||||
|
|
||||||
|
if (!warning.empty()) {
|
||||||
|
if (err) {
|
||||||
|
(*err) += warning;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||||
std::vector<material_t> *materials, std::string *err,
|
std::vector<material_t> *materials, std::string *err,
|
||||||
const char *filename, const char *mtl_basepath,
|
const char *filename, const char *mtl_basedir, bool trianglulate) {
|
||||||
bool trianglulate) {
|
|
||||||
attrib->vertices.clear();
|
attrib->vertices.clear();
|
||||||
attrib->normals.clear();
|
attrib->normals.clear();
|
||||||
attrib->texcoords.clear();
|
attrib->texcoords.clear();
|
||||||
@@ -1075,11 +1400,11 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string basePath;
|
std::string baseDir;
|
||||||
if (mtl_basepath) {
|
if (mtl_basedir) {
|
||||||
basePath = mtl_basepath;
|
baseDir = mtl_basedir;
|
||||||
}
|
}
|
||||||
MaterialFileReader matFileReader(basePath);
|
MaterialFileReader matFileReader(baseDir);
|
||||||
|
|
||||||
return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader,
|
return LoadObj(attrib, shapes, materials, err, &ifs, &matFileReader,
|
||||||
trianglulate);
|
trianglulate);
|
||||||
@@ -1087,8 +1412,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||||
std::vector<material_t> *materials, std::string *err,
|
std::vector<material_t> *materials, std::string *err,
|
||||||
std::istream *inStream,
|
std::istream *inStream, MaterialReader *readMatFn /*= NULL*/,
|
||||||
MaterialReader *readMatFn /*= NULL*/,
|
|
||||||
bool triangulate) {
|
bool triangulate) {
|
||||||
std::stringstream errss;
|
std::stringstream errss;
|
||||||
|
|
||||||
@@ -1222,23 +1546,40 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
// load mtl
|
// load mtl
|
||||||
if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) {
|
if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) {
|
||||||
if (readMatFn) {
|
if (readMatFn) {
|
||||||
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
|
||||||
token += 7;
|
token += 7;
|
||||||
#ifdef _MSC_VER
|
|
||||||
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
|
|
||||||
#else
|
|
||||||
sscanf(token, "%s", namebuf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string err_mtl;
|
std::vector<std::string> filenames;
|
||||||
bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl);
|
SplitString(std::string(token), ' ', filenames);
|
||||||
if (err) {
|
|
||||||
(*err) += err_mtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
if (filenames.empty()) {
|
||||||
faceGroup.clear(); // for safety
|
if (err) {
|
||||||
return false;
|
(*err) +=
|
||||||
|
"WARN: Looks like empty filename for mtllib. Use default "
|
||||||
|
"material. \n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool found = false;
|
||||||
|
for (size_t s = 0; s < filenames.size(); s++) {
|
||||||
|
std::string err_mtl;
|
||||||
|
bool ok = (*readMatFn)(filenames[s].c_str(), materials,
|
||||||
|
&material_map, &err_mtl);
|
||||||
|
if (err && (!err_mtl.empty())) {
|
||||||
|
(*err) += err_mtl; // This should be warn message.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
if (err) {
|
||||||
|
(*err) +=
|
||||||
|
"WARN: Failed to load material file(s). Use default "
|
||||||
|
"material.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1514,28 +1855,45 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
// load mtl
|
// load mtl
|
||||||
if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) {
|
if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) {
|
||||||
if (readMatFn) {
|
if (readMatFn) {
|
||||||
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
|
||||||
token += 7;
|
token += 7;
|
||||||
#ifdef _MSC_VER
|
|
||||||
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
|
|
||||||
#else
|
|
||||||
sscanf(token, "%s", namebuf);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string err_mtl;
|
std::vector<std::string> filenames;
|
||||||
materials.clear();
|
SplitString(std::string(token), ' ', filenames);
|
||||||
bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl);
|
|
||||||
if (err) {
|
|
||||||
(*err) += err_mtl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
if (filenames.empty()) {
|
||||||
return false;
|
if (err) {
|
||||||
}
|
(*err) +=
|
||||||
|
"WARN: Looks like empty filename for mtllib. Use default "
|
||||||
|
"material. \n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bool found = false;
|
||||||
|
for (size_t s = 0; s < filenames.size(); s++) {
|
||||||
|
std::string err_mtl;
|
||||||
|
bool ok = (*readMatFn)(filenames[s].c_str(), &materials,
|
||||||
|
&material_map, &err_mtl);
|
||||||
|
if (err && (!err_mtl.empty())) {
|
||||||
|
(*err) += err_mtl; // This should be warn message.
|
||||||
|
}
|
||||||
|
|
||||||
if (callback.mtllib_cb) {
|
if (ok) {
|
||||||
callback.mtllib_cb(user_data, &materials.at(0),
|
found = true;
|
||||||
static_cast<int>(materials.size()));
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
if (err) {
|
||||||
|
(*err) +=
|
||||||
|
"WARN: Failed to load material file(s). Use default "
|
||||||
|
"material.\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (callback.mtllib_cb) {
|
||||||
|
callback.mtllib_cb(user_data, &materials.at(0),
|
||||||
|
static_cast<int>(materials.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
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 tinyobjloader)
|
||||||
|
|
||||||
|
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} -ltinyobjloader
|
||||||
|
Cflags: -I${includedir}
|
||||||
Reference in New Issue
Block a user