diff --git a/xs/src/admesh/connect.c b/xs/src/admesh/connect.c index 56ebfa144..e9129d007 100644 --- a/xs/src/admesh/connect.c +++ b/xs/src/admesh/connect.c @@ -82,6 +82,16 @@ stl_check_facets_exact(stl_file *stl) { for(i = 0; i < stl->stats.number_of_facets; i++) { facet = stl->facet_start[i]; + // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. + // When using a memcmp on raw floats, those numbers report to be different. + // Unify all +0 and -0 to +0 to make the floats equal under memcmp. + { + uint32_t *f = (uint32_t*)&facet; + for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats + if (*f == 0x80000000) + // Negative zero, switch to positive zero. + *f = 0; + } /* If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. */ if( !memcmp(&facet.vertex[0], &facet.vertex[1], @@ -278,6 +288,16 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) { for(i = 0; i < stl->stats.number_of_facets; i++) { facet = stl->facet_start[i]; + // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. + // When using a memcmp on raw floats, those numbers report to be different. + // Unify all +0 and -0 to +0 to make the floats equal under memcmp. + { + uint32_t *f = (uint32_t*)&facet; + for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats + if (*f == 0x80000000) + // Negative zero, switch to positive zero. + *f = 0; + } for(j = 0; j < 3; j++) { if(stl->neighbors_start[i].neighbor[j] == -1) { edge[j].facet_number = i; diff --git a/xs/src/admesh/stl.h b/xs/src/admesh/stl.h index 7871c0351..99fc61eed 100644 --- a/xs/src/admesh/stl.h +++ b/xs/src/admesh/stl.h @@ -197,6 +197,7 @@ extern void stl_rotate_z(stl_file *stl, float angle); extern void stl_mirror_xy(stl_file *stl); extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); +extern void stl_transform(stl_file *stl, float *trafo3x4); extern void stl_open_merge(stl_file *stl, char *file); extern void stl_invalidate_shared_vertices(stl_file *stl); extern void stl_generate_shared_vertices(stl_file *stl); diff --git a/xs/src/admesh/stlinit.c b/xs/src/admesh/stlinit.c index d7a436665..54f5b836c 100644 --- a/xs/src/admesh/stlinit.c +++ b/xs/src/admesh/stlinit.c @@ -318,29 +318,6 @@ stl_read(stl_file *stl, int first_facet, int first) { } #endif -#if 1 - { - // Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. - // When using a memcmp on raw floats, those numbers report to be different. - // Unify all +0 and -0 to +0 to make the floats equal under memcmp. - uint32_t *f = (uint32_t*)&facet; - int j; - for (j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f == 0x80000000) - // Negative zero, switch to positive zero. - *f = 0; - } -#else - { - // Due to the nature of the floating point numbers, close to zero values may be represented with singificantly higher precision - // than the rest of the vertices. Round them to zero. - float *f = (float*)&facet; - for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats - if (*f > -1e-12f && *f < 1e-12f) - // Negative zero, switch to positive zero. - *f = 0; - } -#endif /* Write the facet into memory. */ memcpy(stl->facet_start+i, &facet, SIZEOF_STL_FACET); stl_facet_stats(stl, facet, first); diff --git a/xs/src/admesh/util.c b/xs/src/admesh/util.c index 0ee6b209c..a786240ad 100644 --- a/xs/src/admesh/util.c +++ b/xs/src/admesh/util.c @@ -185,6 +185,24 @@ void calculate_normals(stl_file *stl) { } } +void stl_transform(stl_file *stl, float *trafo3x4) { + int i_face, i_vertex, i, j; + if (stl->error) + return; + for (i_face = 0; i_face < stl->stats.number_of_facets; ++ i_face) { + stl_vertex *vertices = stl->facet_start[i_face].vertex; + for (i_vertex = 0; i_vertex < 3; ++ i_vertex) { + stl_vertex &v_dst = vertices[i_vertex]; + stl_vertex v_src = v_dst; + v_dst.x = trafo3x4[0] * v_src.x + trafo3x4[1] * v_src.y + trafo3x4[2] * v_src.z + trafo3x4[3]; + v_dst.y = trafo3x4[4] * v_src.x + trafo3x4[5] * v_src.y + trafo3x4[6] * v_src.z + trafo3x4[7]; + v_dst.z = trafo3x4[8] * v_src.x + trafo3x4[9] * v_src.y + trafo3x4[10] * v_src.z + trafo3x4[11]; + } + } + stl_get_size(stl); + calculate_normals(stl); +} + void stl_rotate_x(stl_file *stl, float angle) { int i;