python interface revision
[convexer.git] / cxr / cxr.h
index 5a4542af6d1a3f4055233c6611630e13b771e10b..bb904c4d00ba8ce0522935f03787d0145e11c4e8 100644 (file)
--- a/cxr/cxr.h
+++ b/cxr/cxr.h
@@ -107,7 +107,7 @@ typedef struct cxr_tri_mesh cxr_tri_mesh;
 
 /* Main convexer algorithms */
 /* Convex decomp from mesh */
-CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src );
+CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src, i32 *perrcode );
 CXR_API void cxr_free_world( cxr_world *world );
 CXR_API cxr_tri_mesh *cxr_world_preview( cxr_world *world );
 CXR_API void cxr_free_tri_mesh( cxr_tri_mesh *mesh );
@@ -276,7 +276,9 @@ enum cxr_soliderr
    k_soliderr_non_manifold,
    k_soliderr_bad_manifold,
    k_soliderr_no_solids,
-   k_soliderr_degenerate_implicit
+   k_soliderr_degenerate_implicit,
+   k_soliderr_non_coplanar_vertices,
+   k_soliderr_non_convex_poly
 };
 
 /*
@@ -1556,6 +1558,19 @@ static cxr_mesh *cxr_pull_best_solid(
 #ifdef CXR_DEBUG
       cxr_log( "non-manifold edges are in the mesh: "
                "implicit internal geometry does not have full support\n" );
+
+      v3f *verts = cxr_ab_ptr( mesh->p_abverts, 0 );
+
+      for( int i=0; i<mesh->abloops.count; i++ )
+      {
+         cxr_loop *lp = &mesh->loops[i];
+
+         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
       *err = k_soliderr_non_manifold;
       return NULL;
@@ -1948,6 +1963,40 @@ static cxr_mesh *cxr_to_internal_format(
    return mesh;
 }
 
+static int cxr_poly_convex( cxr_mesh *mesh, cxr_polygon *poly )
+{
+   v3f *verts = cxr_ab_ptr( mesh->p_abverts, 0 );
+
+   for( int i=0; i<poly->loop_total; i++ )
+   {
+      int li0 = poly->loop_start + i,
+          li1 = poly->loop_start + cxr_range( i+1, poly->loop_total ),
+          li2 = poly->loop_start + cxr_range( i+2, poly->loop_total );
+      int i0 = mesh->loops[li0].index,
+          i1 = mesh->loops[li1].index,
+          i2 = mesh->loops[li2].index;
+
+      v3f v0, v1, c;
+
+      v3_sub( verts[i1], verts[i0], v0 );
+      v3_sub( verts[i2], verts[i1], v1 );
+
+      v3_cross( v0, v1, c );
+      if( v3_dot( c, poly->normal ) <= 0.0 )
+      {
+#if CXR_DEBUG
+         cxr_debug_line( verts[i0], verts[i1], colour_error );
+         cxr_debug_box( verts[i1], 0.1, colour_error );
+         cxr_debug_line( verts[i1], verts[i2], colour_error );
+         cxr_debug_line( verts[i1], poly->center, colour_error );
+#endif
+         return 0;
+      }
+   }
+
+   return 1;
+}
+
 static int cxr_solid_checkerr( cxr_mesh *mesh )
 {
    v3f *verts = cxr_ab_ptr( mesh->p_abverts, 0 );
@@ -2113,8 +2162,9 @@ CXR_API void cxr_free_tri_mesh( cxr_tri_mesh *mesh )
    free( mesh );
 }
 
-CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src )
+CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src, i32 *perrcode )
 {
+   u32 error = 0x00;
    cxr_world *world = malloc( sizeof(*world) );
    
    /* Copy data to internal formats */
@@ -2164,12 +2214,20 @@ CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src )
             if( edge->freestyle )
                goto displacement;
          }
+
+         if( !cxr_poly_convex( pinf->pmesh, poly ) )
+         {
+            pinf->invalid = 1;
+            invalid_count ++;
+            error = k_soliderr_non_convex_poly;
+         }
       }
       
       if( cxr_solid_checkerr( pinf->pmesh ) )
       {
          pinf->invalid = 1;
          invalid_count ++;
+         error = k_soliderr_non_coplanar_vertices;
       }
 
       continue;
@@ -2182,7 +2240,6 @@ CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src )
     * Main convex decomp algorithm
     */
    int sources_count = world->absolids.count;
-   u32 error = 0x00;
    
    if( invalid_count )
       goto decomp_failed;
@@ -2228,6 +2285,10 @@ CXR_API cxr_world *cxr_decompose( cxr_static_mesh *src )
 decomp_failed:
    cxr_log( "Error %d\n", error );
    cxr_free_world( world );
+
+   if( perrcode )
+      *perrcode = error;
+
    return NULL;
 }