|
|
|
|
@@ -290,8 +290,7 @@ class MaterialFileReader : public MaterialReader {
|
|
|
|
|
virtual bool operator()(const std::string &matId,
|
|
|
|
|
std::vector<material_t> *materials,
|
|
|
|
|
// std::map<std::string, int> *matMap,
|
|
|
|
|
std::map<unsigned int, int> *matMap,
|
|
|
|
|
std::string *err);
|
|
|
|
|
std::map<unsigned int, int> *matMap, std::string *err);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::string m_mtlBaseDir;
|
|
|
|
|
@@ -305,8 +304,7 @@ class MaterialStreamReader : public MaterialReader {
|
|
|
|
|
virtual bool operator()(const std::string &matId,
|
|
|
|
|
std::vector<material_t> *materials,
|
|
|
|
|
// std::map<std::string, int> *matMap,
|
|
|
|
|
std::map<unsigned int, int> *matMap,
|
|
|
|
|
std::string *err);
|
|
|
|
|
std::map<unsigned int, int> *matMap, std::string *err);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::istream &m_inStream;
|
|
|
|
|
@@ -350,9 +348,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|
|
|
|
/// Loads materials into std::map
|
|
|
|
|
void LoadMtl(
|
|
|
|
|
// std::map<std::string, int> *material_map,
|
|
|
|
|
std::map<unsigned int, int> *material_map,
|
|
|
|
|
std::vector<material_t> *materials, std::istream *inStream,
|
|
|
|
|
std::string *warning);
|
|
|
|
|
std::map<unsigned int, int> *material_map, std::vector<material_t> *materials,
|
|
|
|
|
std::istream *inStream, std::string *warning);
|
|
|
|
|
|
|
|
|
|
} // namespace tinyobj
|
|
|
|
|
|
|
|
|
|
@@ -370,9 +367,10 @@ void LoadMtl(
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
|
|
//#define TINYOBJLOADER_IMPLEMENTATION_BUFREAD
|
|
|
|
|
// #define TINYOBJLOADER_IMPLEMENTATION_BUFREAD
|
|
|
|
|
|
|
|
|
|
#ifdef TINYOBJLOADER_IMPLEMENTATION_BUFREAD
|
|
|
|
|
// TODO(syoyo): Support non-win32 system
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
@@ -444,14 +442,11 @@ class ImportInBuf : public std::streambuf {
|
|
|
|
|
|
|
|
|
|
char *buffer_;
|
|
|
|
|
int fd_;
|
|
|
|
|
uint64_t fsize_, pos_;
|
|
|
|
|
unsigned long long fsize_, pos_;
|
|
|
|
|
size_t buf_sz;
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//***************************************************
|
|
|
|
|
//*************** tigro keywords hash functions begin
|
|
|
|
|
|
|
|
|
|
// tigra: x31 hash function
|
|
|
|
|
|
|
|
|
|
typedef unsigned int khint_t;
|
|
|
|
|
@@ -466,8 +461,7 @@ inline unsigned int X31_hash_stringSZ(const char *s, int sz) {
|
|
|
|
|
int i;
|
|
|
|
|
khint_t h = static_cast<khint_t>(*s);
|
|
|
|
|
|
|
|
|
|
for (++s, i = sz - 1; i && *s; ++s, i--)
|
|
|
|
|
h = (h << 5) - h + static_cast<khint_t>(*s);
|
|
|
|
|
for (++s, i = sz - 1; i && *s; ++s, i--) h = (h << 5) - h + static_cast<khint_t>(*s);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -585,12 +579,10 @@ enum tokens_enum {
|
|
|
|
|
TOK_norm
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// TODO(syoyo): Do not define in global scope.
|
|
|
|
|
|
|
|
|
|
#ifdef __clang__
|
|
|
|
|
#pragma clang diagnostic push
|
|
|
|
|
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
|
|
|
|
#pragma clang diagnostic ignored "-Wexit-time-destructors"
|
|
|
|
|
#pragma clang diagnostic ignored "-Wglobal-constructors"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static std::map<unsigned int, int> hashed_toks;
|
|
|
|
|
@@ -599,7 +591,7 @@ static std::map<unsigned int, int> hashed_toks;
|
|
|
|
|
#pragma clang diagnostic pop
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// functions!
|
|
|
|
|
|
|
|
|
|
static void initHashedTokensMap() {
|
|
|
|
|
// init hashed tokens map
|
|
|
|
|
|
|
|
|
|
@@ -615,22 +607,19 @@ static void initHashedTokensMap() {
|
|
|
|
|
// init hashed tokens map END
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// search token in keywords hash map
|
|
|
|
|
static int token2tok(const char *token) {
|
|
|
|
|
unsigned int token_sz, a_hash;
|
|
|
|
|
|
|
|
|
|
int a_tok;
|
|
|
|
|
|
|
|
|
|
token_sz = static_cast<unsigned int>(strpbrk(token, " \t\r") -
|
|
|
|
|
token); // token length
|
|
|
|
|
token_sz = static_cast<unsigned int>(strpbrk(token, " \t\r") - token); // token length
|
|
|
|
|
|
|
|
|
|
if (token_sz < 1) // delimiter not found, token_sz = strlen(token)
|
|
|
|
|
{
|
|
|
|
|
// token_sz=strlen(token);
|
|
|
|
|
a_hash = X31_hash_string(token);
|
|
|
|
|
} else {
|
|
|
|
|
} else
|
|
|
|
|
a_hash = X31_hash_stringSZ(token, static_cast<int>(token_sz));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a_tok = -1;
|
|
|
|
|
if (hashed_toks.find(a_hash) != hashed_toks.end())
|
|
|
|
|
@@ -639,9 +628,6 @@ static int token2tok(const char *token) {
|
|
|
|
|
return a_tok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************** tigro keywords hash functions END
|
|
|
|
|
//*************************************************
|
|
|
|
|
|
|
|
|
|
MaterialReader::~MaterialReader() {}
|
|
|
|
|
|
|
|
|
|
struct vertex_index {
|
|
|
|
|
@@ -1242,7 +1228,6 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
|
|
|
|
parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0,
|
|
|
|
|
1.0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// Assume texture filename
|
|
|
|
|
#if 0
|
|
|
|
|
@@ -1385,9 +1370,8 @@ static void SplitString(const std::string &s, char delim,
|
|
|
|
|
|
|
|
|
|
void LoadMtl(
|
|
|
|
|
// std::map<std::string, int> *material_map,
|
|
|
|
|
std::map<unsigned int, int> *material_map,
|
|
|
|
|
std::vector<material_t> *materials, std::istream *inStream,
|
|
|
|
|
std::string *warning) {
|
|
|
|
|
std::map<unsigned int, int> *material_map, std::vector<material_t> *materials,
|
|
|
|
|
std::istream *inStream, std::string *warning) {
|
|
|
|
|
// Create a default material anyway.
|
|
|
|
|
material_t material;
|
|
|
|
|
InitMaterial(&material);
|
|
|
|
|
@@ -1440,59 +1424,71 @@ void LoadMtl(
|
|
|
|
|
if (IS_SPACE((token[2]))) {
|
|
|
|
|
// group K
|
|
|
|
|
if (token[0] == 'K') {
|
|
|
|
|
// ambient
|
|
|
|
|
if (token[1] == 'a') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.ambient[0] = r;
|
|
|
|
|
material.ambient[1] = g;
|
|
|
|
|
material.ambient[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
switch (token[1]) {
|
|
|
|
|
case 'a':
|
|
|
|
|
// ambient
|
|
|
|
|
// if (token[1] == 'a')
|
|
|
|
|
{
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.ambient[0] = r;
|
|
|
|
|
material.ambient[1] = g;
|
|
|
|
|
material.ambient[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// diffuse
|
|
|
|
|
if (token[1] == 'd') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.diffuse[0] = r;
|
|
|
|
|
material.diffuse[1] = g;
|
|
|
|
|
material.diffuse[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// diffuse
|
|
|
|
|
case 'd':
|
|
|
|
|
// if (token[1] == 'd')
|
|
|
|
|
{
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.diffuse[0] = r;
|
|
|
|
|
material.diffuse[1] = g;
|
|
|
|
|
material.diffuse[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// specular
|
|
|
|
|
if (token[1] == 's') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.specular[0] = r;
|
|
|
|
|
material.specular[1] = g;
|
|
|
|
|
material.specular[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// specular
|
|
|
|
|
case 's':
|
|
|
|
|
// if (token[1] == 's')
|
|
|
|
|
{
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.specular[0] = r;
|
|
|
|
|
material.specular[1] = g;
|
|
|
|
|
material.specular[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// transmittance
|
|
|
|
|
if (token[1] == 't') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.transmittance[0] = r;
|
|
|
|
|
material.transmittance[1] = g;
|
|
|
|
|
material.transmittance[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// transmittance
|
|
|
|
|
case 't':
|
|
|
|
|
// if (token[1] == 't')
|
|
|
|
|
{
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.transmittance[0] = r;
|
|
|
|
|
material.transmittance[1] = g;
|
|
|
|
|
material.transmittance[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// emission
|
|
|
|
|
if (token[1] == 'e') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.emission[0] = r;
|
|
|
|
|
material.emission[1] = g;
|
|
|
|
|
material.emission[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
// emission
|
|
|
|
|
case 'e':
|
|
|
|
|
// if (token[1] == 'e')
|
|
|
|
|
{
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseReal3(&r, &g, &b, &token);
|
|
|
|
|
material.emission[0] = r;
|
|
|
|
|
material.emission[1] = g;
|
|
|
|
|
material.emission[2] = b;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1521,51 +1517,6 @@ void LoadMtl(
|
|
|
|
|
material.shininess = parseReal(&token);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (token[0] == 'T' && token[1] == 'r') {
|
|
|
|
|
token += 2;
|
|
|
|
|
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 - parseReal(&token);
|
|
|
|
|
}
|
|
|
|
|
has_tr = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tigra: refactoring for new speedup release
|
|
|
|
|
if (token[0] == 'P') {
|
|
|
|
|
// PBR: roughness
|
|
|
|
|
if (token[1] == 'r') {
|
|
|
|
|
token += 2;
|
|
|
|
|
material.roughness = parseReal(&token);
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
// PBR: metallic
|
|
|
|
|
if (token[1] == 'm') {
|
|
|
|
|
token += 2;
|
|
|
|
|
material.metallic = parseReal(&token);
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
// PBR: sheen
|
|
|
|
|
if (token[1] == 's') {
|
|
|
|
|
token += 2;
|
|
|
|
|
material.sheen = parseReal(&token);
|
|
|
|
|
continue;
|
|
|
|
|
} else
|
|
|
|
|
// PBR: clearcoat thickness
|
|
|
|
|
if (token[1] == 'c') {
|
|
|
|
|
token += 2;
|
|
|
|
|
material.clearcoat_thickness = parseReal(&token);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// dissolve
|
|
|
|
|
@@ -1581,6 +1532,43 @@ void LoadMtl(
|
|
|
|
|
has_d = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) {
|
|
|
|
|
token += 2;
|
|
|
|
|
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 - parseReal(&token);
|
|
|
|
|
}
|
|
|
|
|
has_tr = true;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tigra: refactoring for new speedup release
|
|
|
|
|
if (token[0] == 'P' && IS_SPACE(token[2])) {
|
|
|
|
|
token += 2;
|
|
|
|
|
|
|
|
|
|
// PBR: roughness
|
|
|
|
|
if (token[1] == 'r')
|
|
|
|
|
material.roughness = parseReal(&token);
|
|
|
|
|
else
|
|
|
|
|
// PBR: metallic
|
|
|
|
|
if (token[1] == 'm')
|
|
|
|
|
material.metallic = parseReal(&token);
|
|
|
|
|
else
|
|
|
|
|
// PBR: sheen
|
|
|
|
|
if (token[1] == 's')
|
|
|
|
|
material.sheen = parseReal(&token);
|
|
|
|
|
else
|
|
|
|
|
// PBR: clearcoat thickness
|
|
|
|
|
if (token[1] == 'c')
|
|
|
|
|
material.clearcoat_thickness = parseReal(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a_tok = token2tok(token);
|
|
|
|
|
|
|
|
|
|
@@ -2003,169 +1991,164 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
|
|
|
|
|
|
|
|
|
if (token[0] == '#') continue; // comment line
|
|
|
|
|
|
|
|
|
|
if (IS_SPACE((token[1]))) {
|
|
|
|
|
// vertex
|
|
|
|
|
if (token[0] == 'v') {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t x, y, z;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token);
|
|
|
|
|
v.push_back(x);
|
|
|
|
|
v.push_back(y);
|
|
|
|
|
v.push_back(z);
|
|
|
|
|
// vertex
|
|
|
|
|
if (token[0] == 'v' && IS_SPACE((token[1]))) {
|
|
|
|
|
token += 2;
|
|
|
|
|
real_t x, y, z;
|
|
|
|
|
real_t r, g, b;
|
|
|
|
|
parseVertexWithColor(&x, &y, &z, &r, &g, &b, &token);
|
|
|
|
|
v.push_back(x);
|
|
|
|
|
v.push_back(y);
|
|
|
|
|
v.push_back(z);
|
|
|
|
|
|
|
|
|
|
vc.push_back(r);
|
|
|
|
|
vc.push_back(g);
|
|
|
|
|
vc.push_back(b);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
vc.push_back(r);
|
|
|
|
|
vc.push_back(g);
|
|
|
|
|
vc.push_back(b);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// face
|
|
|
|
|
if (token[0] == 'f') {
|
|
|
|
|
token += 2;
|
|
|
|
|
token += strspn(token, " \t");
|
|
|
|
|
// normal
|
|
|
|
|
if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) {
|
|
|
|
|
token += 3;
|
|
|
|
|
real_t x, y, z;
|
|
|
|
|
parseReal3(&x, &y, &z, &token);
|
|
|
|
|
vn.push_back(x);
|
|
|
|
|
vn.push_back(y);
|
|
|
|
|
vn.push_back(z);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::vector<vertex_index> face;
|
|
|
|
|
face.reserve(3);
|
|
|
|
|
// texcoord
|
|
|
|
|
if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) {
|
|
|
|
|
token += 3;
|
|
|
|
|
real_t x, y;
|
|
|
|
|
parseReal2(&x, &y, &token);
|
|
|
|
|
vt.push_back(x);
|
|
|
|
|
vt.push_back(y);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (!IS_NEW_LINE(token[0])) {
|
|
|
|
|
vertex_index vi;
|
|
|
|
|
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
|
|
|
|
|
static_cast<int>(vn.size() / 3),
|
|
|
|
|
static_cast<int>(vt.size() / 2), &vi)) {
|
|
|
|
|
if (err) {
|
|
|
|
|
(*err) =
|
|
|
|
|
"Failed parse `f' line(e.g. zero value for face index).\n";
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
// face
|
|
|
|
|
if (token[0] == 'f' && IS_SPACE((token[1]))) {
|
|
|
|
|
token += 2;
|
|
|
|
|
token += strspn(token, " \t");
|
|
|
|
|
|
|
|
|
|
std::vector<vertex_index> face;
|
|
|
|
|
face.reserve(3);
|
|
|
|
|
|
|
|
|
|
while (!IS_NEW_LINE(token[0])) {
|
|
|
|
|
vertex_index vi;
|
|
|
|
|
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
|
|
|
|
|
static_cast<int>(vn.size() / 3),
|
|
|
|
|
static_cast<int>(vt.size() / 2), &vi)) {
|
|
|
|
|
if (err) {
|
|
|
|
|
(*err) = "Failed parse `f' line(e.g. zero value for face index).\n";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
face.push_back(vi);
|
|
|
|
|
size_t n = strspn(token, " \t\r");
|
|
|
|
|
token += n;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// replace with emplace_back + std::move on C++11
|
|
|
|
|
faceGroup.push_back(std::vector<vertex_index>());
|
|
|
|
|
faceGroup[faceGroup.size() - 1].swap(face);
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
face.push_back(vi);
|
|
|
|
|
size_t n = strspn(token, " \t\r");
|
|
|
|
|
token += n;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// group name
|
|
|
|
|
if (token[0] == 'g') {
|
|
|
|
|
// flush previous face group.
|
|
|
|
|
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material,
|
|
|
|
|
name, triangulate);
|
|
|
|
|
(void)ret; // return value not used.
|
|
|
|
|
// replace with emplace_back + std::move on C++11
|
|
|
|
|
faceGroup.push_back(std::vector<vertex_index>());
|
|
|
|
|
faceGroup[faceGroup.size() - 1].swap(face);
|
|
|
|
|
|
|
|
|
|
if (shape.mesh.indices.size() > 0) {
|
|
|
|
|
shapes->push_back(shape);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shape = shape_t();
|
|
|
|
|
// group name
|
|
|
|
|
if (token[0] == 'g' && IS_SPACE((token[1]))) {
|
|
|
|
|
// flush previous face group.
|
|
|
|
|
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
|
|
|
|
triangulate);
|
|
|
|
|
(void)ret; // return value not used.
|
|
|
|
|
|
|
|
|
|
// material = -1;
|
|
|
|
|
faceGroup.clear();
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> names;
|
|
|
|
|
names.reserve(2);
|
|
|
|
|
|
|
|
|
|
while (!IS_NEW_LINE(token[0])) {
|
|
|
|
|
std::string str = parseString(&token);
|
|
|
|
|
names.push_back(str);
|
|
|
|
|
token += strspn(token, " \t\r"); // skip tag
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(names.size() > 0);
|
|
|
|
|
|
|
|
|
|
// names[0] must be 'g', so skip the 0th element.
|
|
|
|
|
if (names.size() > 1) {
|
|
|
|
|
name = names[1];
|
|
|
|
|
} else {
|
|
|
|
|
name = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
if (shape.mesh.indices.size() > 0) {
|
|
|
|
|
shapes->push_back(shape);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// object name
|
|
|
|
|
if (token[0] == 'o') {
|
|
|
|
|
// flush previous face group.
|
|
|
|
|
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material,
|
|
|
|
|
name, triangulate);
|
|
|
|
|
if (ret) {
|
|
|
|
|
shapes->push_back(shape);
|
|
|
|
|
}
|
|
|
|
|
shape = shape_t();
|
|
|
|
|
|
|
|
|
|
// material = -1;
|
|
|
|
|
faceGroup.clear();
|
|
|
|
|
shape = shape_t();
|
|
|
|
|
// material = -1;
|
|
|
|
|
faceGroup.clear();
|
|
|
|
|
|
|
|
|
|
// @todo { multiple object name? }
|
|
|
|
|
token += 2;
|
|
|
|
|
std::vector<std::string> names;
|
|
|
|
|
names.reserve(2);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
while (!IS_NEW_LINE(token[0])) {
|
|
|
|
|
std::string str = parseString(&token);
|
|
|
|
|
names.push_back(str);
|
|
|
|
|
token += strspn(token, " \t\r"); // skip tag
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(names.size() > 0);
|
|
|
|
|
|
|
|
|
|
// names[0] must be 'g', so skip the 0th element.
|
|
|
|
|
if (names.size() > 1) {
|
|
|
|
|
name = names[1];
|
|
|
|
|
} else {
|
|
|
|
|
name = "";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// object name
|
|
|
|
|
if (token[0] == 'o' && IS_SPACE((token[1]))) {
|
|
|
|
|
// flush previous face group.
|
|
|
|
|
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
|
|
|
|
triangulate);
|
|
|
|
|
if (ret) {
|
|
|
|
|
shapes->push_back(shape);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// material = -1;
|
|
|
|
|
faceGroup.clear();
|
|
|
|
|
shape = shape_t();
|
|
|
|
|
|
|
|
|
|
// @todo { multiple object name? }
|
|
|
|
|
token += 2;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
std::stringstream ss;
|
|
|
|
|
ss << token;
|
|
|
|
|
name = ss.str();
|
|
|
|
|
*/
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
name = std::string(token);
|
|
|
|
|
name = std::string(token);
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (token[0] == 't') {
|
|
|
|
|
tag_t tag;
|
|
|
|
|
|
|
|
|
|
token += 2;
|
|
|
|
|
|
|
|
|
|
tag.name = parseString(&token);
|
|
|
|
|
|
|
|
|
|
tag_sizes ts = parseTagTriple(&token);
|
|
|
|
|
|
|
|
|
|
tag.intValues.resize(static_cast<size_t>(ts.num_ints));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_ints); ++i) {
|
|
|
|
|
tag.intValues[i] = parseInt(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tag.floatValues.resize(static_cast<size_t>(ts.num_reals));
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_reals); ++i) {
|
|
|
|
|
tag.floatValues[i] = parseReal(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tag.stringValues.resize(static_cast<size_t>(ts.num_strings));
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i) {
|
|
|
|
|
tag.stringValues[i] = parseString(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tags.push_back(tag);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (token[0] == 'v' && IS_SPACE((token[2]))) {
|
|
|
|
|
// normal
|
|
|
|
|
if (token[1] == 'n') {
|
|
|
|
|
token += 3;
|
|
|
|
|
real_t x, y, z;
|
|
|
|
|
parseReal3(&x, &y, &z, &token);
|
|
|
|
|
vn.push_back(x);
|
|
|
|
|
vn.push_back(y);
|
|
|
|
|
vn.push_back(z);
|
|
|
|
|
continue;
|
|
|
|
|
if (token[0] == 't' && IS_SPACE(token[1])) {
|
|
|
|
|
tag_t tag;
|
|
|
|
|
|
|
|
|
|
token += 2;
|
|
|
|
|
|
|
|
|
|
tag.name = parseString(&token);
|
|
|
|
|
|
|
|
|
|
tag_sizes ts = parseTagTriple(&token);
|
|
|
|
|
|
|
|
|
|
tag.intValues.resize(static_cast<size_t>(ts.num_ints));
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_ints); ++i) {
|
|
|
|
|
tag.intValues[i] = parseInt(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// texcoord
|
|
|
|
|
if (token[1] == 't') {
|
|
|
|
|
token += 3;
|
|
|
|
|
real_t x, y;
|
|
|
|
|
parseReal2(&x, &y, &token);
|
|
|
|
|
vt.push_back(x);
|
|
|
|
|
vt.push_back(y);
|
|
|
|
|
continue;
|
|
|
|
|
tag.floatValues.resize(static_cast<size_t>(ts.num_reals));
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_reals); ++i) {
|
|
|
|
|
tag.floatValues[i] = parseReal(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tag.stringValues.resize(static_cast<size_t>(ts.num_strings));
|
|
|
|
|
for (size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i) {
|
|
|
|
|
tag.stringValues[i] = parseString(&token);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tags.push_back(tag);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tigra: refactoring for new speedup release
|
|
|
|
|
|