Fix OBJ with multiple volumes

This commit is contained in:
Maxime Gimeno 2020-06-12 11:32:36 +02:00
parent ff63531c3d
commit ce86d3de12
2 changed files with 34 additions and 7 deletions

View File

@ -374,7 +374,7 @@ void test_bgl_OBJ(const std::string filename)
std::ifstream is(filename); std::ifstream is(filename);
bool ok = CGAL::read_OBJ(is, fg); bool ok = CGAL::read_OBJ(is, fg);
assert(ok); assert(ok);
assert(filename != "data/sphere.obj" || (num_vertices(fg) == 162 && num_faces(fg) == 320)); assert(filename != "data/sphere.obj" || (num_vertices(fg) == 324 && num_faces(fg) == 640));
// write with OBJ // write with OBJ
{ {
@ -404,7 +404,7 @@ void test_bgl_OBJ(const std::string filename)
clear(fg); clear(fg);
ok = CGAL::read_OBJ("data/sphere.obj", fg); ok = CGAL::read_OBJ("data/sphere.obj", fg);
assert(ok); assert(ok);
assert(num_vertices(fg) == 162 && num_faces(fg) == 320); assert(num_vertices(fg) == 324 && num_faces(fg) == 640);
// write with OBJ // write with OBJ
{ {

View File

@ -56,11 +56,13 @@ bool read_OBJ(std::istream& is,
set_ascii_mode(is); // obj is ASCII only set_ascii_mode(is); // obj is ASCII only
int mini(1), maxi(-1); int mini(1), maxi(-1);
bool first_o = true;
std::string s; std::string s;
Point p; Point p;
std::string line; std::string line;
bool tex_found(false), norm_found(false); bool tex_found(false), norm_found(false);
std::size_t offset_idx=0;
while(getline(is, line)) while(getline(is, line))
{ {
if(line.empty()) if(line.empty())
@ -69,6 +71,32 @@ bool read_OBJ(std::istream& is,
std::istringstream iss(line); std::istringstream iss(line);
if(!(iss >> s)) if(!(iss >> s))
continue; // can't read anything on the line, whitespace only? continue; // can't read anything on the line, whitespace only?
if(s == "o")
{
if(!first_o)
{
if(maxi == offset_idx -1 && mini == offset_idx + 1)
{
if(verbose)
std::cerr << "No face detected." << std::endl;
return false;
}
if(maxi > static_cast<int>(points.size()-offset_idx) || mini < -static_cast<int>(points.size()-offset_idx))
{
if(verbose)
std::cerr << "a face index is invalid " << std::endl;
return false;
}
mini = 1;
maxi = -1;
}
else
{
first_o = false;
}
offset_idx = points.size();
}
if(s == "v") if(s == "v")
{ {
@ -97,13 +125,13 @@ bool read_OBJ(std::istream& is,
{ {
if(i < 1) if(i < 1)
{ {
faces.back().push_back(points.size() + i); // negative indices are relative references faces.back().push_back(points.size()+offset_idx + i); // negative indices are relative references
if(i < mini) if(i < mini)
mini = i; mini = i;
} }
else else
{ {
faces.back().push_back(i-1); faces.back().push_back(i+offset_idx-1);
if(i-1 > maxi) if(i-1 > maxi)
maxi = i-1; maxi = i-1;
} }
@ -126,15 +154,14 @@ bool read_OBJ(std::istream& is,
std::cout<<"WARNING: normals were found in this file, but were discarded."<<std::endl; std::cout<<"WARNING: normals were found in this file, but were discarded."<<std::endl;
if(tex_found && verbose) if(tex_found && verbose)
std::cout<<"WARNING: textures were found in this file, but were discarded."<<std::endl; std::cout<<"WARNING: textures were found in this file, but were discarded."<<std::endl;
if(maxi == offset_idx -1 && mini == offset_idx + 1)
if(maxi == -1 && mini == 1)
{ {
if(verbose) if(verbose)
std::cerr << "No face detected." << std::endl; std::cerr << "No face detected." << std::endl;
return false; return false;
} }
if(maxi > static_cast<int>(points.size()) || mini < -static_cast<int>(points.size())) if(maxi > static_cast<int>(points.size()-offset_idx) || mini < -static_cast<int>(points.size()-offset_idx))
{ {
if(verbose) if(verbose)
std::cerr << "a face index is invalid " << std::endl; std::cerr << "a face index is invalid " << std::endl;