@ -100,13 +100,15 @@ static void InitScreenCoordinates(OutputVertex& vtx)
void ProcessTriangle ( OutputVertex & v0 , OutputVertex & v1 , OutputVertex & v2 ) {
void ProcessTriangle ( OutputVertex & v0 , OutputVertex & v1 , OutputVertex & v2 ) {
using boost : : container : : static_vector ;
using boost : : container : : static_vector ;
// TODO (neobrain):
// Clipping a planar n-gon against a plane will remove at least 1 vertex and introduces 2 at
// The list of output vertices has some fixed maximum size,
// the new edge (or less in degenerate cases). As such, we can say that each clipping plane
// however I haven't taken the time to figure out what it is exactly.
// introduces at most 1 new vertex to the polygon. Since we start with a triangle and have a
// For now, we hence just assume a maximal size of 256 vertices.
// fixed 6 clipping planes, the maximum number of vertices of the clipped polygon is 3 + 6 = 9.
static const size_t MAX_VERTICES = 256 ;
static const size_t MAX_VERTICES = 9 ;
static_vector < OutputVertex , MAX_VERTICES > buffer_vertices ;
static_vector < OutputVertex , MAX_VERTICES > buffer_a = { v0 , v1 , v2 } ;
static_vector < OutputVertex * , MAX_VERTICES > output_list = { & v0 , & v1 , & v2 } ;
static_vector < OutputVertex , MAX_VERTICES > buffer_b ;
auto * output_list = & buffer_a ;
auto * input_list = & buffer_b ;
// Simple implementation of the Sutherland-Hodgman clipping algorithm.
// Simple implementation of the Sutherland-Hodgman clipping algorithm.
// TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
// TODO: Make this less inefficient (currently lots of useless buffering overhead happens here)
@ -117,48 +119,45 @@ void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
ClippingEdge ( ClippingEdge : : POS_Z , float24 : : FromFloat32 ( + 1.0 ) ) ,
ClippingEdge ( ClippingEdge : : POS_Z , float24 : : FromFloat32 ( + 1.0 ) ) ,
ClippingEdge ( ClippingEdge : : NEG_Z , float24 : : FromFloat32 ( - 1.0 ) ) } ) {
ClippingEdge ( ClippingEdge : : NEG_Z , float24 : : FromFloat32 ( - 1.0 ) ) } ) {
const static_vector < OutputVertex * , MAX_VERTICES > input_list = output_list ;
std : : swap ( input_list , output_list ) ;
output_list . clear ( ) ;
output_list - > clear ( ) ;
const OutputVertex * reference_vertex = input_list . back ( ) ;
const OutputVertex * reference_vertex = & input_list - > back ( ) ;
for ( const auto & vertex : input_list ) {
for ( const auto & vertex : * input_list ) {
// NOTE: This algorithm changes vertex order in some cases!
// NOTE: This algorithm changes vertex order in some cases!
if ( edge . IsInside ( * vertex ) ) {
if ( edge . IsInside ( vertex ) ) {
if ( edge . IsOutSide ( * reference_vertex ) ) {
if ( edge . IsOutSide ( * reference_vertex ) ) {
buffer_vertices . push_back ( edge . GetIntersection ( * vertex , * reference_vertex ) ) ;
output_list - > push_back ( edge . GetIntersection ( vertex , * reference_vertex ) ) ;
output_list . push_back ( & ( buffer_vertices . back ( ) ) ) ;
}
}
output_list . push_back ( vertex ) ;
output_list - > push_back ( vertex ) ;
} else if ( edge . IsInside ( * reference_vertex ) ) {
} else if ( edge . IsInside ( * reference_vertex ) ) {
buffer_vertices . push_back ( edge . GetIntersection ( * vertex , * reference_vertex ) ) ;
output_list - > push_back ( edge . GetIntersection ( vertex , * reference_vertex ) ) ;
output_list . push_back ( & ( buffer_vertices . back ( ) ) ) ;
}
}
reference_vertex = & vertex ;
reference_vertex = vertex ;
}
}
// Need to have at least a full triangle to continue...
// Need to have at least a full triangle to continue...
if ( output_list . size ( ) < 3 )
if ( output_list - > size ( ) < 3 )
return ;
return ;
}
}
InitScreenCoordinates ( * ( output_list [0 ] ) ) ;
InitScreenCoordinates ( ( * output_list ) [0 ] ) ;
InitScreenCoordinates ( * ( output_list [1 ] ) ) ;
InitScreenCoordinates ( ( * output_list ) [1 ] ) ;
for ( size_t i = 0 ; i < output_list . size ( ) - 2 ; i + + ) {
for ( size_t i = 0 ; i < output_list - > size ( ) - 2 ; i + + ) {
OutputVertex & vtx0 = * ( output_list [0 ] ) ;
OutputVertex & vtx0 = ( * output_list ) [0 ] ;
OutputVertex & vtx1 = * ( output_list [i + 1 ] ) ;
OutputVertex & vtx1 = ( * output_list ) [i + 1 ] ;
OutputVertex & vtx2 = * ( output_list [i + 2 ] ) ;
OutputVertex & vtx2 = ( * output_list ) [i + 2 ] ;
InitScreenCoordinates ( vtx2 ) ;
InitScreenCoordinates ( vtx2 ) ;
LOG_TRACE ( Render_Software ,
LOG_TRACE ( Render_Software ,
" Triangle %lu/%lu (%lu buffer vertices) at position (%.3f, %.3f, %.3f, %.3f), "
" Triangle %lu/%lu at position (%.3f, %.3f, %.3f, %.3f), "
" (%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
" (%.3f, %.3f, %.3f, %.3f), (%.3f, %.3f, %.3f, %.3f) and "
" screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f) " ,
" screen position (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f), (%.2f, %.2f, %.2f) " ,
i , output_list . size ( ) , buffer_vertices . size ( ) ,
i , output_list - > size ( ) ,
vtx0 . pos . x . ToFloat32 ( ) , vtx0 . pos . y . ToFloat32 ( ) , vtx0 . pos . z . ToFloat32 ( ) , vtx0 . pos . w . ToFloat32 ( ) ,
vtx0 . pos . x . ToFloat32 ( ) , vtx0 . pos . y . ToFloat32 ( ) , vtx0 . pos . z . ToFloat32 ( ) , vtx0 . pos . w . ToFloat32 ( ) ,
vtx1 . pos . x . ToFloat32 ( ) , vtx1 . pos . y . ToFloat32 ( ) , vtx1 . pos . z . ToFloat32 ( ) , vtx1 . pos . w . ToFloat32 ( ) ,
vtx1 . pos . x . ToFloat32 ( ) , vtx1 . pos . y . ToFloat32 ( ) , vtx1 . pos . z . ToFloat32 ( ) , vtx1 . pos . w . ToFloat32 ( ) ,
vtx2 . pos . x . ToFloat32 ( ) , vtx2 . pos . y . ToFloat32 ( ) , vtx2 . pos . z . ToFloat32 ( ) , vtx2 . pos . w . ToFloat32 ( ) ,
vtx2 . pos . x . ToFloat32 ( ) , vtx2 . pos . y . ToFloat32 ( ) , vtx2 . pos . z . ToFloat32 ( ) , vtx2 . pos . w . ToFloat32 ( ) ,