admesh refactoring: separation of the shared vertices / indices

into an indexed_triangle_set structure
This commit is contained in:
bubnikv 2019-06-10 18:30:54 +02:00
parent 65238a89b1
commit 6defabea53
11 changed files with 154 additions and 162 deletions

View file

@ -29,19 +29,13 @@
#include "stl.h"
void stl_invalidate_shared_vertices(stl_file *stl)
{
stl->v_indices.clear();
stl->v_shared.clear();
}
void stl_generate_shared_vertices(stl_file *stl)
void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
{
// 3 indices to vertex per face
stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct());
its.indices.assign(stl->stats.number_of_facets, v_indices_struct());
// Shared vertices (3D coordinates)
stl->v_shared.clear();
stl->v_shared.reserve(stl->stats.number_of_facets / 2);
its.vertices.clear();
its.vertices.reserve(stl->stats.number_of_facets / 2);
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
@ -51,11 +45,11 @@ void stl_generate_shared_vertices(stl_file *stl)
for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
for (int j = 0; j < 3; ++ j) {
if (stl->v_indices[facet_idx].vertex[j] != -1)
if (its.indices[facet_idx].vertex[j] != -1)
// Shared vertex was already assigned.
continue;
// Create a new shared vertex.
stl->v_shared.emplace_back(stl->facet_start[facet_idx].vertex[j]);
its.vertices.emplace_back(stl->facet_start[facet_idx].vertex[j]);
// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
int facet_in_fan_idx = facet_idx;
bool edge_direction = false;
@ -89,7 +83,7 @@ void stl_generate_shared_vertices(stl_file *stl)
next_edge = pivot_vertex;
}
}
stl->v_indices[facet_in_fan_idx].vertex[pivot_vertex] = stl->v_shared.size() - 1;
its.indices[facet_in_fan_idx].vertex[pivot_vertex] = its.vertices.size() - 1;
fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
@ -130,7 +124,7 @@ void stl_generate_shared_vertices(stl_file *stl)
}
}
bool stl_write_off(stl_file *stl, const char *file)
bool its_write_off(const indexed_triangle_set &its, const char *file)
{
/* Open the file */
FILE *fp = boost::nowide::fopen(file, "w");
@ -143,16 +137,16 @@ bool stl_write_off(stl_file *stl, const char *file)
}
fprintf(fp, "OFF\n");
fprintf(fp, "%d %d 0\n", stl->v_shared.size(), stl->stats.number_of_facets);
for (int i = 0; i < stl->v_shared.size(); ++ i)
fprintf(fp, "\t%f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
fprintf(fp, "%d %d 0\n", (int)its.vertices.size(), (int)its.indices.size());
for (int i = 0; i < its.vertices.size(); ++ i)
fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
for (uint32_t i = 0; i < its.indices.size(); ++ i)
fprintf(fp, "\t3 %d %d %d\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
fclose(fp);
return true;
}
bool stl_write_vrml(stl_file *stl, const char *file)
bool its_write_vrml(const indexed_triangle_set &its, const char *file)
{
/* Open the file */
FILE *fp = boost::nowide::fopen(file, "w");
@ -180,16 +174,16 @@ bool stl_write_vrml(stl_file *stl, const char *file)
fprintf(fp, "\t\t\tpoint [\n");
int i = 0;
for (; i + 1 < stl->v_shared.size(); ++ i)
fprintf(fp, "\t\t\t\t%f %f %f,\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
fprintf(fp, "\t\t\t\t%f %f %f]\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
for (; i + 1 < its.vertices.size(); ++ i)
fprintf(fp, "\t\t\t\t%f %f %f,\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
fprintf(fp, "\t\t\t\t%f %f %f]\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
fprintf(fp, "\t\t}\n");
fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
fprintf(fp, "\t\t\tcoordIndex [\n");
for (int i = 0; i + 1 < (int)stl->stats.number_of_facets; ++ i)
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
for (size_t i = 0; i + 1 < its.indices.size(); ++ i)
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
fprintf(fp, "\t\t}\n");
fprintf(fp, "\t}\n");
fprintf(fp, "}\n");
@ -197,7 +191,7 @@ bool stl_write_vrml(stl_file *stl, const char *file)
return true;
}
bool stl_write_obj(stl_file *stl, const char *file)
bool its_write_obj(const indexed_triangle_set &its, const char *file)
{
FILE *fp = boost::nowide::fopen(file, "w");
@ -209,10 +203,65 @@ bool stl_write_obj(stl_file *stl, const char *file)
return false;
}
for (size_t i = 0; i < stl->v_shared.size(); ++ i)
fprintf(fp, "v %f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1);
for (size_t i = 0; i < its.vertices.size(); ++ i)
fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
for (size_t i = 0; i < its.indices.size(); ++ i)
fprintf(fp, "f %d %d %d\n", its.indices[i].vertex[0]+1, its.indices[i].vertex[1]+1, its.indices[i].vertex[2]+1);
fclose(fp);
return true;
}
// Check validity of the mesh, assert on error.
bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
{
assert(! stl->facet_start.empty());
assert(stl->facet_start.size() == stl->stats.number_of_facets);
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
assert(stl->facet_start.size() == stl->neighbors_start.size());
assert(! stl->neighbors_start.empty());
assert((its.indices.empty()) == (its.vertices.empty()));
assert(stl->stats.number_of_facets > 0);
assert(its.vertices.empty() || its.indices.size() == stl->stats.number_of_facets);
#ifdef _DEBUG
// Verify validity of neighborship data.
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
const int *vertices = (its.indices.empty()) ? nullptr : its.indices[facet_idx].vertex;
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
assert(nbr_face < (int)stl->stats.number_of_facets);
if (nbr_face != -1) {
int nbr_vnot = nbr.which_vertex_not[nbr_idx];
assert(nbr_vnot >= 0 && nbr_vnot < 6);
// Neighbor of the neighbor is the original face.
assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx);
int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3];
assert(vnot_back >= 0 && vnot_back < 6);
assert((nbr_vnot < 3) == (vnot_back < 3));
assert(vnot_back % 3 == (nbr_idx + 2) % 3);
if (vertices != nullptr) {
// Has shared vertices.
if (nbr_vnot < 3) {
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
assert((its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
} else {
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
assert((its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
}
}
}
}
}
#endif /* _DEBUG */
return true;
}
// Check validity of the mesh, assert on error.
bool stl_validate(const stl_file *stl)
{
indexed_triangle_set its;
return stl_validate(stl, its);
}