Merge branch 'dboogert-master'
This commit is contained in:
47
README.md
47
README.md
@@ -19,6 +19,7 @@ Tiny but poweful single file wavefront obj loader written in C++. No dependency
|
||||
What's new
|
||||
----------
|
||||
|
||||
* Jan 29, 2016 : Support n-polygon and OpenSubdiv crease tag! Thanks dboogert!
|
||||
* Nov 26, 2015 : Now single-header only!.
|
||||
* Nov 08, 2015 : Improved API.
|
||||
* Jun 23, 2015 : Various fixes and added more projects using tinyobjloader. Thanks many contributors!
|
||||
@@ -67,16 +68,13 @@ Features
|
||||
* Normal
|
||||
* Material
|
||||
* Unknown material attributes are returned as key-value(value is string) map.
|
||||
* Crease tag('t'). This is OpenSubdiv specific(not in wavefront .obj specification)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
Polygon is converted into triangle.
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
- [ ] Support quad polygon and some tags for OpenSubdiv http://graphics.pixar.com/opensubdiv/
|
||||
* [ ] Support different indices for vertex/normal/texcoord
|
||||
|
||||
License
|
||||
-------
|
||||
@@ -148,4 +146,43 @@ Usage
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
Reading .obj without triangulation. Use `num_vertices[i]` to iterate over faces(indices). `num_vertices[i]` stores the number of vertices for ith face.
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION // define this in only *one* .cc
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
std::string inputfile = "cornell_box.obj";
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool triangulate = false;
|
||||
bool ret = tinyobj::LoadObj(shapes, materials, err, inputfile.c_str(), triangulate);
|
||||
|
||||
if (!err.empty()) { // `err` may contain warning message.
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
|
||||
size_t indexOffset = 0;
|
||||
for (size_t n = 0; n < shapes[i].mesh.num_vertices.size(); n++) {
|
||||
int ngon = shapes[i].mesh.num_vertices[n];
|
||||
for (size_t f = 0; f < ngon; f++) {
|
||||
size_t v = shapes[i].mesh.indices[indexOffset + f];
|
||||
printf(" face[%ld] v[%ld] = (%f, %f, %f)\n", n,
|
||||
shapes[i].mesh.positions[3*v+0],
|
||||
shapes[i].mesh.positions[3*v+1],
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
|
||||
}
|
||||
indexOffset += ngon;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
101
catmark_torus_creases0.obj
Normal file
101
catmark_torus_creases0.obj
Normal file
@@ -0,0 +1,101 @@
|
||||
#
|
||||
# Copyright 2013 Pixar
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
||||
# with the following modification; you may not use this file except in
|
||||
# compliance with the Apache License and the following modification to it:
|
||||
# Section 6. Trademarks. is deleted and replaced with:
|
||||
#
|
||||
# 6. Trademarks. This License does not grant permission to use the trade
|
||||
# names, trademarks, service marks, or product names of the Licensor
|
||||
# and its affiliates, except as required to comply with Section 4(c) of
|
||||
# the License and to reproduce the content of the NOTICE file.
|
||||
#
|
||||
# You may obtain a copy of the Apache License at
|
||||
#
|
||||
# http:#www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the Apache License with the above modification is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the Apache License for the specific
|
||||
# language governing permissions and limitations under the Apache License.
|
||||
#
|
||||
# This file uses centimeters as units for non-parametric coordinates.
|
||||
|
||||
v 1.25052 0.517982 0.353553
|
||||
v 0.597239 0.247384 0.353553
|
||||
v 0.597239 0.247384 -0.353553
|
||||
v 1.25052 0.517982 -0.353553
|
||||
v 0.517982 1.25052 0.353553
|
||||
v 0.247384 0.597239 0.353553
|
||||
v 0.247384 0.597239 -0.353553
|
||||
v 0.517982 1.25052 -0.353553
|
||||
v -0.517982 1.25052 0.353553
|
||||
v -0.247384 0.597239 0.353553
|
||||
v -0.247384 0.597239 -0.353553
|
||||
v -0.517982 1.25052 -0.353553
|
||||
v -1.25052 0.517982 0.353553
|
||||
v -0.597239 0.247384 0.353553
|
||||
v -0.597239 0.247384 -0.353553
|
||||
v -1.25052 0.517982 -0.353553
|
||||
v -1.25052 -0.517982 0.353553
|
||||
v -0.597239 -0.247384 0.353553
|
||||
v -0.597239 -0.247384 -0.353553
|
||||
v -1.25052 -0.517982 -0.353553
|
||||
v -0.517982 -1.25052 0.353553
|
||||
v -0.247384 -0.597239 0.353553
|
||||
v -0.247384 -0.597239 -0.353553
|
||||
v -0.517982 -1.25052 -0.353553
|
||||
v 0.517982 -1.25052 0.353553
|
||||
v 0.247384 -0.597239 0.353553
|
||||
v 0.247384 -0.597239 -0.353553
|
||||
v 0.517982 -1.25052 -0.353553
|
||||
v 1.25052 -0.517982 0.353553
|
||||
v 0.597239 -0.247384 0.353553
|
||||
v 0.597239 -0.247384 -0.353553
|
||||
v 1.25052 -0.517982 -0.353553
|
||||
vt 0 0
|
||||
vt 1 0
|
||||
vt 1 1
|
||||
vt 0 1
|
||||
f 5/1/1 6/2/2 2/3/3 1/4/4
|
||||
f 6/1/5 7/2/6 3/3/7 2/4/8
|
||||
f 7/1/9 8/2/10 4/3/11 3/4/12
|
||||
f 8/1/13 5/2/14 1/3/15 4/4/16
|
||||
f 9/1/17 10/2/18 6/3/19 5/4/20
|
||||
f 10/1/21 11/2/22 7/3/23 6/4/24
|
||||
f 11/1/25 12/2/26 8/3/27 7/4/28
|
||||
f 12/1/29 9/2/30 5/3/31 8/4/32
|
||||
f 13/1/33 14/2/34 10/3/35 9/4/36
|
||||
f 14/1/37 15/2/38 11/3/39 10/4/40
|
||||
f 15/1/41 16/2/42 12/3/43 11/4/44
|
||||
f 16/1/45 13/2/46 9/3/47 12/4/48
|
||||
f 17/1/49 18/2/50 14/3/51 13/4/52
|
||||
f 18/1/53 19/2/54 15/3/55 14/4/56
|
||||
f 19/1/57 20/2/58 16/3/59 15/4/60
|
||||
f 20/1/61 17/2/62 13/3/63 16/4/64
|
||||
f 21/1/65 22/2/66 18/3/67 17/4/68
|
||||
f 22/1/69 23/2/70 19/3/71 18/4/72
|
||||
f 23/1/73 24/2/74 20/3/75 19/4/76
|
||||
f 24/1/77 21/2/78 17/3/79 20/4/80
|
||||
f 25/1/81 26/2/82 22/3/83 21/4/84
|
||||
f 26/1/85 27/2/86 23/3/87 22/4/88
|
||||
f 27/1/89 28/2/90 24/3/91 23/4/92
|
||||
f 28/1/93 25/2/94 21/3/95 24/4/96
|
||||
f 29/1/97 30/2/98 26/3/99 25/4/100
|
||||
f 30/1/101 31/2/102 27/3/103 26/4/104
|
||||
f 31/1/105 32/2/106 28/3/107 27/4/108
|
||||
f 32/1/109 29/2/110 25/3/111 28/4/112
|
||||
f 1/1/113 2/2/114 30/3/115 29/4/116
|
||||
f 2/1/117 3/2/118 31/3/119 30/4/120
|
||||
f 3/1/121 4/2/122 32/3/123 31/4/124
|
||||
f 4/1/125 1/2/126 29/3/127 32/4/128
|
||||
t crease 2/1/0 1 5 4.7
|
||||
t crease 2/1/0 5 9 4.7
|
||||
t crease 2/1/0 9 13 4.7
|
||||
t crease 2/1/0 13 17 4.7
|
||||
t crease 2/1/0 17 21 4.7
|
||||
t crease 2/1/0 21 25 4.7
|
||||
t crease 2/1/0 25 29 4.7
|
||||
t crease 2/1/0 29 1 4.7
|
||||
88
test.cc
88
test.cc
@@ -8,7 +8,7 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials)
|
||||
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::vector<tinyobj::material_t>& materials, bool triangulate = true)
|
||||
{
|
||||
std::cout << "# of shapes : " << shapes.size() << std::endl;
|
||||
std::cout << "# of materials : " << materials.size() << std::endl;
|
||||
@@ -16,10 +16,32 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::ve
|
||||
for (size_t i = 0; i < shapes.size(); i++) {
|
||||
printf("shape[%ld].name = %s\n", i, shapes[i].name.c_str());
|
||||
printf("Size of shape[%ld].indices: %ld\n", i, shapes[i].mesh.indices.size());
|
||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
|
||||
printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]);
|
||||
|
||||
if (triangulate)
|
||||
{
|
||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
||||
assert((shapes[i].mesh.indices.size() % 3) == 0);
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size() / 3; f++) {
|
||||
printf(" idx[%ld] = %d, %d, %d. mat_id = %d\n", f, shapes[i].mesh.indices[3*f+0], shapes[i].mesh.indices[3*f+1], shapes[i].mesh.indices[3*f+2], shapes[i].mesh.material_ids[f]);
|
||||
}
|
||||
} else {
|
||||
for (size_t f = 0; f < shapes[i].mesh.indices.size(); f++) {
|
||||
printf(" idx[%ld] = %d\n", f, shapes[i].mesh.indices[f]);
|
||||
}
|
||||
|
||||
printf("Size of shape[%ld].material_ids: %ld\n", i, shapes[i].mesh.material_ids.size());
|
||||
assert(shapes[i].mesh.material_ids.size() == shapes[i].mesh.num_vertices.size());
|
||||
for (size_t m = 0; m < shapes[i].mesh.material_ids.size(); m++) {
|
||||
printf(" material_id[%ld] = %d\n", m,
|
||||
shapes[i].mesh.material_ids[m]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("shape[%ld].num_faces: %ld\n", i, shapes[i].mesh.num_vertices.size());
|
||||
for (size_t v = 0; v < shapes[i].mesh.num_vertices.size(); v++) {
|
||||
printf(" num_vertices[%ld] = %ld\n", v,
|
||||
static_cast<long>(shapes[i].mesh.num_vertices[v]));
|
||||
}
|
||||
|
||||
printf("shape[%ld].vertices: %ld\n", i, shapes[i].mesh.positions.size());
|
||||
@@ -30,6 +52,44 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::ve
|
||||
shapes[i].mesh.positions[3*v+1],
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].num_tags: %ld\n", i, shapes[i].mesh.tags.size());
|
||||
for (size_t t = 0; t < shapes[i].mesh.tags.size(); t++) {
|
||||
printf(" tag[%ld] = %s ", t, shapes[i].mesh.tags[t].name.c_str());
|
||||
printf(" ints: [");
|
||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j)
|
||||
{
|
||||
printf("%ld", static_cast<long>(shapes[i].mesh.tags[t].intValues[j]));
|
||||
if (j < (shapes[i].mesh.tags[t].intValues.size()-1))
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]");
|
||||
|
||||
printf(" floats: [");
|
||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].floatValues.size(); ++j)
|
||||
{
|
||||
printf("%f", shapes[i].mesh.tags[t].floatValues[j]);
|
||||
if (j < (shapes[i].mesh.tags[t].floatValues.size()-1))
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]");
|
||||
|
||||
printf(" strings: [");
|
||||
for (size_t j = 0; j < shapes[i].mesh.tags[t].stringValues.size(); ++j)
|
||||
{
|
||||
printf("%s", shapes[i].mesh.tags[t].stringValues[j].c_str());
|
||||
if (j < (shapes[i].mesh.tags[t].stringValues.size()-1))
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < materials.size(); i++) {
|
||||
@@ -52,6 +112,7 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::ve
|
||||
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
|
||||
std::map<std::string, std::string>::const_iterator it(materials[i].unknown_parameter.begin());
|
||||
std::map<std::string, std::string>::const_iterator itEnd(materials[i].unknown_parameter.end());
|
||||
|
||||
for (; it != itEnd; it++) {
|
||||
printf(" material.%s = %s\n", it->first.c_str(), it->second.c_str());
|
||||
}
|
||||
@@ -62,7 +123,8 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, const std::ve
|
||||
static bool
|
||||
TestLoadObj(
|
||||
const char* filename,
|
||||
const char* basepath = NULL)
|
||||
const char* basepath = NULL,
|
||||
bool triangulate = true)
|
||||
{
|
||||
std::cout << "Loading " << filename << std::endl;
|
||||
|
||||
@@ -70,7 +132,7 @@ TestLoadObj(
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath);
|
||||
bool ret = tinyobj::LoadObj(shapes, materials, err, filename, basepath, triangulate);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
@@ -80,7 +142,7 @@ TestLoadObj(
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintInfo(shapes, materials);
|
||||
PrintInfo(shapes, materials, triangulate);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -92,7 +154,7 @@ TestStreamLoadObj()
|
||||
std::cout << "Stream Loading " << std::endl;
|
||||
|
||||
std::stringstream objStream;
|
||||
objStream
|
||||
objStream
|
||||
<< "mtllib cube.mtl\n"
|
||||
"\n"
|
||||
"v 0.000000 2.000000 2.000000\n"
|
||||
@@ -125,7 +187,7 @@ TestStreamLoadObj()
|
||||
"f 2 6 7 3\n"
|
||||
"# 6 elements";
|
||||
|
||||
std::string matStream(
|
||||
std::string matStream(
|
||||
"newmtl white\n"
|
||||
"Ka 0 0 0\n"
|
||||
"Kd 1 1 1\n"
|
||||
@@ -172,7 +234,7 @@ std::string matStream(
|
||||
|
||||
private:
|
||||
std::stringstream m_matSStream;
|
||||
};
|
||||
};
|
||||
|
||||
MaterialStringStreamReader matSSReader(matStream);
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
@@ -198,7 +260,6 @@ main(
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
|
||||
if (argc > 1) {
|
||||
const char* basepath = NULL;
|
||||
if (argc > 2) {
|
||||
@@ -209,7 +270,8 @@ main(
|
||||
//assert(true == TestLoadObj("cornell_box.obj"));
|
||||
//assert(true == TestLoadObj("cube.obj"));
|
||||
assert(true == TestStreamLoadObj());
|
||||
assert(true == TestLoadObj("catmark_torus_creases0.obj", NULL, false));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
//
|
||||
|
||||
//
|
||||
// version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension)
|
||||
// version 0.9.16: Make tinyobjloader header-only
|
||||
// version 0.9.15: Change API to handle no mtl file case correctly(#58)
|
||||
// version 0.9.14: Support specular highlight, bump, displacement and alpha map(#53)
|
||||
@@ -68,12 +69,24 @@ typedef struct {
|
||||
std::map<std::string, std::string> unknown_parameter;
|
||||
} material_t;
|
||||
|
||||
typedef struct {
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
std::vector<unsigned int> indices;
|
||||
std::vector<int> material_ids; // per-mesh material ID
|
||||
typedef struct
|
||||
{
|
||||
std::string name;
|
||||
|
||||
std::vector<int> intValues;
|
||||
std::vector<float> floatValues;
|
||||
std::vector<std::string> stringValues;
|
||||
} tag_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
std::vector<float> positions;
|
||||
std::vector<float> normals;
|
||||
std::vector<float> texcoords;
|
||||
std::vector<unsigned int> indices;
|
||||
std::vector<unsigned char> num_vertices; // up to 255 faces
|
||||
std::vector<int> material_ids; // per-mesh material ID
|
||||
std::vector<tag_t> tags; // SubD tag
|
||||
} mesh_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -112,10 +125,11 @@ private:
|
||||
/// Returns true when loading .obj become success.
|
||||
/// Returns warning and error message into `err`
|
||||
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
||||
/// 'triangulate' is optional, and used whether triangulate polygon face in .obj or not.
|
||||
bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
std::string& err, // [output]
|
||||
const char *filename, const char *mtl_basepath = NULL);
|
||||
const char *filename, const char *mtl_basepath = NULL, bool triangulate = true);
|
||||
|
||||
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
|
||||
/// std::istream for materials.
|
||||
@@ -124,7 +138,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
std::string& err, // [output]
|
||||
std::istream &inStream, MaterialReader &readMatFn);
|
||||
std::istream &inStream, MaterialReader &readMatFn, bool triangulate = true);
|
||||
|
||||
/// Loads materials into std::map
|
||||
void LoadMtl(std::map<std::string, int> &material_map, // [output]
|
||||
@@ -161,6 +175,14 @@ struct vertex_index {
|
||||
vertex_index(int vidx, int vtidx, int vnidx)
|
||||
: v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx){}
|
||||
};
|
||||
|
||||
struct tag_sizes {
|
||||
tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {}
|
||||
int num_ints;
|
||||
int num_floats;
|
||||
int num_strings;
|
||||
};
|
||||
|
||||
// for std::map
|
||||
static inline bool operator<(const vertex_index &a, const vertex_index &b) {
|
||||
if (a.v_idx != b.v_idx)
|
||||
@@ -379,6 +401,30 @@ static inline void parseFloat3(float &x, float &y, float &z,
|
||||
z = parseFloat(token);
|
||||
}
|
||||
|
||||
static tag_sizes parseTagTriple(const char* & token)
|
||||
{
|
||||
tag_sizes ts;
|
||||
|
||||
ts.num_ints = atoi(token);
|
||||
token += strcspn(token, "/ \t\r");
|
||||
if (token[0] != '/') {
|
||||
return ts;
|
||||
}
|
||||
token++;
|
||||
|
||||
ts.num_floats = atoi(token);
|
||||
token += strcspn(token, "/ \t\r");
|
||||
if (token[0] != '/') {
|
||||
return ts;
|
||||
}
|
||||
token++;
|
||||
|
||||
ts.num_strings = atoi(token);
|
||||
token += strcspn(token, "/ \t\r") + 1;
|
||||
|
||||
return ts;
|
||||
}
|
||||
|
||||
// Parse triples: i, i/j/k, i//k, i/j
|
||||
static vertex_index parseTriple(const char *&token, int vsize, int vnsize,
|
||||
int vtsize) {
|
||||
@@ -433,13 +479,13 @@ updateVertex(std::map<vertex_index, unsigned int> &vertexCache,
|
||||
positions.push_back(in_positions[3 * static_cast<size_t>(i.v_idx) + 1]);
|
||||
positions.push_back(in_positions[3 * static_cast<size_t>(i.v_idx) + 2]);
|
||||
|
||||
if (i.vn_idx >= 0) {
|
||||
if ((i.vn_idx >= 0) && (static_cast<size_t>(i.vn_idx * 3 + 2) < in_normals.size())) {
|
||||
normals.push_back(in_normals[3 * static_cast<size_t>(i.vn_idx) + 0]);
|
||||
normals.push_back(in_normals[3 * static_cast<size_t>(i.vn_idx) + 1]);
|
||||
normals.push_back(in_normals[3 * static_cast<size_t>(i.vn_idx) + 2]);
|
||||
}
|
||||
|
||||
if (i.vt_idx >= 0) {
|
||||
if ((i.vt_idx >= 0) && (static_cast<size_t>(i.vt_idx * 2 + 1) < in_texcoords.size())) {
|
||||
texcoords.push_back(in_texcoords[2 * static_cast<size_t>(i.vt_idx) + 0]);
|
||||
texcoords.push_back(in_texcoords[2 * static_cast<size_t>(i.vt_idx) + 1]);
|
||||
}
|
||||
@@ -479,7 +525,8 @@ static bool exportFaceGroupToShape(
|
||||
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) {
|
||||
std::vector<tag_t> &tags,
|
||||
const int material_id, const std::string &name, bool clearCache, bool triangulate) {
|
||||
if (faceGroup.empty()) {
|
||||
return false;
|
||||
}
|
||||
@@ -494,30 +541,50 @@ static bool exportFaceGroupToShape(
|
||||
|
||||
size_t npolys = face.size();
|
||||
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++) {
|
||||
i1 = i2;
|
||||
i2 = face[k];
|
||||
if (triangulate) {
|
||||
|
||||
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);
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++) {
|
||||
i1 = i2;
|
||||
i2 = face[k];
|
||||
|
||||
shape.mesh.indices.push_back(v0);
|
||||
shape.mesh.indices.push_back(v1);
|
||||
shape.mesh.indices.push_back(v2);
|
||||
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);
|
||||
shape.mesh.indices.push_back(v2);
|
||||
|
||||
shape.mesh.num_vertices.push_back(3);
|
||||
shape.mesh.material_ids.push_back(material_id);
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
for (size_t k = 0; k < npolys; k++) {
|
||||
unsigned int v = updateVertex(
|
||||
vertexCache, shape.mesh.positions, shape.mesh.normals,
|
||||
shape.mesh.texcoords, in_positions, in_normals, in_texcoords, face[k]);
|
||||
|
||||
shape.mesh.indices.push_back(v);
|
||||
|
||||
}
|
||||
|
||||
shape.mesh.num_vertices.push_back(static_cast<unsigned char>(npolys));
|
||||
shape.mesh.material_ids.push_back(material_id); // per face
|
||||
|
||||
shape.mesh.material_ids.push_back(material_id);
|
||||
}
|
||||
}
|
||||
|
||||
shape.name = name;
|
||||
shape.mesh.tags.swap(tags);
|
||||
|
||||
if (clearCache)
|
||||
vertexCache.clear();
|
||||
@@ -779,7 +846,7 @@ bool MaterialFileReader::operator()(const std::string &matId,
|
||||
bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
std::string &err,
|
||||
const char *filename, const char *mtl_basepath) {
|
||||
const char *filename, const char *mtl_basepath, bool trianglulate) {
|
||||
|
||||
shapes.clear();
|
||||
|
||||
@@ -798,18 +865,19 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
}
|
||||
MaterialFileReader matFileReader(basePath);
|
||||
|
||||
return LoadObj(shapes, materials, err, ifs, matFileReader);
|
||||
return LoadObj(shapes, materials, err, ifs, matFileReader, trianglulate);
|
||||
}
|
||||
|
||||
bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
std::vector<material_t> &materials, // [output]
|
||||
std::string& err,
|
||||
std::istream &inStream, MaterialReader &readMatFn) {
|
||||
std::istream &inStream, MaterialReader &readMatFn, bool triangulate) {
|
||||
std::stringstream errss;
|
||||
|
||||
std::vector<float> v;
|
||||
std::vector<float> vn;
|
||||
std::vector<float> vt;
|
||||
std::vector<tag_t> tags;
|
||||
std::vector<std::vector<vertex_index> > faceGroup;
|
||||
std::string name;
|
||||
|
||||
@@ -917,7 +985,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
|
||||
// Create face group per material.
|
||||
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
|
||||
faceGroup, material, name, true);
|
||||
faceGroup, tags, material, name, true, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
@@ -961,7 +1029,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
|
||||
// flush previous face group.
|
||||
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
|
||||
faceGroup, material, name, true);
|
||||
faceGroup, tags, material, name, true, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
@@ -995,7 +1063,7 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
|
||||
// flush previous face group.
|
||||
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt,
|
||||
faceGroup, material, name, true);
|
||||
faceGroup, tags, material, name, true, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
@@ -1017,11 +1085,51 @@ bool LoadObj(std::vector<shape_t> &shapes, // [output]
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token[0] == 't' && isSpace(token[1])) {
|
||||
tag_t tag;
|
||||
|
||||
char namebuf[4096];
|
||||
token += 2;
|
||||
sscanf(token, "%s", namebuf);
|
||||
tag.name = std::string(namebuf);
|
||||
|
||||
token += tag.name.size() + 1;
|
||||
|
||||
tag_sizes ts = parseTagTriple(token);
|
||||
|
||||
tag.intValues.resize(static_cast<size_t>(ts.num_ints));
|
||||
|
||||
for(size_t i = 0; i < static_cast<size_t>(ts.num_ints); ++i)
|
||||
{
|
||||
tag.intValues[i] = atoi(token);
|
||||
token += strcspn(token, "/ \t\r") + 1;
|
||||
}
|
||||
|
||||
tag.floatValues.resize(static_cast<size_t>(ts.num_floats));
|
||||
for(size_t i = 0; i < static_cast<size_t>(ts.num_floats); ++i)
|
||||
{
|
||||
tag.floatValues[i] = parseFloat(token);
|
||||
token += strcspn(token, "/ \t\r") + 1;
|
||||
}
|
||||
|
||||
tag.stringValues.resize(static_cast<size_t>(ts.num_strings));
|
||||
for(size_t i = 0; i < static_cast<size_t>(ts.num_strings); ++i)
|
||||
{
|
||||
char stringValueBuffer[4096];
|
||||
|
||||
sscanf(token, "%s", stringValueBuffer);
|
||||
tag.stringValues[i] = stringValueBuffer;
|
||||
token += tag.stringValues[i].size() + 1;
|
||||
}
|
||||
|
||||
tags.push_back(tag);
|
||||
}
|
||||
|
||||
// Ignore unknown command.
|
||||
}
|
||||
|
||||
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup,
|
||||
material, name, true);
|
||||
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags,
|
||||
material, name, true, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user