X-Git-Url: https://harrygodden.com/git/?a=blobdiff_plain;f=cxr%2Fcxr.h;h=dd7a8b83092dffc3612042b87aba4216abe6b54f;hb=2ed5781b6391a9bb28c94ee83b9bbafd918a356c;hp=518d197695dc37ac8d5d9085a5201d315eec578a;hpb=9a92cec0e25c758d12c535bb737be598f053b56d;p=convexer.git diff --git a/cxr/cxr.h b/cxr/cxr.h index 518d197..dd7a8b8 100644 --- a/cxr/cxr.h +++ b/cxr/cxr.h @@ -146,7 +146,7 @@ struct cxr_static_mesh struct cxr_edge { i32 i0, i1; - i32 freestyle; + i32 freestyle, sharp; } *edges; @@ -278,7 +278,8 @@ enum cxr_soliderr k_soliderr_no_solids, k_soliderr_degenerate_implicit, k_soliderr_non_coplanar_vertices, - k_soliderr_non_convex_poly + k_soliderr_non_convex_poly, + k_soliderr_bad_result }; /* @@ -516,10 +517,11 @@ CXR_API void cxr_write_test_data( cxr_static_mesh *src ) fprintf( fp, "cxr_edge test_edges[] = {\n" ); for( int i=0; iedge_count; i++ ) { - fprintf( fp, " {%d, %d, %d},\n", + fprintf( fp, " {%d, %d, %d, %d},\n", src->edges[i].i0, src->edges[i].i1, - src->edges[i].freestyle + src->edges[i].freestyle, + src->edges[i].sharp ); } fprintf( fp, "};\n" ); @@ -621,10 +623,12 @@ static void cxr_mesh_clean_edges( cxr_mesh *mesh ) { cxr_edge *orig_edge = &mesh->edges[ orig_edge_id ]; edge.freestyle = orig_edge->freestyle; + edge.sharp = orig_edge->sharp; } else { edge.freestyle = 0; + edge.sharp = 0; } cxr_ab_push( &new_edges, &edge ); @@ -711,9 +715,15 @@ static int cxr_mesh_link_loops( cxr_mesh *mesh ) if( *edge == -1 ) { *edge = i; - break; + goto next; } } + + /* Overflowed edge mapping... Duplicated faces. */ + free( polygon_edge_map ); + return 0; + + next:; } } for( int i = 0; i < mesh->abpolys.count; i ++ ) @@ -1001,7 +1011,7 @@ static int *cxr_mesh_reflex_edges( cxr_mesh *mesh ) edge_tagged[lp->edge_index] = 0; cxr_polygon *polya = &mesh->polys[ lp->poly_left ], - *polyb = &mesh->polys[ lp->poly_right ]; + *polyb = &mesh->polys[ lp->poly_right ]; v4f planeb; normal_to_plane(polyb->normal, polyb->center, planeb); @@ -1320,16 +1330,66 @@ static void cxr_link_manifold( struct temp_manifold *manifold ){ cxr_loop **edge_list = malloc( sizeof(*edge_list) * solid->edge_count ); + int *temp_solid = malloc( solid->count *sizeof(int) ); + int temp_solid_len = 0; int init_reverse = 0; int unique_edge_count = 0; + + /* Try remove splitting faces first */ + { + int split_total = 0; + for( int j=0; jcount; j++ ) + { + cxr_polygon *poly = &mesh->polys[ solid_buffer[solid->start+j] ]; + int interior_count = 0; - /* Gather list of unique edges */ + for( int k=0; kloop_total; k++ ) + { + cxr_loop *loop = &mesh->loops[ poly->loop_start+k ]; + + for( int l=0; lcount; l++ ) + if( loop->poly_right == solid_buffer[solid->start+l] ) + { + interior_count ++; + goto next; + } + + next:; + } + + if( interior_count < poly->loop_total-1 ) + { + split_total ++; + continue; + } + + temp_solid[ temp_solid_len ++ ] = solid_buffer[solid->start+j]; + } + + if( temp_solid_len < 3 || (split_total & 0x2) /* unkown reasons */ ) + { + } + else + { + /* Overwrite original solid */ + for( int j=0; jstart+j ] = temp_solid[ j ]; + + solid->count = temp_solid_len; + } + + free( temp_solid ); + } for( int j=0; jcount; j++ ) { cxr_polygon *poly = &mesh->polys[ solid_buffer[solid->start+j] ]; + /* when discarding, if a face has only one loop that points outwards, + * we keep it */ + + for( int k=0; kloop_total; k++ ) { cxr_loop *loop = &mesh->loops[ poly->loop_start+k ]; @@ -1537,22 +1597,30 @@ static int cxr_build_implicit_geo( cxr_mesh *mesh, int new_polys, int start ) return 1; } -/* - * Convexer's main algorithm - * - * Return the best availible convex solid from mesh, and patch the existing mesh - * to fill the gap where the new mesh left it. - * - * Returns NULL if shape is already convex or empty. - * This function will not preserve edge data such as freestyle, sharp etc. - */ -static cxr_mesh *cxr_pull_best_solid( - cxr_mesh *mesh, - int preserve_more_edges, - enum cxr_soliderr *err ) +static int cxr_reflex_err( cxr_mesh *mesh ) { - *err = k_soliderr_none; + int error = 0; + int *reflex_check = cxr_mesh_reflex_edges( mesh ); + + v3f *temp = cxr_ab_ptr(mesh->p_abverts, 0); + + for( int i=0; iabedges.count; i++ ) + { + if( reflex_check[i] ) + { + cxr_debug_line( temp[mesh->edges[i].i0], + temp[mesh->edges[i].i1], + colour_error ); + error ++; + } + } + + free( reflex_check ); + return error; +} +static int cxr_non_manifold_err( cxr_mesh *mesh ) +{ if( !cxr_mesh_link_loops(mesh) ) { #ifdef CXR_DEBUG @@ -1564,18 +1632,43 @@ static cxr_mesh *cxr_pull_best_solid( for( int i=0; iabloops.count; i++ ) { cxr_loop *lp = &mesh->loops[i]; + cxr_edge *edge = &mesh->edges[lp->edge_index]; + cxr_debug_line( verts[edge->i0], verts[edge->i1], colours_random[1] ); if( lp->poly_left == -1 || lp->poly_right == -1 ) { - cxr_edge *edge = &mesh->edges[lp->edge_index]; cxr_debug_line( verts[edge->i0], verts[edge->i1], colour_error ); } } #endif + return 1; + } + + return 0; +} + +/* + * Convexer's main algorithm + * + * Return the best availible convex solid from mesh, and patch the existing mesh + * to fill the gap where the new mesh left it. + * + * Returns NULL if shape is already convex or empty. + * This function will not preserve edge data such as freestyle, sharp etc. + */ +static cxr_mesh *cxr_pull_best_solid( + cxr_mesh *mesh, + int preserve_more_edges, + enum cxr_soliderr *err ) +{ + *err = k_soliderr_none; + + if( cxr_non_manifold_err( mesh ) ) + { *err = k_soliderr_non_manifold; return NULL; } - + int *edge_tagged = cxr_mesh_reflex_edges( mesh ); int *vertex_tagged = cxr_mesh_reflex_vertices( mesh ); @@ -1689,7 +1782,7 @@ static cxr_mesh *cxr_pull_best_solid( struct temp_manifold manifold; cxr_link_manifold( mesh, solid, solid_buffer, &manifold); - + if( manifold.status == k_manifold_err ) { *err = k_soliderr_bad_manifold; @@ -1917,7 +2010,17 @@ static cxr_mesh *cxr_pull_best_solid( free(solid_buffer); free(candidates); free(best_manifold.loops); - + + /* + * Do final checks on the mesh to make sure we diddn't introduce any + * errors + */ + if( cxr_non_manifold_err( pullmesh ) || cxr_reflex_err( pullmesh ) ) + { + *err = k_soliderr_bad_result; + return NULL; + } + return pullmesh; } @@ -1925,6 +2028,9 @@ static cxr_mesh *cxr_pull_best_solid( free(candidates); free(best_manifold.loops); + if( cxr_non_manifold_err( mesh ) || cxr_reflex_err( mesh ) ) + *err = k_soliderr_bad_result; + return NULL; }