void net_task_menager::receive( INetReader& r ) { send_receive_data_lock.Enter(); u32 id = r.r_u32(); xr_vector<u32>::iterator it =std::find( pool.begin(), pool.end(), id ); if( it == pool.end() ) return; pool.erase( it ); u32 pool_size = pool.size(); send_receive_data_lock.Leave(); VERIFY(inlc_global_data()); //inlc_global_data()->create_read_faces(); inlc_global_data()->g_deflectors()[id]->read( r ); //inlc_global_data()->destroy_read_faces(); u32 size = inlc_global_data()->g_deflectors().size(); clMsg( "received task : %d", id ); DumpDeflctor( id ); VERIFY( size > 0 ); //thProgress+=(1.f/size); Progress(1.f - float(pool.size())/float(size)); clMsg( "num task complited : %d , num task left %d (task num %d)", size - pool_size, pool_size, size ); if(pool.empty()) { clMsg ( "calculation complited" ); clMsg ("%f net lightmaps calculation seconds",start_time.GetElapsed_sec()); } }
void OGF::DumpFaces() { clMsg ("normal:"); for (u32 i=0; i<data.faces.size(); i++) clMsg("face #%4d: %4d %4d %4d",i,int(data.faces[i].v[0]),int(data.faces[i].v[1]),int(data.faces[i].v[2])); clMsg ("fast:"); for (u32 i=0; i<fast_path_data.faces.size(); i++) clMsg("face #%4d: %4d %4d %4d",i,int(fast_path_data.faces[i].v[0]),int(fast_path_data.faces[i].v[1]),int(fast_path_data.faces[i].v[2])); }
void CThread::startup(void* P) { CThread* T = (CThread*)P; if (T->thMessages) clMsg("* THREAD #%d: Started.",T->thID); FPU::m64r (); T->Execute (); T->thCompleted = TRUE; if (T->thMessages) clMsg("* THREAD #%d: Task Completed.",T->thID); }
void create_global_data_write() { clMsg( "create_global_data_write: start" ); gl_data_write = xr_new<INetWriter>( (IGenericStream*)(0), u32(-1) ); //INetWriter w( *stream, u32(-1) ); //send_receive_data_lock.Enter(); inlc_global_data()->write( *gl_data_write ); //send_receive_data_lock.Leave(); clMsg( "create_global_data_write: end, size %d", gl_data_write->count() ); }
void CBuild::SaveTREE (IWriter &fs) { CMemoryWriter MFS; Status ("Geometry buffers..."); xr_vector<u32> remap; remap.reserve (g_tree.size()); for (u32 rid=0; rid<g_tree.size(); rid++) { OGF* o = dynamic_cast<OGF*> (g_tree[rid]); if (o) remap.push_back(rid); } std::stable_sort (remap.begin(),remap.end(),remap_order); clMsg ("remap-size: %d / %d",remap.size(),g_tree.size()); for (u32 sid=0; sid<remap.size(); sid++) { u32 id = remap[sid]; //clMsg ("%3d: subdiv: %d",sid,id); g_tree[id]->PreSave (id); } Status ("Visuals..."); fs.open_chunk (fsL_VISUALS); for (xr_vector<OGF_Base*>::iterator it = g_tree.begin(); it!=g_tree.end(); it++) { u32 idx = u32(it-g_tree.begin()); MFS.open_chunk (idx); (*it)->Save (MFS); MFS.close_chunk (); Progress (float(idx)/float(g_tree.size())); } fs.w (MFS.pointer(),MFS.size()); fs.close_chunk (); clMsg ("Average: %d verts/%d faces, 50(%2.1f), 100(%2.1f), 500(%2.1f), 1000(%2.1f), 5000(%2.1f)", g_batch_verts/g_batch_count, g_batch_faces/g_batch_count, 100.f * float(g_batch_50)/float(g_batch_count), 100.f * float(g_batch_100)/float(g_batch_count), 100.f * float(g_batch_500)/float(g_batch_count), 100.f * float(g_batch_1000)/float(g_batch_count), 100.f * float(g_batch_5000)/float(g_batch_count) ); mem_Compact (); SaveGEOMs ("level.geom", g_VB,g_IB,g_SWI); // Normal SaveGEOMs ("level.geomx", x_VB,x_IB,x_SWI); // Fast-Path Status ("Shader table..."); fs.open_chunk (fsL_SHADERS); fs.w_u32 (g_Shaders.size()); for (xr_vector<LPCSTR>::iterator T=g_Shaders.begin(); T!=g_Shaders.end(); T++) fs.w_stringZ (*T); fs.close_chunk (); //mem_Compact (); }
void net_global_data_impl<gl_base_cl_data>::create_data_file( LPCSTR path ) { FPU::m64r (); Memory.mem_compact (); //std::random_shuffle (inlc_global_data()->g_deflectors().begin(),inlc_global_data()->g_deflectors().end()); clMsg( "create_base_global_data_write: start" ); IWriter * file = FS.w_open(path); inlc_global_data()->write_base( *file ); FS.w_close(file); compress( path ); clMsg( "create_base_global_data_write: end" ); //inlc_global_data()->create_read_faces(); //inlc_global_data()->create_write_faces(); }
void net_global_data_impl<gl_detail_cl_data>::create_data_file( LPCSTR path ) { //FPU::m64r (); //Memory.mem_compact (); //if(!write_faces) //inlc_global_data()->create_write_faces(); clMsg( "gl_detail_cl_data: start" ); IWriter * file = FS.w_open(path); gl_data.write( *file ); FS.w_close(file); compress( path ); clMsg( "gl_detail_cl_data: end" ); }
void __cdecl GetDataCallback(const char* dataDesc, IGenericStream** stream) { clMsg( "GetDataCallback: send start" ); VERIFY(xr_strcmp(dataDesc,"global_data")==0); CTimer time; time.Start(); R_ASSERT(gl_data_write); *stream = CreateGenericStream(); //*stream = gl_data_write->net_stream(); gl_data_write->send_not_clear(*stream); //*stream->Release(); clMsg( "GetDataCallback: send end time elapsed sec: %f, ", time.GetElapsed_sec() ); //(*stream) = new TGenericStream(20000000); //(*stream)->Write(globalDataStream->GetBasePointer(), globalDataStream->GetLength()); }
void net_task_menager::run() { start_time.Start(); create_global_data_write(); inlc_global_data()->create_read_faces(); IGridUser* user = CreateGridUserObject(IGridUser::VERSION); VERIFY( user ); user->BindGetDataCallback(GetDataCallback); Status ("Lighting..."); VERIFY ( inlc_global_data() ); u32 size = inlc_global_data()->g_deflectors().size(); std::random_shuffle (inlc_global_data()->g_deflectors().begin(),inlc_global_data()->g_deflectors().end()); for (u32 dit = 0; dit<size; dit++) pool.push_back(dit); FPU::m64r (); Memory.mem_compact (); for (u32 dit = 0; dit<size; dit++) send( *user, dit ); user->WaitForCompletion(); gl_data_write->clear(); xr_delete(gl_data_write); inlc_global_data()->destroy_read_faces(); user->Release(); clMsg ("%f net lightmaps seconds",start_time.GetElapsed_sec()); }
virtual void Execute() { CDeflector* D = 0; for (;;) { // Get task task_CS.Enter (); thProgress = 1.f - float(task_pool.size())/float(g_deflectors.size()); if (task_pool.empty()) { task_CS.Leave (); return; } D = g_deflectors[task_pool.back()]; task_pool.pop_back (); task_CS.Leave (); // Perform operation try { D->Light (&DB,&LightsSelected,H); } catch (...) { clMsg("* ERROR: CLMThread::Execute - light"); } } }
void net_global_data_impl<gl_implicit_cl_data>::create_data_file( LPCSTR path ) { //FPU::m64r (); //Memory.mem_compact (); //if(!write_faces) //inlc_global_data()->create_write_faces(); clMsg( "create_implicit_data_write: start" ); R_ASSERT(write_faces); IWriter * file = FS.w_open(path); cl_globs.write( *file ); FS.w_close(file); compress( path ); clMsg( "create_implicit_data_write: end" ); }
void CBuild::validate_splits () { for (splitIt it=g_XSplit.begin(); it!=g_XSplit.end(); it++) { u32 MODEL_ID = u32(it-g_XSplit.begin()) ; if ((*it)->size() > c_SS_HighVertLimit*2) { clMsg ("! ERROR: subdiv #%d has more than %d faces (%d)",MODEL_ID,2*c_SS_HighVertLimit,(*it)->size()); } }; }
// Calculate T&B void OGF::CalculateTB() { remove_isolated_verts( data.vertices, data.faces ); // ************************************* Declare inputs Status ( "Declarator..." ); u32 v_count_reserve = iFloor( float( data.vertices.size() )*1.33f ); u32 i_count_reserve = 3*data.faces.size(); mender_mapping_out_to_in_vert .clear( ); mender_mapping_out_to_in_vert .reserve( v_count_reserve ); mender_in_out_verts .reserve( v_count_reserve ); mender_in_out_indices .reserve( i_count_reserve ); mender_in_out_verts .clear( ); mender_in_out_indices .clear( ); fill_mender_input( data.vertices, data.faces, mender_in_out_verts, mender_in_out_indices ); u32 v_was = data.vertices.size(); u32 v_become= mender_in_out_verts.size(); clMsg ("duplication: was[%d] / become[%d] - %2.1f%%",v_was,v_become,100.f*float(v_become-v_was)/float(v_was)); // ************************************* Perform mungle Status ("Calculating basis..."); MeshMender mender ; if ( !mender.Mend ( mender_in_out_verts, mender_in_out_indices, mender_mapping_out_to_in_vert, 1, 0.5, 0.5, 0.0f, MeshMender::DONT_CALCULATE_NORMALS, MeshMender::RESPECT_SPLITS, MeshMender::DONT_FIX_CYLINDRICAL ) ) { xrDebug::Fatal (DEBUG_INFO, "NVMeshMender failed " ); //xrDebug::Fatal (DEBUG_INFO,"NVMeshMender failed (%s)",mender.GetLastError().c_str()); } // ************************************* Bind declarators // bind retrive_data_from_mender_otput( data.vertices, data.faces, mender_in_out_verts, mender_in_out_indices, mender_mapping_out_to_in_vert ); remove_isolated_verts( data.vertices, data.faces ); mender_in_out_verts .clear( ); mender_in_out_indices .clear( ); mender_mapping_out_to_in_vert .clear( ); }
void CBuild::CorrectTJunctions() { Status ("Processing..."); vecJunctions = xr_new<xr_vector<record> > (); vecJunctions->reserve (1024); vecEdges = xr_new<xr_vector<record> > (); vecEdges->reserve (1024); for (u32 I=0; I<g_faces.size(); I++) { Face* F = g_faces[I]; // Iterate on edges for (u32 e=0; e<3; e++) { Vertex *vA,*vB; F->EdgeVerts (e,&vA,&vB); // Iterate on 'vA'-adjacent faces for (u32 f1=0; f1!=vA->adjacent.size(); f1++) { Face* F1 = vA->adjacent[f1]; // Iterate on it's edges for (u32 e1=0; e1<3; e1++) { Vertex *v1,*v2; F1->EdgeVerts (e1,&v1,&v2); edge (v1,v2); if (v1==vA && v2!=vB) check(vA,vB,v2); else if (v2==vA && v1!=vB) check(vA,vB,v1); } } // Iterate on 'vB'-adjacent faces for (u32 f2=0; f2!=vB->adjacent.size(); f2++) { Face* F2 = vB->adjacent[f2]; // Iterate on it's edges for (u32 e1=0; e1<3; e1++) { Vertex *v1,*v2; F2->EdgeVerts (e1,&v1,&v2); edge (v1,v2); if (v1==vB && v2!=vA) check(vA,vB,v2); else if (v2==vB && v1!=vA) check(vA,vB,v1); } } } Progress(float(I)/float(g_faces.size())); } clMsg("*** %d junctions and %d long edges found.",vecJunctions->size(),vecEdges->size()); xr_delete(vecJunctions); xr_delete(vecEdges); }
void transfer(const char *name, xr_vector<T> &dest, IReader& F, u32 chunk) { IReader* O = F.open_chunk(chunk); u32 count = O?(O->length()/sizeof(T)):0; clMsg ("* %16s: %d",name,count); if (count) { dest.reserve(count); dest.insert (dest.begin(), (T*)O->pointer(), (T*)O->pointer() + count); } if (O) O->close (); }
void calc_ogf( xrMU_Model & mu_model ) { // Build OGFs for (xrMU_Model::v_subdivs_it it=mu_model.m_subdivs.begin(); it!=mu_model.m_subdivs.end(); it++) { OGF* pOGF = xr_new<OGF> (); b_material* M = &(pBuild->materials()[it->material]); // and it's material R_ASSERT (M); try { // Common data pOGF->Sector = 0; pOGF->material = it->material; // Collect textures OGF_Texture T; TRY (T.name = pBuild->textures()[M->surfidx].name); TRY (T.pBuildSurface = &(pBuild->textures()[M->surfidx])); TRY (pOGF->textures.push_back(T)); // Collect faces & vertices try { xrMU_Model::v_faces_it _beg = mu_model.m_faces.begin() + it->start; xrMU_Model::v_faces_it _end = _beg + it->count; for (xrMU_Model::v_faces_it Fit =_beg; Fit!=_end; Fit++) { _face* FF = *Fit; R_ASSERT (FF); OGF_AddFace( *pOGF, *FF, mu_model ); } } catch (...) { clMsg("* ERROR: MU2OGF, model %s, *faces*",*(mu_model.m_name)); } } catch (...) { clMsg("* ERROR: MU2OGF, 1st part, model %s",*(mu_model.m_name)); } try { pOGF->Optimize (); } catch (...) { clMsg ("* ERROR: MU2OGF, [optimize], model %s",*(mu_model.m_name)); } try { pOGF->CalcBounds (); } catch (...) { clMsg ("* ERROR: MU2OGF, [bounds], model %s",*(mu_model.m_name)); } try { pOGF->CalculateTB (); } catch (...) { clMsg ("* ERROR: MU2OGF, [calc_tb], model %s",*(mu_model.m_name)); } try { pOGF->MakeProgressive (c_PM_MetricLimit_mu); } catch (...) { clMsg ("* ERROR: MU2OGF, [progressive], model %s",*(mu_model.m_name)); } try { pOGF->Stripify (); } catch (...) { clMsg ("* ERROR: MU2OGF, [stripify], model %s",*(mu_model.m_name)); } it->ogf = pOGF; } }
void CBuild::LightVertex () { g_trans = xr_new<mapVert> (); // Start threads, wait, continue --- perform all the work Status ("Calculating..."); CThreadManager Threads; VLT.init (); CTimer start_time; start_time.Start(); for (u32 thID=0; thID<NUM_THREADS; thID++) Threads.start(xr_new<CVertexLightThread>(thID)); Threads.wait (); clMsg ("%f seconds",start_time.GetElapsed_sec()); // Process all groups Status ("Transluenting..."); for (mapVertIt it=g_trans->begin(); it!=g_trans->end(); it++) { // Unique vecVertex& VL = it->second; std::sort (VL.begin(),VL.end()); VL.erase (std::unique(VL.begin(),VL.end()),VL.end()); // Calc summary color base_color_c C; for (u32 v=0; v<VL.size(); v++) { base_color_c cc; VL[v]->C._get(cc); C.max (cc); } // Calculate final vertex color for (u32 v=0; v<VL.size(); v++) { base_color_c vC; VL[v]->C._get (vC); // trans-level float level = vC._tmp_; // base_color_c R; R.lerp (vC,C,level); R.max (vC); VL[v]->C._set (R); } } xr_delete (g_trans); }
void net_task_menager::send( IGridUser& user, u32 id ) { //send_receive_data_lock.Enter(); IGenericStream* stream = CreateGenericStream(); { INetWriter w( stream, 100 ); w.w_u32( id ); } DWORD t_id = id; user.RunTask( libraries ,"RunTask",stream,Finalize,&t_id,true); clMsg( "send task : %d", id ); DumpDeflctor( id ); //send_receive_data_lock.Leave(); }
void CBuild::mem_CompactSubdivs() { // Memory compact CTimer dwT; dwT.Start(); vecFace temp; for (int SP = 0; SP<int(g_XSplit.size()); SP++) { temp.clear (); temp.assign (g_XSplit[SP]->begin(),g_XSplit[SP]->end()); xr_delete (g_XSplit[SP]); mem_Compact (); g_XSplit[SP] = xr_new<vecFace> (); g_XSplit[SP]->assign(temp.begin(),temp.end()); } clMsg ("%d ms for memory compacting...",dwT.GetElapsed_ms()); }
void vfOptimizeParameters(xr_vector<xr_vector<REAL> > &A, xr_vector<xr_vector<REAL> > &B, xr_vector<REAL> &C, xr_vector<REAL> &D, REAL dEpsilon, REAL dAlpha, REAL dBeta, REAL dNormaFactor, u32 dwMaxIterationCount) { u32 dwTestCount = (u32)B.size(); xr_vector<REAL> daGradient; xr_vector<REAL> daDelta; xr_vector<xr_vector<REAL> > daEvalResults; daEvalResults.resize(dwTestCount); if (!B.size()) { clMsg ("! ERROR : there are no parameters to fit!"); return; } u32 dwParameterCount = (u32)B[0].size(); C.assign (dwParameterCount,1.0f); D.assign (dwParameterCount,0.0f); daDelta.assign (dwParameterCount,0); daGradient.assign (dwParameterCount,0); { for (u32 i=0; i<dwTestCount; i++) daEvalResults[i].resize(dwParameterCount); } u32 i = 0; REAL dFunctional = dfComputeEvalResults(daEvalResults,A,B,C,D), dPreviousFunctional; //clMsg ("* MU-fitter: %6d : %17.8f (%17.8f)",i,dFunctional,dFunctional/dwTestCount); do { dPreviousFunctional = dFunctional; dafGradient (daEvalResults, daGradient, B, dNormaFactor); std::transform (daGradient.begin(), daGradient.end(), daGradient.begin(), std::bind2nd(std::multiplies<REAL>(), -dAlpha)); std::transform (daDelta.begin(), daDelta.end(), daDelta.begin(), std::bind2nd(std::multiplies<REAL>(), dBeta)); std::transform (daGradient.begin(), daGradient.end(), daDelta.begin(), daDelta.begin(), std::plus<REAL>()); std::transform (C.begin(), C.end(), daDelta.begin(), C.begin(), std::plus<REAL>()); std::transform (D.begin(), D.end(), daDelta.begin(), D.begin(), std::plus<REAL>()); dFunctional = dfComputeEvalResults(daEvalResults,A,B,C,D); i++; } while ((((dPreviousFunctional - dFunctional)/dwTestCount) > dEpsilon) && (i <= dwMaxIterationCount)); if (dPreviousFunctional < dFunctional) { std::transform (daDelta.begin(), daDelta.end(), daDelta.begin(), std::bind2nd(std::multiplies<REAL>(), -1)); std::transform (C.begin(), C.end(), daDelta.begin(), C.begin(), std::plus<REAL>()); std::transform (D.begin(), D.end(), daDelta.begin(), D.begin(), std::plus<REAL>()); } dFunctional = dfComputeEvalResults(daEvalResults,A,B,C,D); //clMsg ("* MU-fitter: %6d : %17.8f (%17.8f)",i,dFunctional,dFunctional/dwTestCount); }
void CBuild::Light() { //****************************************** Implicit { FPU::m64r (); Phase ("LIGHT: Implicit..."); mem_Compact (); ImplicitLighting(); } //****************************************** Lmaps { FPU::m64r (); Phase ("LIGHT: LMaps..."); mem_Compact (); // Randomize deflectors std::random_shuffle (g_deflectors.begin(),g_deflectors.end()); for (u32 dit = 0; dit<g_deflectors.size(); dit++) task_pool.push_back(dit); // Main process (4 threads) Status ("Lighting..."); CThreadManager threads; const u32 thNUM = 6; CTimer start_time; start_time.Start(); for (int L=0; L<thNUM; L++) threads.start(xr_new<CLMThread> (L)); threads.wait (500); clMsg ("%f seconds",start_time.GetElapsed_sec()); } //****************************************** Vertex FPU::m64r (); Phase ("LIGHT: Vertex..."); mem_Compact (); LightVertex (); //****************************************** Merge LMAPS { FPU::m64r (); Phase ("LIGHT: Merging lightmaps..."); mem_Compact (); xrPhase_MergeLM (); } }
void xrMU_Model::calc_lighting () { // BB Fbox BB; BB.invalidate (); for (v_vertices_it vit=m_vertices.begin(); vit!=m_vertices.end(); vit++) BB.modify ((*vit)->P); // Export CForm CDB::CollectorPacked CL (BB,(u32)m_vertices.size(),(u32)m_faces.size()); export_cform_rcast (CL,Fidentity); CDB::MODEL* M = xr_new<CDB::MODEL> (); M->build (CL.getV(),(u32)CL.getVS(),CL.getT(),(u32)CL.getTS()); calc_lighting (color,Fidentity,M,inlc_global_data()->L_static(),LP_dont_rgb+LP_dont_sun); xr_delete (M); clMsg ("model '%s' - REF_lighted.",*m_name); }
void CLevelSpawnConstructor::fill_level_changers () { for (u32 i=0, n=(u32)level_changers().size(); i<n; ++i) { if (level_id(level_changers()[i]->m_caLevelToChange) != m_level.id()) continue; bool found = false; GRAPH_POINT_STORAGE::const_iterator I = m_graph_points.begin(); GRAPH_POINT_STORAGE::const_iterator E = m_graph_points.end(); for ( ; I != E; ++I) if (!xr_strcmp(*level_changers()[i]->m_caLevelPointToChange,(*I)->name_replace())) { bool ok = false; for (u32 ii=0, nn = game_graph().header().vertex_count(); ii<nn; ++ii) { if ((game_graph().vertex(ii)->level_id() != m_level.id()) || !game_graph().vertex(ii)->level_point().similar((*I)->o_Position,.001f)) continue; level_changers()[i]->m_tNextGraphID = (GameGraph::_GRAPH_ID)ii; level_changers()[i]->m_tNextPosition = (*I)->o_Position; level_changers()[i]->m_tAngles = (*I)->o_Angle; level_changers()[i]->m_dwNextNodeID = game_graph().vertex(ii)->level_vertex_id(); ok = true; break; } R_ASSERT3 (ok,"Cannot find a correspndance between graph and graph points from level editor! Rebuild graph for the level ",*level_changers()[i]->m_caLevelToChange); level_changers().erase (level_changers().begin() + i); --i; --n; found = true; break; } if (!found) { clMsg ("Graph point %s not found (level changer %s)",*level_changers()[i]->m_caLevelPointToChange,level_changers()[i]->name_replace()); VERIFY (false); } } }
void CBuild::BuildSectors() { Status("Determining sectors..."); Progress(0); u32 SectorMax=0; for (u32 I=0; I<g_tree.size(); I++) if (g_tree[I]->Sector>SectorMax) SectorMax=g_tree[I]->Sector; R_ASSERT(SectorMax<0xffff); u32 SectorCount = SectorMax+1; g_sectors.resize(SectorCount); ZeroMemory(&*g_sectors.begin(),(u32)g_sectors.size()*sizeof(void*)); clMsg("%d sectors accepted.",SectorCount); Status("Spatializing geometry..."); for (u32 I=0; I<g_tree.size(); I++) { u32 Sector = g_tree[I]->Sector; if (0==g_sectors[Sector]) g_sectors[Sector] = xr_new<CSector> (Sector); } Status("Building hierrarhy..."); for (u32 I=0; I<g_sectors.size(); I++) { R_ASSERT(g_sectors[I]); g_sectors[I]->BuildHierrarhy(); Progress(float(I)/float(g_sectors.size())); } Status("Assigning portals, occluders, glows, lights..."); // portals for (u32 I=0; I<portals.size(); I++) { b_portal &P = portals[I]; R_ASSERT(u32(P.sector_front)<g_sectors.size()); R_ASSERT(u32(P.sector_back) <g_sectors.size()); g_sectors[u32(P.sector_front)]->add_portal (u16(I)); g_sectors[u32(P.sector_back)]->add_portal (u16(I)); } // glows for (u32 I=0; I<glows.size(); I++) { b_glow &G = glows[I]; b_material &M = materials[G.dwMaterial]; R_ASSERT(M.sector<g_sectors.size()); g_sectors[M.sector]->add_glow (u16(I)); } // lights for (u32 I=0; I<L_dynamic.size(); I++) { b_light_dynamic &L = L_dynamic[I]; if (L.data.type == D3DLIGHT_DIRECTIONAL) { for (u32 j=0; j<g_sectors.size(); j++) { R_ASSERT(g_sectors[j]); g_sectors[j]->add_light(u16(I)); } } else { if (L.sectors.size()) { for (u32 j=0; j<L.sectors.size(); j++) { R_ASSERT (L.sectors[j]<g_sectors.size()); g_sectors [L.sectors[j]]->add_light(u16(I)); } } else { clMsg("F**k!!! Light at position %f,%f,%f non associated!!!", L.data.position.x,L.data.position.y,L.data.position.z ); } } } }
void CBuild::xrPhase_UVmap() { // Main loop Status ("Processing..."); lc_global_data()->g_deflectors().reserve (64*1024); float p_cost = 1.f / float(g_XSplit.size()); float p_total = 0.f; vecFace faces_affected; for (int SP = 0; SP<int(g_XSplit.size()); SP++) { Progress (p_total+=p_cost); // ManOwaR, unsure: // Call to IsolateVertices() looks useless here // Calculation speed up, so commented // IsolateVertices (FALSE); // Detect vertex-lighting and avoid this subdivision R_ASSERT (!g_XSplit[SP]->empty()); Face* Fvl = g_XSplit[SP]->front(); if (Fvl->Shader().flags.bLIGHT_Vertex) continue; // do-not touch (skip) if (!Fvl->Shader().flags.bRendering) continue; // do-not touch (skip) if (Fvl->hasImplicitLighting()) continue; // do-not touch (skip) // find first poly that doesn't has mapping and start recursion while (TRUE) { // Select maximal sized poly Face * msF = NULL; float msA = 0; for (vecFaceIt it = g_XSplit[SP]->begin(); it!=g_XSplit[SP]->end(); it++) { if ( (*it)->pDeflector == NULL ) { float a = (*it)->CalcArea(); if (a>msA) { msF = (*it); msA = a; } } } if (msF) { CDeflector *D = xr_new<CDeflector>(); lc_global_data()->g_deflectors().push_back (D); // Start recursion from this face start_unwarp_recursion(); D->OA_SetNormal (msF->N); msF->OA_Unwarp (D); //Deflector = D; // break the cycle to startup again D->OA_Export (); // Detach affected faces faces_affected.clear (); for (int i=0; i<int(g_XSplit[SP]->size()); i++) { Face *F = (*g_XSplit[SP])[i]; if ( F->pDeflector == D ) { faces_affected.push_back(F); g_XSplit[SP]->erase (g_XSplit[SP]->begin()+i); i--; } } // detaching itself Detach (&faces_affected); g_XSplit.push_back (xr_new<vecFace> (faces_affected)); } else { if (g_XSplit[SP]->empty()) { xr_delete (g_XSplit[SP]); g_XSplit.erase (g_XSplit.begin()+SP); SP--; } // Cancel infine loop (while) break; } } } clMsg("%d subdivisions...",g_XSplit.size()); err_save (); }
void CBuild::BuildCForm () { // Collecting data Phase ("CFORM: creating..."); vecFace* cfFaces = new vecFace(); vecVertex* cfVertices = new vecVertex(); { xr_vector<bool> cfVertexMarks; cfVertexMarks.assign (lc_global_data()->g_vertices().size(),false); Status("Sorting..."); std::sort(lc_global_data()->g_vertices().begin(),lc_global_data()->g_vertices().end()); Status("Collecting faces..."); cfFaces->reserve (lc_global_data()->g_faces().size()); for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); ++I) { Face* F = *I; if (F->Shader().flags.bCollision) { cfFaces->push_back(F); int index = GetVertexIndex(F->v[0]); cfVertexMarks[index] = true; index = GetVertexIndex(F->v[1]); cfVertexMarks[index] = true; index = GetVertexIndex(F->v[2]); cfVertexMarks[index] = true; } } Status("Collecting vertices..."); cfVertices->reserve (lc_global_data()->g_vertices().size()); std::sort(cfFaces->begin(),cfFaces->end()); for (u32 V=0; V<lc_global_data()->g_vertices().size(); V++) if (cfVertexMarks[V]) cfVertices->push_back(lc_global_data()->g_vertices()[V]); } float p_total = 0; float p_cost = 1.f/(cfVertices->size()); Fbox BB; BB.invalidate(); for (vecVertexIt it = cfVertices->begin(); it!=cfVertices->end(); it++) BB.modify((*it)->P ); // CForm Phase ("CFORM: collision model..."); Status ("Items to process: %d", cfFaces->size()); p_total = 0; p_cost = 1.f/(cfFaces->size()); // Collect faces CDB::CollectorPacked CL (BB,cfVertices->size(),cfFaces->size()); for (vecFaceIt F = cfFaces->begin(); F!=cfFaces->end(); F++) { Face* T = *F; TestEdge (T->v[0],T->v[1],T); TestEdge (T->v[1],T->v[2],T); TestEdge (T->v[2],T->v[0],T); CL.add_face ( T->v[0]->P, T->v[1]->P, T->v[2]->P, T->dwMaterialGame, materials()[T->dwMaterial].sector, T->sm_group ); Progress(p_total+=p_cost); // progress } if (bCriticalErrCnt) { err_save (); clMsg ("MultipleEdges: %d faces",bCriticalErrCnt); } xr_delete (cfFaces); xr_delete (cfVertices); // Models Status ("Models..."); for (u32 ref=0; ref<mu_refs().size(); ref++) mu_refs()[ref]->export_cform_game(CL); // Simplification if (g_params().m_quality!=ebqDraft) SimplifyCFORM (CL); // bb? BB.invalidate (); for (size_t it = 0; it<CL.getVS(); it++) BB.modify( CL.getV()[it] ); // Saving string_path fn; IWriter* MFS = FS.w_open (strconcat(sizeof(fn),fn,pBuild->path,"level.cform")); Status ("Saving..."); // Header hdrCFORM hdr; hdr.version = CFORM_CURRENT_VERSION; hdr.vertcount = (u32)CL.getVS(); hdr.facecount = (u32)CL.getTS(); hdr.aabb = BB; MFS->w (&hdr,sizeof(hdr)); // Data MFS->w (CL.getV(),(u32)CL.getVS()*sizeof(Fvector)); MFS->w (CL.getT(),(u32)CL.getTS()*sizeof(CDB::TRI)); // Clear pDeflector (it is stored in the same memory space with dwMaterialGame) for (vecFaceIt I=lc_global_data()->g_faces().begin(); I!=lc_global_data()->g_faces().end(); I++) { Face* F = *I; F->pDeflector = NULL; } FS.w_close (MFS); }
void CBuild::BuildPVS() { Fvector size; Fvector pos; Fvector ground_dir; Status("Preparing..."); g_TREE_ROOT->bbox.getsize(size); g_pvs_X = iROUND(ceilf(size.x/g_params.m_sample_step))+1; g_pvs_Y = iROUND(ceilf(size.y/g_params.m_sample_step))+1; g_pvs_Z = iROUND(ceilf(size.z/g_params.m_sample_step))+1; clMsg("Ceiling dimensions: [%3d,%3d,%3d]",g_pvs_X, g_pvs_Y, g_pvs_Z); // ground pick setup XRC.RayMode (RAY_ONLYFIRST|RAY_CULL); ground_dir.set (0,-1,0); // reserve memory CFS_File pvs_map ("pvs.temp"); u32 dwSlot = 0; u32 dwSlotsTotal= g_pvs_X*g_pvs_Y*g_pvs_Z; u32 pvs_reserve = dwSlotsTotal/1024 + 512; clMsg("PVS: %d M", (pvs_reserve*sizeof(vecW))/(1024*1024)); g_pvs.reserve (pvs_reserve); // begin! Status("Processing..."); u32 dwStartTime = timeGetTime(); for (int z=0; z<g_pvs_Z; z++) { for (int x=0; x<g_pvs_X; x++) { for (int y=0; y<g_pvs_Y; y++) { pos.set(x,y,z); pos.mul(g_params.m_sample_step); pos.add(g_TREE_ROOT->bbox.min); dwSlot++; // ground pick XRC.RayPick(precalc_identity,1.f,&RCAST_Model,pos,ground_dir,g_params.m_sample_break); if (XRC.GetRayContactCount()==0) { // don't calculate PVS for this point int tmp = -1; pvs_map.write(&tmp,4); continue; } // Sample PVS data g_TREE_ROOT->VisUnroll(pos,g_selected); if (!g_selected.empty()) { g_result.resize(g_selected.size()); ZeroMemory(g_result.begin(),g_result.size()*sizeof(BOOL)); ORM_Process(g_selected.size(),pos,g_selected.begin(),g_result.begin()); // Exclude invisible for (int i=0; i<g_selected.size(); i++) { if (!g_result[i]) { if (g_tree[g_selected[i]]->isPatch) continue; g_selected.erase(g_selected.begin()+i); g_result.erase(g_result.begin()+i); i--; } } } // Compress and record PVS sample pvs_map.w_u32(CompressSelected()); g_selected.clear(); // Statistic if (dwSlot%64 == 63) { Progress(float(dwSlot)/float(dwSlotsTotal)); u32 dwCurrentTime = timeGetTime(); Status("Sample #%d\nSpeed %3.1f samples per second\nPVS entrys: %d", dwSlot,1000.f*float(dwSlot)/float(dwCurrentTime-dwStartTime), g_pvs.size() ); } } } } ORM_Destroy(); clMsg("* PVS entrys: %d", g_pvs.size()); clMsg("* Aver. Speed: %3.1f", 1000.f*float(dwSlot)/float(timeGetTime()-dwStartTime)); }
void CBuild::PreOptimize() { // We use overlapping hash table to avoid boundary conflicts vecVertex* HASH [HDIM_X+1][HDIM_Y+1][HDIM_Z+1]; Fvector VMmin, VMscale, VMeps, scale; // Calculate offset,scale,epsilon Fbox bb = scene_bb; VMscale.set (bb.max.x-bb.min.x, bb.max.y-bb.min.y, bb.max.z-bb.min.z); VMmin.set (bb.min); VMeps.set (VMscale.x/HDIM_X/2,VMscale.y/HDIM_Y/2,VMscale.z/HDIM_Z/2); VMeps.x = (VMeps.x<EPS_L)?VMeps.x:EPS_L; VMeps.y = (VMeps.y<EPS_L)?VMeps.y:EPS_L; VMeps.z = (VMeps.z<EPS_L)?VMeps.z:EPS_L; scale.set (float(HDIM_X),float(HDIM_Y),float(HDIM_Z)); scale.div (VMscale); u32 Vcount = lc_global_data()->g_vertices().size(), Vremoved=0; u32 Fcount = lc_global_data()->g_faces().size(), Fremoved=0; // Pre-alloc memory int _size = (HDIM_X+1)*(HDIM_Y+1)*(HDIM_Z+1); int _average= (Vcount/_size)/2; if (_average<2) _average = 2; { for (int ix=0; ix<HDIM_X+1; ix++) for (int iy=0; iy<HDIM_Y+1; iy++) for (int iz=0; iz<HDIM_Z+1; iz++) { HASH[ix][iy][iz] = new vecVertex(); HASH[ix][iy][iz]->reserve (_average); } } // Status("Processing..."); g_bUnregister = false; for (int it = 0; it<(int)lc_global_data()->g_vertices().size(); it++) { if (0==(it%100000)) { Progress(_sqrt(float(it)/float(lc_global_data()->g_vertices().size()))); Status ("Processing... (%d verts removed)",Vremoved); } if (it>=(int)lc_global_data()->g_vertices().size()) break; Vertex *pTest = lc_global_data()->g_vertices()[it]; Fvector &V = pTest->P; // Hash u32 ix,iy,iz; ix = iFloor ((V.x-VMmin.x)*scale.x); iy = iFloor ((V.y-VMmin.y)*scale.y); iz = iFloor ((V.z-VMmin.z)*scale.z); R_ASSERT (ix<=HDIM_X && iy<=HDIM_Y && iz<=HDIM_Z); vecVertex &H = *(HASH[ix][iy][iz]); // Search similar vertices in hash table for (vecVertexIt T=H.begin(); T!=H.end(); T++) { Vertex *pBase = *T; if (pBase->similar(*pTest,g_params().m_weld_distance)) { while(pTest->m_adjacents.size()) pTest->m_adjacents.front()->VReplace(pTest, pBase); lc_global_data()->destroy_vertex(lc_global_data()->g_vertices()[it]); Vremoved += 1; pTest = NULL; break; } } // If we get here - there is no similar vertices - register in hash tables if (pTest) { H.push_back (pTest); u32 ixE,iyE,izE; ixE = iFloor((V.x+VMeps.x-VMmin.x)*scale.x); iyE = iFloor((V.y+VMeps.y-VMmin.y)*scale.y); izE = iFloor((V.z+VMeps.z-VMmin.z)*scale.z); R_ASSERT(ixE<=HDIM_X && iyE<=HDIM_Y && izE<=HDIM_Z); if (ixE!=ix) HASH[ixE][iy][iz]->push_back (pTest); if (iyE!=iy) HASH[ix][iyE][iz]->push_back (pTest); if (izE!=iz) HASH[ix][iy][izE]->push_back (pTest); if ((ixE!=ix)&&(iyE!=iy)) HASH[ixE][iyE][iz]->push_back (pTest); if ((ixE!=ix)&&(izE!=iz)) HASH[ixE][iy][izE]->push_back (pTest); if ((iyE!=iy)&&(izE!=iz)) HASH[ix][iyE][izE]->push_back (pTest); if ((ixE!=ix)&&(iyE!=iy)&&(izE!=iz)) HASH[ixE][iyE][izE]->push_back (pTest); } } Status("Removing degenerated/duplicated faces..."); g_bUnregister = false; for (u32 it=0; it<lc_global_data()->g_faces().size(); it++) { R_ASSERT (it>=0 && it<(int)lc_global_data()->g_faces().size()); Face* F = lc_global_data()->g_faces()[it]; if ( F->isDegenerated()) { lc_global_data()->destroy_face (lc_global_data()->g_faces()[it]); Fremoved ++; } else { // Check validity F->Verify ( ); } Progress (float(it)/float(lc_global_data()->g_faces().size())); } if (InvalideFaces()) { err_save (); xrDebug::Fatal (DEBUG_INFO,"* FATAL: %d invalid faces. Compilation aborted",InvalideFaces()); } Status ("Adjacency check..."); g_bUnregister = false; for (u32 it = 0; it<lc_global_data()->g_vertices().size(); ++it) { if (lc_global_data()->g_vertices()[it] && (lc_global_data()->g_vertices()[it]->m_adjacents.empty())) { lc_global_data()->destroy_vertex (lc_global_data()->g_vertices()[it]); ++Vremoved; } } Status ("Cleanup..."); lc_global_data()->g_vertices().erase (std::remove(lc_global_data()->g_vertices().begin(),lc_global_data()->g_vertices().end(),(Vertex*)0),lc_global_data()->g_vertices().end()); lc_global_data()->g_faces().erase (std::remove(lc_global_data()->g_faces().begin(),lc_global_data()->g_faces().end(),(Face*)0),lc_global_data()->g_faces().end()); { for (int ix=0; ix<HDIM_X+1; ix++) for (int iy=0; iy<HDIM_Y+1; iy++) for (int iz=0; iz<HDIM_Z+1; iz++) { xr_delete(HASH[ix][iy][iz]); } } mem_Compact (); clMsg("%d vertices removed. (%d left)",Vcount-lc_global_data()->g_vertices().size(),lc_global_data()->g_vertices().size()); clMsg("%d faces removed. (%d left)", Fcount-lc_global_data()->g_faces().size(), lc_global_data()->g_faces().size()); // ------------------------------------------------------------- /* int err_count =0 ; for (int _1=0; _1<g_faces.size(); _1++) { Progress(float(_1)/float(g_faces.size())); for (int _2=0; _2<g_faces.size(); _2++) { if (_1==_2) continue; if (FaceEqual(*g_faces[_1],*g_faces[_2])) { err_count ++; } } } clMsg ("! duplicate/same faces found:%d",err_count); */ // ------------------------------------------------------------- }
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_ResolveMaterials() { // Count number of materials Status ("Calculating materials/subdivs..."); xr_vector<_counter> counts; { counts.reserve (256); for (vecFaceIt F_it=g_faces.begin(); F_it!=g_faces.end(); F_it++) { Face* F = *F_it; BOOL bCreate = TRUE; for (u32 I=0; I<counts.size(); I++) { if (F->dwMaterial == counts[I].dwMaterial) { counts[I].dwCount += 1; bCreate = FALSE; break; } } if (bCreate) { _counter C; C.dwMaterial = F->dwMaterial; C.dwCount = 1; counts.push_back(C); } Progress(float(F_it-g_faces.begin())/float(g_faces.size())); } } Status ("Perfroming subdivisions..."); { g_XSplit.reserve(64*1024); g_XSplit.resize (counts.size()); for (u32 I=0; I<counts.size(); I++) { g_XSplit[I] = xr_new<vecFace> (); g_XSplit[I]->reserve (counts[I].dwCount); } for (vecFaceIt F_it=g_faces.begin(); F_it!=g_faces.end(); F_it++) { Face* F = *F_it; if (!F->Shader().flags.bRendering) continue; for (u32 I=0; I<counts.size(); I++) { if (F->dwMaterial == counts[I].dwMaterial) { g_XSplit[I]->push_back (F); } } Progress(float(F_it-g_faces.begin())/float(g_faces.size())); } } Status ("Removing empty subdivs..."); { for (int SP = 0; SP<int(g_XSplit.size()); SP++) if (g_XSplit[SP]->empty()) xr_delete(g_XSplit[SP]); g_XSplit.erase(std::remove(g_XSplit.begin(),g_XSplit.end(),(vecFace*) NULL),g_XSplit.end()); } Status ("Detaching subdivs..."); { for (u32 it=0; it<g_XSplit.size(); it++) { Detach(g_XSplit[it]); } } clMsg ("%d subdivisions.",g_XSplit.size()); }