/* =============== ClusterMerge Merges the portal visibility for a leaf =============== */ void ClusterMerge( int leafnum ){ leaf_t *leaf; byte portalvector[MAX_PORTALS / 8]; byte uncompressed[MAX_MAP_LEAFS / 8]; byte compressed[MAX_MAP_LEAFS / 8]; int i, j; int numvis; byte *dest; portal_t *p; int pnum; // OR together all the portalvis bits memset( portalvector, 0, portalbytes ); leaf = &leafs[leafnum]; for ( i = 0 ; i < leaf->numportals ; i++ ) { p = leaf->portals[i]; if ( p->status != stat_done ) { Error( "portal not done" ); } for ( j = 0 ; j < portallongs ; j++ ) ( (long *)portalvector )[j] |= ( (long *)p->portalvis )[j]; pnum = p - portals; portalvector[pnum >> 3] |= 1 << ( pnum & 7 ); } // convert portal bits to leaf bits numvis = LeafVectorFromPortalVector( portalvector, uncompressed ); if ( uncompressed[leafnum >> 3] & ( 1 << ( leafnum & 7 ) ) ) { Sys_Printf( "WARNING: Leaf portals saw into leaf\n" ); } uncompressed[leafnum >> 3] |= ( 1 << ( leafnum & 7 ) ); numvis++; // count the leaf itself // save uncompressed for PHS calculation memcpy( uncompressedvis + leafnum * leafbytes, uncompressed, leafbytes ); // // compress the bit string // Sys_FPrintf( SYS_VRB, "cluster %4i : %4i visible\n", leafnum, numvis ); totalvis += numvis; i = CompressVis( uncompressed, compressed ); dest = vismap_p; vismap_p += i; if ( vismap_p > vismap_end ) { Error( "Vismap expansion overflow" ); } dvis->bitofs[leafnum][DVIS_PVS] = dest - vismap; memcpy( dest, compressed, i ); }
/* ================ CalcPHS Calculate the PHS (Potentially Hearable Set) by ORing together all the PVS visible from a leaf ================ */ void CalcPHS (void) { int i, j, k, l, index; int bitbyte; long *dest, *src; byte *scan; int count; byte uncompressed[MAX_MAP_LEAFS/8]; byte compressed[MAX_MAP_LEAFS/8]; printf ("Building PHS...\n"); count = 0; for (i=0 ; i<portalclusters ; i++) { scan = uncompressedvis + i*leafbytes; memcpy (uncompressed, scan, leafbytes); for (j=0 ; j<leafbytes ; j++) { bitbyte = scan[j]; if (!bitbyte) continue; for (k=0 ; k<8 ; k++) { if (! (bitbyte & (1<<k)) ) continue; // OR this pvs row into the phs index = ((j<<3)+k); if (index >= portalclusters) Error ("Bad bit in PVS"); // pad bits should be 0 src = (long *)(uncompressedvis + index*leafbytes); dest = (long *)uncompressed; for (l=0 ; l<leaflongs ; l++) ((long *)uncompressed)[l] |= src[l]; } } for (j=0 ; j<portalclusters ; j++) if (uncompressed[j>>3] & (1<<(j&7)) ) count++; // // compress the bit string // j = CompressVis (uncompressed, compressed); dest = (long *)vismap_p; vismap_p += j; if (vismap_p > vismap_end) Error ("Vismap expansion overflow"); dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap; memcpy (dest, compressed, j); } printf ("Average clusters hearable: %i\n", count/portalclusters); }
/* * @brief Merges the portal visibility for a leaf. */ static void ClusterMerge(uint32_t leaf_num) { leaf_t *leaf; byte portalvector[MAX_BSP_PORTALS / 8]; byte uncompressed[MAX_BSP_LEAFS / 8]; byte compressed[MAX_BSP_LEAFS / 8]; uint32_t i, j; int32_t numvis; byte *dest; portal_t *p; int32_t pnum; if (map_vis.portal_bytes > sizeof(portalvector)) { Com_Error(ERR_FATAL, "VIS overflow. Try making more brushes CONTENTS_DETAIL.\n"); } // OR together all the portal vis bits memset(portalvector, 0, map_vis.portal_bytes); leaf = &map_vis.leafs[leaf_num]; for (i = 0; i < leaf->num_portals; i++) { p = leaf->portals[i]; if (p->status != stat_done) Com_Error(ERR_FATAL, "Portal not done\n"); for (j = 0; j < map_vis.portal_longs; j++) ((long *) portalvector)[j] |= ((long *) p->vis)[j]; pnum = p - map_vis.portals; portalvector[pnum >> 3] |= 1 << (pnum & 7); } // convert portal bits to leaf bits numvis = LeafVectorFromPortalVector(portalvector, uncompressed); if (uncompressed[leaf_num >> 3] & (1 << (leaf_num & 7))) { Com_Warn("Leaf portals saw into leaf\n"); } uncompressed[leaf_num >> 3] |= (1 << (leaf_num & 7)); numvis++; // count the leaf itself // save uncompressed for PHS calculation memcpy(map_vis.uncompressed + leaf_num * map_vis.leaf_bytes, uncompressed, map_vis.leaf_bytes); // compress the bit string Com_Debug("Cluster %4i : %4i visible\n", leaf_num, numvis); visibility_count += numvis; i = CompressVis(uncompressed, compressed); dest = map_vis.pointer; map_vis.pointer += i; if (map_vis.pointer > map_vis.end) Com_Error(ERR_FATAL, "VIS expansion overflow\n"); d_vis->bit_offsets[leaf_num][DVIS_PVS] = dest - map_vis.base; memcpy(dest, compressed, i); }
/* * @brief Calculate the PHS (Potentially Hearable Set) * by ORing together all the PVS visible from a leaf */ static void CalcPHS(void) { uint32_t i, j, k, l, index; int32_t bitbyte; long *dest, *src; byte *scan; int32_t count; byte uncompressed[MAX_BSP_LEAFS / 8]; byte compressed[MAX_BSP_LEAFS / 8]; Com_Verbose("Building PHS...\n"); count = 0; for (i = 0; i < map_vis.portal_clusters; i++) { scan = map_vis.uncompressed + i * map_vis.leaf_bytes; memcpy(uncompressed, scan, map_vis.leaf_bytes); for (j = 0; j < map_vis.leaf_bytes; j++) { bitbyte = scan[j]; if (!bitbyte) continue; for (k = 0; k < 8; k++) { if (!(bitbyte & (1 << k))) continue; // OR this pvs row into the phs index = ((j << 3) + k); if (index >= map_vis.portal_clusters) Com_Error(ERR_FATAL, "Bad bit vector in PVS\n"); // pad bits should be 0 src = (long *) (map_vis.uncompressed + index * map_vis.leaf_bytes); for (l = 0; l < map_vis.leaf_longs; l++) ((long *) uncompressed)[l] |= src[l]; } } for (j = 0; j < map_vis.portal_clusters; j++) if (uncompressed[j >> 3] & (1 << (j & 7))) count++; // compress the bit string j = CompressVis(uncompressed, compressed); dest = (long *) map_vis.pointer; map_vis.pointer += j; if (map_vis.pointer > map_vis.end) Com_Error(ERR_FATAL, "Overflow\n"); d_vis->bit_offsets[i][DVIS_PHS] = (byte *) dest - map_vis.base; memcpy(dest, compressed, j); } if (map_vis.portal_clusters) Com_Print("Average clusters hearable: %i\n", count / map_vis.portal_clusters); else Com_Print("Average clusters hearable: 0\n"); }
static int CompressAndCrosscheckClusterVis( int clusternum ) { int optimized = 0; byte compressed[MAX_MAP_LEAFS/8]; // // compress the bit string // byte *uncompressed = uncompressedvis + clusternum*leafbytes; for ( int i = 0; i < portalclusters; i++ ) { if ( i == clusternum ) continue; if ( CheckBit( uncompressed, i ) ) { byte *other = uncompressedvis + i*leafbytes; if ( !CheckBit( other, clusternum ) ) { ClearBit( uncompressed, i ); optimized++; } } } int numbytes = CompressVis( uncompressed, compressed ); byte *dest = vismap_p; vismap_p += numbytes; if (vismap_p > vismap_end) Error ("Vismap expansion overflow"); dvis->bitofs[clusternum][DVIS_PVS] = dest-vismap; memcpy( dest, compressed, numbytes ); // check vis data DecompressVis( vismap + dvis->bitofs[clusternum][DVIS_PVS], compressed ); return optimized; }
void LeafFlow (int leafnum) { leaf_t *leaf; byte *outbuffer; byte compressed[MAX_MAP_LEAFS/8]; int i, j; int numvis; byte *dest; portal_t *p; // // flow through all portals, collecting visible bits // outbuffer = uncompressed + leafnum*bitbytes; leaf = &leafs[leafnum]; for (i=0 ; i<leaf->numportals ; i++) { p = leaf->portals[i]; if (p->status != stat_done) Error ("portal not done"); for (j=0 ; j<bitbytes ; j++) outbuffer[j] |= p->visbits[j]; } if (outbuffer[leafnum>>3] & (1<<(leafnum&7))) Error ("Leaf portals saw into leaf"); outbuffer[leafnum>>3] |= (1<<(leafnum&7)); numvis = 0; for (i=0 ; i<portalleafs ; i++) if (outbuffer[i>>3] & (1<<(i&3))) numvis++; // // compress the bit string // if (verbose) printf ("leaf %4i : %4i visible\n", leafnum, numvis); totalvis += numvis; if( !noreuse ) { // Vic: reuse old vis data int i; byte *data; data = uncompressed; for( i = 0; i < leafnum; i++, data += bitbytes ) { if( !memcmp( data, outbuffer, bitbytes ) ) { c_reused++; dleafs[leafnum+1].visofs = dleafs[i+1].visofs; return; } } } #if 0 i = bitbytes; memcpy (compressed, outbuffer, bitbytes); #else i = CompressVis (outbuffer, compressed, bitbytes); #endif dest = vismap_p; vismap_p += i; if (vismap_p > vismap_end) Error ("Vismap expansion overflow"); dleafs[leafnum+1].visofs = dest-vismap; // leaf 0 is a common solid memcpy (dest, compressed, i); }