Merge pull request #101 from kavika13/master
Make it easier to use an existing stream reader
This commit is contained in:
@@ -184,6 +184,48 @@ TestLoadObj(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
TestLoadObjFromPreopenedFile(
|
||||||
|
const char* filename,
|
||||||
|
const char* basepath = NULL,
|
||||||
|
bool readMaterials = true,
|
||||||
|
bool triangulate = true)
|
||||||
|
{
|
||||||
|
std::string fullFilename = std::string(basepath) + filename;
|
||||||
|
std::cout << "Loading " << fullFilename << std::endl;
|
||||||
|
|
||||||
|
std::ifstream fileStream(fullFilename);
|
||||||
|
|
||||||
|
if (!fileStream) {
|
||||||
|
std::cerr << "Could not find specified file: " << fullFilename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyobj::MaterialStreamReader materialStreamReader(fileStream);
|
||||||
|
tinyobj::MaterialStreamReader* materialReader = readMaterials
|
||||||
|
? &materialStreamReader
|
||||||
|
: NULL;
|
||||||
|
|
||||||
|
tinyobj::attrib_t attrib;
|
||||||
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
std::vector<tinyobj::material_t> materials;
|
||||||
|
|
||||||
|
std::string err;
|
||||||
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, &fileStream, materialReader);
|
||||||
|
|
||||||
|
if (!err.empty()) {
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
printf("Failed to load/parse .obj.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Loaded material count: " << materials.size() << "\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
TestStreamLoadObj()
|
TestStreamLoadObj()
|
||||||
@@ -351,6 +393,16 @@ TEST_CASE("stream_load", "[Stream]") {
|
|||||||
REQUIRE(true == TestStreamLoadObj());
|
REQUIRE(true == TestStreamLoadObj());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("stream_load_from_file_skipping_materials", "[Stream]") {
|
||||||
|
REQUIRE(true == TestLoadObjFromPreopenedFile(
|
||||||
|
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/false, /*triangulate*/false));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("stream_load_from_file_with_materials", "[Stream]") {
|
||||||
|
REQUIRE(true == TestLoadObjFromPreopenedFile(
|
||||||
|
"../models/pbr-mat-ext.obj", gMtlBasePath, /*readMaterials*/true, /*triangulate*/false));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("trailing_whitespace_in_mtl", "[Issue92]") {
|
TEST_CASE("trailing_whitespace_in_mtl", "[Issue92]") {
|
||||||
tinyobj::attrib_t attrib;
|
tinyobj::attrib_t attrib;
|
||||||
std::vector<tinyobj::shape_t> shapes;
|
std::vector<tinyobj::shape_t> shapes;
|
||||||
|
|||||||
@@ -179,6 +179,19 @@ class MaterialFileReader : public MaterialReader {
|
|||||||
std::string m_mtlBasePath;
|
std::string m_mtlBasePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MaterialStreamReader : public MaterialReader {
|
||||||
|
public:
|
||||||
|
explicit MaterialStreamReader(std::istream &inStream)
|
||||||
|
: m_inStream(inStream) {}
|
||||||
|
virtual ~MaterialStreamReader() {}
|
||||||
|
virtual bool operator()(const std::string &matId,
|
||||||
|
std::vector<material_t> *materials,
|
||||||
|
std::map<std::string, int> *matMap, std::string *err);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::istream &m_inStream;
|
||||||
|
};
|
||||||
|
|
||||||
/// Loads .obj from a file.
|
/// Loads .obj from a file.
|
||||||
/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data
|
/// 'attrib', 'shapes' and 'materials' will be filled with parsed shape data
|
||||||
/// 'shapes' will be filled with parsed shape data
|
/// 'shapes' will be filled with parsed shape data
|
||||||
@@ -209,7 +222,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
|||||||
/// Returns warning and error message into `err`
|
/// Returns warning and error message into `err`
|
||||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||||
std::vector<material_t> *materials, std::string *err,
|
std::vector<material_t> *materials, std::string *err,
|
||||||
std::istream *inStream, MaterialReader *readMatFn,
|
std::istream *inStream, MaterialReader *readMatFn = NULL,
|
||||||
bool triangulate = true);
|
bool triangulate = true);
|
||||||
|
|
||||||
/// Loads materials into std::map
|
/// Loads materials into std::map
|
||||||
@@ -1010,6 +1023,22 @@ bool MaterialFileReader::operator()(const std::string &matId,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MaterialStreamReader::operator()(const std::string &matId,
|
||||||
|
std::vector<material_t> *materials,
|
||||||
|
std::map<std::string, int> *matMap,
|
||||||
|
std::string *err) {
|
||||||
|
LoadMtl(matMap, materials, &m_inStream);
|
||||||
|
if (!m_inStream) {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "WARN: Material stream in error state."
|
||||||
|
<< " Created a default material.";
|
||||||
|
if (err) {
|
||||||
|
(*err) += ss.str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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_basepath,
|
||||||
@@ -1042,7 +1071,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|||||||
|
|
||||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||||
std::vector<material_t> *materials, std::string *err,
|
std::vector<material_t> *materials, std::string *err,
|
||||||
std::istream *inStream, MaterialReader *readMatFn,
|
std::istream *inStream,
|
||||||
|
MaterialReader *readMatFn /*= NULL*/,
|
||||||
bool triangulate) {
|
bool triangulate) {
|
||||||
std::stringstream errss;
|
std::stringstream errss;
|
||||||
|
|
||||||
@@ -1173,23 +1203,25 @@ 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]))) {
|
||||||
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
if (readMatFn) {
|
||||||
token += 7;
|
char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE];
|
||||||
|
token += 7;
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
|
sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf));
|
||||||
#else
|
#else
|
||||||
sscanf(token, "%s", namebuf);
|
sscanf(token, "%s", namebuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string err_mtl;
|
std::string err_mtl;
|
||||||
bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl);
|
bool ok = (*readMatFn)(namebuf, materials, &material_map, &err_mtl);
|
||||||
if (err) {
|
if (err) {
|
||||||
(*err) += err_mtl;
|
(*err) += err_mtl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
faceGroup.clear(); // for safety
|
faceGroup.clear(); // for safety
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user