Fixing "opening an obj file causes Slic3r to become stuck and use 100% on one core" #221

Extended the OBJ parser to triangulate quads. Higher order polygons are not supported though.
This commit is contained in:
bubnikv 2017-04-03 10:05:22 +02:00
parent 8ac1d37b10
commit 1719952f49
2 changed files with 56 additions and 11 deletions

View file

@ -26,38 +26,83 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
// Count the faces and verify, that all faces are triangular.
size_t num_faces = 0;
size_t num_quads = 0;
for (size_t i = 0; i < data.vertices.size(); ) {
size_t j = i;
for (; j < data.vertices.size() && data.vertices[j].coordIdx != -1; ++ j) ;
if (i == j)
continue;
if (j - i != 3) {
// Non-triangular faces are not supported as of now.
size_t face_vertices = j - i;
if (face_vertices != 3 && face_vertices != 4) {
// Non-triangular and non-quad faces are not supported as of now.
return false;
}
num_faces ++;
i = j;
if (face_vertices == 4)
++ num_quads;
++ num_faces;
i = j + 1;
}
// Convert ObjData into STL.
TriangleMesh mesh;
stl_file &stl = mesh.stl;
stl.stats.type = inmemory;
stl.stats.number_of_facets = num_faces;
stl.stats.original_num_facets = num_faces;
stl.stats.number_of_facets = int(num_faces + num_quads);
stl.stats.original_num_facets = int(num_faces + num_quads);
// stl_allocate clears all the allocated data to zero, all normals are set to zeros as well.
stl_allocate(&stl);
size_t i_face = 0;
for (size_t i = 0; i < data.vertices.size(); ++ i) {
if (data.vertices[i].coordIdx == -1)
continue;
stl_facet &facet = stl.facet_start[i_face ++];
size_t num_normals = 0;
stl_normal normal = { 0.f };
for (unsigned int v = 0; v < 3; ++ v) {
const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
if (vertex.normalIdx != -1)
memcpy(&facet.normal.x, &data.normals[vertex.normalIdx*3], 3 * sizeof(float));
if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2];
++ num_normals;
}
}
}
if (data.vertices[i].coordIdx != -1) {
// This is a quad. Produce the other triangle.
stl_facet &facet2 = stl.facet_start[i_face++];
facet2.vertex[0] = facet.vertex[0];
facet2.vertex[1] = facet.vertex[2];
const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet2.vertex[2].x, &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float));
if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2];
++ num_normals;
}
if (num_normals == 4) {
// Normalize an average normal of a quad.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z);
if (len > EPSILON) {
normal.x /= len;
normal.y /= len;
normal.z /= len;
facet.normal = normal;
facet2.normal = normal;
}
}
} else if (num_normals == 3) {
// Normalize an average normal of a triangle.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z);
if (len > EPSILON) {
normal.x /= len;
normal.y /= len;
normal.z /= len;
facet.normal = normal;
}
}
}
stl_get_size(&stl);
mesh.repair();
if (mesh.facets_count() == 0) {

View file

@ -346,8 +346,8 @@ bool objparse(const char *path, ObjData &data)
}
::fclose(pFile);
printf("vertices: %d\r\n", data.vertices.size() / 4);
printf("coords: %d\r\n", data.coordinates.size());
// printf("vertices: %d\r\n", data.vertices.size() / 4);
// printf("coords: %d\r\n", data.coordinates.size());
return true;
}