static qboolean Model_MapCreatePVS(struct map *map) { unsigned char *visdata, *scan; struct dleaf *in; int p, i; map->vis_rowlongs = (map->visleafs + 31) >> 5; map->vis_rowbytes = map->vis_rowlongs * 4; map->pvs = (unsigned char *) calloc(map->vis_rowbytes * map->visleafs, sizeof(unsigned char)); if (map->pvs == NULL) return false; if (map->header->lumps[LUMP_VISIBILITY].filelen == 0) return false; visdata = map->mod_base + map->header->lumps[LUMP_VISIBILITY].fileofs; in = (struct dleaf *)(map->mod_base + map->header->lumps[LUMP_LEAFS].fileofs); in++; scan = map->pvs; for (i=0; i<map->visleafs; i++, in++, scan += map->vis_rowbytes) { p = LittleLong(in->visofs); memcpy(scan, (p == -1) ? map->novis : DecompressVis (map, visdata + p), map->vis_rowbytes); } return true; }
static void LoadQ1Vis(bspfile_t *f, byte *vis, int size) { if (!size) { Com_DPrintf("No visinfo in map\n"); f->numClusters = 1; // required f->visRowSize = 1; // required f->visInfo = NULL; return; } // NOTE: 'size' is ignored later // create dummy clusters: 1 cluster per 1 leaf f->numClusters = f->numLeafs; int rowSize; f->visRowSize = rowSize = (f->numClusters + 7) >> 3; byte *dst = new (f->extraChain) byte [rowSize * f->numClusters]; f->visInfo = dst; // start from leaf #1 (leaf 0 is CONTENTS_SOLID and have no stored visinfo) for (int i = 1; i < f->numLeafs; i++, dst += rowSize) DecompressVis(dst, vis, f->leafs1[i].visofs, rowSize); Com_DPrintf("Decompressed vis: %d -> %d bytes\n", size, rowSize * f->numClusters); }
byte * dxModel::LeafPVS(mleaf_s *leaf) { if (leaf == leafs) { return novis; } return DecompressVis(leaf->compressed_vis); }
void PvsForOrigin (vec3_t org, byte *pvs) { dleaf_t *leaf; if (!visdatasize) { memset (pvs, 255, (numleafs+7)/8 ); return; } leaf = PointInLeaf (org); if (leaf->visofs == -1) Error ("leaf->visofs == -1"); DecompressVis (&dvisdata[leaf->visofs], pvs); }
static void LoadQ2Vis(bspfile_t *f, dBsp2Vis_t *vis, int size) { #if !LITTLE_ENDIAN if (size) // should process this only when map have visibility data { LTL(vis->numClusters); int j = vis->numClusters; for (int i = 0; i < j ; i++) { LTL(vis->bitOfs[i][0]); LTL(vis->bitOfs[i][1]); } } #endif if (!size) { Com_DPrintf("No visinfo in map\n"); if (f->numClusters > 1) { if (developer->integer) appWPrintf("WARNING: map with cluster info but without visinfo\n"); } f->numClusters = 1; // required f->visRowSize = 1; // required f->visInfo = NULL; return; } // NOTE: 'size' is ignored later int rowSize; f->visRowSize = rowSize = (f->numClusters + 7) >> 3; // decompress visinfo byte *dst = new (f->extraChain) byte [rowSize * f->numClusters]; f->visInfo = dst; for (int i = 0; i < f->numClusters; i++, dst += rowSize) DecompressVis(dst, vis, vis->bitOfs[i][dBsp2Vis_t::PVS], rowSize); Com_DPrintf("Decompressed vis: %d -> %d bytes\n", size, rowSize * f->numClusters); }
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; }
//----------------------------------------------------------------------------- // Using the PVS, compute the visible fog volumes from each leaf //----------------------------------------------------------------------------- static void CalcVisibleFogVolumes() { byte uncompressed[MAX_MAP_LEAFS/8]; int i, j, k; // Clear the contents flags for water testing for (i = 0; i < numleafs; ++i) { dleafs[i].contents &= ~CONTENTS_TESTFOGVOLUME; g_LeafMinDistToWater[i] = 65535; } for (i = 0; i < numleafs; ++i) { // If we've already discovered that this leaf needs testing, // no need to go through the work again... if (dleafs[i].contents & CONTENTS_TESTFOGVOLUME) { Assert((dleafs[i].contents & (CONTENTS_SLIME | CONTENTS_WATER)) == 0); continue; } // Don't bother checking fog volumes from solid leaves if (dleafs[i].contents & CONTENTS_SOLID) continue; // Look only for leaves which are visible from leaves that have fluid in them. if ( dleafs[i].leafWaterDataID == -1 ) continue; // Don't bother about looking from CONTENTS_SLIME; we're not going to treat that as interesting. // because slime is opaque if ( dleafs[i].contents & CONTENTS_SLIME ) continue; // First get the vis data.. int cluster = dleafs[i].cluster; if (cluster < 0) continue; DecompressVis( &dvisdata[dvis->bitofs[cluster][DVIS_PVS]], uncompressed ); // Iterate over all potentially visible clusters from this leaf for (j = 0; j < dvis->numclusters; ++j) { // Don't need to bother if this is the same as the current cluster if (j == cluster) continue; if ( !CheckBit( uncompressed, j ) ) continue; // Found a visible cluster, now iterate over all leaves // inside that cluster for (k = 0; k < g_ClusterLeaves[j].leafCount; ++k) { int nClusterLeaf = g_ClusterLeaves[j].leafs[k]; // Don't bother checking fog volumes from solid leaves if ( dleafs[nClusterLeaf].contents & CONTENTS_SOLID ) continue; // Don't bother checking from any leaf that's got fluid in it if ( dleafs[nClusterLeaf].leafWaterDataID != -1 ) continue; // Here, we've found a case where a non-liquid leaf is visible from a liquid leaf // So, in this case, we have to do the expensive test during rendering. dleafs[nClusterLeaf].contents |= CONTENTS_TESTFOGVOLUME; } } } }
static float CalcDistanceFromLeafToWater( int leafNum ) { byte uncompressed[MAX_MAP_LEAFS/8]; int j, k; // If we know that this one doesn't see a water surface then don't bother doing anything. if( ((dleafs[leafNum].contents & CONTENTS_TESTFOGVOLUME) == 0) && ( dleafs[leafNum].leafWaterDataID == -1 ) ) return 65535; // FIXME: make a define for this. // First get the vis data.. int cluster = dleafs[leafNum].cluster; if (cluster < 0) return 65535; // FIXME: make a define for this. DecompressVis( &dvisdata[dvis->bitofs[cluster][DVIS_PVS]], uncompressed ); float minDist = 65535.0f; // FIXME: make a define for this. Vector leafMin, leafMax; leafMin[0] = ( float )dleafs[leafNum].mins[0]; leafMin[1] = ( float )dleafs[leafNum].mins[1]; leafMin[2] = ( float )dleafs[leafNum].mins[2]; leafMax[0] = ( float )dleafs[leafNum].maxs[0]; leafMax[1] = ( float )dleafs[leafNum].maxs[1]; leafMax[2] = ( float )dleafs[leafNum].maxs[2]; /* CUtlVector<listplane_t> temp; // build a convex solid out of the planes so that we can get at the triangles. for( j = dleafs[i].firstleafbrush; j < dleafs[i].firstleafbrush + dleafs[i].numleafbrushes; j++ ) { dbrush_t *pBrush = &dbrushes[j]; for( k = pBrush->firstside; k < pBrush->firstside + pBrush->numsides; k++ ) { dbrushside_t *pside = dbrushsides + k; dplane_t *pplane = dplanes + pside->planenum; AddListPlane( &temp, pplane->normal[0], pplane->normal[1], pplane->normal[2], pplane->dist ); } CPhysConvex *pConvex = physcollision->ConvexFromPlanes( (float *)temp.Base(), temp.Count(), VPHYSICS_MERGE ); ConvertConvexToCollide( &pConvex, temp.RemoveAll(); } */ // Iterate over all potentially visible clusters from this leaf for (j = 0; j < dvis->numclusters; ++j) { // Don't need to bother if this is the same as the current cluster if (j == cluster) continue; // If the cluster isn't in our current pvs, then get out of here. if ( !CheckBit( uncompressed, j ) ) continue; // Found a visible cluster, now iterate over all leaves // inside that cluster for (k = 0; k < g_ClusterLeaves[j].leafCount; ++k) { int nClusterLeaf = g_ClusterLeaves[j].leafs[k]; // Don't bother testing the ones that don't see a water boundary. if( ((dleafs[nClusterLeaf].contents & CONTENTS_TESTFOGVOLUME) == 0) && ( dleafs[nClusterLeaf].leafWaterDataID == -1 ) ) continue; // Find the minimum distance between each surface on the boundary of the leaf // that we have the pvs for and each water surface in the leaf that we are testing. int nFirstFaceID = dleafs[nClusterLeaf].firstleafface; for( int leafFaceID = 0; leafFaceID < dleafs[nClusterLeaf].numleaffaces; ++leafFaceID ) { int faceID = dleaffaces[nFirstFaceID + leafFaceID]; dface_t *pFace = &dfaces[faceID]; if( pFace->texinfo == -1 ) continue; texinfo_t *pTexInfo = &texinfo[pFace->texinfo]; if( pTexInfo->flags & SURF_WARP ) { // Woo hoo!!! We found a water face. // compare the bounding box of the face with the bounding // box of the leaf that we are looking from and see // what the closest distance is. // FIXME: this could be a face/face distance between the water // face and the bounding volume of the leaf. // Get the bounding box of the face Vector faceMin, faceMax; GetBoundsForFace( faceID, faceMin, faceMax ); float dist = GetMinDistanceBetweenBoundingBoxes( leafMin, leafMax, faceMin, faceMax ); if( dist < minDist ) { minDist = dist; } } } } } return minDist; }