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