Format source code.

This commit is contained in:
Syoyo Fujita
2015-02-15 16:51:38 +09:00
parent a67a60d19f
commit 9979275835
2 changed files with 212 additions and 244 deletions

341
tiny_obj_loader.cc Executable file → Normal file
View File

@@ -1,12 +1,13 @@
// //
// Copyright 2012-2015, Syoyo Fujita. // Copyright 2012-2015, Syoyo Fujita.
// //
// Licensed under 2-clause BSD liecense. // Licensed under 2-clause BSD liecense.
// //
// //
// version 0.9.8: Fix multi-materials(per-face material ID). // version 0.9.8: Fix multi-materials(per-face material ID).
// version 0.9.7: Support multi-materials(per-face material ID) per object/group. // version 0.9.7: Support multi-materials(per-face material ID) per
// object/group.
// version 0.9.6: Support Ni(index of refraction) mtl parameter. // version 0.9.6: Support Ni(index of refraction) mtl parameter.
// Parse transmittance material parameter correctly. // Parse transmittance material parameter correctly.
// version 0.9.5: Parse multiple group name. // version 0.9.5: Parse multiple group name.
@@ -18,7 +19,6 @@
// version 0.9.0: Initial // version 0.9.0: Initial
// //
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
@@ -35,17 +35,19 @@ namespace tinyobj {
struct vertex_index { struct vertex_index {
int v_idx, vt_idx, vn_idx; int v_idx, vt_idx, vn_idx;
vertex_index() {}; vertex_index(){};
vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}; vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx){};
vertex_index(int vidx, int vtidx, int vnidx) : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {}; vertex_index(int vidx, int vtidx, int vnidx)
: v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx){};
}; };
// for std::map // for std::map
static inline bool operator<(const vertex_index& a, const vertex_index& b) static inline bool operator<(const vertex_index &a, const vertex_index &b) {
{ if (a.v_idx != b.v_idx)
if (a.v_idx != b.v_idx) return (a.v_idx < b.v_idx); return (a.v_idx < b.v_idx);
if (a.vn_idx != b.vn_idx) return (a.vn_idx < b.vn_idx); if (a.vn_idx != b.vn_idx)
if (a.vt_idx != b.vt_idx) return (a.vt_idx < b.vt_idx); return (a.vn_idx < b.vn_idx);
if (a.vt_idx != b.vt_idx)
return (a.vt_idx < b.vt_idx);
return false; return false;
} }
@@ -56,17 +58,14 @@ struct obj_shape {
std::vector<float> vt; std::vector<float> vt;
}; };
static inline bool isSpace(const char c) { static inline bool isSpace(const char c) { return (c == ' ') || (c == '\t'); }
return (c == ' ') || (c == '\t');
}
static inline bool isNewLine(const char c) { static inline bool isNewLine(const char c) {
return (c == '\r') || (c == '\n') || (c == '\0'); return (c == '\r') || (c == '\n') || (c == '\0');
} }
// Make index zero-base, and also support relative index. // Make index zero-base, and also support relative index.
static inline int fixIndex(int idx, int n) static inline int fixIndex(int idx, int n) {
{
int i; int i;
if (idx > 0) { if (idx > 0) {
@@ -79,8 +78,7 @@ static inline int fixIndex(int idx, int n)
return i; return i;
} }
static inline std::string parseString(const char*& token) static inline std::string parseString(const char *&token) {
{
std::string s; std::string s;
int b = strspn(token, " \t"); int b = strspn(token, " \t");
int e = strcspn(token, " \t\r"); int e = strcspn(token, " \t\r");
@@ -90,89 +88,73 @@ static inline std::string parseString(const char*& token)
return s; return s;
} }
static inline int parseInt(const char*& token) static inline int parseInt(const char *&token) {
{
token += strspn(token, " \t"); token += strspn(token, " \t");
int i = atoi(token); int i = atoi(token);
token += strcspn(token, " \t\r"); token += strcspn(token, " \t\r");
return i; return i;
} }
static inline float parseFloat(const char*& token) static inline float parseFloat(const char *&token) {
{
token += strspn(token, " \t"); token += strspn(token, " \t");
float f = (float)atof(token); float f = (float)atof(token);
token += strcspn(token, " \t\r"); token += strcspn(token, " \t\r");
return f; return f;
} }
static inline void parseFloat2( static inline void parseFloat2(float &x, float &y, const char *&token) {
float& x, float& y,
const char*& token)
{
x = parseFloat(token); x = parseFloat(token);
y = parseFloat(token); y = parseFloat(token);
} }
static inline void parseFloat3( static inline void parseFloat3(float &x, float &y, float &z,
float& x, float& y, float& z, const char *&token) {
const char*& token)
{
x = parseFloat(token); x = parseFloat(token);
y = parseFloat(token); y = parseFloat(token);
z = parseFloat(token); z = parseFloat(token);
} }
// Parse triples: i, i/j/k, i//k, i/j // Parse triples: i, i/j/k, i//k, i/j
static vertex_index parseTriple( static vertex_index parseTriple(const char *&token, int vsize, int vnsize,
const char* &token, int vtsize) {
int vsize, vertex_index vi(-1);
int vnsize,
int vtsize)
{
vertex_index vi(-1);
vi.v_idx = fixIndex(atoi(token), vsize); vi.v_idx = fixIndex(atoi(token), vsize);
token += strcspn(token, "/ \t\r"); token += strcspn(token, "/ \t\r");
if (token[0] != '/') { if (token[0] != '/') {
return vi; return vi;
} }
token++;
// i//k
if (token[0] == '/') {
token++; token++;
// i//k
if (token[0] == '/') {
token++;
vi.vn_idx = fixIndex(atoi(token), vnsize);
token += strcspn(token, "/ \t\r");
return vi;
}
// i/j/k or i/j
vi.vt_idx = fixIndex(atoi(token), vtsize);
token += strcspn(token, "/ \t\r");
if (token[0] != '/') {
return vi;
}
// i/j/k
token++; // skip '/'
vi.vn_idx = fixIndex(atoi(token), vnsize); vi.vn_idx = fixIndex(atoi(token), vnsize);
token += strcspn(token, "/ \t\r"); token += strcspn(token, "/ \t\r");
return vi; return vi;
}
// i/j/k or i/j
vi.vt_idx = fixIndex(atoi(token), vtsize);
token += strcspn(token, "/ \t\r");
if (token[0] != '/') {
return vi;
}
// i/j/k
token++; // skip '/'
vi.vn_idx = fixIndex(atoi(token), vnsize);
token += strcspn(token, "/ \t\r");
return vi;
} }
static unsigned int static unsigned int
updateVertex( updateVertex(std::map<vertex_index, unsigned int> &vertexCache,
std::map<vertex_index, unsigned int>& vertexCache, std::vector<float> &positions, std::vector<float> &normals,
std::vector<float>& positions, std::vector<float> &texcoords,
std::vector<float>& normals, const std::vector<float> &in_positions,
std::vector<float>& texcoords, const std::vector<float> &in_normals,
const std::vector<float>& in_positions, const std::vector<float> &in_texcoords, const vertex_index &i) {
const std::vector<float>& in_normals,
const std::vector<float>& in_texcoords,
const vertex_index& i)
{
const std::map<vertex_index, unsigned int>::iterator it = vertexCache.find(i); const std::map<vertex_index, unsigned int>::iterator it = vertexCache.find(i);
if (it != vertexCache.end()) { if (it != vertexCache.end()) {
@@ -180,21 +162,21 @@ updateVertex(
return it->second; return it->second;
} }
assert(in_positions.size() > (unsigned int) (3*i.v_idx+2)); assert(in_positions.size() > (unsigned int)(3 * i.v_idx + 2));
positions.push_back(in_positions[3*i.v_idx+0]); positions.push_back(in_positions[3 * i.v_idx + 0]);
positions.push_back(in_positions[3*i.v_idx+1]); positions.push_back(in_positions[3 * i.v_idx + 1]);
positions.push_back(in_positions[3*i.v_idx+2]); positions.push_back(in_positions[3 * i.v_idx + 2]);
if (i.vn_idx >= 0) { if (i.vn_idx >= 0) {
normals.push_back(in_normals[3*i.vn_idx+0]); normals.push_back(in_normals[3 * i.vn_idx + 0]);
normals.push_back(in_normals[3*i.vn_idx+1]); normals.push_back(in_normals[3 * i.vn_idx + 1]);
normals.push_back(in_normals[3*i.vn_idx+2]); normals.push_back(in_normals[3 * i.vn_idx + 2]);
} }
if (i.vt_idx >= 0) { if (i.vt_idx >= 0) {
texcoords.push_back(in_texcoords[2*i.vt_idx+0]); texcoords.push_back(in_texcoords[2 * i.vt_idx + 0]);
texcoords.push_back(in_texcoords[2*i.vt_idx+1]); texcoords.push_back(in_texcoords[2 * i.vt_idx + 1]);
} }
unsigned int idx = positions.size() / 3 - 1; unsigned int idx = positions.size() / 3 - 1;
@@ -203,13 +185,13 @@ updateVertex(
return idx; return idx;
} }
void InitMaterial(material_t& material) { void InitMaterial(material_t &material) {
material.name = ""; material.name = "";
material.ambient_texname = ""; material.ambient_texname = "";
material.diffuse_texname = ""; material.diffuse_texname = "";
material.specular_texname = ""; material.specular_texname = "";
material.normal_texname = ""; material.normal_texname = "";
for (int i = 0; i < 3; i ++) { for (int i = 0; i < 3; i++) {
material.ambient[i] = 0.f; material.ambient[i] = 0.f;
material.diffuse[i] = 0.f; material.diffuse[i] = 0.f;
material.specular[i] = 0.f; material.specular[i] = 0.f;
@@ -223,25 +205,20 @@ void InitMaterial(material_t& material) {
material.unknown_parameter.clear(); material.unknown_parameter.clear();
} }
static bool static bool exportFaceGroupToShape(
exportFaceGroupToShape( shape_t &shape, std::map<vertex_index, unsigned int> vertexCache,
shape_t& shape, const std::vector<float> &in_positions,
std::map<vertex_index, unsigned int> vertexCache, const std::vector<float> &in_normals,
const std::vector<float> &in_positions, const std::vector<float> &in_texcoords,
const std::vector<float> &in_normals, const std::vector<std::vector<vertex_index>> &faceGroup,
const std::vector<float> &in_texcoords, const int material_id, const std::string &name, bool clearCache) {
const std::vector<std::vector<vertex_index> >& faceGroup,
const int material_id,
const std::string &name,
bool clearCache)
{
if (faceGroup.empty()) { if (faceGroup.empty()) {
return false; return false;
} }
// Flatten vertices and indices // Flatten vertices and indices
for (size_t i = 0; i < faceGroup.size(); i++) { for (size_t i = 0; i < faceGroup.size(); i++) {
const std::vector<vertex_index>& face = faceGroup[i]; const std::vector<vertex_index> &face = faceGroup[i];
vertex_index i0 = face[0]; vertex_index i0 = face[0];
vertex_index i1(-1); vertex_index i1(-1);
@@ -254,9 +231,15 @@ exportFaceGroupToShape(
i1 = i2; i1 = i2;
i2 = face[k]; i2 = face[k];
unsigned int v0 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0); unsigned int v0 = updateVertex(
unsigned int v1 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1); vertexCache, shape.mesh.positions, shape.mesh.normals,
unsigned int v2 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2); shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0);
unsigned int v1 = updateVertex(
vertexCache, shape.mesh.positions, shape.mesh.normals,
shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1);
unsigned int v2 = updateVertex(
vertexCache, shape.mesh.positions, shape.mesh.normals,
shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2);
shape.mesh.indices.push_back(v0); shape.mesh.indices.push_back(v0);
shape.mesh.indices.push_back(v1); shape.mesh.indices.push_back(v1);
@@ -264,30 +247,26 @@ exportFaceGroupToShape(
shape.mesh.material_ids.push_back(material_id); shape.mesh.material_ids.push_back(material_id);
} }
} }
shape.name = name; shape.name = name;
if (clearCache) if (clearCache)
vertexCache.clear(); vertexCache.clear();
return true; return true;
} }
std::string LoadMtl ( std::string LoadMtl(std::map<std::string, int> &material_map,
std::map<std::string, int>& material_map, std::vector<material_t> &materials,
std::vector<material_t>& materials, std::istream &inStream) {
std::istream& inStream)
{
material_map.clear(); material_map.clear();
std::stringstream err; std::stringstream err;
material_t material; material_t material;
int maxchars = 8192; // Alloc enough size. int maxchars = 8192; // Alloc enough size.
std::vector<char> buf(maxchars); // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size.
while (inStream.peek() != -1) { while (inStream.peek() != -1) {
inStream.getline(&buf[0], maxchars); inStream.getline(&buf[0], maxchars);
@@ -295,10 +274,12 @@ std::string LoadMtl (
// Trim newline '\r\n' or '\n' // Trim newline '\r\n' or '\n'
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); if (linebuf[linebuf.size() - 1] == '\n')
linebuf.erase(linebuf.size() - 1);
} }
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); if (linebuf[linebuf.size() - 1] == '\r')
linebuf.erase(linebuf.size() - 1);
} }
// Skip if empty line. // Skip if empty line.
@@ -307,21 +288,23 @@ std::string LoadMtl (
} }
// Skip leading space. // Skip leading space.
const char* token = linebuf.c_str(); const char *token = linebuf.c_str();
token += strspn(token, " \t"); token += strspn(token, " \t");
assert(token); assert(token);
if (token[0] == '\0') continue; // empty line if (token[0] == '\0')
continue; // empty line
if (token[0] == '#') continue; // comment line
if (token[0] == '#')
continue; // comment line
// new mtl // new mtl
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) { if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) {
// flush previous material. // flush previous material.
if (!material.name.empty()) if (!material.name.empty()) {
{ material_map.insert(
material_map.insert(std::pair<std::string, int>(material.name, materials.size())); std::pair<std::string, int>(material.name, materials.size()));
materials.push_back(material); materials.push_back(material);
} }
// initial temporary material // initial temporary material
@@ -334,7 +317,7 @@ std::string LoadMtl (
material.name = namebuf; material.name = namebuf;
continue; continue;
} }
// ambient // ambient
if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 'a' && isSpace((token[2]))) {
token += 2; token += 2;
@@ -345,7 +328,7 @@ std::string LoadMtl (
material.ambient[2] = b; material.ambient[2] = b;
continue; continue;
} }
// diffuse // diffuse
if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 'd' && isSpace((token[2]))) {
token += 2; token += 2;
@@ -356,7 +339,7 @@ std::string LoadMtl (
material.diffuse[2] = b; material.diffuse[2] = b;
continue; continue;
} }
// specular // specular
if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 's' && isSpace((token[2]))) {
token += 2; token += 2;
@@ -367,7 +350,7 @@ std::string LoadMtl (
material.specular[2] = b; material.specular[2] = b;
continue; continue;
} }
// transmittance // transmittance
if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) { if (token[0] == 'K' && token[1] == 't' && isSpace((token[2]))) {
token += 2; token += 2;
@@ -387,7 +370,7 @@ std::string LoadMtl (
} }
// emission // emission
if(token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) { if (token[0] == 'K' && token[1] == 'e' && isSpace(token[2])) {
token += 2; token += 2;
float r, g, b; float r, g, b;
parseFloat3(r, g, b, token); parseFloat3(r, g, b, token);
@@ -398,7 +381,7 @@ std::string LoadMtl (
} }
// shininess // shininess
if(token[0] == 'N' && token[1] == 's' && isSpace(token[2])) { if (token[0] == 'N' && token[1] == 's' && isSpace(token[2])) {
token += 2; token += 2;
material.shininess = parseFloat(token); material.shininess = parseFloat(token);
continue; continue;
@@ -452,29 +435,29 @@ std::string LoadMtl (
} }
// unknown parameter // unknown parameter
const char* _space = strchr(token, ' '); const char *_space = strchr(token, ' ');
if(!_space) { if (!_space) {
_space = strchr(token, '\t'); _space = strchr(token, '\t');
} }
if(_space) { if (_space) {
int len = _space - token; int len = _space - token;
std::string key(token, len); std::string key(token, len);
std::string value = _space + 1; std::string value = _space + 1;
material.unknown_parameter.insert(std::pair<std::string, std::string>(key, value)); material.unknown_parameter.insert(
std::pair<std::string, std::string>(key, value));
} }
} }
// flush last material. // flush last material.
material_map.insert(std::pair<std::string, int>(material.name, materials.size())); material_map.insert(
std::pair<std::string, int>(material.name, materials.size()));
materials.push_back(material); materials.push_back(material);
return err.str(); return err.str();
} }
std::string MaterialFileReader::operator() ( std::string MaterialFileReader::operator()(const std::string &matId,
const std::string& matId, std::vector<material_t> &materials,
std::vector<material_t>& materials, std::map<std::string, int> &matMap) {
std::map<std::string, int>& matMap)
{
std::string filepath; std::string filepath;
if (!m_mtlBasePath.empty()) { if (!m_mtlBasePath.empty()) {
@@ -487,13 +470,9 @@ std::string MaterialFileReader::operator() (
return LoadMtl(matMap, materials, matIStream); return LoadMtl(matMap, materials, matIStream);
} }
std::string std::string LoadObj(std::vector<shape_t> &shapes,
LoadObj( std::vector<material_t> &materials, // [output]
std::vector<shape_t>& shapes, const char *filename, const char *mtl_basepath) {
std::vector<material_t>& materials, // [output]
const char* filename,
const char* mtl_basepath)
{
shapes.clear(); shapes.clear();
@@ -509,34 +488,31 @@ LoadObj(
if (mtl_basepath) { if (mtl_basepath) {
basePath = mtl_basepath; basePath = mtl_basepath;
} }
MaterialFileReader matFileReader( basePath ); MaterialFileReader matFileReader(basePath);
return LoadObj(shapes, materials, ifs, matFileReader); return LoadObj(shapes, materials, ifs, matFileReader);
} }
std::string LoadObj( std::string LoadObj(std::vector<shape_t> &shapes,
std::vector<shape_t>& shapes, std::vector<material_t> &materials, // [output]
std::vector<material_t>& materials, // [output] std::istream &inStream, MaterialReader &readMatFn) {
std::istream& inStream,
MaterialReader& readMatFn)
{
std::stringstream err; std::stringstream err;
std::vector<float> v; std::vector<float> v;
std::vector<float> vn; std::vector<float> vn;
std::vector<float> vt; std::vector<float> vt;
std::vector<std::vector<vertex_index> > faceGroup; std::vector<std::vector<vertex_index>> faceGroup;
std::string name; std::string name;
// material // material
std::map<std::string, int> material_map; std::map<std::string, int> material_map;
std::map<vertex_index, unsigned int> vertexCache; std::map<vertex_index, unsigned int> vertexCache;
int material = -1; int material = -1;
shape_t shape; shape_t shape;
int maxchars = 8192; // Alloc enough size. int maxchars = 8192; // Alloc enough size.
std::vector<char> buf(maxchars); // Alloc enough size. std::vector<char> buf(maxchars); // Alloc enough size.
while (inStream.peek() != -1) { while (inStream.peek() != -1) {
inStream.getline(&buf[0], maxchars); inStream.getline(&buf[0], maxchars);
@@ -544,10 +520,12 @@ std::string LoadObj(
// Trim newline '\r\n' or '\n' // Trim newline '\r\n' or '\n'
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1); if (linebuf[linebuf.size() - 1] == '\n')
linebuf.erase(linebuf.size() - 1);
} }
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
if (linebuf[linebuf.size()-1] == '\r') linebuf.erase(linebuf.size()-1); if (linebuf[linebuf.size() - 1] == '\r')
linebuf.erase(linebuf.size() - 1);
} }
// Skip if empty line. // Skip if empty line.
@@ -556,13 +534,15 @@ std::string LoadObj(
} }
// Skip leading space. // Skip leading space.
const char* token = linebuf.c_str(); const char *token = linebuf.c_str();
token += strspn(token, " \t"); token += strspn(token, " \t");
assert(token); assert(token);
if (token[0] == '\0') continue; // empty line if (token[0] == '\0')
continue; // empty line
if (token[0] == '#') continue; // comment line
if (token[0] == '#')
continue; // comment line
// vertex // vertex
if (token[0] == 'v' && isSpace((token[1]))) { if (token[0] == 'v' && isSpace((token[1]))) {
@@ -603,14 +583,15 @@ std::string LoadObj(
std::vector<vertex_index> face; std::vector<vertex_index> face;
while (!isNewLine(token[0])) { while (!isNewLine(token[0])) {
vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2); vertex_index vi =
parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2);
face.push_back(vi); face.push_back(vi);
int n = strspn(token, " \t\r"); int n = strspn(token, " \t\r");
token += n; token += n;
} }
faceGroup.push_back(face); faceGroup.push_back(face);
continue; continue;
} }
@@ -622,7 +603,8 @@ std::string LoadObj(
sscanf(token, "%s", namebuf); sscanf(token, "%s", namebuf);
// Create face group per material. // Create face group per material.
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
faceGroup, material, name, true);
if (ret) { if (ret) {
faceGroup.clear(); faceGroup.clear();
} }
@@ -635,7 +617,6 @@ std::string LoadObj(
} }
continue; continue;
} }
// load mtl // load mtl
@@ -643,13 +624,13 @@ std::string LoadObj(
char namebuf[4096]; char namebuf[4096];
token += 7; token += 7;
sscanf(token, "%s", namebuf); sscanf(token, "%s", namebuf);
std::string err_mtl = readMatFn(namebuf, materials, material_map); std::string err_mtl = readMatFn(namebuf, materials, material_map);
if (!err_mtl.empty()) { if (!err_mtl.empty()) {
faceGroup.clear(); // for safety faceGroup.clear(); // for safety
return err_mtl; return err_mtl;
} }
continue; continue;
} }
@@ -657,14 +638,15 @@ std::string LoadObj(
if (token[0] == 'g' && isSpace((token[1]))) { if (token[0] == 'g' && isSpace((token[1]))) {
// flush previous face group. // flush previous face group.
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
faceGroup, material, name, true);
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
shape = shape_t(); shape = shape_t();
//material = -1; // material = -1;
faceGroup.clear(); faceGroup.clear();
std::vector<std::string> names; std::vector<std::string> names;
@@ -690,12 +672,13 @@ std::string LoadObj(
if (token[0] == 'o' && isSpace((token[1]))) { if (token[0] == 'o' && isSpace((token[1]))) {
// flush previous face group. // flush previous face group.
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
faceGroup, material, name, true);
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
//material = -1; // material = -1;
faceGroup.clear(); faceGroup.clear();
shape = shape_t(); shape = shape_t();
@@ -705,21 +688,19 @@ std::string LoadObj(
sscanf(token, "%s", namebuf); sscanf(token, "%s", namebuf);
name = std::string(namebuf); name = std::string(namebuf);
continue; continue;
} }
// Ignore unknown command. // Ignore unknown command.
} }
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true); bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup,
material, name, true);
if (ret) { if (ret) {
shapes.push_back(shape); shapes.push_back(shape);
} }
faceGroup.clear(); // for safety faceGroup.clear(); // for safety
return err.str(); return err.str();
} }
} }

