std::unique_ptr<bsp_tree_node> GenerateTreeRecursion(std::vector<pcs_polygon> &polygons, std::vector<int>&contained) { PCS_Model::BSP_CUR_DEPTH++; if(PCS_Model::BSP_MAX_DEPTH < PCS_Model::BSP_CUR_DEPTH) PCS_Model::BSP_MAX_DEPTH = PCS_Model::BSP_CUR_DEPTH; if (PCS_Model::BSP_CUR_DEPTH > 500) { PCS_Model::BSP_COMPILE_ERROR = true; return std::unique_ptr<bsp_tree_node>((bsp_tree_node*)NULL); //WHOA wtf infinite recursion! } std::unique_ptr<bsp_tree_node> node(new bsp_tree_node); MakeBound(node->bound_max, node->bound_min, contained, polygons); if (contained.size() == 1) { //we're a polygon.. w00t node->Type = POLY; node->poly_num = contained; } else { // we're a sortnorm vector3d cmax = polygons[contained[0]].centeroid; vector3d cmin = polygons[contained[0]].centeroid; for (std::vector<int>::iterator it = contained.begin() + 1; it < contained.end(); ++it) { ExpandBoundingBoxes(cmax, cmin, polygons[*it].centeroid); } std::vector<int> front, back; if (!Bisect(cmax, cmin, node->point, node->normal, polygons, contained, front, back)) { node->Type = POLY; node->poly_num = contained; } else { node->Type = SPLIT; node->front = GenerateTreeRecursion(polygons, front); node->back = GenerateTreeRecursion(polygons, back); } } PCS_Model::BSP_CUR_DEPTH--; return node; }
std::unique_ptr<bsp_tree_node> MakeTree(std::vector<pcs_polygon> &polygons, vector3d &Max, vector3d &Min) { std::vector<int> polylist(polygons.size()); for (unsigned int i = 0; i < polylist.size(); i++) { polylist[i] = i; } MakeBound(Max, Min, polylist, polygons); // we want to give padding so as to not make the outermost bounding regions too tight Max = Max +vector3d(0.1f, 0.1f, 0.1f); Min = Min -vector3d(0.1f, 0.1f, 0.1f); if (polygons.empty()) { return std::unique_ptr<bsp_tree_node>((bsp_tree_node*)NULL); } wxLongLong time = wxGetLocalTimeMillis(); PCS_Model::BSP_CUR_DEPTH = 0; std::unique_ptr<bsp_tree_node> node = GenerateTreeRecursion(polygons, polylist); PCS_Model::BSP_TREE_TIME += (wxGetLocalTimeMillis() - time).ToLong(); return node; }
//================================================================== SimplePrimitiveBase::CheckSplitRes SimplePrimitiveBase::CheckForSplit( const Hider &hider, int out_bound2d[4], bool &out_uSplit, bool &out_vSplit ) { const Matrix44 &mtxLocalWorld = mpTransform->GetMatrix(); DASSERT( mDiceGridWd == -1 && mDiceGridHe == -1 ); Float3_ testDicePo[ MAX_MAKE_BOUND_OUT_SIZE ]; Bound bound; bound.Reset(); MakeBound( bound, testDicePo ); float pixelArea = hider.RasterEstimate( bound, mtxLocalWorld, out_bound2d ); if ( pixelArea <= MP_GRID_MAX_SIZE ) { if ( pixelArea < RI_EPSILON ) { return CHECKSPLITRES_CULL; } float dim = DSqrt( pixelArea ); mDiceGridWd = DMT_SIMD_PADSIZE( (int)ceilf( dim ) ); mDiceGridHe = (int)ceilf( dim ); out_uSplit = false; out_vSplit = false; return CHECKSPLITRES_DICE; // will dice } else { #if 0 SlVec2 locUV[ TEST_DICE_SIMD_BLOCKS ]; // set last item to 0 to be safe when using the AddReduce() later on locUV[ TEST_DICE_SIMD_BLOCKS - 1 ] = SlVec2( 0.f, 0.f ); fillUVsArray( locUV, 1.0f / (TEST_DICE_LEN - 1), 1.0f / (TEST_DICE_LEN - 1), TEST_DICE_LEN, TEST_DICE_LEN ); //Float3_ avg_dPdu( 0.f, 0.f, 0.f ); //Float3_ avg_dPdv( 0.f, 0.f, 0.f ); SlScalar avg_dPdu( 0.f ); SlScalar avg_dPdv( 0.f ); for (u_int i=0; i < TEST_DICE_SIMD_BLOCKS; ++i) { SlVec3 posLS; SlVec3 dPdu; SlVec3 dPdv; Eval_dPdu_dPdv( locUV[ i ], posLS, &dPdu, &dPdv ); avg_dPdu += dPdu.GetLengthSqr(); avg_dPdv += dPdv.GetLengthSqr(); } // divide by the total number of elements //avg_dPdu /= (float)TEST_DICE_SIMD_BLOCKS * DMT_SIMD_FLEN; //avg_dPdv /= (float)TEST_DICE_SIMD_BLOCKS * DMT_SIMD_FLEN; /* Float3 avg_dPdu_s( avg_dPdu.x().AddReduce(), // avg_dPdu.x()[0] + avg_dPdu.x()[1] ... avg_dPdu.y().AddReduce(), avg_dPdu.z().AddReduce() ); Float3 avg_dPdv_s( avg_dPdv.x().AddReduce(), // avg_dPdv.x()[0] + avg_dPdv.x()[1] ... avg_dPdv.y().AddReduce(), avg_dPdv.z().AddReduce() ); */ float lenU = avg_dPdu.AddReduce(); float lenV = avg_dPdv.AddReduce(); if ( lenU < lenV ) { out_uSplit = false; out_vSplit = true; } else { out_uSplit = true; out_vSplit = false; } #else out_uSplit = true; out_vSplit = true; #endif return CHECKSPLITRES_SPLIT; // will split } }