Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2daec8be53 | ||
|
|
c2ff3f12fc | ||
|
|
e0b39341fc | ||
|
|
947582b592 | ||
|
|
c207ff3561 | ||
|
|
41dd7c806e | ||
|
|
aa4dabe64f | ||
|
|
9868630d0e | ||
|
|
f2397573f3 | ||
|
|
7d5699118e |
@@ -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));
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
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
|
||||||
@@ -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
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -530,6 +530,21 @@ 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());
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int
|
int
|
||||||
main(
|
main(
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ THE SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
//
|
//
|
||||||
|
// 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 +267,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 +296,13 @@ 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.
|
||||||
@@ -934,6 +936,18 @@ 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) {
|
||||||
// Create a default material anyway.
|
// Create a default material anyway.
|
||||||
@@ -1279,22 +1293,24 @@ 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. Created a default material.";
|
<< " ] not found." << std::endl;
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += ss.str();
|
(*err) += ss.str();
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadMtl(matMap, materials, &matIStream);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1303,21 +1319,22 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LoadMtl(matMap, materials, &m_inStream);
|
||||||
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();
|
||||||
@@ -1335,11 +1352,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 +1498,37 @@ 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));
|
std::vector<std::string> filenames;
|
||||||
#else
|
SplitString(std::string(token), ' ', filenames);
|
||||||
sscanf(token, "%s", namebuf);
|
|
||||||
#endif
|
if (filenames.empty()) {
|
||||||
|
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;
|
std::string err_mtl;
|
||||||
bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl);
|
bool ok = (*readMatFn)(filenames[s].c_str(), materials, &material_map, &err_mtl);
|
||||||
if (err) {
|
if (err && (!err_mtl.empty())) {
|
||||||
(*err) += err_mtl;
|
(*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 +1804,46 @@ 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
|
token += 7;
|
||||||
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
|
|
||||||
#else
|
std::vector<std::string> filenames;
|
||||||
sscanf(token, "%s", namebuf);
|
SplitString(std::string(token), ' ', filenames);
|
||||||
#endif
|
|
||||||
|
if (filenames.empty()) {
|
||||||
|
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;
|
std::string err_mtl;
|
||||||
materials.clear();
|
bool ok = (*readMatFn)(filenames[s].c_str(), &materials, &material_map, &err_mtl);
|
||||||
bool ok = (*readMatFn)(namebuf, &materials, &material_map, &err_mtl);
|
if (err && (!err_mtl.empty())) {
|
||||||
if (err) {
|
(*err) += err_mtl; // This should be warn message.
|
||||||
(*err) += err_mtl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user