/* ============ MergeLeafPortals ============ */ void MergeLeafPortals(void) { int i, j, k, nummerges, hintsmerged; leaf_t *leaf; vportal_t *p1, *p2; fixedWinding_t *w; nummerges = 0; hintsmerged = 0; for (i = 0; i < portalclusters; i++) { leaf = &leafs[i]; if (leaf->merged >= 0) continue; for (j = 0; j < leaf->numportals; j++) { p1 = leaf->portals[j]; if (p1->removed) continue; for (k = j+1; k < leaf->numportals; k++) { p2 = leaf->portals[k]; if (p2->removed) continue; if (p1->leaf == p2->leaf) { w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal); if (w) { free( p1->winding ); //% FreeWinding(p1->winding); p1->winding = w; if (p1->hint && p2->hint) hintsmerged++; p1->hint |= p2->hint; SetPortalSphere(p1); p2->removed = qtrue; nummerges++; i--; break; } } } if (k < leaf->numportals) break; } } Sys_Printf("%6d portals merged\n", nummerges); Sys_Printf("%6d hint portals merged\n", hintsmerged); }
/* ============ LoadPortals ============ */ void LoadPortals(char *name) { int i, j, hint; vportal_t *p; leaf_t *l; char magic[80]; FILE *f; int numpoints; fixedWinding_t *w; int leafnums[2]; visPlane_t plane; if(!strcmp(name, "-")) f = stdin; else { f = fopen(name, "r"); if(!f) Error("LoadPortals: couldn't read %s\n", name); } if(fscanf(f, "%79s\n%i\n%i\n%i\n", magic, &portalclusters, &numportals, &numfaces) != 4) Error("LoadPortals: failed to read header"); if(strcmp(magic, PORTALFILE)) Error("LoadPortals: not a portal file"); Sys_Printf("%6i portalclusters\n", portalclusters); Sys_Printf("%6i numportals\n", numportals); Sys_Printf("%6i numfaces\n", numfaces); if(numportals > MAX_PORTALS) Error("MAX_PORTALS"); // these counts should take advantage of 64 bit systems automatically leafbytes = ((portalclusters + 63) & ~63) >> 3; leaflongs = leafbytes / sizeof(long); portalbytes = ((numportals * 2 + 63) & ~63) >> 3; portallongs = portalbytes / sizeof(long); // each file portal is split into two memory portals portals = safe_malloc(2 * numportals * sizeof(vportal_t)); memset(portals, 0, 2 * numportals * sizeof(vportal_t)); leafs = safe_malloc(portalclusters * sizeof(leaf_t)); memset(leafs, 0, portalclusters * sizeof(leaf_t)); for(i = 0; i < portalclusters; i++) leafs[i].merged = -1; numBSPVisBytes = VIS_HEADER_SIZE + portalclusters * leafbytes; if(numBSPVisBytes > MAX_MAP_VISIBILITY) Error("MAX_MAP_VISIBILITY exceeded"); ((int *)bspVisBytes)[0] = portalclusters; ((int *)bspVisBytes)[1] = leafbytes; for(i = 0, p = portals; i < numportals; i++) { if(fscanf(f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) Error("LoadPortals: reading portal %i", i); if(numpoints > MAX_POINTS_ON_WINDING) Error("LoadPortals: portal %i has too many points", i); if((unsigned)leafnums[0] > portalclusters || (unsigned)leafnums[1] > portalclusters) Error("LoadPortals: reading portal %i", i); if(fscanf(f, "%i ", &hint) != 1) Error("LoadPortals: reading hint state"); w = p->winding = NewFixedWinding(numpoints); w->numpoints = numpoints; for(j = 0; j < numpoints; j++) { double v[3]; int k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if(fscanf(f, "(%lf %lf %lf ) ", &v[0], &v[1], &v[2]) != 3) Error("LoadPortals: reading portal %i", i); for(k = 0; k < 3; k++) w->points[j][k] = v[k]; } fscanf(f, "\n"); // calc plane PlaneFromWinding(w, &plane); // create forward portal l = &leafs[leafnums[0]]; if(l->numportals == MAX_PORTALS_ON_LEAF) Error("Leaf with too many portals"); l->portals[l->numportals] = p; l->numportals++; p->num = i + 1; p->hint = hint; p->winding = w; VectorSubtract(vec3_origin, plane.normal, p->plane.normal); p->plane.dist = -plane.dist; p->leaf = leafnums[1]; SetPortalSphere(p); p++; // create backwards portal l = &leafs[leafnums[1]]; if(l->numportals == MAX_PORTALS_ON_LEAF) Error("Leaf with too many portals"); l->portals[l->numportals] = p; l->numportals++; p->num = i + 1; p->hint = hint; p->winding = NewFixedWinding(w->numpoints); p->winding->numpoints = w->numpoints; for(j = 0; j < w->numpoints; j++) { VectorCopy(w->points[w->numpoints - 1 - j], p->winding->points[j]); } p->plane = plane; p->leaf = leafnums[0]; SetPortalSphere(p); p++; } faces = safe_malloc(2 * numfaces * sizeof(vportal_t)); memset(faces, 0, 2 * numfaces * sizeof(vportal_t)); faceleafs = safe_malloc(portalclusters * sizeof(leaf_t)); memset(faceleafs, 0, portalclusters * sizeof(leaf_t)); for(i = 0, p = faces; i < numfaces; i++) { if(fscanf(f, "%i %i ", &numpoints, &leafnums[0]) != 2) Error("LoadPortals: reading portal %i", i); w = p->winding = NewFixedWinding(numpoints); w->numpoints = numpoints; for(j = 0; j < numpoints; j++) { double v[3]; int k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if(fscanf(f, "(%lf %lf %lf ) ", &v[0], &v[1], &v[2]) != 3) Error("LoadPortals: reading portal %i", i); for(k = 0; k < 3; k++) w->points[j][k] = v[k]; } fscanf(f, "\n"); // calc plane PlaneFromWinding(w, &plane); l = &faceleafs[leafnums[0]]; l->merged = -1; if(l->numportals == MAX_PORTALS_ON_LEAF) Error("Leaf with too many faces"); l->portals[l->numportals] = p; l->numportals++; p->num = i + 1; p->winding = w; // normal pointing out of the leaf VectorSubtract(vec3_origin, plane.normal, p->plane.normal); p->plane.dist = -plane.dist; p->leaf = -1; SetPortalSphere(p); p++; } fclose(f); }
/* * @brief */ static void LoadPortals(const char *filename) { uint32_t i; portal_t *p; leaf_t *l; char magic[80]; char *buffer, *s; int32_t len; int32_t num_points; winding_t *w; int32_t leaf_nums[2]; plane_t plane; if (Fs_Load(filename, (void **) &buffer) == -1) Com_Error(ERR_FATAL, "Could not open %s\n", filename); s = buffer; memset(&map_vis, 0, sizeof(map_vis)); if (sscanf(s, "%79s\n%u\n%u\n%n", magic, &map_vis.portal_clusters, &map_vis.num_portals, &len) != 3) Com_Error(ERR_FATAL, "Failed to read header: %s\n", filename); s += len; if (g_strcmp0(magic, PORTALFILE)) Com_Error(ERR_FATAL, "Not a portal file: %s\n", filename); Com_Verbose("Loading %4u portals, %4u clusters from %s...\n", map_vis.num_portals, map_vis.portal_clusters, filename); // these counts should take advantage of 64 bit systems automatically map_vis.leaf_bytes = ((map_vis.portal_clusters + 63) & ~63) >> 3; map_vis.leaf_longs = map_vis.leaf_bytes / sizeof(long); map_vis.portal_bytes = ((map_vis.num_portals * 2 + 63) & ~63) >> 3; map_vis.portal_longs = map_vis.portal_bytes / sizeof(long); // each file portal is split into two memory portals map_vis.portals = Mem_Malloc(2 * map_vis.num_portals * sizeof(portal_t)); // allocate the leafs map_vis.leafs = Mem_Malloc(map_vis.portal_clusters * sizeof(leaf_t)); map_vis.uncompressed_size = map_vis.portal_clusters * map_vis.leaf_bytes; map_vis.uncompressed = Mem_Malloc(map_vis.uncompressed_size); map_vis.base = map_vis.pointer = d_bsp.vis_data; d_vis->num_clusters = map_vis.portal_clusters; map_vis.pointer = (byte *) &d_vis->bit_offsets[map_vis.portal_clusters]; map_vis.end = map_vis.base + MAX_BSP_VISIBILITY; for (i = 0, p = map_vis.portals; i < map_vis.num_portals; i++) { int32_t j; if (sscanf(s, "%i %i %i %n", &num_points, &leaf_nums[0], &leaf_nums[1], &len) != 3) { Com_Error(ERR_FATAL, "Failed to read portal %i\n", i); } s += len; if (num_points > MAX_POINTS_ON_WINDING) { Com_Error(ERR_FATAL, "Portal %i has too many points\n", i); } if ((uint32_t) leaf_nums[0] > map_vis.portal_clusters || (uint32_t) leaf_nums[1] > map_vis.portal_clusters) { Com_Error(ERR_FATAL, "Portal %i has invalid leafs\n", i); } w = p->winding = NewWinding(num_points); w->original = true; w->num_points = num_points; for (j = 0; j < num_points; j++) { double v[3]; int32_t k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if (sscanf(s, "(%lf %lf %lf ) %n", &v[0], &v[1], &v[2], &len) != 3) Com_Error(ERR_FATAL, "Failed to read portal vertex definition %i:%i\n", i, j); s += len; for (k = 0; k < 3; k++) w->points[j][k] = v[k]; } if (sscanf(s, "\n%n", &len)) { s += len; } // calc plane PlaneFromWinding(w, &plane); // create forward portal l = &map_vis.leafs[leaf_nums[0]]; if (l->num_portals == MAX_PORTALS_ON_LEAF) Com_Error(ERR_FATAL, "MAX_PORTALS_ON_LEAF\n"); l->portals[l->num_portals] = p; l->num_portals++; p->winding = w; VectorSubtract(vec3_origin, plane.normal, p->plane.normal); p->plane.dist = -plane.dist; p->leaf = leaf_nums[1]; SetPortalSphere(p); p++; // create backwards portal l = &map_vis.leafs[leaf_nums[1]]; if (l->num_portals == MAX_PORTALS_ON_LEAF) Com_Error(ERR_FATAL, "MAX_PORTALS_ON_LEAF\n"); l->portals[l->num_portals] = p; l->num_portals++; p->winding = NewWinding(w->num_points); p->winding->num_points = w->num_points; for (j = 0; j < w->num_points; j++) { VectorCopy(w->points[w->num_points - 1 - j], p->winding->points[j]); } p->plane = plane; p->leaf = leaf_nums[0]; SetPortalSphere(p); p++; } Fs_Free(buffer); }
/* ============ LoadPortals ============ */ void LoadPortals( char *name ){ int i, j; portal_t *p; leaf_t *l; char magic[80]; FILE *f; int numpoints; winding_t *w; int leafnums[2]; plane_t plane; if ( !strcmp( name,"-" ) ) { f = stdin; } else { f = fopen( name, "r" ); if ( !f ) { Error( "LoadPortals: couldn't read %s\n",name ); } } if ( fscanf( f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals ) != 3 ) { Error( "LoadPortals: failed to read header" ); } if ( strcmp( magic,PORTALFILE ) ) { Error( "LoadPortals: not a portal file" ); } Sys_Printf( "%4i portalclusters\n", portalclusters ); Sys_Printf( "%4i numportals\n", numportals ); // these counts should take advantage of 64 bit systems automatically leafbytes = ( ( portalclusters + 63 ) & ~63 ) >> 3; leaflongs = leafbytes / sizeof( long ); portalbytes = ( ( numportals * 2 + 63 ) & ~63 ) >> 3; portallongs = portalbytes / sizeof( long ); // each file portal is split into two memory portals portals = malloc( 2 * numportals * sizeof( portal_t ) ); memset( portals, 0, 2 * numportals * sizeof( portal_t ) ); leafs = malloc( portalclusters * sizeof( leaf_t ) ); memset( leafs, 0, portalclusters * sizeof( leaf_t ) ); originalvismapsize = portalclusters * leafbytes; uncompressedvis = malloc( originalvismapsize ); vismap = vismap_p = dvisdata; dvis->numclusters = portalclusters; vismap_p = (byte *)&dvis->bitofs[portalclusters]; vismap_end = vismap + MAX_MAP_VISIBILITY; for ( i = 0, p = portals ; i < numportals ; i++ ) { if ( fscanf( f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1] ) != 3 ) { Error( "LoadPortals: reading portal %i", i ); } if ( numpoints > MAX_POINTS_ON_WINDING ) { Error( "LoadPortals: portal %i has too many points", i ); } if ( (unsigned)leafnums[0] > portalclusters || (unsigned)leafnums[1] > portalclusters ) { Error( "LoadPortals: reading portal %i", i ); } w = p->winding = NewWinding( numpoints ); w->original = true; w->numpoints = numpoints; for ( j = 0 ; j < numpoints ; j++ ) { double v[3]; int k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if ( fscanf( f, "(%lf %lf %lf ) " , &v[0], &v[1], &v[2] ) != 3 ) { Error( "LoadPortals: reading portal %i", i ); } for ( k = 0 ; k < 3 ; k++ ) w->points[j][k] = v[k]; } fscanf( f, "\n" ); // calc plane PlaneFromWinding( w, &plane ); // create forward portal l = &leafs[leafnums[0]]; if ( l->numportals == MAX_PORTALS_ON_LEAF ) { Error( "Leaf with too many portals" ); } l->portals[l->numportals] = p; l->numportals++; p->winding = w; VectorSubtract( vec3_origin, plane.normal, p->plane.normal ); p->plane.dist = -plane.dist; p->leaf = leafnums[1]; SetPortalSphere( p ); p++; // create backwards portal l = &leafs[leafnums[1]]; if ( l->numportals == MAX_PORTALS_ON_LEAF ) { Error( "Leaf with too many portals" ); } l->portals[l->numportals] = p; l->numportals++; p->winding = NewWinding( w->numpoints ); p->winding->numpoints = w->numpoints; for ( j = 0 ; j < w->numpoints ; j++ ) { VectorCopy( w->points[w->numpoints - 1 - j], p->winding->points[j] ); } p->plane = plane; p->leaf = leafnums[0]; SetPortalSphere( p ); p++; } fclose( f ); }
/* ============ LoadPortals ============ */ void LoadPortals (char *name) { int i, j; portal_t *p; leaf_t *l; char magic[80]; int numpoints; winding_t *w; int leafnums[2]; plane_t plane; FILE *f; // Open the portal file. if ( g_bUseMPI ) { // If we're using MPI, copy off the file to a temporary first. This will download the file // from the MPI master, then we get to use nice functions like fscanf on it. char tempPath[MAX_PATH], tempFile[MAX_PATH]; if ( GetTempPath( sizeof( tempPath ), tempPath ) == 0 ) { Error( "LoadPortals: GetTempPath failed.\n" ); } if ( GetTempFileName( tempPath, "vvis_portal_", 0, tempFile ) == 0 ) { Error( "LoadPortals: GetTempFileName failed.\n" ); } // Read all the data from the network file into memory. FileHandle_t hFile = g_pFileSystem->Open(name, "r"); if ( hFile == FILESYSTEM_INVALID_HANDLE ) Error( "LoadPortals( %s ): couldn't get file from master.\n", name ); CUtlVector<char> data; data.SetSize( g_pFileSystem->Size( hFile ) ); g_pFileSystem->Read( data.Base(), data.Count(), hFile ); g_pFileSystem->Close( hFile ); // Dump it into a temp file. f = fopen( tempFile, "wt" ); fwrite( data.Base(), 1, data.Count(), f ); fclose( f ); // Open the temp file up. f = fopen( tempFile, "rSTD" ); // read only, sequential, temporary, delete on close } else { f = fopen( name, "r" ); } if ( !f ) Error ("LoadPortals: couldn't read %s\n",name); if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &g_numportals) != 3) Error ("LoadPortals: failed to read header"); if (stricmp(magic,PORTALFILE)) Error ("LoadPortals: not a portal file"); Msg ("%4i portalclusters\n", portalclusters); Msg ("%4i numportals\n", g_numportals); if (g_numportals * 2 >= MAX_PORTALS) { Error("The map overflows the max portal count (%d of max %d)!\n", g_numportals, MAX_PORTALS / 2 ); } // these counts should take advantage of 64 bit systems automatically leafbytes = ((portalclusters+63)&~63)>>3; leaflongs = leafbytes/sizeof(long); portalbytes = ((g_numportals*2+63)&~63)>>3; portallongs = portalbytes/sizeof(long); // each file portal is split into two memory portals portals = (portal_t*)malloc(2*g_numportals*sizeof(portal_t)); memset (portals, 0, 2*g_numportals*sizeof(portal_t)); leafs = (leaf_t*)malloc(portalclusters*sizeof(leaf_t)); memset (leafs, 0, portalclusters*sizeof(leaf_t)); originalvismapsize = portalclusters*leafbytes; uncompressedvis = (byte*)malloc(originalvismapsize); vismap = vismap_p = dvisdata; dvis->numclusters = portalclusters; vismap_p = (byte *)&dvis->bitofs[portalclusters]; vismap_end = vismap + MAX_MAP_VISIBILITY; for (i=0, p=portals ; i<g_numportals ; i++) { if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) Error ("LoadPortals: reading portal %i", i); if (numpoints > MAX_POINTS_ON_WINDING) Error ("LoadPortals: portal %i has too many points", i); if ( (unsigned)leafnums[0] > portalclusters || (unsigned)leafnums[1] > portalclusters) Error ("LoadPortals: reading portal %i", i); w = p->winding = NewWinding (numpoints); w->original = true; w->numpoints = numpoints; for (j=0 ; j<numpoints ; j++) { double v[3]; int k; // scanf into double, then assign to vec_t // so we don't care what size vec_t is if (fscanf (f, "(%lf %lf %lf ) " , &v[0], &v[1], &v[2]) != 3) Error ("LoadPortals: reading portal %i", i); for (k=0 ; k<3 ; k++) w->points[j][k] = v[k]; } fscanf (f, "\n"); // calc plane PlaneFromWinding (w, &plane); // create forward portal l = &leafs[leafnums[0]]; if (l->numportals == MAX_PORTALS_ON_LEAF) Error ("Leaf %d (portal %d) with too many portals. Use vbsp -glview to compile, then glview -portal -portalhighlight X or -leafhighlight L to view the problem.", leafnums[0], i ); l->portals[l->numportals] = p; l->numportals++; p->winding = w; VectorSubtract (vec3_origin, plane.normal, p->plane.normal); p->plane.dist = -plane.dist; p->leaf = leafnums[1]; SetPortalSphere (p); p++; // create backwards portal l = &leafs[leafnums[1]]; if (l->numportals == MAX_PORTALS_ON_LEAF) Error ("Leaf %d (portal %d) with too many portals. Use vbsp -glview to compile, then glview -portal -portalhighlight X or -leafhighlight L to view the problem.", leafnums[1], i ); l->portals[l->numportals] = p; l->numportals++; p->winding = NewWinding(w->numpoints); p->winding->numpoints = w->numpoints; for (j=0 ; j<w->numpoints ; j++) { VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); } p->plane = plane; p->leaf = leafnums[0]; SetPortalSphere (p); p++; } fclose (f); }