Format source code.
This commit is contained in:
341
tiny_obj_loader.cc
Executable file → Normal file
341
tiny_obj_loader.cc
Executable file → Normal 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user