void EDetailManager::InvalidateSlots() { int slot_cnt = dtH.size_x*dtH.size_z; for (int k=0; k<slot_cnt; k++){ DetailSlot* it = &dtSlots[k]; it->w_id(0,DetailSlot::ID_Empty); it->w_id(1,DetailSlot::ID_Empty); it->w_id(2,DetailSlot::ID_Empty); it->w_id(3,DetailSlot::ID_Empty); } InvalidateCache(); }
void EDetailManager::UpdateSlotBBox(int sx, int sz, DetailSlot& slot) { Fbox bbox; Frect rect; GetSlotRect (rect,sx,sz); bbox.min.set (rect.x1, m_BBox.min.y, rect.y1); bbox.max.set (rect.x2, m_BBox.max.y, rect.y2); SBoxPickInfoVec pinf; ETOOLS::box_options(0); if (Scene->BoxPickObjects(bbox,pinf,&m_SnapObjects)){ bbox.grow (EPS_L_VAR); Fplane frustum_planes[4]; frustum_planes[0].build(bbox.min,left_vec); frustum_planes[1].build(bbox.min,back_vec); frustum_planes[2].build(bbox.max,right_vec); frustum_planes[3].build(bbox.max,fwd_vec); CFrustum frustum; frustum.CreateFromPlanes(frustum_planes,4); float y_min = flt_max; float y_max = flt_min; for (SBoxPickInfoIt it=pinf.begin(); it!=pinf.end(); it++){ for (int k=0; k<(int)it->inf.size(); k++){ float range; Fvector verts[3]; it->e_obj->GetFaceWorld(it->s_obj->_Transform(),it->e_mesh,it->inf[k].id,verts); sPoly sSrc (verts,3); sPoly sDest; sPoly* sRes = frustum.ClipPoly(sSrc, sDest); if (sRes){ for (u32 k=0; k<sRes->size(); k++){ float H = (*sRes)[k].y; if (H>y_max) y_max = H+0.03f; if (H<y_min) y_min = H-0.03f; } slot.w_y (y_min,y_max-y_min); slot.w_id(0,DetailSlot::ID_Empty); slot.w_id(1,DetailSlot::ID_Empty); slot.w_id(2,DetailSlot::ID_Empty); slot.w_id(3,DetailSlot::ID_Empty); } } } }else{ ZeroMemory(&slot,sizeof(DetailSlot)); slot.w_id(0,DetailSlot::ID_Empty); slot.w_id(1,DetailSlot::ID_Empty); slot.w_id(2,DetailSlot::ID_Empty); slot.w_id(3,DetailSlot::ID_Empty); } }
bool EDetailManager::UpdateSlotObjects(int x, int z){ srand(time(NULL)); DetailSlot* slot = dtSlots+z*dtH.size_x+x; Irect R; GetSlotTCRect(R,x,z); //ELog.Msg(mtInformation,"TC [%d,%d]-[%d,%d]",R.x1,R.y1,R.x2,R.y2); SIndexDistVec best; // find best color index { for (int v=R.y1; v<=R.y2; v++){ for (int u=R.x1; u<=R.x2; u++){ u32 clr; if (m_Base.GetColor(clr,u,v)){ Fcolor C; C.set(clr); FindClosestIndex(C,best); } } } } std::sort(best.begin(),best.end(),CompareWeightFunc); // пройдем по 4 частям слота и определим плотность заполнения (учесть переворот V) Irect P[4]; float dx=float(R.x2-R.x1)/2.f; float dy=float(R.y2-R.y1)/2.f; // 2 3 // 0 1 P[0].x1=R.x1; P[0].y1=iFloor(R.y1+dy+0.501f); P[0].x2=iFloor(R.x1+dx+.499f); P[0].y2=R.y2; P[1].x1=iFloor(R.x1+dx+0.501f); P[1].y1=iFloor(R.y1+dy+0.501f); P[1].x2=R.x2; P[1].y2=R.y2; P[2].x1=R.x1; P[2].y1=R.y1; P[2].x2=iFloor(R.x1+dx+.499f); P[2].y2=iFloor(R.y1+dy+.499f); P[3].x1=iFloor(R.x1+dx+0.501f); P[3].y1=R.y1; P[3].x2=R.x2; P[3].y2=iFloor(R.y1+dx+.499f); for (int part=0; part<4; part++){ float alpha=0; int cnt=0; for (int v=P[part].y1; v<=P[part].y2; v++){ for (int u=P[part].x1; u<=P[part].x2; u++){ u32 clr; if (m_Base.GetColor(clr,u,v)){ Fcolor C; C.set(clr); CalcClosestCount(part,C,best); alpha+=C.a; cnt++; } } } alpha/=(cnt?float(cnt):1); alpha*=0.5f; for (u32 i=0; i<best.size(); i++) best[i].dens[part] = cnt?(best[i].cnt[part]*alpha)/float(cnt):0; } // fill empty slots R_ASSERT(best.size()); int id=-1; u32 o_cnt=0; for (u32 i=0; i<best.size(); i++) o_cnt+=m_ColorIndices[best[i].index].size(); // равномерно заполняем пустые слоты if (o_cnt>best.size()){ while (best.size()<4){ do{ id++; if (id>3) id=0; }while(m_ColorIndices[best[id].index].size()<=1); best.push_back(SIndexDist()); best.back()=best[id]; if (best.size()==o_cnt) break; } } // заполним палитру и установим Random'ы // Msg("Slot: %d %d",x,z); for(u32 k=0; k<best.size(); k++){ // objects ColorIndexPairIt CI=m_ColorIndices.find(best[k].index); R_ASSERT(CI!=m_ColorIndices.end()); U8Vec elem; elem.resize(CI->second.size()); for (U8It b_it=elem.begin(); b_it!=elem.end(); b_it++) *b_it=u8(b_it-elem.begin()); // best_rand A(DetailRandom); std::random_shuffle(elem.begin(),elem.end());//,A); for (b_it=elem.begin(); b_it!=elem.end(); b_it++){ bool bNotFound=true; slot->w_id (k, GetObject(CI,*b_it)); for (u32 j=0; j<k; j++) if (slot->r_id(j)==slot->r_id(k)){ bNotFound = false; break; } if (bNotFound) break; } slot->color_editor(); // density float f = ((EDetail*)objects[slot->r_id(k)])->m_fDensityFactor; slot->palette[k].a0 = (u16)iFloor(best[k].dens[0]*f*15.f+.5f); slot->palette[k].a1 = (u16)iFloor(best[k].dens[1]*f*15.f+.5f); slot->palette[k].a2 = (u16)iFloor(best[k].dens[2]*f*15.f+.5f); slot->palette[k].a3 = (u16)iFloor(best[k].dens[3]*f*15.f+.5f); } // определим ID незаполненных слотов как пустышки for(k=best.size(); k<4; k++) slot->w_id(k,DetailSlot::ID_Empty); return true; }