void CopyFace( face_t* in, face_t* out) { int i; out->face_winding = NewWinding(in->face_winding->numpoints); out->face_winding->numpoints = in->face_winding->numpoints; for (i = 0; i<in->face_winding->numpoints; i++) { VectorCopy(in->face_winding->points[i],out->face_winding->points[i]); } for (i = 0; i<3; i++) { VectorCopy(in->planepts[i],out->planepts[i]); } }
/* ============ 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) { printf ("LoadPortals: couldn't read %s\n",name); printf ("No vising performed.\n"); exit (1); } } if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalleafs, &numportals) != 3) Error ("LoadPortals: failed to read header"); if (strcmp(magic,PORTALFILE)) Error ("LoadPortals: not a portal file"); printf ("%4i portalleafs\n", portalleafs); printf ("%4i numportals\n", numportals); bitbytes = ((portalleafs+63)&~63)>>3; bitlongs = bitbytes/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(portalleafs*sizeof(leaf_t)); memset (leafs, 0, portalleafs*sizeof(leaf_t)); originalvismapsize = portalleafs*((portalleafs+7)/8); vismap = vismap_p = dvisdata; 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] > portalleafs || (unsigned)leafnums[1] > portalleafs) 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 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]; 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]; p++; } fclose (f); }
/* Clips the winding to the plane, returning the new winding on the positive side Frees the input winding. If keepon is TRUE, an exactly on-plane winding will be saved, otherwise it will be clipped away. */ winding_t *ClipWinding (winding_t *in, plane_t *split, bool keepon) { vec_t dists[MAX_POINTS_ON_WINDING]; int sides[MAX_POINTS_ON_WINDING]; int counts[3]; vec_t dot; int i, j; vec_t *p1, *p2; vec3_t mid; winding_t *neww; int maxpts; counts[0] = counts[1] = counts[2] = 0; // determine sides for each point for (i=0 ; i<in->numpoints ; i++) { dot = Math_DotProduct(in->points[i],split->normal); dot -= split->dist; dists[i] = dot; if (dot > ON_EPSILON) sides[i] = SIDE_FRONT; else if (dot < -ON_EPSILON) sides[i] = SIDE_BACK; else sides[i] = SIDE_ON; counts[sides[i]]++; } sides[i] = sides[0]; dists[i] = dists[0]; if (keepon && !counts[0] && !counts[1]) return in; if (!counts[0]) { FreeWinding (in); return NULL; } if (!counts[1]) return in; maxpts = in->numpoints+4; // can't use counts[0]+2 because // of fp grouping errors neww = NewWinding (maxpts); for (i=0 ; i<in->numpoints ; i++) { p1 = in->points[i]; if (sides[i] == SIDE_ON) { Math_VectorCopy(p1,neww->points[neww->numpoints]); neww->numpoints++; continue; } if (sides[i] == SIDE_FRONT) { Math_VectorCopy(p1,neww->points[neww->numpoints]); neww->numpoints++; } if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) continue; // generate a split point p2 = in->points[(i+1)%in->numpoints]; dot = dists[i] / (dists[i]-dists[i+1]); for (j=0 ; j<3 ; j++) { // avoid round off error when possible if (split->normal[j] == 1) mid[j] = split->dist; else if (split->normal[j] == -1) mid[j] = -split->dist; else mid[j] = p1[j] + dot*(p2[j]-p1[j]); } Math_VectorCopy(mid,neww->points[neww->numpoints]); neww->numpoints++; } if (neww->numpoints > maxpts) Error ("ClipWinding: points exceeded estimate"); // free the original winding FreeWinding (in); return neww; }
winding_t *BasePolyForPlane (plane_t *p) { int i, x; vec_t max, v; vec3_t org, vright, vup; winding_t *w; // find the major axis max = -BOGUS_RANGE; x = -1; for (i=0 ; i<3; i++) { v = fabs(p->normal[i]); if (v > max) { x = i; max = v; } } if (x==-1) Error("BasePolyForPlane: no axis found"); Math_VectorCopy(vec3_origin,vup); switch (x) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = Math_DotProduct(vup,p->normal); Math_VectorMA(vup,-v,p->normal,vup); Math_VectorNormalize(vup); Math_VectorScale(p->normal,p->dist,org); Math_CrossProduct(vup,p->normal,vright); Math_VectorScale(vup,8192,vup); Math_VectorScale(vright,8192,vright); // project a really big axis aligned box onto the plane w = NewWinding (4); Math_VectorSubtract(org,vright,w->points[0]); Math_VectorAdd(w->points[0],vup,w->points[0]); Math_VectorAdd(org,vright,w->points[1]); Math_VectorAdd(w->points[1],vup,w->points[1]); Math_VectorAdd(org,vright,w->points[2]); Math_VectorSubtract(w->points[2],vup,w->points[2]); Math_VectorSubtract(org,vright,w->points[3]); Math_VectorSubtract(w->points[3],vup,w->points[3]); w->numpoints = 4; return w; }
static void LoadPortals (char *name) { const char *line; char *err; int numpoints, i, j, k; int read_leafs = 0; int clusternums[2]; cluster_t *cluster; plane_t plane; portal_t *portal; winding_t *winding; QFile *f; if (!strcmp (name, "-")) f = Qdopen (0, "rt"); // create a QFile of stdin else { f = Qopen (name, "r"); if (!f) { printf ("LoadPortals: couldn't read %s\n", name); printf ("No vising performed.\n"); exit (1); } } line = Qgetline (f); if (line && (!strcmp (line, PORTALFILE "\n") || !strcmp (line, PORTALFILE "\r\n"))) { line = Qgetline (f); if (!line || sscanf (line, "%i\n", &portalclusters) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); if (!line || sscanf (line, "%i\n", &numportals) != 1) Sys_Error ("LoadPortals: failed to read header"); numrealleafs = portalclusters; } else if (line && (!strcmp (line, PORTALFILE_AM "\n") || !strcmp (line, PORTALFILE_AM "\r\n"))) { line = Qgetline (f); if (!line || sscanf (line, "%i\n", &portalclusters) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); if (!line || sscanf (line, "%i\n", &numportals) != 1) Sys_Error ("LoadPortals: failed to read header"); line = Qgetline (f); if (!line || sscanf (line, "%i\n", &numrealleafs) != 1) Sys_Error ("LoadPortals: failed to read header"); read_leafs = 1; } else { Sys_Error ("LoadPortals: not a portal file"); } if (options.verbosity >= 0) { printf ("%4i portalclusters\n", portalclusters); printf ("%4i numportals\n", numportals); printf ("%4i numrealleafs\n", numrealleafs); } bitbytes = ((portalclusters + 63) & ~63) >> 3; bitlongs = bitbytes / sizeof (long); bitbytes_l = ((numrealleafs + 63) & ~63) >> 3; // each file portal is split into two memory portals, one for each // direction portals = calloc (2 * numportals, sizeof (portal_t)); clusters = calloc (portalclusters, sizeof (cluster_t)); originalvismapsize = numrealleafs * ((numrealleafs + 7) / 8); for (i = 0, portal = portals; i < numportals; i++) { line = Qgetline (f); if (!line) Sys_Error ("LoadPortals: reading portal %i", i); numpoints = strtol (line, &err, 10); if (err == line) Sys_Error ("LoadPortals: reading portal %i", i); line = err; for (j = 0; j < 2; j++) { clusternums[j] = strtol (line, &err, 10); if (err == line) Sys_Error ("LoadPortals: reading portal %i", i); line = err; } if (numpoints > MAX_POINTS_ON_WINDING) Sys_Error ("LoadPortals: portal %i has too many points", i); if ((unsigned) clusternums[0] > (unsigned) portalclusters || (unsigned) clusternums[1] > (unsigned) portalclusters) Sys_Error ("LoadPortals: reading portal %i", i); winding = portal->winding = NewWinding (numpoints); winding->original = true; winding->numpoints = numpoints; for (j = 0; j < numpoints; j++) { // (%ld %ld %ld) while (isspace ((byte) *line)) line++; if (*line++ != '(') Sys_Error ("LoadPortals: reading portal %i", i); for (k = 0; k < 3; k++) { winding->points[j][k] = strtod (line, &err); if (err == line) Sys_Error ("LoadPortals: reading portal %i", i); line = err; } while (isspace ((byte) *line)) line++; if (*line++ != ')') Sys_Error ("LoadPortals: reading portal %i", i); } // calc plane PlaneFromWinding (winding, &plane); // create forward portal cluster = &clusters[clusternums[0]]; if (cluster->numportals == MAX_PORTALS_ON_CLUSTER) Sys_Error ("Cluster with too many portals"); cluster->portals[cluster->numportals] = portal; cluster->numportals++; portal->winding = winding; VectorNegate (plane.normal, portal->plane.normal); portal->plane.dist = -plane.dist; portal->cluster = clusternums[1]; portal++; // create backwards portal cluster = &clusters[clusternums[1]]; if (cluster->numportals == MAX_PORTALS_ON_CLUSTER) Sys_Error ("Cluster with too many portals"); cluster->portals[cluster->numportals] = portal; cluster->numportals++; portal->winding = winding; portal->plane = plane; portal->cluster = clusternums[0]; portal++; } leafcluster = calloc (numrealleafs, sizeof (int)); if (read_leafs) { for (i = 0; i < numrealleafs; i++) { line = Qgetline (f); if (sscanf (line, "%i\n", &leafcluster[i]) != 1) Sys_Error ("LoadPortals: parse error in leaf->cluster " "mappings"); } } else { for (i = 0; i < numrealleafs; i++) leafcluster[i] = i; } Qclose (f); }
winding_t * BaseWindingForPlane (const plane_t *p) { int i, x; vec_t max, v; vec3_t org, vright, vup; winding_t *w; // find the major axis max = -BOGUS; x = -1; for (i = 0; i < 3; i++) { v = fabs (p->normal[i]); if (v > max) { x = i; max = v; } } if (x == -1) Sys_Error ("BaseWindingForPlane: no axis found"); VectorZero (vup); switch (x) { case 0: case 1: vup[2] = 1; break; case 2: vup[0] = 1; break; } v = DotProduct (vup, p->normal); VectorMultSub (vup, v, p->normal, vup); _VectorNormalize (vup); VectorScale (p->normal, p->dist, org); CrossProduct (vup, p->normal, vright); VectorScale (vup, BOGUS, vup); VectorScale (vright, BOGUS, vright); // project a really big axis aligned box onto the plane w = NewWinding (4); VectorSubtract (org, vright, w->points[0]); VectorAdd (w->points[0], vup, w->points[0]); VectorAdd (org, vright, w->points[1]); VectorAdd (w->points[1], vup, w->points[1]); VectorAdd (org, vright, w->points[2]); VectorSubtract (w->points[2], vup, w->points[2]); VectorSubtract (org, vright, w->points[3]); VectorSubtract (w->points[3], vup, w->points[3]); w->numpoints = 4; return w; }
winding_t * ClipWinding (winding_t *in, plane_t *split, qboolean keepon) { int maxpts, i, j; int *sides; int counts[3]; vec_t dot; vec_t *dists; vec_t *p1, *p2; vec3_t mid; winding_t *neww; counts[0] = counts[1] = counts[2] = 0; // +1 for duplicating the first point sides = alloca ((in->numpoints + 1) * sizeof (int)); dists = alloca ((in->numpoints + 1) * sizeof (vec_t)); // determine sides for each point for (i = 0; i < in->numpoints; i++) { dot = DotProduct (in->points[i], split->normal); dot -= split->dist; dists[i] = dot; if (dot > ON_EPSILON) sides[i] = SIDE_FRONT; else if (dot < -ON_EPSILON) sides[i] = SIDE_BACK; else { sides[i] = SIDE_ON; } counts[sides[i]]++; } // duplicate the first point sides[i] = sides[0]; dists[i] = dists[0]; if (keepon && !counts[SIDE_FRONT] && !counts[SIDE_BACK]) return in; if (!counts[SIDE_FRONT]) { FreeWinding (in); return NULL; } if (!counts[SIDE_BACK]) return in; for (maxpts = 0, i = 0; i < in->numpoints; i++) { if (!(sides[i] & 1)) maxpts++; if ((sides[i] ^ 1) == sides[i + 1]) maxpts++; } neww = NewWinding (maxpts); for (i = 0; i < in->numpoints; i++) { p1 = in->points[i]; if (sides[i] == SIDE_ON) { if (neww->numpoints == maxpts) Sys_Error ("ClipWinding: points exceeded estimate"); VectorCopy (p1, neww->points[neww->numpoints]); neww->numpoints++; continue; } if (sides[i] == SIDE_FRONT) { if (neww->numpoints == maxpts) Sys_Error ("ClipWinding: points exceeded estimate"); VectorCopy (p1, neww->points[neww->numpoints]); neww->numpoints++; } if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) continue; if (neww->numpoints == maxpts) Sys_Error ("ClipWinding: points exceeded estimate"); // generate a split point p2 = in->points[(i + 1) % in->numpoints]; dot = dists[i] / (dists[i] - dists[i + 1]); for (j = 0; j < 3; j++) { // avoid round off error when possible if (split->normal[j] == 1) mid[j] = split->dist; else if (split->normal[j] == -1) mid[j] = -split->dist; else mid[j] = p1[j] + dot * (p2[j] - p1[j]); } VectorCopy (mid, neww->points[neww->numpoints]); neww->numpoints++; } // free the original winding FreeWinding (in); return neww; }
/* ================== DivideWinding Divides a winding by a plane, producing one or two windings. The original winding is not damaged or freed. If only on one side, the returned winding will be the input winding. If on both sides, two new windings will be created. ================== */ void DivideWinding (winding_t *in, plane_t *split, winding_t **front, winding_t **back) { vec_t dists[MAX_POINTS_ON_WINDING]; int sides[MAX_POINTS_ON_WINDING]; int counts[3]; vec_t dot; int i, j; vec_t *p1, *p2; vec3_t mid; winding_t *f, *b; int maxpts; counts[0] = counts[1] = counts[2] = 0; // determine sides for each point for (i=0 ; i<in->numpoints ; i++) { dot = DotProduct (in->points[i], split->normal); dot -= split->dist; dists[i] = dot; if (dot > ON_EPSILON) sides[i] = SIDE_FRONT; else if (dot < -ON_EPSILON) sides[i] = SIDE_BACK; else { sides[i] = SIDE_ON; } counts[sides[i]]++; } sides[i] = sides[0]; dists[i] = dists[0]; *front = *back = NULL; if (!counts[0]) { *back = in; return; } if (!counts[1]) { *front = in; return; } maxpts = in->numpoints+4; // can't use counts[0]+2 because // of fp grouping errors *front = f = NewWinding (maxpts); *back = b = NewWinding (maxpts); for (i=0 ; i<in->numpoints ; i++) { p1 = in->points[i]; if (sides[i] == SIDE_ON) { VectorCopy (p1, f->points[f->numpoints]); f->numpoints++; VectorCopy (p1, b->points[b->numpoints]); b->numpoints++; continue; } if (sides[i] == SIDE_FRONT) { VectorCopy (p1, f->points[f->numpoints]); f->numpoints++; } if (sides[i] == SIDE_BACK) { VectorCopy (p1, b->points[b->numpoints]); b->numpoints++; } if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) continue; // generate a split point p2 = in->points[(i+1)%in->numpoints]; dot = dists[i] / (dists[i]-dists[i+1]); for (j=0 ; j<3 ; j++) { // avoid round off error when possible if (split->normal[j] == 1) mid[j] = split->dist; else if (split->normal[j] == -1) mid[j] = -split->dist; else mid[j] = p1[j] + dot*(p2[j]-p1[j]); } VectorCopy (mid, f->points[f->numpoints]); f->numpoints++; VectorCopy (mid, b->points[b->numpoints]); b->numpoints++; } if (f->numpoints > maxpts || b->numpoints > maxpts) Error ("ClipWinding: points exceeded estimate"); }
/* * @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); }
/* ============ LoadPortals ============ */ void LoadPortals(char *name, bsp2_t *bsp) { int i, j, count; 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) { logprint("%s: couldn't read %s\n", __func__, name); logprint("No vising performed.\n"); exit(1); } } /* * Parse the portal file header */ count = fscanf(f, "%79s\n", magic); if (count != 1) Error("%s: unknown header: %s\n", __func__, magic); if (!strcmp(magic, PORTALFILE)) { count = fscanf(f, "%i\n%i\n", &portalleafs, &numportals); if (count != 2) Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE); portalleafs_real = portalleafs; logprint("%6d leafs\n", portalleafs); logprint("%6d portals\n", numportals); } else if (!strcmp(magic, PORTALFILE2)) { count = fscanf(f, "%i\n%i\n%i\n", &portalleafs_real, &portalleafs, &numportals); if (count != 3) Error("%s: unable to parse %s HEADER\n", __func__, PORTALFILE); logprint("%6d leafs\n", portalleafs_real); logprint("%6d clusters\n", portalleafs); logprint("%6d portals\n", numportals); } else { Error("%s: unknown header: %s\n", __func__, magic); } leafbytes = ((portalleafs + 63) & ~63) >> 3; leaflongs = leafbytes / sizeof(long); leafbytes_real = ((portalleafs_real + 63) & ~63) >> 3; // 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(portalleafs * sizeof(leaf_t)); memset(leafs, 0, portalleafs * sizeof(leaf_t)); originalvismapsize = portalleafs_real * ((portalleafs_real + 7) / 8); // FIXME - more intelligent allocation? bsp->dvisdata = malloc(MAX_MAP_VISIBILITY); if (!bsp->dvisdata) Error("%s: dvisdata allocation failed (%i bytes)", __func__, MAX_MAP_VISIBILITY); memset(bsp->dvisdata, 0, MAX_MAP_VISIBILITY); vismap = vismap_p = bsp->dvisdata; 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("%s: reading portal %i", __func__, i); if (numpoints > MAX_WINDING) Error("%s: portal %i has too many points", __func__, i); if ((unsigned)leafnums[0] > (unsigned)portalleafs || (unsigned)leafnums[1] > (unsigned)portalleafs) Error("%s: reading portal %i", __func__, i); w = p->winding = NewWinding(numpoints); w->numpoints = numpoints; for (j = 0; j < numpoints; j++) { double v[3]; int k; // scanf into double, then assign to vec_t if (fscanf(f, "(%lf %lf %lf ) ", &v[0], &v[1], &v[2]) != 3) Error("%s: reading portal %i", __func__, i); for (k = 0; k < 3; k++) w->points[j][k] = (vec_t)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]; SetWindingSphere(p->winding); 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++; // Create a reverse winding p->winding = NewWinding(numpoints); p->winding->numpoints = numpoints; for (j = 0; j < numpoints; ++j) VectorCopy(w->points[numpoints - (j + 1)], p->winding->points[j]); //p->winding = w; p->plane = plane; p->leaf = leafnums[0]; SetWindingSphere(p->winding); p++; } /* Load the cluster expansion map if needed */ if (portalleafs != portalleafs_real) { clustermap = malloc(portalleafs_real * sizeof(int)); for (i = 0; i < portalleafs; i++) { while (1) { int leafnum; count = fscanf(f, "%i", &leafnum); if (!count || count == EOF) break; if (leafnum < 0) break; if (leafnum >= portalleafs_real) Error("Invalid leaf number in cluster map (%d >= %d", leafnum, portalleafs_real); clustermap[leafnum] = i; } if (count == EOF) break; } if (i < portalleafs) Error("Couldn't read cluster map (%d / %d)\n", i, portalleafs); } fclose(f); }