void xrMerge() { // clear marks to "false" used.assign (g_nodes.size(),false); // rmark.assign(g_nodes.size(),false); // iterate on nodes u32 group_id = 0; u32 start_time = timeGetTime(); for (u32 Size=16; Size>2; Size/=2) { Msg("Pass size: %d",Size); for (u32 i=0; i<g_nodes.size(); i++) { if (!used[i]) { // analyze vertex& Start = g_nodes[i]; int px,pz; px = iFloor(Start.Pos.x/g_params.fPatchSize+EPS_L); pz = iFloor(Start.Pos.z/g_params.fPatchSize+EPS_L); if (px%Size!=0 || pz%Size!=0) continue; if (QuadFit(i,Size)) CreatePN(group_id); } Progress(float(i)/float(g_nodes.size())); } } for (u32 i=0; i<g_nodes.size(); i++) { if (!used[i]) { // analyze ProcessOne (i,8); CreatePN (group_id); } Progress(float(i)/float(g_nodes.size())); } Msg("Optimization ratio: %2.1f%%\n", 100.f*float(group_id)/float(g_nodes.size()) ); Msg("%d / %d\n%d seconds elapsed.", group_id,g_nodes.size(), (timeGetTime()-start_time)/1000); }
IC void Begin (int count) { q_List.reserve (8192); q_Clear.reserve (8192); q_Marks.assign (count,false); }
void xrSmoothNodes() { Nodes smoothed; smoothed.reserve(g_nodes.size()); Marks mark; mark.assign(g_nodes.size(),false); int inv_count = 0; for (u32 i=0; i<g_nodes.size(); i++) { vertex& N = g_nodes[i]; Fvector P1,P2,P3,P4,P,REF; int c; // smooth point LF { bool bCorner = false; c=1; N.PointLF(REF); P1.set(REF); if (N.nLeft()!=InvalidNode) { vertex& L = g_nodes[N.nLeft()]; L.PointFR(P); merge(P1); if (L.nForward()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[L.nForward()]; C.PointRB(P); merge(P1); } } if (N.nForward()!=InvalidNode) { vertex& F = g_nodes[N.nForward()]; F.PointBL(P); merge(P1); if ((!bCorner) && (F.nLeft()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[F.nLeft()]; C.PointRB(P); merge(P1); } } R_ASSERT(c<=4); P1.div(float(c)); } // smooth point FR { bool bCorner = false; c=1; N.PointFR(REF); P2.set(REF); if (N.nForward()!=InvalidNode) { vertex& F = g_nodes[N.nForward()]; F.PointRB(P); merge(P2); if (F.nRight()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[F.nRight()]; C.PointBL(P); merge(P2); } } if (N.nRight()!=InvalidNode) { vertex& R = g_nodes[N.nRight()]; R.PointLF(P); merge(P2); if ((!bCorner) && (R.nForward()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[R.nForward()]; C.PointBL(P); merge(P2); } } R_ASSERT(c<=4); P2.div(float(c)); } // smooth point RB { bool bCorner = false; c=1; N.PointRB(REF); P3.set(REF); if (N.nRight()!=InvalidNode) { vertex& R = g_nodes[N.nRight()]; R.PointBL(P); merge(P3); if (R.nBack()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[R.nBack()]; C.PointLF(P); merge(P3); } } if (N.nBack()!=InvalidNode) { vertex& B = g_nodes[N.nBack()]; B.PointFR(P); merge(P3); if ((!bCorner) && (B.nRight()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[B.nRight()]; C.PointLF(P); merge(P3); } } R_ASSERT(c<=4); P3.div(float(c)); } // smooth point BL { bool bCorner = false; c=1; N.PointBL(REF); P4.set(REF); if (N.nBack()!=InvalidNode) { vertex& B = g_nodes[N.nBack()]; B.PointLF(P); merge(P4); if (B.nLeft()!=InvalidNode) { bCorner = true; vertex& C = g_nodes[B.nLeft()]; C.PointFR(P); merge(P4); } } if (N.nLeft()!=InvalidNode) { vertex& L = g_nodes[N.nLeft()]; L.PointRB(P); merge(P4); if ((!bCorner) && (L.nBack()!=InvalidNode)) { bCorner = true; vertex& C = g_nodes[L.nBack()]; C.PointFR(P); merge(P4); } } R_ASSERT(c<=4); P4.div(float(c)); } // align plane Fvector data[4]; data[0]=P1; data[1]=P2; data[2]=P3; data[3]=P4; Fvector vOffs,vNorm,D; vNorm.set(N.Plane.n); vOffs.set(N.Pos); Mgc::OrthogonalPlaneFit( 4,(Mgc::Vector3*)data, *((Mgc::Vector3*)&vOffs), *((Mgc::Vector3*)&vNorm) ); if (vNorm.y<0) vNorm.invert(); // create _new node vertex NEW = N; NEW.Plane.build (vOffs,vNorm); D.set (0,1,0); N.Plane.intersectRayPoint(N.Pos,D,NEW.Pos); // "project" position smoothed.push_back (NEW); // verify placement /* mark[i] = !!ValidNode (NEW); if (!mark[i]) inv_count++;. */ } g_nodes = smoothed; if (inv_count) Msg("%d invalid nodes detected",inv_count); }