IMPLEMENTATION
*/
-#define CXR_API
+#define CXR_API
#define CXR_EPSILON 0.001
#define CXR_PLANE_SIMILARITY_MAX 0.998
#define CXR_BIG_NUMBER 1e300
/* 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 );
struct cxr_material
{
i32 res[2];
- const char *name;
+ char *name;
}
*materials;
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,
+ k_soliderr_bad_result
};
/*
}
fprintf( fp, "};\n" );
- fprintf( fp, "struct cxr_static_loop test_loops[] = {\n" );
+ fprintf( fp, "cxr_static_loop test_loops[] = {\n" );
for( int i=0; i<src->loop_count; i ++ )
{
fprintf( fp, " {%d, %d},\n",
}
fprintf( fp, "};\n" );
- fprintf( fp, "struct cxr_polygon test_polys[] = {\n" );
+ fprintf( fp, "cxr_polygon test_polys[] = {\n" );
for( int i=0; i <src->poly_count; i++ )
{
fprintf( fp, " {%d, %d, {%f, %f, %f}, {%f, %f, %f}},\n",
}
fprintf( fp, "};\n" );
- fprintf( fp, "struct cxr_edge test_edges[] = {\n" );
+ fprintf( fp, "cxr_edge test_edges[] = {\n" );
for( int i=0; i<src->edge_count; i++ )
{
fprintf( fp, " {%d, %d, %d},\n",
}
fprintf( fp, "};\n" );
- fprintf( fp, "struct cxr_static_mesh test_mesh = {\n" );
+ fprintf( fp, "cxr_static_mesh test_mesh = {\n" );
fprintf( fp, " .vertices = test_verts,\n" );
fprintf( fp, " .loops = test_loops,\n" );
fprintf( fp, " .edges = test_edges,\n" );
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 ++ )
return 1;
}
+static int cxr_reflex_err( cxr_mesh *mesh )
+{
+ int error = 0;
+ int *reflex_check = cxr_mesh_reflex_edges( mesh );
+
+ v3f *temp = cxr_ab_ptr(mesh->p_abverts, 0);
+
+ for( int i=0; i<mesh->abedges.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
+ 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
+ return 1;
+ }
+
+ return 0;
+}
+
/*
* Convexer's main algorithm
*
{
*err = k_soliderr_none;
- if( !cxr_mesh_link_loops(mesh) )
+ if( cxr_non_manifold_err( mesh ) )
{
-#ifdef CXR_DEBUG
- cxr_log( "non-manifold edges are in the mesh: "
- "implicit internal geometry does not have full support\n" );
-#endif
*err = k_soliderr_non_manifold;
return NULL;
}
-
+
int *edge_tagged = cxr_mesh_reflex_edges( mesh );
int *vertex_tagged = cxr_mesh_reflex_vertices( mesh );
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;
}
free(candidates);
free(best_manifold.loops);
+ if( cxr_non_manifold_err( mesh ) || cxr_reflex_err( mesh ) )
+ *err = k_soliderr_bad_result;
+
return NULL;
}
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 );
cxr_ab_free( &world->abverts );
cxr_ab_free( &world->absolids );
- free( world->materials );
+
+ if( world->materials )
+ {
+ for( int i=0; i<world->material_count; i++ )
+ free( world->materials[i].name );
+
+ free( world->materials );
+ }
free( world );
}
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 */
size_t dsize = sizeof(cxr_material) * src->material_count;
world->materials = malloc( dsize );
memcpy( world->materials, src->materials, dsize );
+
+ for( int i=0; i<src->material_count; i++ )
+ {
+ world->materials[i].name = malloc(strlen(src->materials[i].name) +1);
+ strcpy( world->materials[i].name, src->materials[i].name );
+ }
+ world->material_count = src->material_count;
}
else world->materials = NULL;
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;
* Main convex decomp algorithm
*/
int sources_count = world->absolids.count;
- u32 error = 0x00;
if( invalid_count )
goto decomp_failed;
decomp_failed:
cxr_log( "Error %d\n", error );
cxr_free_world( world );
+
+ if( perrcode )
+ *perrcode = error;
+
return NULL;
}
* TODO(harry): Error checking is needed here for bad input data
*/
- int dispedge[16];
+ int dispedge[17];
v2f corner_uvs[4];
int dispedge_count;
int disp_count = 0;
tx = (double)k/(double)(5-1);
v3_lerp( lside0, lside1, tx, lref );
v3_muls( verts[grid[index]], ctx->scale, vworld );
- v3_add( ctx->offset, vworld, ctx->offset );
+ v3_add( ctx->offset, vworld, vworld );
v3_sub( vworld, lref, vdelta );
v3_copy( vdelta, normals[index] );
world_corners[side[0]] );
cxr_vdf_kv( output, "material", matptr->name );
-
cxr_vdf_kaxis( output, "uaxis",
texinfo_shared.uaxis,
texinfo_shared.offset[0],