subd support: n-sided polygons & pixar crease tags
+ optional parameter to triangulate polygons to maintain compatibility + added create tag test & example subd crease tag file from OpenSubD source code
This commit is contained in:
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
|
||||
59
test.cc
59
test.cc
@@ -7,14 +7,16 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
|
||||
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes)
|
||||
static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes, bool triangulate = true)
|
||||
{
|
||||
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());
|
||||
if (triangulate)
|
||||
{
|
||||
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]);
|
||||
}
|
||||
@@ -28,6 +30,50 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes)
|
||||
shapes[i].mesh.positions[3*v+2]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].numFaces: %ld\n", i, shapes[i].mesh.numVertices.size());
|
||||
for (size_t v = 0; v < shapes[i].mesh.numVertices.size(); v++) {
|
||||
printf(" numVerts[%ld] = %ld\n", v,
|
||||
(long) shapes[i].mesh.numVertices[v]);
|
||||
}
|
||||
|
||||
printf("shape[%ld].numTags: %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 (int j = 0; j < shapes[i].mesh.tags[t].intValues.size(); ++j)
|
||||
{
|
||||
printf("%ld", (long) shapes[i].mesh.tags[t].intValues[j]);
|
||||
if (j < (shapes[i].mesh.tags[t].intValues.size()-1))
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("]");
|
||||
|
||||
printf(" floats: [");
|
||||
for (int 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 (int 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");
|
||||
}
|
||||
|
||||
printf("shape[%ld].material.name = %s\n", i, shapes[i].material.name.c_str());
|
||||
printf(" material.Ka = (%f, %f ,%f)\n", shapes[i].material.ambient[0], shapes[i].material.ambient[1], shapes[i].material.ambient[2]);
|
||||
printf(" material.Kd = (%f, %f ,%f)\n", shapes[i].material.diffuse[0], shapes[i].material.diffuse[1], shapes[i].material.diffuse[2]);
|
||||
@@ -54,19 +100,20 @@ static void PrintInfo(const std::vector<tinyobj::shape_t>& shapes)
|
||||
static bool
|
||||
TestLoadObj(
|
||||
const char* filename,
|
||||
const char* basepath = NULL)
|
||||
const char* basepath = NULL,
|
||||
bool triangulate = true)
|
||||
{
|
||||
std::cout << "Loading " << filename << std::endl;
|
||||
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::string err = tinyobj::LoadObj(shapes, filename, basepath);
|
||||
std::string err = tinyobj::LoadObj(shapes, filename, basepath, triangulate);
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
PrintInfo(shapes);
|
||||
PrintInfo(shapes, triangulate);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -174,7 +221,6 @@ main(
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
|
||||
if (argc > 1) {
|
||||
const char* basepath = NULL;
|
||||
if (argc > 2) {
|
||||
@@ -185,6 +231,7 @@ 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;
|
||||
|
||||
@@ -38,6 +38,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)
|
||||
{
|
||||
@@ -122,6 +130,30 @@ static inline void parseFloat3(
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
@@ -184,13 +216,13 @@ updateVertex(
|
||||
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) {
|
||||
if (i.vn_idx >= 0 && (i.vn_idx * 3 + 2) < in_normals.size() ) {
|
||||
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) {
|
||||
if (i.vt_idx >= 0 && (i.vt_idx * 2 +1) < in_texcoords.size()) {
|
||||
texcoords.push_back(in_texcoords[2*i.vt_idx+0]);
|
||||
texcoords.push_back(in_texcoords[2*i.vt_idx+1]);
|
||||
}
|
||||
@@ -228,9 +260,11 @@ exportFaceGroupToShape(
|
||||
const std::vector<float> &in_normals,
|
||||
const std::vector<float> &in_texcoords,
|
||||
const std::vector<std::vector<vertex_index> >& faceGroup,
|
||||
std::vector<tag_t>& tags,
|
||||
const material_t &material,
|
||||
const std::string &name,
|
||||
const bool is_material_seted)
|
||||
const bool is_material_seted,
|
||||
const bool triangulate)
|
||||
{
|
||||
if (faceGroup.empty()) {
|
||||
return false;
|
||||
@@ -247,12 +281,13 @@ exportFaceGroupToShape(
|
||||
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||
const std::vector<vertex_index>& face = faceGroup[i];
|
||||
|
||||
size_t npolys = face.size();
|
||||
|
||||
if (triangulate) {
|
||||
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;
|
||||
@@ -265,8 +300,19 @@ exportFaceGroupToShape(
|
||||
indices.push_back(v0);
|
||||
indices.push_back(v1);
|
||||
indices.push_back(v2);
|
||||
}
|
||||
|
||||
shape.mesh.numVertices.push_back(3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t k = 0; k < npolys; k++) {
|
||||
unsigned int v = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, face[k]);
|
||||
indices.push_back(v);
|
||||
|
||||
shape.mesh.numVertices.push_back(npolys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
@@ -277,6 +323,7 @@ exportFaceGroupToShape(
|
||||
shape.mesh.normals.swap(normals);
|
||||
shape.mesh.texcoords.swap(texcoords);
|
||||
shape.mesh.indices.swap(indices);
|
||||
shape.mesh.tags.swap(tags);
|
||||
|
||||
if(is_material_seted) {
|
||||
shape.material = material;
|
||||
@@ -499,7 +546,8 @@ std::string
|
||||
LoadObj(
|
||||
std::vector<shape_t>& shapes,
|
||||
const char* filename,
|
||||
const char* mtl_basepath)
|
||||
const char* mtl_basepath,
|
||||
bool triangulate)
|
||||
{
|
||||
|
||||
shapes.clear();
|
||||
@@ -518,19 +566,22 @@ LoadObj(
|
||||
}
|
||||
MaterialFileReader matFileReader( basePath );
|
||||
|
||||
return LoadObj(shapes, ifs, matFileReader);
|
||||
return LoadObj(shapes, ifs, matFileReader, triangulate);
|
||||
}
|
||||
|
||||
std::string LoadObj(
|
||||
std::vector<shape_t>& shapes,
|
||||
std::istream& inStream,
|
||||
MaterialReader& readMatFn)
|
||||
MaterialReader& readMatFn,
|
||||
bool triangulate)
|
||||
{
|
||||
std::stringstream err;
|
||||
|
||||
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;
|
||||
|
||||
@@ -656,7 +707,7 @@ std::string LoadObj(
|
||||
|
||||
// flush previous face group.
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, material, name, is_material_seted, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
@@ -688,7 +739,7 @@ std::string LoadObj(
|
||||
|
||||
// flush previous face group.
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, material, name, is_material_seted, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
@@ -706,11 +757,51 @@ std::string LoadObj(
|
||||
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(ts.num_ints);
|
||||
|
||||
for(int i = 0; i < ts.num_ints; ++i)
|
||||
{
|
||||
tag.intValues[i] = atoi(token);
|
||||
token += strcspn(token, "/ \t\r") + 1;
|
||||
}
|
||||
|
||||
tag.floatValues.resize(ts.num_floats);
|
||||
for(int i = 0; i < ts.num_floats; ++i)
|
||||
{
|
||||
tag.floatValues[i] = parseFloat(token);
|
||||
token += strcspn(token, "/ \t\r") + 1;
|
||||
}
|
||||
|
||||
tag.stringValues.resize(ts.num_strings);
|
||||
for(int i = 0; i < 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.
|
||||
}
|
||||
|
||||
shape_t shape;
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, tags, material, name, is_material_seted, triangulate);
|
||||
if (ret) {
|
||||
shapes.push_back(shape);
|
||||
}
|
||||
|
||||
@@ -34,12 +34,23 @@ typedef struct
|
||||
std::map<std::string, std::string> unknown_parameter;
|
||||
} material_t;
|
||||
|
||||
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> numVertices; //Is it worth it 255 faces
|
||||
std::vector<tag_t> tags;
|
||||
} mesh_t;
|
||||
|
||||
typedef struct
|
||||
@@ -82,7 +93,9 @@ class MaterialFileReader:
|
||||
std::string LoadObj(
|
||||
std::vector<shape_t>& shapes, // [output]
|
||||
const char* filename,
|
||||
const char* mtl_basepath = NULL);
|
||||
const char* mtl_basepath = NULL,
|
||||
bool triangulate = true
|
||||
);
|
||||
|
||||
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
|
||||
/// std::istream for materials.
|
||||
@@ -90,7 +103,8 @@ std::string LoadObj(
|
||||
std::string LoadObj(
|
||||
std::vector<shape_t>& shapes, // [output]
|
||||
std::istream& inStream,
|
||||
MaterialReader& readMatFn);
|
||||
MaterialReader& readMatFn,
|
||||
bool triangulate = true);
|
||||
|
||||
/// Loads materials into std::map
|
||||
/// Returns an empty string if successful
|
||||
|
||||
Reference in New Issue
Block a user