void CBuild::MergeLM() { vecDefl Layer; vecDefl deflNew; vecDefl SEL; Status("Processing..."); for (u32 light_layer=0; light_layer<pBuild->lights.size(); light_layer++) { // Select all deflectors, which contain this light-layer Layer.clear (); b_light* L_base = pBuild->lights[light_layer].original; for (int it=0; it<(int)g_deflectors.size(); it++) { if (g_deflectors[it].bMerged) continue; if (0==g_deflectors[it].GetLayer(L_base)) continue; Layer.push_back (g_deflectors[it]); } if (Layer.empty()) continue; // Resort layer // Merge this layer while (Layer.size()) { // Sort layer (by material and distance from "base" deflector) Deflector = Layer[0]; std::sort (Layer.begin()+1,Layer.end(),cmp_defl); // Select first deflectors which can fit int maxarea = lmap_size*lmap_size*6; // Max up to 6 lm selected int curarea = 0; for (it=1; it<(int)Layer.size(); it++) { int defl_area = Layer[it]->GetLayer(L_base)->Area(); if (curarea + defl_area > maxarea) break; curarea += defl_area; SEL.push_back(Layer[it]); } if (SEL.empty()) { // No deflectors found to merge // Simply transfer base deflector to _new list deflNew.push_back(Deflector); g_deflectors.erase(g_deflectors.begin()); } else { // Transfer rects SEL.push_back(Deflector); for (int K=0; K<(int)SEL.size(); K++) { _rect T; T.a.set (0,0); T.b.set (SEL[K]->lm.dwWidth+2*BORDER-1, SEL[K]->lm.dwHeight+2*BORDER-1); T.iArea = SEL[K]->iArea; selected.push_back (T); perturb.push_back (K); } // Sort by size decreasing and startup std::sort (perturb.begin(),perturb.end(),cmp_rect); InitSurface (); int id = perturb[0]; _rect &First = selected[id]; _rect_register (First,SEL[id],FALSE); best.push_back (First); best_seq.push_back (id); brect.set (First); // Process collected.reserve (SEL.size()); for (int R=1; R<(int)selected.size(); R++) { int ID = perturb[R]; if (_rect_place(selected[ID],SEL[ID])) { brect.Merge (collected.back()); best.push_back (collected.back()); best_seq.push_back (ID); } Progress(float(R)/float(selected.size())); } R_ASSERT (brect.a.x==0 && brect.a.y==0); // Analyze resuls clMsg("%3d / %3d - [%d,%d]",best.size(),selected.size(),brect.SizeX(),brect.SizeY()); CDeflector* pDEFL = new CDeflector(); pDEFL->lm.bHasAlpha = FALSE; pDEFL->lm.dwWidth = lmap_size; pDEFL->lm.dwHeight = lmap_size; for (K = 0; K<(int)best.size(); K++) { int iRealIndex = best_seq [K]; _rect& Place = best [K]; _point& Offset = Place.a; BOOL bRotated; b_texture& T = SEL[iRealIndex]->lm; int T_W = (int)T.dwWidth + 2*BORDER; int T_H = (int)T.dwHeight + 2*BORDER; if (Place.SizeX() == T_W) { R_ASSERT(Place.SizeY() == T_H); bRotated = FALSE; } else { R_ASSERT(Place.SizeX() == T_H); R_ASSERT(Place.SizeY() == T_W); bRotated = TRUE; } // Merge pDEFL->Capture (SEL[iRealIndex],Offset.x,Offset.y,Place.SizeX(),Place.SizeY(),bRotated); // Destroy old deflector vecDeflIt OLD = std::find(g_deflectors.begin(),g_deflectors.end(),SEL[iRealIndex]); VERIFY (OLD!=g_deflectors.end()); g_deflectors.erase(OLD); xr_delete (SEL[iRealIndex]); } pDEFL->Save (); deflNew.push_back (pDEFL); // Cleanup SEL.clear (); collected.clear (); selected.clear (); perturb.clear (); best.clear (); best_seq.clear (); brect.iArea = INT_MAX; } Progress(1.f-float(g_deflectors.size())/float(dwOldCount)); } } R_ASSERT(g_deflectors.empty()); g_deflectors = deflNew; clMsg ("%d lightmaps builded",g_deflectors.size()); }
void CBuild::xrPhase_MergeLM() { vecDefl Layer; // **** Select all deflectors, which contain this light-layer Layer.clear (); for (u32 it=0; it<g_deflectors.size(); it++) { CDeflector* D = g_deflectors[it]; if (D->bMerged) continue; Layer.push_back (D); } // Merge this layer (which left unmerged) while (Layer.size()) { string512 phase_name; sprintf (phase_name,"Building lightmap %d...",g_lightmaps.size()); Phase (phase_name); // Sort layer by similarity (state changes) // + calc material area Status ("Selection..."); for (u32 it=0; it<materials.size(); it++) materials[it].internal_max_area = 0; for (u32 it=0; it<Layer.size(); it++) { CDeflector* D = Layer[it]; materials[D->GetBaseMaterial()].internal_max_area = _max(D->layer.Area(),materials[D->GetBaseMaterial()].internal_max_area); } std::stable_sort(Layer.begin(),Layer.end(),sort_defl_complex); // Select first deflectors which can fit Status ("Selection..."); u32 maxarea = c_LMAP_size*c_LMAP_size*8; // Max up to 8 lm selected u32 curarea = 0; u32 merge_count = 0; for (u32 it=0; it<(int)Layer.size(); it++) { int defl_area = Layer[it]->layer.Area(); if (curarea + defl_area > maxarea) break; curarea += defl_area; merge_count ++; } // Startup Status ("Processing..."); _InitSurface (); CLightmap* lmap = xr_new<CLightmap> (); g_lightmaps.push_back (lmap); // Process for (u32 it=0; it<merge_count; it++) { if (0==(it%1024)) Status ("Process [%d/%d]...",it,merge_count); lm_layer& L = Layer[it]->layer; L_rect rT,rS; rS.a.set (0,0); rS.b.set (L.width+2*BORDER-1, L.height+2*BORDER-1); rS.iArea = L.Area(); rT = rS; if (_rect_place(rT,&L)) { BOOL bRotated; if (rT.SizeX() == rS.SizeX()) { R_ASSERT(rT.SizeY() == rS.SizeY()); bRotated = FALSE; } else { R_ASSERT(rT.SizeX() == rS.SizeY()); R_ASSERT(rT.SizeY() == rS.SizeX()); bRotated = TRUE; } lmap->Capture (Layer[it],rT.a.x,rT.a.y,rT.SizeX(),rT.SizeY(),bRotated); Layer[it]->bMerged = TRUE; } Progress(_sqrt(float(it)/float(merge_count))); } Progress (1.f); // Remove merged lightmaps Status ("Cleanup..."); vecDeflIt last = std::remove_if (Layer.begin(),Layer.end(),pred_remove()); Layer.erase (last,Layer.end()); // Save Status ("Saving..."); lmap->Save (); } clMsg ("%d lightmaps builded",g_lightmaps.size()); // Cleanup deflectors Progress (1.f); Status ("Destroying deflectors..."); for (u32 it=0; it<g_deflectors.size(); it++) xr_delete(g_deflectors[it]); g_deflectors.clear_and_free (); }