static void DrawPolyPolygonRaw(Draw& draw, const Point *vertices, int vertex_count, const int *subpolygon_counts, int subpolygon_count_count, bool is_inside, int outline_width, Color outline_color ) { #ifdef SYSTEMDRAW SystemDraw *w = dynamic_cast<SystemDraw *>(&draw); if(w) { SystemDraw& draw = *w; #endif draw.SetDrawPen(outline_width, outline_color); ASSERT(sizeof(POINT) == sizeof(Point)); // modify algorithm when not enum { MAX_POLY = 8000 }; if(subpolygon_count_count == 1 && vertex_count < MAX_POLY) Polygon(draw, (const POINT *)vertices, vertex_count); else if(vertex_count < MAX_POLY) PolyPolygon(draw, (const POINT *)vertices, subpolygon_counts, subpolygon_count_count); else { if(is_inside) { draw.SetDrawPen(PEN_NULL, Black); Vector<Point> split_vertices; Vector<int> split_counts; #ifdef SYSTEMDRAW SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, split_vertices, split_counts, Size(9999, 9999)); #else SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, split_vertices, split_counts, draw.GetClip()); #endif //!! todo: maxcount for splitpolygon const Point *sv = split_vertices.Begin(); for(const int *sc = split_counts.Begin(), *se = split_counts.End(); sc < se; sc++) { Polygon(draw, (const POINT *)sv, *sc); sv += *sc; } } if(outline_width != PEN_NULL) { draw.DrawPolyPolyline(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, outline_width, outline_color, Null); Buffer<Point> finish(2 * subpolygon_count_count); Buffer<int> counts(subpolygon_count_count); Fill(&counts[0], &counts[subpolygon_count_count], 2); Point *d = finish; const Point *p = vertices; const int *c = subpolygon_counts, *e = c + subpolygon_count_count; while(c < e) { *d++ = *p; *d++ = (p += *c++)[-1]; } draw.DrawPolyPolyline(finish, 2 * subpolygon_count_count, counts, subpolygon_count_count, outline_width, outline_color, Null); } draw.SetDrawPen(outline_width, outline_color); } #ifdef SYSTEMDRAW } #endif }
static void FillPolyPolygonRaw(GC gc, Drawable drawable, Rect clip, Point offset, const Point *vertices, int vertex_count, const int *subpolygon_counts, int subpolygon_count_count) { enum { MAX_VERTEX_COUNT = 10000 }; if(subpolygon_count_count == 1 && vertex_count <= MAX_VERTEX_COUNT) { Buffer<XPoint> out_points(vertex_count); const Point *in = vertices; for(XPoint *out = out_points, *end = out + vertex_count; out < end; out++, in++) { out -> x = (short)(in -> x + offset.x); out -> y = (short)(in -> y + offset.y); } XFillPolygon(Xdisplay, drawable, gc, out_points, vertex_count, Nonconvex, CoordModeOrigin); } else { Vector<Point> split_vertices; ASSERT(sizeof(XPoint) <= sizeof(Point)); // modify algorithm when not Vector<int> split_counts; SplitPolygon(vertices, vertex_count, subpolygon_counts, subpolygon_count_count, split_vertices, split_counts, clip); const Point *sv = split_vertices.Begin(); XPoint *dv = reinterpret_cast<XPoint *>(split_vertices.Begin()); for(const int *sc = split_counts.Begin(), *se = split_counts.End(); sc < se; sc++) { for(XPoint *db = dv, *de = dv + *sc; db < de; db++, sv++) { db -> x = (short)(sv -> x + offset.x); db -> y = (short)(sv -> y + offset.y); } XFillPolygon(Xdisplay, drawable, gc, dv, *sc, Nonconvex, CoordModeOrigin); } } }
void DropPolygonRecursive( node_t *n, polygon_t *p ) { if ( n->child[0] == -1 && n->child[1] == -1 ) { fp_t area; // leaf area = PolygonArea( p ); // printf( " split: %f\n", area ); if ( area > g_best_area ) { g_best_area = area; g_best_leaf = n; } } else { polygon_t *front; polygon_t *back; // node SplitPolygon( p, n->norm, n->dist, &front, &back ); if ( front ) { DropPolygonRecursive( &g_nodes[n->child[0]], front ); FreePolygon( front ); } if ( back ) { DropPolygonRecursive( &g_nodes[n->child[1]], back ); FreePolygon( back ); } } }
void ClipPolygonInPlace( polygon_t **inout, vec3d_t norm, fp_t dist ) { polygon_t *front, *back; SplitPolygon( *inout, norm, dist, &front, &back ); if ( front ) FreePolygon( front ); FreePolygon( *inout ); *inout = back; }
void SplitPortal ( PORTAL* Portal, PLANE* Plane, PORTAL* FrontSplit, PORTAL* BackSplit ) { // this function simply calls SplitPolygon, and is a convenient wrapper // for the splitting of the POLYGON safe type castable portal type SplitPolygon ( ( POLYGON* ) Portal, Plane, ( POLYGON* ) FrontSplit, ( POLYGON* ) BackSplit ); FrontSplit->NumberOfLeafs = Portal->NumberOfLeafs; BackSplit->NumberOfLeafs = Portal->NumberOfLeafs; memcpy ( FrontSplit->LeafOwnerArray, Portal->LeafOwnerArray, sizeof ( long ) * Portal->NumberOfLeafs ); memcpy ( BackSplit->LeafOwnerArray, Portal->LeafOwnerArray, sizeof ( long ) * Portal->NumberOfLeafs ); }
void BSPTree::BuildTree(UniquePtr<BSPTreeNode>& aRoot, std::deque<gfx::Polygon3D>& aPolygons) { if (aPolygons.empty()) { return; } const gfx::Polygon3D& splittingPlane = aRoot->First(); std::deque<gfx::Polygon3D> backPolygons, frontPolygons; for (gfx::Polygon3D& polygon : aPolygons) { size_t pos = 0, neg = 0; nsTArray<float> dots = CalculateDotProduct(splittingPlane, polygon, pos, neg); // Back polygon if (pos == 0 && neg > 0) { backPolygons.push_back(std::move(polygon)); } // Front polygon else if (pos > 0 && neg == 0) { frontPolygons.push_back(std::move(polygon)); } // Coplanar polygon else if (pos == 0 && neg == 0) { aRoot->polygons.push_back(std::move(polygon)); } // Polygon intersects with the splitting plane. else if (pos > 0 && neg > 0) { nsTArray<gfx::Point3D> backPoints, frontPoints; SplitPolygon(splittingPlane, polygon, dots, backPoints, frontPoints); backPolygons.push_back(gfx::Polygon3D(std::move(backPoints))); frontPolygons.push_back(gfx::Polygon3D(std::move(frontPoints))); } } if (!backPolygons.empty()) { aRoot->back.reset(new BSPTreeNode(PopFront(backPolygons))); BuildTree(aRoot->back, backPolygons); } if (!frontPolygons.empty()) { aRoot->front.reset(new BSPTreeNode(PopFront(frontPolygons))); BuildTree(aRoot->front, frontPolygons); } }
// Please only call this on triangulated meshes.. that makes the rest of my coding easier void SplitIntersecting(std::vector<pcs_polygon> &polygons, vector3d plane_point, vector3d plane_normal) { std::vector<pcs_polygon> newpolys; unsigned int i; for (i = 0; i < polygons.size(); i++) { if (Intersects(polygons[i], plane_point, plane_normal)) { SplitPolygon(polygons, i, plane_point, plane_normal, newpolys); } } // add new polygons int in = polygons.size(); polygons.resize(in+newpolys.size()); for (i = 1; i < newpolys.size(); i++) { polygons[in+i] = newpolys[i]; } }
/* ==================== Portal_SplitNode ==================== */ void Portal_SplitNode( cnode_t *node ) { cplane_t *pl; portal_t *p, *pnext; int side; cnode_t *othernode; portal_t *frontportal, *backportal; polygon_t *front, *back; pl = node->pl; side = 0; for ( p = node->portals; p ; p=pnext ) { if ( p->nodes[0] == node ) side = 0; else if ( p->nodes[1] == node ) side = 1; else Error( "Portal_SplitNode: can't find node in portal.\n" ); pnext = p->next[side]; othernode = p->nodes[!side]; RemovePortalFromNode( p, p->nodes[0] ); RemovePortalFromNode( p, p->nodes[1] ); SplitPolygon( p->p, pl->norm, pl->dist, &front, &back ); FreePolygon( p->p ); if ( !front && !back ) Error( "Portal_SplitNode: no front and back after split.\n" ); if ( !front ) { // polygon is back p->p = back; if ( side ) // node was back of portal AddPortalToNodes( p, othernode, node->child[1] ); else // node was front AddPortalToNodes( p, node->child[1], othernode ); continue; } if ( !back ) { // polygon is front p->p = front; if ( side ) // node was back of portal AddPortalToNodes( p, othernode, node->child[0] ); else AddPortalToNodes( p, node->child[0], othernode ); continue; } // // portal got split // frontportal = p; frontportal->p = front; backportal = NewPortal(); memcpy( backportal, p, sizeof( portal_t ) ); backportal->p = back; if ( side ) // node was back of portal { AddPortalToNodes( frontportal, othernode, node->child[0] ); AddPortalToNodes( backportal, othernode, node->child[1] ); } else { AddPortalToNodes( frontportal, node->child[0], othernode ); AddPortalToNodes( backportal, node->child[1], othernode ); } } node->portals = NULL; }
MagicDGP::LightMesh3D* PoissonReconstruction::SurfaceTrimmer(int argc , char* argv[], std::vector< PlyValueVertex< float > >& vertices, std::vector< std::vector< int > >& polygons) { cmdLineString In( "in" ) , Out( "out" ); cmdLineInt Smooth( "smooth" , 5 ); cmdLineFloat Trim( "trim" ) , IslandAreaRatio( "aRatio" , 0.001f ); cmdLineFloatArray< 2 > ColorRange( "color" ); cmdLineReadable PolygonMesh( "polygonMesh" ); cmdLineReadable* params[] = { &In , &Out , &Trim , &PolygonMesh , &ColorRange , &Smooth , &IslandAreaRatio }; int paramNum = sizeof(params)/sizeof(cmdLineReadable*); cmdLineParse( argc , argv, paramNum , params , 0 ); float min , max; //std::vector< PlyValueVertex< float > > vertices; //std::vector< std::vector< int > > polygons; //int ft , commentNum = paramNum+2; //char** comments; //bool readFlags[ PlyValueVertex< float >::Components ]; //PlyReadPolygons( In.value , vertices , polygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , &comments , &commentNum , readFlags ); //if( !readFlags[3] ){ fprintf( stderr , "[ERROR] vertices do not have value flag\n" ) ; return EXIT_FAILURE; } for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); min = max = vertices[0].value; for( size_t i=0 ; i<vertices.size() ; i++ ) min = std::min< float >( min , vertices[i].value ) , max = std::max< float >( max , vertices[i].value ); printf( "Value Range: [%f,%f]\n" , min , max ); if( Trim.set ) { hash_map< long long , int > vertexTable; std::vector< std::vector< int > > ltPolygons , gtPolygons; std::vector< bool > ltFlags , gtFlags; /*for( int i=0 ; i<paramNum+2 ; i++ ) comments[i+commentNum]=new char[1024]; sprintf( comments[commentNum++] , "Running Surface Trimmer (V5)" ); if( In.set ) sprintf(comments[commentNum++],"\t--%s %s" , In.name , In.value ); if( Out.set ) sprintf(comments[commentNum++],"\t--%s %s" , Out.name , Out.value ); if( Trim.set ) sprintf(comments[commentNum++],"\t--%s %f" , Trim.name , Trim.value ); if( Smooth.set ) sprintf(comments[commentNum++],"\t--%s %d" , Smooth.name , Smooth.value ); if( IslandAreaRatio.set ) sprintf(comments[commentNum++],"\t--%s %f" , IslandAreaRatio.name , IslandAreaRatio.value ); if( PolygonMesh.set ) sprintf(comments[commentNum++],"\t--%s" , PolygonMesh.name );*/ double t=Time(); for( size_t i=0 ; i<polygons.size() ; i++ ) SplitPolygon( polygons[i] , vertices , <Polygons , >Polygons , <Flags , >Flags , vertexTable , Trim.value ); if( IslandAreaRatio.value>0 ) { std::vector< std::vector< int > > _ltPolygons , _gtPolygons; std::vector< std::vector< int > > ltComponents , gtComponents; SetConnectedComponents( ltPolygons , ltComponents ); SetConnectedComponents( gtPolygons , gtComponents ); std::vector< double > ltAreas( ltComponents.size() , 0. ) , gtAreas( gtComponents.size() , 0. ); std::vector< bool > ltComponentFlags( ltComponents.size() , false ) , gtComponentFlags( gtComponents.size() , false ); double area = 0.; for( size_t i=0 ; i<ltComponents.size() ; i++ ) { for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) { ltAreas[i] += PolygonArea( vertices , ltPolygons[ ltComponents[i][j] ] ); ltComponentFlags[i] = ( ltComponentFlags[i] || ltFlags[ ltComponents[i][j] ] ); } area += ltAreas[i]; } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) { gtAreas[i] += PolygonArea( vertices , gtPolygons[ gtComponents[i][j] ] ); gtComponentFlags[i] = ( gtComponentFlags[i] || gtFlags[ gtComponents[i][j] ] ); } area += gtAreas[i]; } for( size_t i=0 ; i<ltComponents.size() ; i++ ) { if( ltAreas[i]<area*IslandAreaRatio.value && ltComponentFlags[i] ) for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _gtPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); else for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _ltPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { if( gtAreas[i]<area*IslandAreaRatio.value && gtComponentFlags[i] ) for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _ltPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); else for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _gtPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); } ltPolygons = _ltPolygons , gtPolygons = _gtPolygons; } if( !PolygonMesh.set ) { { std::vector< std::vector< int > > polys = ltPolygons; Triangulate( vertices , ltPolygons , polys ) , ltPolygons = polys; } { std::vector< std::vector< int > > polys = gtPolygons; Triangulate( vertices , gtPolygons , polys ) , gtPolygons = polys; } } RemoveHangingVertices( vertices , gtPolygons ); MagicDGP::LightMesh3D* pExportMesh = new MagicDGP::LightMesh3D; for (int pIndex = 0; pIndex < vertices.size(); pIndex++) { PlyValueVertex< float > vert = vertices.at(pIndex); MagicMath::Vector3 vertPos(vert.point[0], vert.point[1], vert.point[2]); pExportMesh->InsertVertex(vertPos); } for (int pIndex = 0; pIndex < gtPolygons.size(); pIndex++) { MagicDGP::FaceIndex faceIdx; for (int k = 0; k < 3; k++) { faceIdx.mIndex[k] = gtPolygons.at(pIndex).at(k); } pExportMesh->InsertFace(faceIdx); } pExportMesh->UpdateNormal(); return pExportMesh; } else { //if( ColorRange.set ) min = ColorRange.values[0] , max = ColorRange.values[1]; //std::vector< PlyColorVertex< float > > outVertices; //ColorVertices( vertices , outVertices , min , max ); ////if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , ft , comments , commentNum ); //if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , 1 , NULL , 0 ); } return NULL; }
u_list_t * ScanPolygon( polygon_t *poly, vec3d_t norm, fp_t dist, fp_t step ) { fp_t max_d; int i; fp_t d; polygon_t *remain; u_list_t *frag_list; // printf( "dist: %f, step: %f\n", dist,step ); // Vec3dPrint( norm ); // get max dist of poly towards the plane max_d = -999999.9; for ( i = 0; i < poly->pointnum; i++ ) { d = Vec3dDotProduct( norm, poly->p[i] ) - dist; if ( d > max_d ) max_d = d; } if ( max_d < 0.0 ) { d = -ceil( (-max_d)/step ) * step; } else { d = ceil( (max_d)/step ) * step; } dist += d; remain = CopyPolygon( poly ); frag_list = NEWTYPE( u_list_t ); U_InitList( frag_list ); for( ; remain ; ) { polygon_t *front, *back; // printf( "split dist: %f\n", dist ); SplitPolygon( remain, norm, dist, &front, &back ); if ( front ) { scan_frag_t *frag; frag = NEWTYPE( scan_frag_t ); frag->p = front; frag->dist = dist; U_ListInsertAtHead( frag_list, frag ); // printf( "hit!\n" ); } dist -= step; remain = back; } return frag_list; }
void CSG_SplitBrush_new( cbspbrush_t *in, cplane_t *plane, cbspbrush_t **front, cbspbrush_t **back ) { int i; int exact; polygon_t *splitpoly; cbspbrush_t *b, *f; *front = *back = NULL; // // split plane part of brush ? // exact = CSG_IsExactOnPlane( in, plane ); if ( exact == BRUSH_BACK_ON ) { *back = CopyBrush( in ); return; } if ( exact == BRUSH_FRONT_ON ) { *front = CopyBrush( in ); return; } // // real check // splitpoly = BasePolygonForPlane( plane->norm, plane->dist ); for ( i = 0; i < in->surfacenum; i++ ) { ClipPolygonInPlace( &splitpoly, in->surfaces[i].pl->norm, in->surfaces[i].pl->dist ); if ( !splitpoly ) break; } if ( !splitpoly ) { // no splitpoly => brush is not split by plane // determine on which side of plane is the complete brush int check = -1; for ( i = 0; i < in->surfacenum; i++ ) { if ( !in->surfaces[i].p ) continue; check = CheckPolygonWithPlane( in->surfaces[i].p, plane->norm, plane->dist ); if ( check == POLY_BACK ) break; else if ( check == POLY_FRONT ) break; else if ( check == POLY_ON ) continue; printf( "?" ); } if ( check == POLY_BACK ) { *back = CopyBrush( in ); return; } else if ( check == POLY_FRONT ) { *front = CopyBrush( in ); return; } else { printf( "can't get planeside of brush.\n" ); *front = NULL; *back = NULL; return; } } // // split input brush // f = NewBrush( in->surfacenum + 2 ); b = NewBrush( in->surfacenum + 2 ); f->surfacenum = b->surfacenum = 0; f->original = in->original; b->original = in->original; f->contents = in->contents; b->contents = in->contents; for( i = 0; i < in->surfacenum; i++ ) { polygon_t *fpoly, *bpoly; SplitPolygon( in->surfaces[i].p, plane->norm, plane->dist, &fpoly, &bpoly ); if ( fpoly ) { // add polygon to front brush and copy the rest if ( f->surfacenum == in->surfacenum + 2 ) Error( "reached max surfs\n" ); memcpy( &f->surfaces[f->surfacenum], &in->surfaces[i], sizeof( csurface_t ) ); f->surfaces[f->surfacenum].p = fpoly; f->surfacenum++; } if ( bpoly ) { // add polygon to back brush and copy the rest if ( b->surfacenum == in->surfacenum + 2 ) Error( "reached max surfs\n" ); memcpy( &b->surfaces[b->surfacenum], &in->surfaces[i], sizeof( csurface_t ) ); b->surfaces[b->surfacenum].p = bpoly; b->surfacenum++; } } // // add split plane to front and back brush // // the backside brush gets the plane if ( f->surfacenum == in->surfacenum + 2 ) Error( "reached max surfs\n" ); b->surfaces[b->surfacenum].pl = plane; b->surfaces[b->surfacenum].td = NULL; b->surfaces[b->surfacenum].state = SURFACE_STATE_BYSPLIT; b->surfaces[b->surfacenum].contents = 0; b->surfaces[b->surfacenum].p = splitpoly; b->surfacenum++; // the frontside brush gets the flipplane if ( b->surfacenum == in->surfacenum + 2 ) Error( "reached max surfs\n" ); f->surfaces[f->surfacenum].pl = plane->flipplane; f->surfaces[f->surfacenum].td = NULL; f->surfaces[f->surfacenum].state = SURFACE_STATE_BYSPLIT; f->surfaces[f->surfacenum].contents = 0; f->surfaces[f->surfacenum].p = PolygonFlip( splitpoly ); f->surfacenum++; if ( b->surfacenum < 4 ) { printf( "no back %d\n", b->surfacenum ); FreeBrush( b ); b = NULL; } if ( f->surfacenum < 4 ) { printf( "no front %d\n", f->surfacenum ); FreeBrush( f ); f = NULL; } if ( b ) CalcBrushBounds( b ); if ( f ) CalcBrushBounds( f ); *back = b; *front = f; }
int main( int argc , char* argv[] ) { int paramNum = sizeof(params)/sizeof(cmdLineReadable*); cmdLineParse( argc-1 , &argv[1] , paramNum , params , 0 ); #if FOR_RELEASE if( !In.set || !Trim.set ) { ShowUsage( argv[0] ); return EXIT_FAILURE; } #else // !FOR_RELEASE if( !In.set ) { ShowUsage( argv[0] ); return EXIT_FAILURE; } #endif // FOR_RELEASE float min , max; std::vector< PlyValueVertex< float > > vertices; std::vector< std::vector< int > > polygons; int ft , commentNum = paramNum+2; char** comments; bool readFlags[ PlyValueVertex< float >::Components ]; PlyReadPolygons( In.value , vertices , polygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , &comments , &commentNum , readFlags ); if( !readFlags[3] ){ fprintf( stderr , "[ERROR] vertices do not have value flag\n" ) ; return EXIT_FAILURE; } #if 0 if( Trim.set ) for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons , Trim.value-0.5f , Trim.value+0.5f ); else for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); #else for( int i=0 ; i<Smooth.value ; i++ ) SmoothValues( vertices , polygons ); #endif min = max = vertices[0].value; for( size_t i=0 ; i<vertices.size() ; i++ ) min = std::min< float >( min , vertices[i].value ) , max = std::max< float >( max , vertices[i].value ); printf( "Value Range: [%f,%f]\n" , min , max ); if( Trim.set ) { hash_map< long long , int > vertexTable; std::vector< std::vector< int > > ltPolygons , gtPolygons; std::vector< bool > ltFlags , gtFlags; for( int i=0 ; i<paramNum+2 ; i++ ) comments[i+commentNum]=new char[1024]; sprintf( comments[commentNum++] , "Running Surface Trimmer (V5)" ); if( In.set ) sprintf(comments[commentNum++],"\t--%s %s" , In.name , In.value ); if( Out.set ) sprintf(comments[commentNum++],"\t--%s %s" , Out.name , Out.value ); if( Trim.set ) sprintf(comments[commentNum++],"\t--%s %f" , Trim.name , Trim.value ); if( Smooth.set ) sprintf(comments[commentNum++],"\t--%s %d" , Smooth.name , Smooth.value ); if( IslandAreaRatio.set ) sprintf(comments[commentNum++],"\t--%s %f" , IslandAreaRatio.name , IslandAreaRatio.value ); if( PolygonMesh.set ) sprintf(comments[commentNum++],"\t--%s" , PolygonMesh.name ); double t=Time(); for( size_t i=0 ; i<polygons.size() ; i++ ) SplitPolygon( polygons[i] , vertices , <Polygons , >Polygons , <Flags , >Flags , vertexTable , Trim.value ); if( IslandAreaRatio.value>0 ) { std::vector< std::vector< int > > _ltPolygons , _gtPolygons; std::vector< std::vector< int > > ltComponents , gtComponents; SetConnectedComponents( ltPolygons , ltComponents ); SetConnectedComponents( gtPolygons , gtComponents ); std::vector< double > ltAreas( ltComponents.size() , 0. ) , gtAreas( gtComponents.size() , 0. ); std::vector< bool > ltComponentFlags( ltComponents.size() , false ) , gtComponentFlags( gtComponents.size() , false ); double area = 0.; for( size_t i=0 ; i<ltComponents.size() ; i++ ) { for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) { ltAreas[i] += PolygonArea( vertices , ltPolygons[ ltComponents[i][j] ] ); ltComponentFlags[i] = ( ltComponentFlags[i] || ltFlags[ ltComponents[i][j] ] ); } area += ltAreas[i]; } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) { gtAreas[i] += PolygonArea( vertices , gtPolygons[ gtComponents[i][j] ] ); gtComponentFlags[i] = ( gtComponentFlags[i] || gtFlags[ gtComponents[i][j] ] ); } area += gtAreas[i]; } for( size_t i=0 ; i<ltComponents.size() ; i++ ) { if( ltAreas[i]<area*IslandAreaRatio.value && ltComponentFlags[i] ) for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _gtPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); else for( size_t j=0 ; j<ltComponents[i].size() ; j++ ) _ltPolygons.push_back( ltPolygons[ ltComponents[i][j] ] ); } for( size_t i=0 ; i<gtComponents.size() ; i++ ) { if( gtAreas[i]<area*IslandAreaRatio.value && gtComponentFlags[i] ) for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _ltPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); else for( size_t j=0 ; j<gtComponents[i].size() ; j++ ) _gtPolygons.push_back( gtPolygons[ gtComponents[i][j] ] ); } ltPolygons = _ltPolygons , gtPolygons = _gtPolygons; } if( !PolygonMesh.set ) { { std::vector< std::vector< int > > polys = ltPolygons; Triangulate( vertices , ltPolygons , polys ) , ltPolygons = polys; } { std::vector< std::vector< int > > polys = gtPolygons; Triangulate( vertices , gtPolygons , polys ) , gtPolygons = polys; } } RemoveHangingVertices( vertices , gtPolygons ); sprintf( comments[commentNum++] , "#Trimmed In: %9.1f (s)" , Time()-t ); if( Out.set ) PlyWritePolygons( Out.value , vertices , gtPolygons , PlyValueVertex< float >::Properties , PlyValueVertex< float >::Components , ft , comments , commentNum ); } else { if( ColorRange.set ) min = ColorRange.values[0] , max = ColorRange.values[1]; std::vector< PlyColorVertex< float > > outVertices; ColorVertices( vertices , outVertices , min , max ); if( Out.set ) PlyWritePolygons( Out.value , outVertices , polygons , PlyColorVertex< float >::Properties , PlyColorVertex< float >::Components , ft , comments , commentNum ); } return EXIT_SUCCESS; }
/* ============= R_AddShadowCaster Polygons must be added in front to back order! ============= */ svnode_t *R_AddShadowCaster(svnode_t *node, vec3_t *v, int vnum, msurface_t *surf,int depth) { int sign; int signs[MAX_POLY_VERT],signs2[MAX_POLY_VERT]; vec3_t v1[MAX_POLY_VERT],v2[MAX_POLY_VERT]; int vnum1,vnum2; int i; if (depth > 1500) { Con_Printf("to deep\n"); return NULL; } if (vnum == 0) return NULL; sign = 0; for (i=0; i<vnum; i++) { sign |= signs[i] = Epsilon_Sign (DotProduct (v[i], node->splitplane->normal)- node->splitplane->dist); } if (sign == 1) { if (node->children[0] != NULL) { R_AddShadowCaster (node->children[0], v, vnum, surf, depth+1); } else { svBsp_NumCutPolys++; } } else if (sign == 2) { if (node->children[1] != NULL) { R_AddShadowCaster (node->children[1], v, vnum, surf, depth+1); } else { node->children[1] = ExpandVolume(v, signs, vnum, surf); if (surf->visframe != r_lightTimestamp) { //Store it out as visible surf->shadowchain = shadowchain; surf->visframe = r_lightTimestamp; surf->polys->lightTimestamp = r_lightTimestamp; shadowchain = surf; svBsp_NumKeptPolys++; } } } else if (sign == 3) { SplitPolygon(&v[0], &signs[0], vnum, node->splitplane, &v1[0], &vnum1, &v2[0], &vnum2); if (node->children[0] != NULL) { R_AddShadowCaster (node->children[0], v1, vnum1, surf, depth+1); } else { svBsp_NumCutPolys++; } if (vnum2 == 0) return NULL; if (node->children[1] != NULL) { R_AddShadowCaster (node->children[1], v2, vnum2, surf, depth+1); } else { node->children[1] = ExpandVolume (v2, signs2, vnum2, surf); if (surf->visframe != r_lightTimestamp) { //Store it out as visible surf->shadowchain = shadowchain; surf->visframe = r_lightTimestamp; surf->polys->lightTimestamp = r_lightTimestamp; shadowchain = surf; svBsp_NumKeptPolys++; } } } return NULL; }