29 Commits

Author SHA1 Message Date
Syoyo Fujita
7c3206f919 Ignore Tr parameter when d exists in MTL(#43) 2016-12-31 21:05:37 +09:00
Syoyo Fujita
4886eebbf4 Merge pull request #120 from dPavelDev/master
Fixed error in getting material name in LoadObjWithCallback
2016-12-30 20:17:28 +09:00
dPavelDev
91c727e204 Fixed error in getting material name in LoadObjWithCallback 2016-12-29 15:45:23 +03:00
Syoyo Fujita
26bdacedf6 Merge pull request #119 from jamiesnape/fix-cmake-dir
Add MIT license file, use GNUInstallDirs module, fix cmake directory location
2016-12-29 01:55:00 +09:00
Jamie Snape
7212ee47eb Use GNUInstallDirs module and fix cmake directory location 2016-12-28 11:11:59 -05:00
Jamie Snape
0fe1bb96c2 Add MIT license file 2016-12-28 11:10:07 -05:00
Syoyo Fujita
4bd75baaae Merge pull request #118 from jamiesnape/cleanup
Fix some formatting inconsistencies, fix typo, update minimum CMake
2016-12-21 01:00:16 +09:00
Jamie Snape
bbcfe59c0f Update minimum required version of CMake 2016-12-20 09:44:47 -05:00
Jamie Snape
38c07d34c4 Fix typo in destination of CMake export file 2016-12-20 09:44:26 -05:00
Jamie Snape
2019ace3b7 Remove excess padding around some parentheses in CMake files 2016-12-20 09:32:41 -05:00
Jamie Snape
ad96ff0769 Consistently use spaces instead of tabs in CMake files 2016-12-20 09:32:41 -05:00
Syoyo Fujita
d7f83f29f0 Fix for Windows platform. 2016-12-20 15:42:15 +09:00
Syoyo Fujita
98fad65028 Merge pull request #117 from jamiesnape/cmake-pkg-config
Write and install CMake package config and pkg-config files
2016-12-20 13:56:36 +09:00
Jamie Snape
e88016c63f Write and install pkg-config file 2016-12-19 11:45:00 -05:00
Jamie Snape
edabf19461 Write and install CMake package config files
This allows find_package(tinyobjloader) to be called.
2016-12-19 11:44:39 -05:00
Syoyo Fujita
8bed734a18 Merge branch 'master' of github.com:syoyo/tinyobjloader 2016-12-09 01:51:33 +09:00
Syoyo Fujita
60ffb3ca9a Add missing files. Fixes #115. 2016-12-09 01:51:03 +09:00
Syoyo Fujita
6507e70236 Merge pull request #113 from ReinierMaas/patch-1
Update README.md
2016-12-07 00:55:28 +09:00
Syoyo Fujita
2daec8be53 Search .mtl and texture from .obj's base dir.
Fix bad memory access.
2016-12-07 00:54:12 +09:00
Syoyo Fujita
c2ff3f12fc Support multiple filenames for mtllib line. Fixes #112. 2016-12-06 23:44:55 +09:00
Reinier Maas
a6a134a60e Update README.md
Basedline -> baseline
2016-12-06 15:38:26 +01:00
Syoyo Fujita
e0b39341fc Merge pull request #111 from longjon/python2
Support Python 2.7
2016-12-06 14:37:05 +09:00
Syoyo Fujita
947582b592 Merge pull request #110 from longjon/python-attribs
(Re-)expose attributes to Python
2016-12-06 14:36:14 +09:00
Jonathan L Long
c207ff3561 Support Python 2.7. 2016-12-05 15:24:22 -08:00
Jonathan L Long
41dd7c806e (Re-)expose attribs to Python. 2016-12-05 15:12:28 -08:00
Syoyo Fujita
aa4dabe64f Describe default behavior of mtl_basedir. 2016-11-23 17:17:35 +09:00
Syoyo Fujita
9868630d0e Fix windows build of loader_example. 2016-11-04 12:36:15 +09:00
Syoyo Fujita
f2397573f3 Merge pull request #107 from Warezovvv/master
Little intuitive improvements
2016-11-03 17:39:16 +09:00
Nikita Krupitskas
7d5699118e Little intuitive improvements 2016-11-03 11:23:21 +03:00
21 changed files with 2051 additions and 115 deletions

View File

@@ -2,7 +2,9 @@
#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)
@@ -22,40 +24,112 @@ set(tinyobjloader-examples-objsticher
${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
View File

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

View File

@@ -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

View File

@@ -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,10 +550,12 @@ 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);
if ((o.material_id < materials.size())) {
std::string diffuse_texname = materials[o.material_id].diffuse_texname; std::string diffuse_texname = materials[o.material_id].diffuse_texname;
if (diffuse_texname.length() > 0) { if (textures.find(diffuse_texname) != textures.end()) {
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]); 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));
glColorPointer(3, GL_FLOAT, stride, (const void*)(sizeof(float) * 6)); glColorPointer(3, GL_FLOAT, stride, (const void*)(sizeof(float) * 6));

View File

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

View File

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

View File

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

View File

@@ -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" }

View File

@@ -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;

View File

@@ -90,7 +90,7 @@ 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);
@@ -100,6 +100,14 @@ const char *mmap_file(size_t *len, const char* filename)
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();

View File

@@ -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
@@ -364,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;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
} }

View File

@@ -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;
} }
@@ -530,6 +531,39 @@ TEST_CASE("texture_opts", "[Issue85]") {
REQUIRE(tinyobj::TEXTURE_TYPE_CUBE_BACK == materials[2].displacement_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(

View File

@@ -23,6 +23,8 @@ THE SOFTWARE.
*/ */
// //
// 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.3 : Support parsing texture options(#85)
// version 1.0.2 : Improve parsing speed by about a factor of 2 for large // version 1.0.2 : Improve parsing speed by about a factor of 2 for large
// files(#105) // files(#105)
@@ -266,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 {
@@ -295,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.
@@ -325,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
@@ -934,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);
@@ -985,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;
@@ -1078,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) {
// `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); material.dissolve = 1.0f - parseFloat(&token);
}
has_tr = true;
continue; continue;
} }
@@ -1271,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,
@@ -1279,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;
} }
@@ -1303,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();
@@ -1335,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);
@@ -1481,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 (filenames.empty()) {
if (err) { if (err) {
(*err) += err_mtl; (*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) { if (ok) {
faceGroup.clear(); // for safety found = true;
return false; break;
}
}
if (!found) {
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
"material.\n";
}
}
} }
} }
@@ -1773,30 +1855,47 @@ 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 (filenames.empty()) {
if (err) { if (err) {
(*err) += err_mtl; (*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) { if (ok) {
return false; found = true;
break;
}
} }
if (!found) {
if (err) {
(*err) +=
"WARN: Failed to load material file(s). Use default "
"material.\n";
}
} else {
if (callback.mtllib_cb) { if (callback.mtllib_cb) {
callback.mtllib_cb(user_data, &materials.at(0), callback.mtllib_cb(user_data, &materials.at(0),
static_cast<int>(materials.size())); static_cast<int>(materials.size()));
} }
} }
}
}
continue; continue;
} }

View File

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

15
tinyobjloader.pc.in Normal file
View File

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