@ -1,6 +1,8 @@
# include "common.h"
# include "matrix.h"
# include "bsp.h"
# include "face.h"
# include "gpc.h"
// Heron's formula, yoinked from: https://www.cuemath.com/measurement/area-of-triangle/
static double face_triangleArea ( Vec3 v0 , Vec3 v1 , Vec3 v2 )
@ -52,3 +54,47 @@ double face_computeArea(const world_t* world, const face_t* face)
return totalArea ;
}
std : : vector < Vec3 > face_optimizeGeometry ( const std : : vector < Vec3 > faceVertices , Matrix4x4 textureTransform )
{
std : : vector < Vec3 > result ;
// Some faces have redundant/degenerate vertices. We can optimize those by passing their polygons through GPC.
gpc_polygon facePolygon = { 0 } ;
gpc_vertex_list contour ;
contour . num_vertices = faceVertices . size ( ) ;
contour . vertex = ( gpc_vertex * ) malloc ( contour . num_vertices * sizeof ( gpc_vertex ) ) ;
if ( contour . vertex = = NULL )
return result ;
int idx = 0 ;
for ( auto vertIter = faceVertices . cbegin ( ) ; vertIter ! = faceVertices . cend ( ) ; + + vertIter )
{
Vec3 st = textureTransform . TransformPoint ( * vertIter ) ;
contour . vertex [ idx + + ] = gpc_vertex { st . x , st . y } ;
}
gpc_add_contour ( & facePolygon , & contour , 0 ) ;
// Intersect the face's polygon with itself. That should get rid of any redundant vertices.
gpc_polygon optimized = { 0 } ;
gpc_polygon_clip ( GPC_INT , & facePolygon , & facePolygon , & optimized ) ;
if ( optimized . num_contours < 1 )
return result ;
// Transform the optimized polygon back to world space
textureTransform . Invert ( ) ;
gpc_vertex_list * newContour = & optimized . contour [ 0 ] ;
for ( int i = 0 ; i < newContour - > num_vertices ; + + i )
{
Vec3 st = Vec3 ( newContour - > vertex [ i ] . x , newContour - > vertex [ i ] . y , 0.0 ) ;
Vec3 vert = textureTransform . TransformPoint ( st ) ;
result . push_back ( vert ) ;
}
gpc_free_polygon ( & optimized ) ;
gpc_free_polygon ( & facePolygon ) ;
return result ;
}