View File

@@ -12,68 +12,61 @@
namespace tinyobj { namespace tinyobj {
typedef struct typedef struct {
{ std::string name;
std::string name;
float ambient[3]; float ambient[3];
float diffuse[3]; float diffuse[3];
float specular[3]; float specular[3];
float transmittance[3]; float transmittance[3];
float emission[3]; float emission[3];
float shininess; float shininess;
float ior; // index of refraction float ior; // index of refraction
float dissolve; // 1 == opaque; 0 == fully transparent float dissolve; // 1 == opaque; 0 == fully transparent
// illumination model (see http://www.fileformat.info/format/material/) // illumination model (see http://www.fileformat.info/format/material/)
int illum; int illum;
std::string ambient_texname; std::string ambient_texname;
std::string diffuse_texname; std::string diffuse_texname;
std::string specular_texname; std::string specular_texname;
std::string normal_texname; std::string normal_texname;
std::map<std::string, std::string> unknown_parameter; std::map<std::string, std::string> unknown_parameter;
} material_t; } material_t;
typedef struct typedef struct {
{ std::vector<float> positions;
std::vector<float> positions; std::vector<float> normals;
std::vector<float> normals; std::vector<float> texcoords;
std::vector<float> texcoords; std::vector<unsigned int> indices;
std::vector<unsigned int> indices; std::vector<int> material_ids; // per-mesh material ID
std::vector<int> material_ids; // per-mesh material ID
} mesh_t; } mesh_t;
typedef struct typedef struct {
{ std::string name;
std::string name; mesh_t mesh;
mesh_t mesh;
} shape_t; } shape_t;
class MaterialReader class MaterialReader {
{
public: public:
MaterialReader(){} MaterialReader() {}
virtual ~MaterialReader(){} virtual ~MaterialReader() {}
virtual std::string operator() ( virtual std::string operator()(const std::string &matId,
const std::string& matId, std::vector<material_t> &materials,
std::vector<material_t>& materials, std::map<std::string, int> &matMap) = 0;
std::map<std::string, int>& matMap) = 0;
}; };
class MaterialFileReader: class MaterialFileReader : public MaterialReader {
public MaterialReader public:
{ MaterialFileReader(const std::string &mtl_basepath)
public: : m_mtlBasePath(mtl_basepath) {}
MaterialFileReader(const std::string& mtl_basepath): m_mtlBasePath(mtl_basepath) {} virtual ~MaterialFileReader() {}
virtual ~MaterialFileReader() {} virtual std::string operator()(const std::string &matId,
virtual std::string operator() ( std::vector<material_t> &materials,
const std::string& matId, std::map<std::string, int> &matMap);
std::vector<material_t>& materials,
std::map<std::string, int>& matMap);
private: private:
std::string m_mtlBasePath; std::string m_mtlBasePath;
}; };
/// Loads .obj from a file. /// Loads .obj from a file.
@@ -81,27 +74,21 @@ class MaterialFileReader:
/// The function returns error string. /// The function returns error string.
/// Returns empty string when loading .obj success. /// Returns empty string when loading .obj success.
/// 'mtl_basepath' is optional, and used for base path for .mtl file. /// 'mtl_basepath' is optional, and used for base path for .mtl file.
std::string LoadObj( std::string LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<shape_t>& shapes, // [output] std::vector<material_t> &materials, // [output]
std::vector<material_t>& materials, // [output] const char *filename, const char *mtl_basepath = NULL);
const char* filename,
const char* mtl_basepath = NULL);
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve /// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
/// std::istream for materials. /// std::istream for materials.
/// Returns empty string when loading .obj success. /// Returns empty string when loading .obj success.
std::string LoadObj( std::string LoadObj(std::vector<shape_t> &shapes, // [output]
std::vector<shape_t>& shapes, // [output] std::vector<material_t> &materials, // [output]
std::vector<material_t>& materials, // [output] std::istream &inStream, MaterialReader &readMatFn);
std::istream& inStream,
MaterialReader& readMatFn);
/// Loads materials into std::map /// Loads materials into std::map
/// Returns an empty string if successful /// Returns an empty string if successful
std::string LoadMtl ( std::string LoadMtl(std::map<std::string, int> &material_map,
std::map<std::string, int>& material_map, std::vector<material_t> &materials, std::istream &inStream);
std::vector<material_t>& materials,
std::istream& inStream);
} }
#endif // _TINY_OBJ_LOADER_H #endif // _TINY_OBJ_LOADER_H