/* * @brief */ static void CalcVis(void) { uint32_t i; RunThreadsOn(map_vis.num_portals * 2, true, BaseVis); SortPortals(); // fast vis just uses migh_tsee for a very loose bound if (fastvis) { for (i = 0; i < map_vis.num_portals * 2; i++) { map_vis.portals[i].vis = map_vis.portals[i].flood; map_vis.portals[i].status = stat_done; } } else { RunThreadsOn(map_vis.num_portals * 2, true, FinalVis); } // assemble the leaf vis lists by OR-ing and compressing the portal lists for (i = 0; i < map_vis.portal_clusters; i++) ClusterMerge(i); if (map_vis.portal_clusters) Com_Print("Average clusters visible: %i\n", visibility_count / map_vis.portal_clusters); else Com_Print("Average clusters visible: 0\n"); }
void MakeAllScales (void) { strcpy(transferfile, source); StripExtension( transferfile ); DefaultExtension( transferfile, ".r2" ); if ( !incremental || !IsIncremental(incrementfile) || (unsigned)readtransfers(transferfile, num_patches) != num_patches ) { // determine visibility between patches BuildVisMatrix (); RunThreadsOn (num_patches, true, MakeScales); if ( incremental ) writetransfers(transferfile, num_patches); else unlink(transferfile); // release visibility matrix FreeVisMatrix (); } qprintf ("transfer lists: %5.1f megs\n" , (float)total_transfer * sizeof(transfer_t) / (1024*1024)); }
/* * ============= * LightWorld * ============= */ static void LightWorld(void) { if (dlightdata) free(dlightdata); if (colored) lightdatasize = MAX_MAP_LIGHTING; else lightdatasize = MAX_MAP_LIGHTING / 4; dlightdata = malloc(lightdatasize + 16); /* for alignment */ if (!dlightdata) Error("%s: allocation of %i bytes failed.", __func__, lightdatasize); memset(dlightdata, 0, lightdatasize + 16); if (litfile) lightdatasize /= 4; /* align filebase to a 4 byte boundary */ filebase = file_p = (byte *)(((unsigned long)dlightdata + 3) & ~3); file_end = filebase + lightdatasize; if (colored && litfile) { /* litfile data stored in dlightdata, after the white light */ lit_filebase = file_end + 12 - ((unsigned long)file_end % 12); lit_file_p = lit_filebase; lit_file_end = lit_filebase + 3 * (MAX_MAP_LIGHTING / 4); } RunThreadsOn(0, numfaces, LightThread); logprint("Lighting Completed.\n\n"); lightdatasize = file_p - filebase; logprint("lightdatasize: %i\n", lightdatasize); }
//=========================================================================== // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int)) { if (numthreads == -1) ThreadSetDefault (); workfunction = func; RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction); } //end of the function RunThreadsOnIndividual
/* ================== CalcPortalVis ================== */ void CalcPortalVis(const bsp2_t *bsp) { int i, startcount; portal_t *p; // fastvis just uses mightsee for a very loose bound if (fastvis) { for (i = 0; i < numportals * 2; i++) { portals[i].visbits = portals[i].mightsee; portals[i].status = pstat_done; } return; } /* * Count the already completed portals in case we loaded previous state */ startcount = 0; for (i = 0, p = portals; i < numportals * 2; i++, p++) { if (p->status == pstat_done) startcount++; } RunThreadsOn(startcount, numportals * 2, LeafThread, NULL); if (verbose) { logprint("portalcheck: %i portaltest: %i portalpass: %i\n", c_portalcheck, c_portaltest, c_portalpass); logprint("c_vistest: %i c_mighttest: %i c_mightseeupdate %i\n", c_vistest, c_mighttest, c_mightseeupdate); } }
/* ============= LightWorld ============= */ void LightWorld (void) { // Allocate max lightdata if (dlightdata1 != NULL) free (dlightdata1); if (dlightdata3 != NULL) free (dlightdata3); dlightdata1 = malloc (MAX_MAP_LIGHTING); dlightdata3 = malloc (MAX_MAP_LIGHTING * 3); lightdatasize1 = MAX_MAP_LIGHTING; lightdatasize3 = MAX_MAP_LIGHTING * 3; filebase1 = file_p1 = dlightdata1; file_end1 = filebase1 + MAX_MAP_LIGHTING; filebase3 = file_p3 = dlightdata3; file_end3 = filebase3 + MAX_MAP_LIGHTING * 3; RunThreadsOn (LightThread); lightdatasize1 = file_p1 - filebase1; lightdatasize3 = file_p3 - filebase3; logprintf ("lightdatasize: %s\n", PrtSize (lightdatasize1)); }
// run threads on individual numbers void RunThreadsOnIndividual(int workcnt, qboolean showpacifier, void(*func)(int)) { if( numthreads <= 0 ) ThreadSetDefault(); if ( threaded == qtrue ) Error("RunThreadsOnIndividual: recursively entered!"); workfunction = func; RunThreadsOn(workcnt, showpacifier, RunThreadsOnIndividualThread); }
/** * @brief Entry point for all thread work requests. */ void RunSingleThreadOn (void (*func)(unsigned int), int unsigned workcount, qboolean progress, const char *id) { int saved_numthreads = threadstate.numthreads; threadstate.numthreads = 1; RunThreadsOn(func, workcount, progress, id); threadstate.numthreads = saved_numthreads; }
/* ============= LightWorld ============= */ void LightWorld (void) { filebase = file_p = dlightdata; file_end = filebase + MAX_MAP_LIGHTING; RunThreadsOn (LightThread); lightdatasize = file_p - filebase; printf ("lightdatasize: %i\n", lightdatasize); }
/* ================== CalcVis ================== */ void CalcVis (void) { int i; RunThreadsOn (numportals*2, true, BasePortalVis); CalcPortalVis (); // // assemble the leaf vis lists by oring and compressing the portal lists // for (i=0 ; i<portalleafs ; i++) LeafFlow (i); printf ("average leafs visible: %i\n", totalvis / portalleafs); }
/* ================== CalcPortalVis ================== */ void CalcPortalVis (void) { int i; // fastvis just uses the flood result for a very loose bound if (fastvis) { for (i=0 ; i<numportals*2 ; i++) { portals[i].portalvis = portals[i].portalflood; portals[i].status = stat_done; } return; } RunThreadsOn(numportals*2, true, PortalFlow); }
/* ================== CalcVis ================== */ void CalcVis (void) { int i; RunThreadsOn (numportals*2, true, BasePortalVis); SortPortals (); CalcPortalVis (); // // assemble the leaf vis lists by oring and compressing the portal lists // for (i=0 ; i<portalclusters ; i++) ClusterMerge (i); Con_Print("Average clusters visible: %i\n", totalvis / portalclusters); }
/* ================== CalcPortalVis ================== */ void CalcPortalVis (void) { int i; // fastvis just uses mightsee for a very loose bound if (fastvis) { for (i=0 ; i<numportals*2 ; i++) { portals[i].visbits = portals[i].mightsee; portals[i].status = stat_done; } return; } leafon = 0; RunThreadsOn (numportals*2, true, LeafThread); qprintf ("portalcheck: %i portaltest: %i portalpass: %i\n",c_portalcheck, c_portaltest, c_portalpass); qprintf ("c_vistest: %i c_mighttest: %i\n",c_vistest, c_mighttest); }
/* ============= BounceLight ============= */ void BounceLight (void) { unsigned i; vec3_t added; char name[64]; for (i=0 ; i<num_patches ; i++) VectorScale( patches[i].totallight, TRANSFER_SCALE, emitlight[i] ); for (i=0 ; i<numbounce ; i++) { RunThreadsOn (num_patches, true, GatherLight); CollectLight( added ); qprintf ("\tBounce #%i added RGB(%.0f, %.0f, %.0f)\n", i+1, added[0], added[1], added[2] ); if ( dumppatches && (i==0 || i == (unsigned)numbounce-1) ) { sprintf (name, "bounce%i.txt", i); WriteWorld (name); } } }
void ComputePerLeafAmbientLighting() { // Figure out which lights should go in the per-leaf ambient cubes. int nInAmbientCube = 0; int nSurfaceLights = 0; for ( int i=0; i < *pNumworldlights; i++ ) { dworldlight_t *wl = &dworldlights[i]; if ( IsLeafAmbientSurfaceLight( wl ) ) wl->flags |= DWL_FLAGS_INAMBIENTCUBE; else wl->flags &= ~DWL_FLAGS_INAMBIENTCUBE; if ( wl->type == emit_surface ) ++nSurfaceLights; if ( wl->flags & DWL_FLAGS_INAMBIENTCUBE ) ++nInAmbientCube; } Msg( "%d of %d (%d%% of) surface lights went in leaf ambient cubes.\n", nInAmbientCube, nSurfaceLights, nSurfaceLights ? ((nInAmbientCube*100) / nSurfaceLights) : 0 ); g_LeafAmbientSamples.SetCount(numleafs); if ( g_bUseMPI ) { // Distribute the work among the workers. VMPI_SetCurrentStage( "ComputeLeafAmbientLighting" ); DistributeWork( numleafs, VMPI_DISTRIBUTEWORK_PACKETID, VMPI_ProcessLeafAmbient, VMPI_ReceiveLeafAmbientResults ); } else { RunThreadsOn(numleafs, true, ThreadComputeLeafAmbient); } // now write out the data Msg("Writing leaf ambient..."); g_pLeafAmbientIndex->RemoveAll(); g_pLeafAmbientLighting->RemoveAll(); g_pLeafAmbientIndex->SetCount( numleafs ); g_pLeafAmbientLighting->EnsureCapacity( numleafs*4 ); for ( int leafID = 0; leafID < numleafs; leafID++ ) { const CUtlVector<ambientsample_t> &list = g_LeafAmbientSamples[leafID]; g_pLeafAmbientIndex->Element(leafID).ambientSampleCount = list.Count(); if ( !list.Count() ) { g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = 0; } else { g_pLeafAmbientIndex->Element(leafID).firstAmbientSample = g_pLeafAmbientLighting->Count(); // compute the samples in disk format. Encode the positions in 8-bits using leaf bounds fractions for ( int i = 0; i < list.Count(); i++ ) { int outIndex = g_pLeafAmbientLighting->AddToTail(); dleafambientlighting_t &light = g_pLeafAmbientLighting->Element(outIndex); light.x = Fixed8Fraction( list[i].pos.x, dleafs[leafID].mins[0], dleafs[leafID].maxs[0] ); light.y = Fixed8Fraction( list[i].pos.y, dleafs[leafID].mins[1], dleafs[leafID].maxs[1] ); light.z = Fixed8Fraction( list[i].pos.z, dleafs[leafID].mins[2], dleafs[leafID].maxs[2] ); light.pad = 0; for ( int side = 0; side < 6; side++ ) { VectorToColorRGBExp32( list[i].cube[side], light.cube.m_Color[side] ); } } } } for ( int i = 0; i < numleafs; i++ ) { // UNDONE: Do this dynamically in the engine instead. This will allow us to sample across leaf // boundaries always which should improve the quality of lighting in general if ( g_pLeafAmbientIndex->Element(i).ambientSampleCount == 0 ) { if ( !(dleafs[i].contents & CONTENTS_SOLID) ) { Msg("Bad leaf ambient for leaf %d\n", i ); } int refLeaf = NearestNeighborWithLight(i); g_pLeafAmbientIndex->Element(i).ambientSampleCount = 0; g_pLeafAmbientIndex->Element(i).firstAmbientSample = refLeaf; } } Msg("done\n"); }
/* * ProcessWorldModel */ static void ProcessWorldModel(void){ entity_t *e; tree_t *tree; boolean_t leaked; boolean_t optimize; e = &entities[entity_num]; brush_start = e->first_brush; brush_end = brush_start + e->num_brushes; leaked = false; // perform per-block operations if(block_xh * 1024 > map_maxs[0]) block_xh = floor(map_maxs[0] / 1024.0); if((block_xl + 1) * 1024 < map_mins[0]) block_xl = floor(map_mins[0] / 1024.0); if(block_yh * 1024 > map_maxs[1]) block_yh = floor(map_maxs[1] / 1024.0); if((block_yl + 1) * 1024 < map_mins[1]) block_yl = floor(map_mins[1] / 1024.0); if(block_xl < -4) block_xl = -4; if(block_yl < -4) block_yl = -4; if(block_xh > 3) block_xh = 3; if(block_yh > 3) block_yh = 3; for(optimize = false; optimize <= true; optimize++){ Com_Verbose("--------------------------------------------\n"); RunThreadsOn((block_xh - block_xl + 1) * (block_yh - block_yl + 1), !verbose, ProcessBlock_Thread); // build the division tree // oversizing the blocks guarantees that all the boundaries // will also get nodes. Com_Verbose("--------------------------------------------\n"); tree = AllocTree(); tree->head_node = BlockTree(block_xl - 1, block_yl - 1, block_xh + 1, block_yh + 1); tree->mins[0] = (block_xl) * 1024; tree->mins[1] = (block_yl) * 1024; tree->mins[2] = map_mins[2] - 8; tree->maxs[0] = (block_xh + 1) * 1024; tree->maxs[1] = (block_yh + 1) * 1024; tree->maxs[2] = map_maxs[2] + 8; // perform the global operations MakeTreePortals(tree); if(FloodEntities(tree)) FillOutside(tree->head_node); else { leaked = true; LeakFile(tree); if(leaktest){ Com_Error(ERR_FATAL, "--- MAP LEAKED, ABORTING LEAKTEST ---\n"); } Com_Verbose("**** leaked ****\n"); } MarkVisibleSides(tree, brush_start, brush_end); if(noopt || leaked) break; if(!optimize){ FreeTree(tree); } } FloodAreas(tree); MakeFaces(tree->head_node); FixTjuncs(tree->head_node); if(!noprune) PruneNodes(tree->head_node); WriteBSP(tree->head_node); if(!leaked) WritePortalFile(tree); FreeTree(tree); }
void RunThreadsOnIndividual(int workcnt, bool showpacifier, q_threadfunction func) { workfunction = func; RunThreadsOn(workcnt, showpacifier, ThreadWorkerFunction); }