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:
parent
8ac1d37b10
commit
1719952f49
2 changed files with 56 additions and 11 deletions
|
@ -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.
|
// Count the faces and verify, that all faces are triangular.
|
||||||
size_t num_faces = 0;
|
size_t num_faces = 0;
|
||||||
|
size_t num_quads = 0;
|
||||||
for (size_t i = 0; i < data.vertices.size(); ) {
|
for (size_t i = 0; i < data.vertices.size(); ) {
|
||||||
size_t j = i;
|
size_t j = i;
|
||||||
for (; j < data.vertices.size() && data.vertices[j].coordIdx != -1; ++ j) ;
|
for (; j < data.vertices.size() && data.vertices[j].coordIdx != -1; ++ j) ;
|
||||||
if (i == j)
|
if (i == j)
|
||||||
continue;
|
continue;
|
||||||
if (j - i != 3) {
|
size_t face_vertices = j - i;
|
||||||
// Non-triangular faces are not supported as of now.
|
if (face_vertices != 3 && face_vertices != 4) {
|
||||||
|
// Non-triangular and non-quad faces are not supported as of now.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
num_faces ++;
|
if (face_vertices == 4)
|
||||||
i = j;
|
++ num_quads;
|
||||||
|
++ num_faces;
|
||||||
|
i = j + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert ObjData into STL.
|
// Convert ObjData into STL.
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
stl_file &stl = mesh.stl;
|
stl_file &stl = mesh.stl;
|
||||||
stl.stats.type = inmemory;
|
stl.stats.type = inmemory;
|
||||||
stl.stats.number_of_facets = num_faces;
|
stl.stats.number_of_facets = int(num_faces + num_quads);
|
||||||
stl.stats.original_num_facets = num_faces;
|
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);
|
stl_allocate(&stl);
|
||||||
size_t i_face = 0;
|
size_t i_face = 0;
|
||||||
for (size_t i = 0; i < data.vertices.size(); ++ i) {
|
for (size_t i = 0; i < data.vertices.size(); ++ i) {
|
||||||
if (data.vertices[i].coordIdx == -1)
|
if (data.vertices[i].coordIdx == -1)
|
||||||
continue;
|
continue;
|
||||||
stl_facet &facet = stl.facet_start[i_face ++];
|
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) {
|
for (unsigned int v = 0; v < 3; ++ v) {
|
||||||
const ObjParser::ObjVertex &vertex = data.vertices[i++];
|
const ObjParser::ObjVertex &vertex = data.vertices[i++];
|
||||||
memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
|
memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
|
||||||
if (vertex.normalIdx != -1)
|
if (vertex.normalIdx != -1) {
|
||||||
memcpy(&facet.normal.x, &data.normals[vertex.normalIdx*3], 3 * sizeof(float));
|
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);
|
stl_get_size(&stl);
|
||||||
mesh.repair();
|
mesh.repair();
|
||||||
if (mesh.facets_count() == 0) {
|
if (mesh.facets_count() == 0) {
|
||||||
|
|
|
@ -346,8 +346,8 @@ bool objparse(const char *path, ObjData &data)
|
||||||
}
|
}
|
||||||
::fclose(pFile);
|
::fclose(pFile);
|
||||||
|
|
||||||
printf("vertices: %d\r\n", data.vertices.size() / 4);
|
// printf("vertices: %d\r\n", data.vertices.size() / 4);
|
||||||
printf("coords: %d\r\n", data.coordinates.size());
|
// printf("coords: %d\r\n", data.coordinates.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue