Compare commits
2 Commits
afl
...
better-cxx
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e2cd27c64 | ||
|
|
49726abcf1 |
@@ -98,7 +98,6 @@ TinyObjLoader is successfully used in ...
|
||||
* PBR material extension for .MTL. Its proposed here: http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
|
||||
* Callback API for custom loading.
|
||||
* Double precision support(for HPC application).
|
||||
* Smoothing group
|
||||
|
||||
|
||||
## TODO
|
||||
@@ -106,6 +105,8 @@ TinyObjLoader is successfully used in ...
|
||||
* [ ] Fix obj_sticker example.
|
||||
* [ ] More unit test codes.
|
||||
* [x] Texture options
|
||||
* [ ] Normal vector generation
|
||||
* [ ] Support smoothing groups
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -172,3 +172,5 @@ bool WriteObj(const std::string& filename, const std::vector<tinyobj::shape_t>&
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ extern "C" {
|
||||
#include <windows.h>
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#include <mmsystem.h>
|
||||
@@ -143,15 +143,15 @@ float eye[3], lookat[3], up[3];
|
||||
|
||||
GLFWwindow* window;
|
||||
|
||||
static std::string GetBaseDir(const std::string& filepath) {
|
||||
static std::string GetBaseDir(const std::string &filepath) {
|
||||
if (filepath.find_last_of("/\\") != std::string::npos)
|
||||
return filepath.substr(0, filepath.find_last_of("/\\"));
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool FileExists(const std::string& abs_filename) {
|
||||
static bool FileExists(const std::string &abs_filename) {
|
||||
bool ret;
|
||||
FILE* fp = fopen(abs_filename.c_str(), "rb");
|
||||
FILE *fp = fopen(abs_filename.c_str(), "rb");
|
||||
if (fp) {
|
||||
ret = true;
|
||||
fclose(fp);
|
||||
@@ -191,106 +191,14 @@ static void CalcNormal(float N[3], float v0[3], float v1[3], float v2[3]) {
|
||||
|
||||
N[0] /= len;
|
||||
N[1] /= len;
|
||||
N[2] /= len;
|
||||
}
|
||||
}
|
||||
|
||||
namespace // Local utility functions
|
||||
{
|
||||
struct vec3 {
|
||||
float v[3];
|
||||
vec3() {
|
||||
v[0] = 0.0f;
|
||||
v[1] = 0.0f;
|
||||
v[2] = 0.0f;
|
||||
}
|
||||
};
|
||||
|
||||
void normalizeVector(vec3 &v) {
|
||||
float len2 = v.v[0] * v.v[0] + v.v[1] * v.v[1] + v.v[2] * v.v[2];
|
||||
if (len2 > 0.0f) {
|
||||
float len = sqrtf(len2);
|
||||
|
||||
v.v[0] /= len;
|
||||
v.v[1] /= len;
|
||||
v.v[2] /= len;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if `mesh_t` contains smoothing group id.
|
||||
bool hasSmoothingGroup(const tinyobj::shape_t& shape)
|
||||
{
|
||||
for (size_t i = 0; i < shape.mesh.smoothing_group_ids.size(); i++) {
|
||||
if (shape.mesh.smoothing_group_ids[i] > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void computeSmoothingNormals(const tinyobj::attrib_t& attrib, const tinyobj::shape_t& shape,
|
||||
std::map<int, vec3>& smoothVertexNormals) {
|
||||
smoothVertexNormals.clear();
|
||||
std::map<int, vec3>::iterator iter;
|
||||
|
||||
for (size_t f = 0; f < shape.mesh.indices.size() / 3; f++) {
|
||||
// Get the three indexes of the face (all faces are triangular)
|
||||
tinyobj::index_t idx0 = shape.mesh.indices[3 * f + 0];
|
||||
tinyobj::index_t idx1 = shape.mesh.indices[3 * f + 1];
|
||||
tinyobj::index_t idx2 = shape.mesh.indices[3 * f + 2];
|
||||
|
||||
// Get the three vertex indexes and coordinates
|
||||
int vi[3]; // indexes
|
||||
float v[3][3]; // coordinates
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
vi[0] = idx0.vertex_index;
|
||||
vi[1] = idx1.vertex_index;
|
||||
vi[2] = idx2.vertex_index;
|
||||
assert(vi[0] >= 0);
|
||||
assert(vi[1] >= 0);
|
||||
assert(vi[2] >= 0);
|
||||
|
||||
v[0][k] = attrib.vertices[3 * vi[0] + k];
|
||||
v[1][k] = attrib.vertices[3 * vi[1] + k];
|
||||
v[2][k] = attrib.vertices[3 * vi[2] + k];
|
||||
}
|
||||
|
||||
// Compute the normal of the face
|
||||
float normal[3];
|
||||
CalcNormal(normal, v[0], v[1], v[2]);
|
||||
|
||||
// Add the normal to the three vertexes
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
iter = smoothVertexNormals.find(vi[i]);
|
||||
if (iter != smoothVertexNormals.end()) {
|
||||
// add
|
||||
iter->second.v[0] += normal[0];
|
||||
iter->second.v[1] += normal[1];
|
||||
iter->second.v[2] += normal[2];
|
||||
} else {
|
||||
smoothVertexNormals[vi[i]].v[0] = normal[0];
|
||||
smoothVertexNormals[vi[i]].v[1] = normal[1];
|
||||
smoothVertexNormals[vi[i]].v[2] = normal[2];
|
||||
}
|
||||
}
|
||||
|
||||
} // f
|
||||
|
||||
// Normalize the normals, that is, make them unit vectors
|
||||
for (iter = smoothVertexNormals.begin(); iter != smoothVertexNormals.end();
|
||||
iter++) {
|
||||
normalizeVector(iter->second);
|
||||
}
|
||||
|
||||
} // computeSmoothingNormals
|
||||
} // namespace
|
||||
|
||||
static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
std::vector<DrawObject>* drawObjects,
|
||||
std::vector<tinyobj::material_t>& materials,
|
||||
std::map<std::string, GLuint>& textures,
|
||||
const char* filename) {
|
||||
std::vector<DrawObject>* drawObjects,
|
||||
std::vector<tinyobj::material_t>& materials,
|
||||
std::map<std::string, GLuint>& textures,
|
||||
const char* filename) {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
|
||||
@@ -309,8 +217,8 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
#endif
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename,
|
||||
base_dir.c_str());
|
||||
bool ret =
|
||||
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, base_dir.c_str());
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
@@ -334,62 +242,56 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
materials.push_back(tinyobj::material_t());
|
||||
|
||||
for (size_t i = 0; i < materials.size(); i++) {
|
||||
printf("material[%d].diffuse_texname = %s\n", int(i),
|
||||
materials[i].diffuse_texname.c_str());
|
||||
printf("material[%d].diffuse_texname = %s\n", int(i), materials[i].diffuse_texname.c_str());
|
||||
}
|
||||
|
||||
// Load diffuse textures
|
||||
{
|
||||
for (size_t m = 0; m < materials.size(); m++) {
|
||||
tinyobj::material_t* mp = &materials[m];
|
||||
for (size_t m = 0; m < materials.size(); m++) {
|
||||
tinyobj::material_t* mp = &materials[m];
|
||||
|
||||
if (mp->diffuse_texname.length() > 0) {
|
||||
// Only load the texture if it is not already loaded
|
||||
if (textures.find(mp->diffuse_texname) == textures.end()) {
|
||||
GLuint texture_id;
|
||||
int w, h;
|
||||
int comp;
|
||||
|
||||
if (mp->diffuse_texname.length() > 0) {
|
||||
// Only load the texture if it is not already loaded
|
||||
if (textures.find(mp->diffuse_texname) == textures.end()) {
|
||||
GLuint texture_id;
|
||||
int w, h;
|
||||
int comp;
|
||||
std::string texture_filename = mp->diffuse_texname;
|
||||
if (!FileExists(texture_filename)) {
|
||||
// Append base dir.
|
||||
texture_filename = base_dir + mp->diffuse_texname;
|
||||
if (!FileExists(texture_filename)) {
|
||||
std::cerr << "Unable to find file: " << mp->diffuse_texname << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* image = stbi_load(texture_filename.c_str(), &w, &h, &comp, STBI_default);
|
||||
if (!image) {
|
||||
std::cerr << "Unable to load texture: " << texture_filename << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "Loaded texture: " << texture_filename << ", w = " << w << ", h = " << h << ", comp = " << comp << std::endl;
|
||||
|
||||
std::string texture_filename = mp->diffuse_texname;
|
||||
if (!FileExists(texture_filename)) {
|
||||
// Append base dir.
|
||||
texture_filename = base_dir + mp->diffuse_texname;
|
||||
if (!FileExists(texture_filename)) {
|
||||
std::cerr << "Unable to find file: " << mp->diffuse_texname
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if (comp == 3) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
|
||||
}
|
||||
else if (comp == 4) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
} else {
|
||||
assert(0); // TODO
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
stbi_image_free(image);
|
||||
textures.insert(std::make_pair(mp->diffuse_texname, texture_id));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char* image =
|
||||
stbi_load(texture_filename.c_str(), &w, &h, &comp, STBI_default);
|
||||
if (!image) {
|
||||
std::cerr << "Unable to load texture: " << texture_filename
|
||||
<< std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << "Loaded texture: " << texture_filename << ", w = " << w
|
||||
<< ", h = " << h << ", comp = " << comp << std::endl;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
if (comp == 3) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
|
||||
GL_UNSIGNED_BYTE, image);
|
||||
} else if (comp == 4) {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, image);
|
||||
} else {
|
||||
assert(0); // TODO
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
stbi_image_free(image);
|
||||
textures.insert(std::make_pair(mp->diffuse_texname, texture_id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bmin[0] = bmin[1] = bmin[2] = std::numeric_limits<float>::max();
|
||||
@@ -399,55 +301,30 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
for (size_t s = 0; s < shapes.size(); s++) {
|
||||
DrawObject o;
|
||||
std::vector<float> buffer; // pos(3float), normal(3float), color(3float)
|
||||
|
||||
// Check for smoothing group and compute smoothing normals
|
||||
std::map<int, vec3> smoothVertexNormals;
|
||||
if (hasSmoothingGroup(shapes[s]) > 0) {
|
||||
std::cout << "Compute smoothingNormal for shape [" << s << "]" << std::endl;
|
||||
computeSmoothingNormals(attrib, shapes[s], smoothVertexNormals);
|
||||
}
|
||||
|
||||
for (size_t f = 0; f < shapes[s].mesh.indices.size() / 3; f++) {
|
||||
tinyobj::index_t idx0 = shapes[s].mesh.indices[3 * f + 0];
|
||||
tinyobj::index_t idx1 = shapes[s].mesh.indices[3 * f + 1];
|
||||
tinyobj::index_t idx2 = shapes[s].mesh.indices[3 * f + 2];
|
||||
|
||||
|
||||
int current_material_id = shapes[s].mesh.material_ids[f];
|
||||
|
||||
if ((current_material_id < 0) ||
|
||||
(current_material_id >= static_cast<int>(materials.size()))) {
|
||||
if ((current_material_id < 0) || (current_material_id >= static_cast<int>(materials.size()))) {
|
||||
// Invaid material ID. Use default material.
|
||||
current_material_id =
|
||||
materials.size() -
|
||||
1; // Default material is added to the last item in `materials`.
|
||||
current_material_id = materials.size() - 1; // Default material is added to the last item in `materials`.
|
||||
}
|
||||
// if (current_material_id >= materials.size()) {
|
||||
// std::cerr << "Invalid material index: " << current_material_id <<
|
||||
// std::endl;
|
||||
//if (current_material_id >= materials.size()) {
|
||||
// std::cerr << "Invalid material index: " << current_material_id << std::endl;
|
||||
//}
|
||||
//
|
||||
float diffuse[3];
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
diffuse[i] = materials[current_material_id].diffuse[i];
|
||||
diffuse[i] = materials[current_material_id].diffuse[i];
|
||||
}
|
||||
float tc[3][2];
|
||||
if (attrib.texcoords.size() > 0) {
|
||||
if ((idx0.texcoord_index < 0) || (idx1.texcoord_index < 0) ||
|
||||
(idx2.texcoord_index < 0)) {
|
||||
// face does not contain valid uv index.
|
||||
tc[0][0] = 0.0f;
|
||||
tc[0][1] = 0.0f;
|
||||
tc[1][0] = 0.0f;
|
||||
tc[1][1] = 0.0f;
|
||||
tc[2][0] = 0.0f;
|
||||
tc[2][1] = 0.0f;
|
||||
} else {
|
||||
assert(attrib.texcoords.size() >
|
||||
size_t(2 * idx0.texcoord_index + 1));
|
||||
assert(attrib.texcoords.size() >
|
||||
size_t(2 * idx1.texcoord_index + 1));
|
||||
assert(attrib.texcoords.size() >
|
||||
size_t(2 * idx2.texcoord_index + 1));
|
||||
assert(attrib.texcoords.size() > 2 * idx0.texcoord_index + 1);
|
||||
assert(attrib.texcoords.size() > 2 * idx1.texcoord_index + 1);
|
||||
assert(attrib.texcoords.size() > 2 * idx2.texcoord_index + 1);
|
||||
|
||||
// Flip Y coord.
|
||||
tc[0][0] = attrib.texcoords[2 * idx0.texcoord_index];
|
||||
@@ -456,14 +333,13 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
tc[1][1] = 1.0f - attrib.texcoords[2 * idx1.texcoord_index + 1];
|
||||
tc[2][0] = attrib.texcoords[2 * idx2.texcoord_index];
|
||||
tc[2][1] = 1.0f - attrib.texcoords[2 * idx2.texcoord_index + 1];
|
||||
}
|
||||
} else {
|
||||
tc[0][0] = 0.0f;
|
||||
tc[0][1] = 0.0f;
|
||||
tc[1][0] = 0.0f;
|
||||
tc[1][1] = 0.0f;
|
||||
tc[2][0] = 0.0f;
|
||||
tc[2][1] = 0.0f;
|
||||
tc[0][0] = 0.0f;
|
||||
tc[0][1] = 0.0f;
|
||||
tc[1][0] = 0.0f;
|
||||
tc[1][1] = 0.0f;
|
||||
tc[2][0] = 0.0f;
|
||||
tc[2][1] = 0.0f;
|
||||
}
|
||||
|
||||
float v[3][3];
|
||||
@@ -487,63 +363,27 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
}
|
||||
|
||||
float n[3][3];
|
||||
{
|
||||
bool invalid_normal_index = false;
|
||||
if (attrib.normals.size() > 0) {
|
||||
int nf0 = idx0.normal_index;
|
||||
int nf1 = idx1.normal_index;
|
||||
int nf2 = idx2.normal_index;
|
||||
|
||||
if ((nf0 < 0) || (nf1 < 0) || (nf2 < 0)) {
|
||||
// normal index is missing from this face.
|
||||
invalid_normal_index = true;
|
||||
} else {
|
||||
for (int k = 0; k < 3; k++) {
|
||||
assert(size_t(3 * nf0 + k) < attrib.normals.size());
|
||||
assert(size_t(3 * nf1 + k) < attrib.normals.size());
|
||||
assert(size_t(3 * nf2 + k) < attrib.normals.size());
|
||||
n[0][k] = attrib.normals[3 * nf0 + k];
|
||||
n[1][k] = attrib.normals[3 * nf1 + k];
|
||||
n[2][k] = attrib.normals[3 * nf2 + k];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
invalid_normal_index = true;
|
||||
}
|
||||
|
||||
if (invalid_normal_index && !smoothVertexNormals.empty()) {
|
||||
// Use smoothing normals
|
||||
int f0 = idx0.vertex_index;
|
||||
int f1 = idx1.vertex_index;
|
||||
int f2 = idx2.vertex_index;
|
||||
|
||||
if (f0 >= 0 && f1 >= 0 && f2 >= 0) {
|
||||
n[0][0] = smoothVertexNormals[f0].v[0];
|
||||
n[0][1] = smoothVertexNormals[f0].v[1];
|
||||
n[0][2] = smoothVertexNormals[f0].v[2];
|
||||
|
||||
n[1][0] = smoothVertexNormals[f1].v[0];
|
||||
n[1][1] = smoothVertexNormals[f1].v[1];
|
||||
n[1][2] = smoothVertexNormals[f1].v[2];
|
||||
|
||||
n[2][0] = smoothVertexNormals[f2].v[0];
|
||||
n[2][1] = smoothVertexNormals[f2].v[1];
|
||||
n[2][2] = smoothVertexNormals[f2].v[2];
|
||||
|
||||
invalid_normal_index = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalid_normal_index) {
|
||||
// compute geometric normal
|
||||
CalcNormal(n[0], v[0], v[1], v[2]);
|
||||
n[1][0] = n[0][0];
|
||||
n[1][1] = n[0][1];
|
||||
n[1][2] = n[0][2];
|
||||
n[2][0] = n[0][0];
|
||||
n[2][1] = n[0][1];
|
||||
n[2][2] = n[0][2];
|
||||
if (attrib.normals.size() > 0) {
|
||||
int f0 = idx0.normal_index;
|
||||
int f1 = idx1.normal_index;
|
||||
int f2 = idx2.normal_index;
|
||||
assert(f0 >= 0);
|
||||
assert(f1 >= 0);
|
||||
assert(f2 >= 0);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
n[0][k] = attrib.normals[3 * f0 + k];
|
||||
n[1][k] = attrib.normals[3 * f1 + k];
|
||||
n[2][k] = attrib.normals[3 * f2 + k];
|
||||
}
|
||||
} else {
|
||||
// compute geometric normal
|
||||
CalcNormal(n[0], v[0], v[1], v[2]);
|
||||
n[1][0] = n[0][0];
|
||||
n[1][1] = n[0][1];
|
||||
n[1][2] = n[0][2];
|
||||
n[2][0] = n[0][0];
|
||||
n[2][1] = n[0][1];
|
||||
n[2][2] = n[0][2];
|
||||
}
|
||||
|
||||
for (int k = 0; k < 3; k++) {
|
||||
@@ -556,9 +396,11 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
// Combine normal and diffuse to get color.
|
||||
float normal_factor = 0.2;
|
||||
float diffuse_factor = 1 - normal_factor;
|
||||
float c[3] = {n[k][0] * normal_factor + diffuse[0] * diffuse_factor,
|
||||
n[k][1] * normal_factor + diffuse[1] * diffuse_factor,
|
||||
n[k][2] * normal_factor + diffuse[2] * diffuse_factor};
|
||||
float c[3] = {
|
||||
n[k][0] * normal_factor + diffuse[0] * diffuse_factor,
|
||||
n[k][1] * normal_factor + diffuse[1] * diffuse_factor,
|
||||
n[k][2] * normal_factor + diffuse[2] * diffuse_factor
|
||||
};
|
||||
float len2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2];
|
||||
if (len2 > 0.0f) {
|
||||
float len = sqrtf(len2);
|
||||
@@ -570,7 +412,7 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
buffer.push_back(c[0] * 0.5 + 0.5);
|
||||
buffer.push_back(c[1] * 0.5 + 0.5);
|
||||
buffer.push_back(c[2] * 0.5 + 0.5);
|
||||
|
||||
|
||||
buffer.push_back(tc[k][0]);
|
||||
buffer.push_back(tc[k][1]);
|
||||
}
|
||||
@@ -580,22 +422,19 @@ static bool LoadObjAndConvert(float bmin[3], float bmax[3],
|
||||
o.numTriangles = 0;
|
||||
|
||||
// OpenGL viewer does not support texturing with per-face material.
|
||||
if (shapes[s].mesh.material_ids.size() > 0 &&
|
||||
shapes[s].mesh.material_ids.size() > s) {
|
||||
o.material_id = shapes[s].mesh.material_ids[0]; // use the material ID
|
||||
// of the first face.
|
||||
if (shapes[s].mesh.material_ids.size() > 0 && shapes[s].mesh.material_ids.size() > s) {
|
||||
o.material_id = shapes[s].mesh.material_ids[0]; // use the material ID of the first face.
|
||||
} else {
|
||||
o.material_id = materials.size() - 1; // = ID for default material.
|
||||
o.material_id = materials.size() - 1; // = ID for default material.
|
||||
}
|
||||
printf("shape[%d] material_id %d\n", int(s), int(o.material_id));
|
||||
|
||||
|
||||
if (buffer.size() > 0) {
|
||||
glGenBuffers(1, &o.vb_id);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, o.vb_id);
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer.size() * sizeof(float),
|
||||
&buffer.at(0), GL_STATIC_DRAW);
|
||||
o.numTriangles = buffer.size() / (3 + 3 + 3 + 2) /
|
||||
3; // 3:vtx, 3:normal, 3:col, 2:texcoord
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer.size() * sizeof(float), &buffer.at(0),
|
||||
GL_STATIC_DRAW);
|
||||
o.numTriangles = buffer.size() / (3 + 3 + 3 + 2) / 3; // 3:vtx, 3:normal, 3:col, 2:texcoord
|
||||
|
||||
printf("shape[%d] # of triangles = %d\n", static_cast<int>(s),
|
||||
o.numTriangles);
|
||||
@@ -628,7 +467,7 @@ static void reshapeFunc(GLFWwindow* window, int w, int h) {
|
||||
}
|
||||
|
||||
static void keyboardFunc(GLFWwindow* window, int key, int scancode, int action,
|
||||
int mods) {
|
||||
int mods) {
|
||||
(void)window;
|
||||
(void)scancode;
|
||||
(void)mods;
|
||||
@@ -710,9 +549,7 @@ static void motionFunc(GLFWwindow* window, double mouse_x, double mouse_y) {
|
||||
prevMouseY = mouse_y;
|
||||
}
|
||||
|
||||
static void Draw(const std::vector<DrawObject>& drawObjects,
|
||||
std::vector<tinyobj::material_t>& materials,
|
||||
std::map<std::string, GLuint>& textures) {
|
||||
static void Draw(const std::vector<DrawObject>& drawObjects, std::vector<tinyobj::material_t>& materials, std::map<std::string, GLuint>& textures) {
|
||||
glPolygonMode(GL_FRONT, GL_FILL);
|
||||
glPolygonMode(GL_BACK, GL_FILL);
|
||||
|
||||
@@ -735,7 +572,7 @@ static void Draw(const std::vector<DrawObject>& drawObjects,
|
||||
if ((o.material_id < materials.size())) {
|
||||
std::string diffuse_texname = materials[o.material_id].diffuse_texname;
|
||||
if (textures.find(diffuse_texname) != textures.end()) {
|
||||
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[diffuse_texname]);
|
||||
}
|
||||
}
|
||||
glVertexPointer(3, GL_FLOAT, stride, (const void*)0);
|
||||
@@ -831,8 +668,7 @@ int main(int argc, char** argv) {
|
||||
float bmin[3], bmax[3];
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
std::map<std::string, GLuint> textures;
|
||||
if (false == LoadObjAndConvert(bmin, bmax, &gDrawObjects, materials, textures,
|
||||
argv[1])) {
|
||||
if (false == LoadObjAndConvert(bmin, bmax, &gDrawObjects, materials, textures, argv[1])) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import os, sys
|
||||
import glob
|
||||
import subprocess
|
||||
|
||||
def main():
|
||||
for g in glob.glob("../tests/afl/id*"):
|
||||
print(g)
|
||||
|
||||
cmd = ["../a.out", g]
|
||||
|
||||
proc = subprocess.Popen(cmd)
|
||||
try:
|
||||
outs, errs = proc.communicate(timeout=15)
|
||||
print(outs)
|
||||
except TimeoutExpired:
|
||||
proc.kill()
|
||||
outs, errs = proc.communicate()
|
||||
|
||||
|
||||
main()
|
||||
@@ -29,10 +29,10 @@ extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TINYOBJ_USE_CXX11
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#if __has_warning("-Wzero-as-null-pointer-constant")
|
||||
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -70,7 +70,7 @@ class timerutil {
|
||||
}
|
||||
time_t current() {
|
||||
struct timeval t;
|
||||
gettimeofday(&t, NULL);
|
||||
gettimeofday(&t, tobj_null);
|
||||
return static_cast<time_t>(t.tv_sec * 1000 + t.tv_usec);
|
||||
}
|
||||
|
||||
@@ -145,9 +145,6 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
|
||||
assert(shapes[i].mesh.num_face_vertices.size() ==
|
||||
shapes[i].mesh.material_ids.size());
|
||||
|
||||
assert(shapes[i].mesh.num_face_vertices.size() ==
|
||||
shapes[i].mesh.smoothing_group_ids.size());
|
||||
|
||||
printf("shape[%ld].num_faces: %lu\n", static_cast<long>(i),
|
||||
static_cast<unsigned long>(shapes[i].mesh.num_face_vertices.size()));
|
||||
|
||||
@@ -168,8 +165,6 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
|
||||
|
||||
printf(" face[%ld].material_id = %d\n", static_cast<long>(f),
|
||||
shapes[i].mesh.material_ids[f]);
|
||||
printf(" face[%ld].smoothing_group_id = %d\n", static_cast<long>(f),
|
||||
shapes[i].mesh.smoothing_group_ids[f]);
|
||||
|
||||
index_offset += fnum;
|
||||
}
|
||||
@@ -273,7 +268,7 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
|
||||
}
|
||||
}
|
||||
|
||||
static bool TestLoadObj(const char* filename, const char* basepath = NULL,
|
||||
static bool TestLoadObj(const char* filename, const char* basepath = tobj_null,
|
||||
bool triangulate = true) {
|
||||
std::cout << "Loading " << filename << std::endl;
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
o cube
|
||||
mtllib cube.mtl
|
||||
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v -0.500000 0.500000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
|
||||
g cube
|
||||
usemtl cube
|
||||
s 1
|
||||
f 1/1 2/2 3/3
|
||||
f 3/3 2/2 4/4
|
||||
s 2
|
||||
f 3/1 4/2 5/3
|
||||
f 5/3 4/2 6/4
|
||||
s 3
|
||||
f 5/4 6/3 7/2
|
||||
f 7/2 6/3 8/1
|
||||
s 4
|
||||
f 7/1 8/2 1/3
|
||||
f 1/3 8/2 2/4
|
||||
s 5
|
||||
f 2/1 8/2 4/3
|
||||
f 4/3 8/2 6/4
|
||||
s 6
|
||||
f 7/1 1/2 5/3
|
||||
f 5 1 3
|
||||
@@ -1,23 +0,0 @@
|
||||
newmtl test1
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.0000 0.0000 0.0000
|
||||
Kd 0.5 0.2 0.2
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
|
||||
newmtl test2
|
||||
Ns 10.0000
|
||||
Ni 1.5000
|
||||
d 1.0000
|
||||
Tr 0.0000
|
||||
Tf 1.0000 1.0000 1.0000
|
||||
illum 2
|
||||
Ka 0.0000 0.0000 0.0000
|
||||
Kd 0.2 0.5 0.2
|
||||
Ks 0.0000 0.0000 0.0000
|
||||
Ke 0.0000 0.0000 0.0000
|
||||
@@ -1,51 +0,0 @@
|
||||
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
mtllib issue-162-smoothing-group.mtl
|
||||
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v -0.500000 0.500000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
|
||||
vt 0.000000 0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 1.000000 1.000000
|
||||
|
||||
vn 0.000000 0.000000 1.000000
|
||||
vn 0.000000 1.000000 0.000000
|
||||
vn 0.000000 0.000000 -1.000000
|
||||
vn 0.000000 -1.000000 0.000000
|
||||
vn 1.000000 0.000000 0.000000
|
||||
vn -1.000000 0.000000 0.000000
|
||||
|
||||
usemtl test1
|
||||
g test1
|
||||
s 1
|
||||
f 1/1/1 2/2/1 3/3/1
|
||||
f 3/3/1 2/2/1 4/4/1
|
||||
|
||||
usemtl test2
|
||||
g test2
|
||||
|
||||
s off
|
||||
f 3/1/2 4/2/2 5/3/2
|
||||
f 5/3/2 4/2/2 6/4/2
|
||||
s 3
|
||||
f 5/4/3 6/3/3 7/2/3
|
||||
f 7/2/3 6/3/3 8/1/3
|
||||
s 4
|
||||
f 7/1/4 8/2/4 1/3/4
|
||||
f 1/3/4 8/2/4 2/4/4
|
||||
s 0
|
||||
f 2/1/5 8/2/5 4/3/5
|
||||
f 4/3/5 8/2/5 6/4/5
|
||||
s 6
|
||||
f 7/1/6 1/2/6 5/3/6
|
||||
f 5/3/6 1/2/6 3/4/6
|
||||
@@ -1,22 +0,0 @@
|
||||
# from tinyobjloader issue #29
|
||||
|
||||
v 0.000000 2.000000 0.000000
|
||||
v 0.000000 0.000000 0.000000
|
||||
v 2.000000 0.000000 0.000000
|
||||
v 2.000000 2.000000 0.000000
|
||||
v 4.000000 0.000000 -3.255298
|
||||
v 4.000000 2.000000 -3.255298
|
||||
#vn 0.000000 0.000000 1.000000
|
||||
#vn 0.000000 0.000000 1.000000
|
||||
#vn 0.276597 0.000000 0.960986
|
||||
#vn 0.276597 0.000000 0.960986
|
||||
#vn 0.531611 0.000000 0.846988
|
||||
#vn 0.531611 0.000000 0.846988
|
||||
# 6 vertices
|
||||
|
||||
# 6 normals
|
||||
|
||||
g all
|
||||
s 1
|
||||
f 1//1 2//2 3//3 4//4
|
||||
f 4//4 3//3 5//5
|
||||
@@ -1,24 +0,0 @@
|
||||
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
|
||||
@@ -1,35 +0,0 @@
|
||||
mtllib smoothing-normal.mtl
|
||||
|
||||
v 0.000000 2.000000 2.000000
|
||||
v 0.000000 0.000000 2.000000
|
||||
v 2.000000 0.000000 2.000000
|
||||
v 2.000000 2.000000 2.000000
|
||||
v 0.000000 2.000000 0.000000
|
||||
v 0.000000 0.000000 0.000000
|
||||
v 2.000000 0.000000 0.000000
|
||||
v 2.000000 2.000000 0.000000
|
||||
# 8 vertices
|
||||
|
||||
g front cube
|
||||
usemtl white
|
||||
s 1
|
||||
f 1 2 3 4
|
||||
#g bottom cube
|
||||
#usemtl white
|
||||
s 1
|
||||
f 2 6 7 3
|
||||
|
||||
g back cube
|
||||
# expects white material
|
||||
s off
|
||||
f 8 7 6 5
|
||||
#g right cube
|
||||
#usemtl red
|
||||
#f 4 3 7 8
|
||||
#g top cube
|
||||
#usemtl white
|
||||
#f 5 1 4 8
|
||||
#g left cube
|
||||
#usemtl green
|
||||
#f 5 6 2 1
|
||||
# 6 elements
|
||||
@@ -1,17 +0,0 @@
|
||||
Command line used to find this crash:
|
||||
|
||||
afl-fuzz -i in -o out ./test_loader @@
|
||||
|
||||
If you can't reproduce a bug outside of afl-fuzz, be sure to set the same
|
||||
memory limit. The limit used for this fuzzing session was 50.0 MB.
|
||||
|
||||
Need a tool to minimize test cases before investigating the crashes or sending
|
||||
them to a vendor? Check out the afl-tmin that comes with the fuzzer!
|
||||
|
||||
Found any cool bugs in open-source tools using afl-fuzz? If yes, please drop
|
||||
me a mail at <lcamtuf@coredump.cx> once the issues are fixed - I'd love to
|
||||
add your finds to the gallery at:
|
||||
|
||||
http://lcamtuf.coredump.cx/afl/
|
||||
|
||||
Thanks :-)
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
} cube
|
||||
|
||||
v d.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1/6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
f 1//4 5//4 55555555555555 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
@@ -1,35 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
4
|
||||
f 1//4 6//4 2//4
|
||||
f
|
||||
g cube
|
||||
|
||||
v 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
n 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 //5
|
||||
f 5//5 8//5 6//5
|
||||
f 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
@@ -1,34 +0,0 @@
|
||||
# cube.ob7//3
|
||||
f 3//3 4//3 8//3j
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1˙0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
f 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,29 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1,0
|
||||
T 0.0 1.0 0.0
|
||||
v 4.0 1c0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 /////////////////////////////.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
v˙ 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8K/31
|
||||
f/6 4//6 3//6
|
||||
f 1//6 2 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5"
|
||||
f 1//4 5//4 2222222222224f 1//2 7//2 5 6//4 2//4
|
||||
f 3//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
@@ -1,33 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0<>0 0.0 -1.0
|
||||
vn 0.0 1.0 00
|
||||
vn 0.0 -Ę.0 0.0
|
||||
vn 1. 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 40000000000000000vvvvvvvvvvvvvvvv00000080000000//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
f 1//4 56//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
@@ -1,32 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 08//3
|
||||
f 5//5 7//5 8//5!Šf 5//5 8//5 6//5
|
||||
f 1//4 5//4 65555//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
@@ -1,33 +0,0 @@
|
||||
# cube.7//3
|
||||
f 3//3 4//3 8//3
|
||||
obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v .0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5!Šf 5//5 8//5 6//5
|
||||
f 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
@@ -1,30 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cuvP 0.0 0.0 .0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5!Šf 5//5 8//5 6//5
|
||||
f 1//4 5//4 6//4
|
||||
f 1//4 6666666666666666//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
@@ -1,33 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
t 1//4 5/-4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
@@ -1,33 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
t 1//4 -5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
@@ -1,35 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v 1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 !.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0 0.0
|
||||
vn 0.0 8//5 6//5
|
||||
t 1//4 -1.0 0.0
|
||||
vn 1.0 0.0 0.0
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 8//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
t 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4 f 2//1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,32 +0,0 @@
|
||||
# cube.obj
|
||||
#
|
||||
|
||||
g cube
|
||||
|
||||
v 0.0 0.0 0.0
|
||||
v 0.0 0.0 1.0
|
||||
v 0.0 1.0 0.0
|
||||
v 0.0 1.0 1.0
|
||||
v Ď1.0 0.0 0.0
|
||||
v 1.0 0.0 1.0
|
||||
v 1.0 1.0 0.0
|
||||
v 1.0 1.0 1.0
|
||||
|
||||
vn 0.0 0.0 1.0
|
||||
vn 0.0 0.0 -1.0
|
||||
vn 0.0 1.0
|
||||
vn 1.0 0.0 0.0
|
||||
vn -1.0 0.0 0.0
|
||||
|
||||
f 1//2 7//2 5//2
|
||||
f 1//2 3//2 7//2
|
||||
f 1//6 4//6 3//6
|
||||
f 1//6 2//6 4//6
|
||||
f 3//3 8//3 7//3
|
||||
f 3//3 4//3 811111//3
|
||||
f 5//5 7//5 8//5
|
||||
f 5//5 8//5 6//5
|
||||
t 1//4 5//4 6//4
|
||||
f 1//4 6//4 2//4
|
||||
f 2B/1 6//1 8//1
|
||||
f 2//1 8//1 4//1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -717,65 +717,6 @@ TEST_CASE("texture-name-whitespace", "[Issue145]") {
|
||||
|
||||
}
|
||||
|
||||
TEST_CASE("smoothing-group", "[Issue162]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "../models/issue-162-smoothing-group.obj", gMtlBasePath);
|
||||
|
||||
|
||||
if (!err.empty()) {
|
||||
std::cerr << "[Issue162] " << err << std::endl;
|
||||
}
|
||||
|
||||
REQUIRE(true == ret);
|
||||
REQUIRE(2 == shapes.size());
|
||||
|
||||
REQUIRE(2 == shapes[0].mesh.smoothing_group_ids.size());
|
||||
REQUIRE(1 == shapes[0].mesh.smoothing_group_ids[0]);
|
||||
REQUIRE(1 == shapes[0].mesh.smoothing_group_ids[1]);
|
||||
|
||||
REQUIRE(10 == shapes[1].mesh.smoothing_group_ids.size());
|
||||
REQUIRE(0 == shapes[1].mesh.smoothing_group_ids[0]);
|
||||
REQUIRE(0 == shapes[1].mesh.smoothing_group_ids[1]);
|
||||
REQUIRE(3 == shapes[1].mesh.smoothing_group_ids[2]);
|
||||
REQUIRE(3 == shapes[1].mesh.smoothing_group_ids[3]);
|
||||
REQUIRE(4 == shapes[1].mesh.smoothing_group_ids[4]);
|
||||
REQUIRE(4 == shapes[1].mesh.smoothing_group_ids[5]);
|
||||
REQUIRE(0 == shapes[1].mesh.smoothing_group_ids[6]);
|
||||
REQUIRE(0 == shapes[1].mesh.smoothing_group_ids[7]);
|
||||
REQUIRE(6 == shapes[1].mesh.smoothing_group_ids[8]);
|
||||
REQUIRE(6 == shapes[1].mesh.smoothing_group_ids[9]);
|
||||
|
||||
}
|
||||
|
||||
// Fuzzer test.
|
||||
// Just check if it does not crash.
|
||||
|
||||
TEST_CASE("afl000000", "[AFL]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "./afl/id:000000,sig:11,src:000000,op:havoc,rep:128", gMtlBasePath);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
}
|
||||
|
||||
TEST_CASE("afl000001", "[AFL]") {
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, "./afl/id:000001,sig:11,src:000000,op:havoc,rep:64", gMtlBasePath);
|
||||
|
||||
REQUIRE(true == ret);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
main(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2012-2018 Syoyo Fujita and many contributors.
|
||||
Copyright (c) 2012-2017 Syoyo Fujita and many contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -23,8 +23,6 @@ THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//
|
||||
// version 1.2.0 : Hardened implementation(#xxx)
|
||||
// version 1.1.1 : Support smoothing groups(#162)
|
||||
// version 1.1.0 : Support parsing vertex color(#144)
|
||||
// version 1.0.8 : Fix parsing `g` tag just after `usemtl`(#138)
|
||||
// version 1.0.7 : Support multiple tex options(#126)
|
||||
@@ -53,12 +51,31 @@ THE SOFTWARE.
|
||||
|
||||
namespace tinyobj {
|
||||
|
||||
//
|
||||
// Please define `TINYOBJ_USE_CXX11` flag when you compile tinyobjloader with C++11 compiler.
|
||||
//
|
||||
#ifdef TINYOBJ_USE_CXX11
|
||||
#if defined(_MSC_VER)
|
||||
# if _MSC_VER < 1800
|
||||
# error This project needs at least Visual Studio 2013
|
||||
# endif
|
||||
#define tobj_null nullptr
|
||||
#elif __cplusplus <= 199711L
|
||||
# error This project can only be compiled with a compiler that supports C++11
|
||||
#else
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#if __has_warning("-Wzero-as-null-pointer-constant")
|
||||
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
|
||||
#define tobj_null nullptr
|
||||
|
||||
#endif
|
||||
#else // !TINYOBJ_USE_CXX11
|
||||
#define tobj_null NULL
|
||||
#endif
|
||||
|
||||
|
||||
// https://en.wikipedia.org/wiki/Wavefront_.obj_file says ...
|
||||
//
|
||||
@@ -227,10 +244,7 @@ typedef struct {
|
||||
// face. 3 = polygon, 4 = quad,
|
||||
// ... Up to 255.
|
||||
std::vector<int> material_ids; // per-face material ID
|
||||
std::vector<unsigned int> smoothing_group_ids; // per-face smoothing group
|
||||
// ID(0 = off. positive value
|
||||
// = group id)
|
||||
std::vector<tag_t> tags; // SubD tag
|
||||
std::vector<tag_t> tags; // SubD tag
|
||||
} mesh_t;
|
||||
|
||||
typedef struct {
|
||||
@@ -271,14 +285,14 @@ typedef struct callback_t_ {
|
||||
void (*object_cb)(void *user_data, const char *name);
|
||||
|
||||
callback_t_()
|
||||
: vertex_cb(NULL),
|
||||
normal_cb(NULL),
|
||||
texcoord_cb(NULL),
|
||||
index_cb(NULL),
|
||||
usemtl_cb(NULL),
|
||||
mtllib_cb(NULL),
|
||||
group_cb(NULL),
|
||||
object_cb(NULL) {}
|
||||
: vertex_cb(tobj_null),
|
||||
normal_cb(tobj_null),
|
||||
texcoord_cb(tobj_null),
|
||||
index_cb(tobj_null),
|
||||
usemtl_cb(tobj_null),
|
||||
mtllib_cb(tobj_null),
|
||||
group_cb(tobj_null),
|
||||
object_cb(tobj_null) {}
|
||||
} callback_t;
|
||||
|
||||
class MaterialReader {
|
||||
@@ -330,7 +344,7 @@ class MaterialStreamReader : public MaterialReader {
|
||||
/// or not.
|
||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
std::vector<material_t> *materials, std::string *err,
|
||||
const char *filename, const char *mtl_basedir = NULL,
|
||||
const char *filename, const char *mtl_basedir = tobj_null,
|
||||
bool triangulate = true);
|
||||
|
||||
/// Loads .obj from a file with custom user callback.
|
||||
@@ -340,9 +354,9 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
/// Returns warning and error message into `err`
|
||||
/// See `examples/callback_api/` for how to use this function.
|
||||
bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
||||
void *user_data = NULL,
|
||||
MaterialReader *readMatFn = NULL,
|
||||
std::string *err = NULL);
|
||||
void *user_data = tobj_null,
|
||||
MaterialReader *readMatFn = tobj_null,
|
||||
std::string *err = tobj_null);
|
||||
|
||||
/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve
|
||||
/// std::istream for materials.
|
||||
@@ -350,7 +364,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
||||
/// Returns warning and error message into `err`
|
||||
bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
std::vector<material_t> *materials, std::string *err,
|
||||
std::istream *inStream, MaterialReader *readMatFn = NULL,
|
||||
std::istream *inStream, MaterialReader *readMatFn = tobj_null,
|
||||
bool triangulate = true);
|
||||
|
||||
/// Loads materials into std::map
|
||||
@@ -360,6 +374,10 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
||||
|
||||
} // namespace tinyobj
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // TINY_OBJ_LOADER_H_
|
||||
|
||||
#ifdef TINYOBJLOADER_IMPLEMENTATION
|
||||
@@ -376,27 +394,23 @@ void LoadMtl(std::map<std::string, int> *material_map,
|
||||
|
||||
namespace tinyobj {
|
||||
|
||||
#ifdef TINYOBJ_USE_CXX11
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wc++98-compat"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MaterialReader::~MaterialReader() {}
|
||||
|
||||
struct vertex_index_t {
|
||||
struct vertex_index {
|
||||
int v_idx, vt_idx, vn_idx;
|
||||
vertex_index_t() : v_idx(-1), vt_idx(-1), vn_idx(-1) {}
|
||||
explicit vertex_index_t(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {}
|
||||
vertex_index_t(int vidx, int vtidx, int vnidx)
|
||||
vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {}
|
||||
explicit 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) {}
|
||||
};
|
||||
|
||||
// Internal data structure for face representation
|
||||
// index + smoothing group.
|
||||
struct face_t {
|
||||
unsigned int
|
||||
smoothing_group_id; // smoothing group id. 0 = smoothing groupd is off.
|
||||
int pad_;
|
||||
std::vector<vertex_index_t> vertex_indices; // face vertex indices.
|
||||
|
||||
face_t() : smoothing_group_id(0) {}
|
||||
};
|
||||
|
||||
struct tag_sizes {
|
||||
tag_sizes() : num_ints(0), num_reals(0), num_strings(0) {}
|
||||
int num_ints;
|
||||
@@ -684,12 +698,11 @@ static inline void parseV(real_t *x, real_t *y, real_t *z, real_t *w,
|
||||
}
|
||||
|
||||
// Extension: parse vertex with colors(6 items)
|
||||
static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z,
|
||||
real_t *r, real_t *g, real_t *b,
|
||||
const char **token,
|
||||
const double default_x = 0.0,
|
||||
const double default_y = 0.0,
|
||||
const double default_z = 0.0) {
|
||||
static inline bool parseVertexWithColor(real_t *x, real_t *y, real_t *z, real_t *r,
|
||||
real_t *g, real_t *b,
|
||||
const char **token, const double default_x = 0.0,
|
||||
const double default_y = 0.0,
|
||||
const double default_z = 0.0) {
|
||||
(*x) = parseReal(token, default_x);
|
||||
(*y) = parseReal(token, default_y);
|
||||
(*z) = parseReal(token, default_z);
|
||||
@@ -752,7 +765,7 @@ static tag_sizes parseTagTriple(const char **token) {
|
||||
return ts;
|
||||
}
|
||||
|
||||
(*token)++; // Skip '/'
|
||||
(*token)++; // Skip '/'
|
||||
|
||||
(*token) += strspn((*token), " \t");
|
||||
ts.num_reals = atoi((*token));
|
||||
@@ -760,7 +773,7 @@ static tag_sizes parseTagTriple(const char **token) {
|
||||
if ((*token)[0] != '/') {
|
||||
return ts;
|
||||
}
|
||||
(*token)++; // Skip '/'
|
||||
(*token)++; // Skip '/'
|
||||
|
||||
ts.num_strings = parseInt(token);
|
||||
|
||||
@@ -769,12 +782,12 @@ static tag_sizes parseTagTriple(const char **token) {
|
||||
|
||||
// Parse triples with index offsets: i, i/j/k, i//k, i/j
|
||||
static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
|
||||
vertex_index_t *ret) {
|
||||
vertex_index *ret) {
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vertex_index_t vi(-1);
|
||||
vertex_index vi(-1);
|
||||
|
||||
if (!fixIndex(atoi((*token)), vsize, &(vi.v_idx))) {
|
||||
return false;
|
||||
@@ -822,8 +835,8 @@ static bool parseTriple(const char **token, int vsize, int vnsize, int vtsize,
|
||||
}
|
||||
|
||||
// Parse raw triples: i, i/j/k, i//k, i/j
|
||||
static vertex_index_t parseRawTriple(const char **token) {
|
||||
vertex_index_t vi(static_cast<int>(0)); // 0 is an invalid index in OBJ
|
||||
static vertex_index parseRawTriple(const char **token) {
|
||||
vertex_index vi(static_cast<int>(0)); // 0 is an invalid index in OBJ
|
||||
|
||||
vi.v_idx = atoi((*token));
|
||||
(*token) += strcspn((*token), "/ \t\r");
|
||||
@@ -931,7 +944,7 @@ static bool ParseTextureNameAndOption(std::string *texname,
|
||||
token += 4;
|
||||
parseReal2(&(texopt->brightness), &(texopt->contrast), &token, 0.0, 1.0);
|
||||
} else {
|
||||
// Assume texture filename
|
||||
// Assume texture filename
|
||||
#if 0
|
||||
size_t len = strcspn(token, " \t\r"); // untile next space
|
||||
texture_name = std::string(token, token + len);
|
||||
@@ -995,255 +1008,60 @@ static void InitMaterial(material_t *material) {
|
||||
material->unknown_parameter.clear();
|
||||
}
|
||||
|
||||
// code from https://wrf.ecse.rpi.edu//Research/Short_Notes/pnpoly.html
|
||||
static int pnpoly(int nvert, float *vertx, float *verty, float testx,
|
||||
float testy) {
|
||||
int i, j, c = 0;
|
||||
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
|
||||
if (((verty[i] > testy) != (verty[j] > testy)) &&
|
||||
(testx <
|
||||
(vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) +
|
||||
vertx[i]))
|
||||
c = !c;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// TODO(syoyo): refactor function.
|
||||
static bool exportFaceGroupToShape(shape_t *shape,
|
||||
const std::vector<face_t> &faceGroup,
|
||||
const std::vector<tag_t> &tags,
|
||||
const int material_id,
|
||||
const std::string &name, bool triangulate,
|
||||
const std::vector<real_t> &v) {
|
||||
static bool exportFaceGroupToShape(
|
||||
shape_t *shape, const std::vector<std::vector<vertex_index> > &faceGroup,
|
||||
const std::vector<tag_t> &tags, const int material_id,
|
||||
const std::string &name, bool triangulate) {
|
||||
if (faceGroup.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flatten vertices and indices
|
||||
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||
const face_t &face = faceGroup[i];
|
||||
const std::vector<vertex_index> &face = faceGroup[i];
|
||||
|
||||
size_t npolys = face.vertex_indices.size();
|
||||
vertex_index i0 = face[0];
|
||||
vertex_index i1(-1);
|
||||
vertex_index i2 = face[1];
|
||||
|
||||
if (npolys < 3) {
|
||||
// ??? Invalid face definition.
|
||||
continue;
|
||||
}
|
||||
|
||||
vertex_index_t i0 = face.vertex_indices[0];
|
||||
vertex_index_t i1(-1);
|
||||
vertex_index_t i2 = face.vertex_indices[1];
|
||||
size_t npolys = face.size();
|
||||
|
||||
if (triangulate) {
|
||||
// find the two axes to work in
|
||||
size_t axes[2] = {1, 2};
|
||||
for (size_t k = 0; k < npolys; ++k) {
|
||||
i0 = face.vertex_indices[(k + 0) % npolys];
|
||||
i1 = face.vertex_indices[(k + 1) % npolys];
|
||||
i2 = face.vertex_indices[(k + 2) % npolys];
|
||||
size_t vi0 = size_t(i0.v_idx);
|
||||
size_t vi1 = size_t(i1.v_idx);
|
||||
size_t vi2 = size_t(i2.v_idx);
|
||||
// Polygon -> triangle fan conversion
|
||||
for (size_t k = 2; k < npolys; k++) {
|
||||
i1 = i2;
|
||||
i2 = face[k];
|
||||
|
||||
if (((3 * vi0 + 2) >= v.size()) ||
|
||||
((3 * vi1 + 2) >= v.size()) ||
|
||||
((3 * vi2 + 2) >= v.size())) {
|
||||
// Invalid triangle.
|
||||
// FIXME(syoyo): Is it ok to simply skip this invalid triangle?
|
||||
continue;
|
||||
}
|
||||
real_t v0x = v[vi0 * 3 + 0];
|
||||
real_t v0y = v[vi0 * 3 + 1];
|
||||
real_t v0z = v[vi0 * 3 + 2];
|
||||
real_t v1x = v[vi1 * 3 + 0];
|
||||
real_t v1y = v[vi1 * 3 + 1];
|
||||
real_t v1z = v[vi1 * 3 + 2];
|
||||
real_t v2x = v[vi2 * 3 + 0];
|
||||
real_t v2y = v[vi2 * 3 + 1];
|
||||
real_t v2z = v[vi2 * 3 + 2];
|
||||
real_t e0x = v1x - v0x;
|
||||
real_t e0y = v1y - v0y;
|
||||
real_t e0z = v1z - v0z;
|
||||
real_t e1x = v2x - v1x;
|
||||
real_t e1y = v2y - v1y;
|
||||
real_t e1z = v2z - v1z;
|
||||
float cx = std::fabs(e0y * e1z - e0z * e1y);
|
||||
float cy = std::fabs(e0z * e1x - e0x * e1z);
|
||||
float cz = std::fabs(e0x * e1y - e0y * e1x);
|
||||
const float epsilon = 0.0001f;
|
||||
if (cx > epsilon || cy > epsilon || cz > epsilon) {
|
||||
// found a corner
|
||||
if (cx > cy && cx > cz) {
|
||||
} else {
|
||||
axes[0] = 0;
|
||||
if (cz > cx && cz > cy) axes[1] = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
index_t idx0, idx1, idx2;
|
||||
idx0.vertex_index = i0.v_idx;
|
||||
idx0.normal_index = i0.vn_idx;
|
||||
idx0.texcoord_index = i0.vt_idx;
|
||||
idx1.vertex_index = i1.v_idx;
|
||||
idx1.normal_index = i1.vn_idx;
|
||||
idx1.texcoord_index = i1.vt_idx;
|
||||
idx2.vertex_index = i2.v_idx;
|
||||
idx2.normal_index = i2.vn_idx;
|
||||
idx2.texcoord_index = i2.vt_idx;
|
||||
|
||||
real_t area = 0;
|
||||
for (size_t k = 0; k < npolys; ++k) {
|
||||
i0 = face.vertex_indices[(k + 0) % npolys];
|
||||
i1 = face.vertex_indices[(k + 1) % npolys];
|
||||
size_t vi0 = size_t(i0.v_idx);
|
||||
size_t vi1 = size_t(i1.v_idx);
|
||||
if (((vi0 * 3 + axes[0]) >= v.size()) ||
|
||||
((vi0 * 3 + axes[1]) >= v.size()) ||
|
||||
((vi1 * 3 + axes[0]) >= v.size()) ||
|
||||
((vi1 * 3 + axes[1]) >= v.size())) {
|
||||
// Invalid index.
|
||||
continue;
|
||||
}
|
||||
real_t v0x = v[vi0 * 3 + axes[0]];
|
||||
real_t v0y = v[vi0 * 3 + axes[1]];
|
||||
real_t v1x = v[vi1 * 3 + axes[0]];
|
||||
real_t v1y = v[vi1 * 3 + axes[1]];
|
||||
area += (v0x * v1y - v0y * v1x) * 0.5f;
|
||||
}
|
||||
shape->mesh.indices.push_back(idx0);
|
||||
shape->mesh.indices.push_back(idx1);
|
||||
shape->mesh.indices.push_back(idx2);
|
||||
|
||||
int maxRounds =
|
||||
10; // arbitrary max loop count to protect against unexpected errors
|
||||
|
||||
face_t remainingFace = face; // copy
|
||||
size_t guess_vert = 0;
|
||||
vertex_index_t ind[3];
|
||||
real_t vx[3];
|
||||
real_t vy[3];
|
||||
while (remainingFace.vertex_indices.size() > 3 && maxRounds > 0) {
|
||||
npolys = remainingFace.vertex_indices.size();
|
||||
if (guess_vert >= npolys) {
|
||||
maxRounds -= 1;
|
||||
guess_vert -= npolys;
|
||||
}
|
||||
for (size_t k = 0; k < 3; k++) {
|
||||
ind[k] = remainingFace.vertex_indices[(guess_vert + k) % npolys];
|
||||
size_t vi = size_t(ind[k].v_idx);
|
||||
if (((vi * 3 + axes[0]) >= v.size()) ||
|
||||
((vi * 3 + axes[1]) >= v.size())) {
|
||||
// ???
|
||||
vx[k] = static_cast<real_t>(0.0);
|
||||
vy[k] = static_cast<real_t>(0.0);
|
||||
} else {
|
||||
vx[k] = v[vi * 3 + axes[0]];
|
||||
vy[k] = v[vi * 3 + axes[1]];
|
||||
}
|
||||
}
|
||||
real_t e0x = vx[1] - vx[0];
|
||||
real_t e0y = vy[1] - vy[0];
|
||||
real_t e1x = vx[2] - vx[1];
|
||||
real_t e1y = vy[2] - vy[1];
|
||||
real_t cross = e0x * e1y - e0y * e1x;
|
||||
// if an internal angle
|
||||
if (cross * area < 0.0f) {
|
||||
guess_vert += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check all other verts in case they are inside this triangle
|
||||
bool overlap = false;
|
||||
for (size_t otherVert = 3; otherVert < npolys; ++otherVert) {
|
||||
size_t idx = (guess_vert + otherVert) % npolys;
|
||||
|
||||
if (idx >= remainingFace.vertex_indices.size()) {
|
||||
// ???
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t ovi = size_t(
|
||||
remainingFace.vertex_indices[idx]
|
||||
.v_idx);
|
||||
|
||||
if (((ovi * 3 + axes[0]) >= v.size()) ||
|
||||
((ovi * 3 + axes[1]) >= v.size())) {
|
||||
// ???
|
||||
continue;
|
||||
}
|
||||
real_t tx = v[ovi * 3 + axes[0]];
|
||||
real_t ty = v[ovi * 3 + axes[1]];
|
||||
if (pnpoly(3, vx, vy, tx, ty)) {
|
||||
overlap = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (overlap) {
|
||||
guess_vert += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// this triangle is an ear
|
||||
{
|
||||
index_t idx0, idx1, idx2;
|
||||
idx0.vertex_index = ind[0].v_idx;
|
||||
idx0.normal_index = ind[0].vn_idx;
|
||||
idx0.texcoord_index = ind[0].vt_idx;
|
||||
idx1.vertex_index = ind[1].v_idx;
|
||||
idx1.normal_index = ind[1].vn_idx;
|
||||
idx1.texcoord_index = ind[1].vt_idx;
|
||||
idx2.vertex_index = ind[2].v_idx;
|
||||
idx2.normal_index = ind[2].vn_idx;
|
||||
idx2.texcoord_index = ind[2].vt_idx;
|
||||
|
||||
shape->mesh.indices.push_back(idx0);
|
||||
shape->mesh.indices.push_back(idx1);
|
||||
shape->mesh.indices.push_back(idx2);
|
||||
|
||||
shape->mesh.num_face_vertices.push_back(3);
|
||||
shape->mesh.material_ids.push_back(material_id);
|
||||
shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id);
|
||||
}
|
||||
|
||||
// remove v1 from the list
|
||||
size_t removed_vert_index = (guess_vert + 1) % npolys;
|
||||
while (removed_vert_index + 1 < npolys) {
|
||||
remainingFace.vertex_indices[removed_vert_index] =
|
||||
remainingFace.vertex_indices[removed_vert_index + 1];
|
||||
removed_vert_index += 1;
|
||||
}
|
||||
remainingFace.vertex_indices.pop_back();
|
||||
}
|
||||
|
||||
if (remainingFace.vertex_indices.size() == 3) {
|
||||
i0 = remainingFace.vertex_indices[0];
|
||||
i1 = remainingFace.vertex_indices[1];
|
||||
i2 = remainingFace.vertex_indices[2];
|
||||
{
|
||||
index_t idx0, idx1, idx2;
|
||||
idx0.vertex_index = i0.v_idx;
|
||||
idx0.normal_index = i0.vn_idx;
|
||||
idx0.texcoord_index = i0.vt_idx;
|
||||
idx1.vertex_index = i1.v_idx;
|
||||
idx1.normal_index = i1.vn_idx;
|
||||
idx1.texcoord_index = i1.vt_idx;
|
||||
idx2.vertex_index = i2.v_idx;
|
||||
idx2.normal_index = i2.vn_idx;
|
||||
idx2.texcoord_index = i2.vt_idx;
|
||||
|
||||
shape->mesh.indices.push_back(idx0);
|
||||
shape->mesh.indices.push_back(idx1);
|
||||
shape->mesh.indices.push_back(idx2);
|
||||
|
||||
shape->mesh.num_face_vertices.push_back(3);
|
||||
shape->mesh.material_ids.push_back(material_id);
|
||||
shape->mesh.smoothing_group_ids.push_back(face.smoothing_group_id);
|
||||
}
|
||||
shape->mesh.num_face_vertices.push_back(3);
|
||||
shape->mesh.material_ids.push_back(material_id);
|
||||
}
|
||||
} else {
|
||||
for (size_t k = 0; k < npolys; k++) {
|
||||
index_t idx;
|
||||
idx.vertex_index = face.vertex_indices[k].v_idx;
|
||||
idx.normal_index = face.vertex_indices[k].vn_idx;
|
||||
idx.texcoord_index = face.vertex_indices[k].vt_idx;
|
||||
idx.vertex_index = face[k].v_idx;
|
||||
idx.normal_index = face[k].vn_idx;
|
||||
idx.texcoord_index = face[k].vt_idx;
|
||||
shape->mesh.indices.push_back(idx);
|
||||
}
|
||||
|
||||
shape->mesh.num_face_vertices.push_back(
|
||||
static_cast<unsigned char>(npolys));
|
||||
shape->mesh.material_ids.push_back(material_id); // per face
|
||||
shape->mesh.smoothing_group_ids.push_back(
|
||||
face.smoothing_group_id); // per face
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1752,17 +1570,13 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
std::vector<real_t> vt;
|
||||
std::vector<real_t> vc;
|
||||
std::vector<tag_t> tags;
|
||||
std::vector<face_t> faceGroup;
|
||||
std::vector<std::vector<vertex_index> > faceGroup;
|
||||
std::string name;
|
||||
|
||||
// material
|
||||
std::map<std::string, int> material_map;
|
||||
int material = -1;
|
||||
|
||||
// smoothing group id
|
||||
unsigned int current_smoothing_id =
|
||||
0; // Initial value. 0 means no smoothing.
|
||||
|
||||
shape_t shape;
|
||||
|
||||
std::string linebuf;
|
||||
@@ -1835,13 +1649,11 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
token += 2;
|
||||
token += strspn(token, " \t");
|
||||
|
||||
face_t face;
|
||||
|
||||
face.smoothing_group_id = current_smoothing_id;
|
||||
face.vertex_indices.reserve(3);
|
||||
std::vector<vertex_index> face;
|
||||
face.reserve(3);
|
||||
|
||||
while (!IS_NEW_LINE(token[0])) {
|
||||
vertex_index_t vi;
|
||||
vertex_index vi;
|
||||
if (!parseTriple(&token, static_cast<int>(v.size() / 3),
|
||||
static_cast<int>(vn.size() / 3),
|
||||
static_cast<int>(vt.size() / 2), &vi)) {
|
||||
@@ -1851,13 +1663,14 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
return false;
|
||||
}
|
||||
|
||||
face.vertex_indices.push_back(vi);
|
||||
face.push_back(vi);
|
||||
size_t n = strspn(token, " \t\r");
|
||||
token += n;
|
||||
}
|
||||
|
||||
// replace with emplace_back + std::move on C++11
|
||||
faceGroup.push_back(face);
|
||||
faceGroup.push_back(std::vector<vertex_index>());
|
||||
faceGroup[faceGroup.size() - 1].swap(face);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -1881,7 +1694,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
// this time.
|
||||
// just clear `faceGroup` after `exportFaceGroupToShape()` call.
|
||||
exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
||||
triangulate, v);
|
||||
triangulate);
|
||||
faceGroup.clear();
|
||||
material = newMaterialId;
|
||||
}
|
||||
@@ -1936,7 +1749,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
if (token[0] == 'g' && IS_SPACE((token[1]))) {
|
||||
// flush previous face group.
|
||||
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
||||
triangulate, v);
|
||||
triangulate);
|
||||
(void)ret; // return value not used.
|
||||
|
||||
if (shape.mesh.indices.size() > 0) {
|
||||
@@ -1973,7 +1786,7 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
if (token[0] == 'o' && IS_SPACE((token[1]))) {
|
||||
// flush previous face group.
|
||||
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
||||
triangulate, v);
|
||||
triangulate);
|
||||
if (ret) {
|
||||
shapes->push_back(shape);
|
||||
}
|
||||
@@ -1992,7 +1805,6 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
}
|
||||
|
||||
if (token[0] == 't' && IS_SPACE(token[1])) {
|
||||
const int max_tag_nums = 8192; // FIXME(syoyo): Parameterize.
|
||||
tag_t tag;
|
||||
|
||||
token += 2;
|
||||
@@ -2001,27 +1813,6 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
|
||||
tag_sizes ts = parseTagTriple(&token);
|
||||
|
||||
if (ts.num_ints < 0) {
|
||||
ts.num_ints = 0;
|
||||
}
|
||||
if (ts.num_ints > max_tag_nums) {
|
||||
ts.num_ints = max_tag_nums;
|
||||
}
|
||||
|
||||
if (ts.num_reals < 0) {
|
||||
ts.num_reals = 0;
|
||||
}
|
||||
if (ts.num_reals > max_tag_nums) {
|
||||
ts.num_reals = max_tag_nums;
|
||||
}
|
||||
|
||||
if (ts.num_strings < 0) {
|
||||
ts.num_strings = 0;
|
||||
}
|
||||
if (ts.num_strings > max_tag_nums) {
|
||||
ts.num_strings = max_tag_nums;
|
||||
}
|
||||
|
||||
tag.intValues.resize(static_cast<size_t>(ts.num_ints));
|
||||
|
||||
for (size_t i = 0; i < static_cast<size_t>(ts.num_ints); ++i) {
|
||||
@@ -2039,49 +1830,13 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
|
||||
}
|
||||
|
||||
tags.push_back(tag);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token[0] == 's' && IS_SPACE(token[1])) {
|
||||
// smoothing group id
|
||||
token += 2;
|
||||
|
||||
// skip space.
|
||||
token += strspn(token, " \t"); // skip space
|
||||
|
||||
if (token[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token[0] == '\r' || token[1] == '\n') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(token) >= 3) {
|
||||
if (token[0] == 'o' && token[1] == 'f' && token[2] == 'f') {
|
||||
current_smoothing_id = 0;
|
||||
}
|
||||
} else {
|
||||
// assume number
|
||||
int smGroupId = parseInt(&token);
|
||||
if (smGroupId < 0) {
|
||||
// parse error. force set to 0.
|
||||
// FIXME(syoyo): Report warning.
|
||||
current_smoothing_id = 0;
|
||||
} else {
|
||||
current_smoothing_id = static_cast<unsigned int>(smGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
} // smoothing group id
|
||||
|
||||
// Ignore unknown command.
|
||||
}
|
||||
|
||||
bool ret = exportFaceGroupToShape(&shape, faceGroup, tags, material, name,
|
||||
triangulate, v);
|
||||
triangulate);
|
||||
// exportFaceGroupToShape return false when `usemtl` is called in the last
|
||||
// line.
|
||||
// we also add `shape` to `shapes` when `shape.mesh` has already some
|
||||
@@ -2189,7 +1944,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
||||
|
||||
indices.clear();
|
||||
while (!IS_NEW_LINE(token[0])) {
|
||||
vertex_index_t vi = parseRawTriple(&token);
|
||||
vertex_index vi = parseRawTriple(&token);
|
||||
|
||||
index_t idx;
|
||||
idx.vertex_index = vi.v_idx;
|
||||
@@ -2312,7 +2067,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
||||
static_cast<int>(names_out.size()));
|
||||
|
||||
} else {
|
||||
callback.group_cb(user_data, NULL, 0);
|
||||
callback.group_cb(user_data, tobj_null, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2386,6 +2141,7 @@ bool LoadObjWithCallback(std::istream &inStream, const callback_t &callback,
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
} // namespace tinyobj
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user