Initial commit.
This commit is contained in:
4
README.md
Normal file
4
README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
tinyobjloader
|
||||
=============
|
||||
|
||||
Tiny but poweful single file wavefront obj loader written in C++. no dependency except for C++ STL.
|
||||
24
cornell_box.mtl
Normal file
24
cornell_box.mtl
Normal file
@@ -0,0 +1,24 @@
|
||||
newmtl white
|
||||
Ka 0 0 0
|
||||
Kd 1 1 1
|
||||
Ks 0 0 0
|
||||
|
||||
newmtl red
|
||||
Ka 0 0 0
|
||||
Kd 1 0 0
|
||||
Ks 0 0 0
|
||||
|
||||
newmtl green
|
||||
Ka 0 0 0
|
||||
Kd 0 1 0
|
||||
Ks 0 0 0
|
||||
|
||||
newmtl blue
|
||||
Ka 0 0 0
|
||||
Kd 0 0 1
|
||||
Ks 0 0 0
|
||||
|
||||
newmtl light
|
||||
Ka 20 20 20
|
||||
Kd 1 1 1
|
||||
Ks 0 0 0
|
||||
145
cornell_box.obj
Normal file
145
cornell_box.obj
Normal file
@@ -0,0 +1,145 @@
|
||||
# cornell_box.obj and cornell_box.mtl are grabbed from Intel's embree project.
|
||||
# original cornell box data
|
||||
# comment
|
||||
|
||||
# empty line including some space
|
||||
|
||||
|
||||
mtllib cornell_box.mtl
|
||||
|
||||
o floor
|
||||
usemtl white
|
||||
v 552.8 0.0 0.0
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 559.2
|
||||
v 549.6 0.0 559.2
|
||||
|
||||
v 130.0 0.0 65.0
|
||||
v 82.0 0.0 225.0
|
||||
v 240.0 0.0 272.0
|
||||
v 290.0 0.0 114.0
|
||||
|
||||
v 423.0 0.0 247.0
|
||||
v 265.0 0.0 296.0
|
||||
v 314.0 0.0 456.0
|
||||
v 472.0 0.0 406.0
|
||||
|
||||
f 1 2 3 4
|
||||
f 8 7 6 5
|
||||
f 12 11 10 9
|
||||
|
||||
o light
|
||||
usemtl light
|
||||
v 343.0 548.0 227.0
|
||||
v 343.0 548.0 332.0
|
||||
v 213.0 548.0 332.0
|
||||
v 213.0 548.0 227.0
|
||||
#f -4 -3 -2 -1
|
||||
|
||||
o ceiling
|
||||
usemtl white
|
||||
v 556.0 548.8 0.0
|
||||
v 556.0 548.8 559.2
|
||||
v 0.0 548.8 559.2
|
||||
v 0.0 548.8 0.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
o back_wall
|
||||
usemtl white
|
||||
v 549.6 0.0 559.2
|
||||
v 0.0 0.0 559.2
|
||||
v 0.0 548.8 559.2
|
||||
v 556.0 548.8 559.2
|
||||
f -4 -3 -2 -1
|
||||
|
||||
o front_wall
|
||||
usemtl blue
|
||||
v 549.6 0.0 0
|
||||
v 0.0 0.0 0
|
||||
v 0.0 548.8 0
|
||||
v 556.0 548.8 0
|
||||
#f -1 -2 -3 -4
|
||||
|
||||
o green_wall
|
||||
usemtl green
|
||||
v 0.0 0.0 559.2
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 548.8 0.0
|
||||
v 0.0 548.8 559.2
|
||||
f -4 -3 -2 -1
|
||||
|
||||
o red_wall
|
||||
usemtl red
|
||||
v 552.8 0.0 0.0
|
||||
v 549.6 0.0 559.2
|
||||
v 556.0 548.8 559.2
|
||||
v 556.0 548.8 0.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
o short_block
|
||||
usemtl white
|
||||
|
||||
v 130.0 165.0 65.0
|
||||
v 82.0 165.0 225.0
|
||||
v 240.0 165.0 272.0
|
||||
v 290.0 165.0 114.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 290.0 0.0 114.0
|
||||
v 290.0 165.0 114.0
|
||||
v 240.0 165.0 272.0
|
||||
v 240.0 0.0 272.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 130.0 0.0 65.0
|
||||
v 130.0 165.0 65.0
|
||||
v 290.0 165.0 114.0
|
||||
v 290.0 0.0 114.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 82.0 0.0 225.0
|
||||
v 82.0 165.0 225.0
|
||||
v 130.0 165.0 65.0
|
||||
v 130.0 0.0 65.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 240.0 0.0 272.0
|
||||
v 240.0 165.0 272.0
|
||||
v 82.0 165.0 225.0
|
||||
v 82.0 0.0 225.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
o tall_block
|
||||
usemtl white
|
||||
|
||||
v 423.0 330.0 247.0
|
||||
v 265.0 330.0 296.0
|
||||
v 314.0 330.0 456.0
|
||||
v 472.0 330.0 406.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
usemtl white
|
||||
v 423.0 0.0 247.0
|
||||
v 423.0 330.0 247.0
|
||||
v 472.0 330.0 406.0
|
||||
v 472.0 0.0 406.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 472.0 0.0 406.0
|
||||
v 472.0 330.0 406.0
|
||||
v 314.0 330.0 456.0
|
||||
v 314.0 0.0 456.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 314.0 0.0 456.0
|
||||
v 314.0 330.0 456.0
|
||||
v 265.0 330.0 296.0
|
||||
v 265.0 0.0 296.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
v 265.0 0.0 296.0
|
||||
v 265.0 330.0 296.0
|
||||
v 423.0 330.0 247.0
|
||||
v 423.0 0.0 247.0
|
||||
f -4 -3 -2 -1
|
||||
|
||||
33
premake4.lua
Normal file
33
premake4.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
lib_sources = {
|
||||
"tiny_obj_loader.cc"
|
||||
}
|
||||
|
||||
sources = {
|
||||
"test.cc",
|
||||
}
|
||||
|
||||
-- premake4.lua
|
||||
solution "TinyObjLoaderSolution"
|
||||
configurations { "Release", "Debug" }
|
||||
|
||||
if (os.is("windows")) then
|
||||
platforms { "x32", "x64" }
|
||||
else
|
||||
platforms { "native", "x32", "x64" }
|
||||
end
|
||||
|
||||
-- A project defines one build target
|
||||
project "tinyobjloader"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
files { lib_sources, sources }
|
||||
|
||||
configuration "Debug"
|
||||
defines { "DEBUG" } -- -DDEBUG
|
||||
flags { "Symbols" }
|
||||
targetname "test_tinyobjloader_debug"
|
||||
|
||||
configuration "Release"
|
||||
-- defines { "NDEBUG" } -- -NDEBUG
|
||||
flags { "Symbols", "Optimize" }
|
||||
targetname "test_tinyobjloader"
|
||||
45
test.cc
Normal file
45
test.cc
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
int
|
||||
main(
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
std::string inputfile = "cornell_box.obj";
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
|
||||
if (argc > 1) {
|
||||
inputfile = std::string(argv[1]);
|
||||
}
|
||||
|
||||
std::string err = tinyobj::LoadObj(shapes, inputfile.c_str());
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
||||
printf("shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
||||
printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
||||
assert((shapes[i].mesh.positions.size() % 3) == 0);
|
||||
for (size_t v = 0; v < shapes[i].mesh.positions.size() / 3; v++) {
|
||||
printf(" v[%ld] = (%f, %f, %f)\n", v,
|
||||
shapes[i].mesh.positions[3*v+0],
|
||||
shapes[i].mesh.positions[3*v+1],
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
381
tiny_obj_loader.cc
Normal file
381
tiny_obj_loader.cc
Normal file
@@ -0,0 +1,381 @@
|
||||
//
|
||||
// Copyright 2012, Syoyo Fujita.
|
||||
//
|
||||
// Licensed under 2-clause BSD liecense.
|
||||
//
|
||||
|
||||
//
|
||||
// version 0.9.0: Initial
|
||||
//
|
||||
|
||||
//
|
||||
// @todo { Read .mtl }
|
||||
//
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
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) {};
|
||||
|
||||
};
|
||||
// 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);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct obj_shape {
|
||||
std::vector<float> v;
|
||||
std::vector<float> vn;
|
||||
std::vector<float> vt;
|
||||
};
|
||||
|
||||
static inline bool isSpace(const char c) {
|
||||
return (c == ' ') || (c == '\t');
|
||||
}
|
||||
|
||||
// Make index zero-base, and also support relative index.
|
||||
static inline int fixIndex(int idx, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (idx > 0) {
|
||||
i = idx - 1;
|
||||
} else if (idx == 0) {
|
||||
i = 0;
|
||||
} else { // negative value = relative
|
||||
i = n + idx;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
x = parseFloat(token);
|
||||
y = parseFloat(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);
|
||||
|
||||
vi.v_idx = fixIndex(atoi(token), vsize);
|
||||
token += strcspn(token, "/ \t\r");
|
||||
if (token[0] != '/') {
|
||||
return vi;
|
||||
}
|
||||
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
|
||||
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)
|
||||
{
|
||||
const std::map<vertex_index, unsigned int>::iterator it = vertexCache.find(i);
|
||||
|
||||
if (it != vertexCache.end()) {
|
||||
// found cache
|
||||
return it->second;
|
||||
}
|
||||
|
||||
assert(in_positions.size() > (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]);
|
||||
}
|
||||
|
||||
if (i.vt_idx >= 0) {
|
||||
texcoords.push_back(in_texcoords[3*i.vt_idx+0]);
|
||||
texcoords.push_back(in_texcoords[3*i.vt_idx+1]);
|
||||
texcoords.push_back(in_texcoords[3*i.vt_idx+2]);
|
||||
}
|
||||
|
||||
unsigned int idx = positions.size() / 3 - 1;
|
||||
vertexCache[i] = idx;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static bool
|
||||
exportFaceGroupToShape(
|
||||
shape_t& shape,
|
||||
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 std::string name)
|
||||
{
|
||||
if (faceGroup.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flattened version of vertex data
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
std::map<vertex_index, unsigned int> vertexCache;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
// Flatten vertices and indices
|
||||
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||
const std::vector<vertex_index>& face = faceGroup[i];
|
||||
|
||||
vertex_index i0 = face[0];
|
||||
vertex_index i1(-1);
|
||||
vertex_index i2 = face[1];
|
||||
|
||||
size_t npolys = face.size();
|
||||
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++) {
|
||||
i1 = i2;
|
||||
i2 = face[k];
|
||||
|
||||
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
|
||||
unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
|
||||
unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
|
||||
|
||||
indices.push_back(v0);
|
||||
indices.push_back(v1);
|
||||
indices.push_back(v2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Construct shape.
|
||||
//
|
||||
shape.name = name;
|
||||
shape.mesh.positions.swap(positions);
|
||||
shape.mesh.normals.swap(normals);
|
||||
shape.mesh.texcoords.swap(texcoords);
|
||||
shape.mesh.indices.swap(indices);
|
||||
|
||||
// @todo { material, name }
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
std::string
|
||||
LoadObj(
|
||||
std::vector<shape_t>& shapes,
|
||||
const char* filename)
|
||||
{
|
||||
|
||||
shapes.clear();
|
||||
|
||||
std::stringstream err;
|
||||
|
||||
std::ifstream ifs(filename);
|
||||
if (!ifs) {
|
||||
err << "Cannot open file [" << filename << "]" << std::endl;
|
||||
return err.str();
|
||||
}
|
||||
|
||||
std::vector<float> v;
|
||||
std::vector<float> vn;
|
||||
std::vector<float> vt;
|
||||
std::vector<std::vector<vertex_index> > faceGroup;
|
||||
std::string name;
|
||||
|
||||
int maxchars = 8192; // Alloc enough size.
|
||||
std::vector<char> buf(maxchars); // Alloc enough size.
|
||||
while (ifs.peek() != -1) {
|
||||
ifs.getline(&buf[0], maxchars);
|
||||
|
||||
std::string linebuf(&buf[0]);
|
||||
|
||||
// Trim newline '\r\n' or '\r'
|
||||
if (linebuf.size() > 0) {
|
||||
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||
}
|
||||
if (linebuf.size() > 0) {
|
||||
if (linebuf[linebuf.size()-1] == '\n') linebuf.erase(linebuf.size()-1);
|
||||
}
|
||||
|
||||
// Skip if empty line.
|
||||
if (linebuf.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip leading space.
|
||||
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
|
||||
|
||||
// vertex
|
||||
if (token[0] == 'v' && isSpace((token[1]))) {
|
||||
token += 2;
|
||||
float x, y, z;
|
||||
parseFloat3(x, y, z, token);
|
||||
v.push_back(x);
|
||||
v.push_back(y);
|
||||
v.push_back(z);
|
||||
continue;
|
||||
}
|
||||
|
||||
// normal
|
||||
if (token[0] == 'v' && token[1] == 'n' && isSpace((token[2]))) {
|
||||
token += 3;
|
||||
float x, y, z;
|
||||
parseFloat3(x, y, z, token);
|
||||
vn.push_back(x);
|
||||
vn.push_back(y);
|
||||
vn.push_back(z);
|
||||
continue;
|
||||
}
|
||||
|
||||
// texcoord
|
||||
if (token[0] == 'v' && token[1] == 't' && isSpace((token[2]))) {
|
||||
token += 3;
|
||||
float x, y;
|
||||
parseFloat2(x, y, token);
|
||||
vt.push_back(x);
|
||||
vt.push_back(y);
|
||||
continue;
|
||||
}
|
||||
|
||||
// face
|
||||
if (token[0] == 'f' && isSpace((token[1]))) {
|
||||
token += 2;
|
||||
token += strspn(token, " \t");
|
||||
|
||||
std::vector<vertex_index> face;
|
||||
while (token[0] && (token[1] != '\0')) {
|
||||
vertex_index vi = parseTriple(token, v.size() / 3, vn.size() / 3, vt.size() / 2);
|
||||
face.push_back(vi);
|
||||
int n = strspn(token, " \t");
|
||||
token += n;
|
||||
}
|
||||
|
||||
faceGroup.push_back(face);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// use mtl
|
||||
if ((0 == strncmp(token, "usemtl", 6)) && isSpace((token[6]))) {
|
||||
|
||||
// flush previous face group.
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, name);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
faceGroup.clear();
|
||||
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// load mtl
|
||||
if ((0 == strncmp(token, "mtllib", 6)) && isSpace((token[6]))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// object name
|
||||
if (token[0] == 'o' && isSpace((token[1]))) {
|
||||
char namebuf[4096];
|
||||
token += 2;
|
||||
sscanf(token, "%s", namebuf);
|
||||
name = std::string(namebuf);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore unknown command.
|
||||
}
|
||||
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, name);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
faceGroup.clear(); // for safety
|
||||
|
||||
return err.str();
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
53
tiny_obj_loader.h
Normal file
53
tiny_obj_loader.h
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// Copyright 2012, Syoyo Fujita.
|
||||
//
|
||||
// Licensed under 2-clause BSD liecense.
|
||||
//
|
||||
#ifndef _TINY_OBJ_LOADER_H
|
||||
#define _TINY_OBJ_LOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace tinyobj {
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
|
||||
float ambient[3];
|
||||
float diffuse[3];
|
||||
float specular[3];
|
||||
float transmittance[3];
|
||||
|
||||
std::string ambient_texname;
|
||||
std::string diffuse_texname;
|
||||
std::string specular_texname;
|
||||
} material_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
std::vector<unsigned int> indices;
|
||||
} mesh_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
material_t material;
|
||||
mesh_t mesh;
|
||||
} shape_t;
|
||||
|
||||
/// Loads .obj from a file.
|
||||
/// 'shapes' will be filled with parsed shape data
|
||||
/// The function returns error string.
|
||||
/// Returns empty string when loading .obj success.
|
||||
std::string LoadObj(
|
||||
std::vector<shape_t>& shapes, // [output]
|
||||
const char* filename);
|
||||
|
||||
};
|
||||
|
||||
#endif // _TINY_OBJ_LOADER_H
|
||||
Reference in New Issue
Block a user