X-Git-Url: https://skaterift.com/git/?a=blobdiff_plain;f=src%2Fconvexer.c;h=5fac72984d2f489a9aefdc7632d39e8c0489871e;hb=4b19eaf2f9c56078172b3979e856da7abf372e91;hp=adcaf6007a2ae626a9b8d94b9bd9e52ce4523673;hpb=4a01d99d563ce228c13591bbed3e24f05241c586;p=convexer.git diff --git a/src/convexer.c b/src/convexer.c index adcaf60..5fac729 100644 --- a/src/convexer.c +++ b/src/convexer.c @@ -59,7 +59,7 @@ typedef v3f m4x3f[4]; typedef v3f boxf[2]; #define CXR_EPSILON 0.001 -#define CXR_PLANE_SIMILARITY_MAX 0.999 +#define CXR_PLANE_SIMILARITY_MAX 0.998 #define CXR_BIG_NUMBER 1e300 #define CXR_INTERIOR_ANGLE_MAX 0.998 #define CXR_API @@ -799,7 +799,7 @@ static struct cxr_mesh *cxr_pull_best_solid( for( int j=0; jloop_total; j++ ) { struct cxr_loop *loop = cxr_ab_ptr(&mesh->loops, polya->loop_start+j); - if( plane_polarity( planeb, vertices[loop->index] ) > 0.000025 || + if( plane_polarity( planeb, vertices[loop->index] ) > 0.001 || v3_dot(polya->normal,polyb->normal) > CXR_PLANE_SIMILARITY_MAX ) { edge_tagged[i] = 1; @@ -912,8 +912,8 @@ IL_TAG_NEXT_VERT:; edge_tagged[i] = 1; } - /* Debug stuff -- - for( int i=0; icount; i++ ) if( vertex_tagged[i] ) cxr_debug_box( vertices[i], 0.03, (v4f){0.0,0.0,0.0,1.0}); @@ -926,7 +926,7 @@ IL_TAG_NEXT_VERT:; if( hot_edge[i] ) cxr_debug_line( vertices[ edge->i0 ], vertices[ edge->i1 ], (v4f){0.0,1.0,1.0,1.0}); } - */ + // count regions int *faces_tagged = malloc(mesh->polys.count*sizeof(int)); @@ -942,6 +942,12 @@ IL_TAG_NEXT_VERT:; } *candidates = malloc( mesh->polys.count *sizeof(struct csolid) ); int candidate_count = 0; + + struct tedge + { + int i0, i1; + } + *edge_references = malloc( mesh->edges.count *sizeof(struct tedge) ); for( int i=0; ipolys.count; i++ ) { @@ -975,11 +981,15 @@ IL_TAG_NEXT_VERT:; { if( !edge_tagged[loop->edge_index] ) { + // TODO(harry): + // // Need to look ahead 1 step to make sure he does not want // to add any more planes that are coplanar with some of // our existing group // - // TODO: is this unused due to hotedge improvements? leaving for safety... + // This can sort out SOME invalid configs, but not all. + // It would be nice to find a more robust clustering algorithm for this. + // struct cxr_polygon *poly_to_add = cxr_ab_ptr(&mesh->polys, loop->poly_right ); for( int l=0; l < poly_to_add->loop_total; l++ ) @@ -1004,8 +1014,6 @@ IL_TAG_NEXT_VERT:; IL_SKIP_SIMILAR_PLANES:; } - // This plane passed all checks so we can add it to the current solid - solid[ solid_len ++ ] = loop->poly_right; faces_tagged[ loop->poly_right ] = i; changed = 1; @@ -1019,6 +1027,25 @@ IL_TAG_NEXT_VERT:; if(changed) goto IL_SEARCH_CONTINUE; + // The current method can create some invalid configurations + // filter those out that dont work and un-tag the faces + for( int j=0; jpolys, solid[j]), + *polyk = cxr_ab_ptr(&mesh->polys, solid[k]); + + if( v3_dot( polyj->normal, polyk->normal ) > CXR_PLANE_SIMILARITY_MAX ) + { + for( int l=0; lstart = solid_buffer_len; @@ -1035,8 +1062,12 @@ IL_TAG_NEXT_VERT:; v3_divs( csolid->center, solid_len, csolid->center ); solid_buffer_len += solid_len; + + IL_CANCEL_SOLID:; } + free( edge_references ); + // Create all candidates who have one or less non-manifolds edges // Loop each candidate, determine the manifold, and pick the best one @@ -1269,13 +1300,6 @@ IL_TAG_NEXT_VERT:; exist_face->loop_total = -1; } - - // Split manifold up by unique planes if it has more than 1 - // otherwise, just use that face - // - // TODO: Need to build new manifold in sections, stably - // currently there is an unsupported case where the manifold splits - // are on located on an implicit face, causing 1-length manifolds. int new_polys = 0; int pullmesh_new_start = pullmesh->polys.count; @@ -1301,7 +1325,7 @@ IL_TAG_NEXT_VERT:; // When it is even, it appears that internal implicit geometry is required, so we // need to fold the loops we create. Its really weird, but for some reason works on // the geometry rules we've defined. - // TODO: Find a well defined rule here. + // TODO(harry): Find a well defined rule here. int collapse_used_segments = (u32)fewest_manifold_splits & 0x1? 0: 1; @@ -1755,9 +1779,6 @@ CXR_API struct cxr_input_mesh *cxr_decompose(struct cxr_input_mesh *src) struct cxr_auto_buffer solids; cxr_ab_init( &solids, sizeof(struct cxr_mesh *), 2 ); - // TODO: Preprocessor stages - // - Split mesh up into islands before doing anything here - // - Snap vertices to grid (0.25u) ? while(1) { struct cxr_mesh *res = cxr_pull_best_solid( main_mesh, &abverts, 0, &error ); @@ -1896,9 +1917,10 @@ static void cxr_write_disp(struct cxr_mesh *mesh, struct cxr_input_mesh *inputme v3_add( poly->normal, avg_normal, avg_normal ); } v3_divs( avg_normal, mesh->polys.count, avg_normal ); - v3_normalize( avg_normal ); // TODO: This can be zero length. Should add a safety check + v3_normalize( avg_normal ); // TODO(harry): This can be zero length. Should add a safety check // normalize function that checks for small length before // carrying out, otherwise we get inf/nan values... + int n_cardinal = cxr_cardinal( avg_normal, -1 ); // Approximately matching the area of the result brush faces to the actual area @@ -1983,6 +2005,9 @@ static void cxr_write_disp(struct cxr_mesh *mesh, struct cxr_input_mesh *inputme } } + // TODO(harry): This currently only supports power 2 displacements + // its quite straightforward to upgrade it. + // int dispedge[16]; v2f corner_uvs[4]; int dispedge_count; @@ -2172,7 +2197,7 @@ static void cxr_write_disp(struct cxr_mesh *mesh, struct cxr_input_mesh *inputme // Create brush vertices based on UV map // Create V reference based on first displacement. - // TODO: This is not the moststable selection method! + // TODO(harry): This is not the moststable selection method! // faces can come in any order, so the first disp will of course // always vary. Additionaly the triangle can be oriented differently. // @@ -2513,6 +2538,44 @@ IL_DISP_ERROR_COUNT: free( vertinfo ); } +static int cxr_solid_checkerr(struct cxr_mesh *mesh, struct cxr_auto_buffer *abverts ) +{ + int err_count = 0; + + for( int i=0; ipolys.count; i++ ) + { + int plane_err = 0; + + struct cxr_polygon *poly = cxr_ab_ptr(&mesh->polys,i); + v4f plane; + + normal_to_plane( poly->normal, poly->center, plane ); + + for( int j=0; jloop_total; j++ ) + { + struct cxr_loop *loop = cxr_ab_ptr(&mesh->loops, poly->loop_start+j); + double *vert = cxr_ab_ptr(abverts,loop->index); + + if( fabs(plane_polarity(plane,vert)) > 0.0025 ) + { + err_count ++; + plane_err ++; + + v3f ref; + plane_project_point( plane, vert, ref ); + + cxr_debug_line( ref, vert, colour_error ); + cxr_debug_box( vert, 0.1, colour_error ); + } + } + + if( plane_err ) + cxr_debug_poly( mesh, poly, cxr_ab_ptr(abverts,0), colour_error ); + } + + return err_count; +} + CXR_API i32 cxr_convert_mesh_to_vmf(struct cxr_input_mesh *src, struct cxr_vdf *output) { // Split mesh into islands @@ -2520,20 +2583,17 @@ CXR_API i32 cxr_convert_mesh_to_vmf(struct cxr_input_mesh *src, struct cxr_vdf * struct cxr_mesh *main_mesh = cxr_to_internal_format(src, &abverts); u32 error = 0x00; + int invalid_count = 0; struct solidinf { struct cxr_mesh *pmesh; - int is_displacement; + int is_displacement, invalid; }; struct cxr_auto_buffer solids; cxr_ab_init( &solids, sizeof(struct solidinf), 2 ); - // TODO: Preprocessor stages - // - Split mesh up into islands before doing anything here (DONE) - // - Snap vertices to grid (0.25u) ? - // Preprocessor 1: Island seperation // --------------- @@ -2548,7 +2608,7 @@ CXR_API i32 cxr_convert_mesh_to_vmf(struct cxr_input_mesh *src, struct cxr_vdf * } cxr_ab_push( &solids, &(struct solidinf){main_mesh,0} ); - // Preprocessor 2: Displacement break-out + // Preprocessor 2: Displacement break-out and error checking // --------------- for( int i=0; ipmesh, &abverts ) ) + { + pinf->invalid = 1; + invalid_count ++; + } + continue; IL_SOLID_IS_DISPLACEMENT:; @@ -2583,7 +2649,7 @@ CXR_API i32 cxr_convert_mesh_to_vmf(struct cxr_input_mesh *src, struct cxr_vdf * { struct solidinf pinf = *(struct solidinf *)cxr_ab_ptr(&solids, i); - if( pinf.is_displacement ) + if( pinf.is_displacement || pinf.invalid ) continue; while(1)