void WritePortalFile_r (node_t *node) { int i; portal_t *p; winding_t *w; dplane_t *pl, plane2; if (!node->contents) { WritePortalFile_r (node->children[0]); WritePortalFile_r (node->children[1]); return; } if (node->contents == CONTENTS_SOLID) return; for (p = node->portals ; p ; ) { w = p->winding; if (w && p->nodes[0] == node) { if ( (watervis && p->nodes[0]->contents != CONTENTS_SOLID && p->nodes[1]->contents != CONTENTS_SOLID) || (p->nodes[0]->contents == p->nodes[1]->contents) ) { // write out to the file // sometimes planes get turned around when they are very near // the changeover point between different axis. interpret the // plane the same way vis will, and flip the side orders if needed PlaneFromWinding (w, &plane2); if ( DotProduct (p->plane.normal, plane2.normal) < 1.0-ON_EPSILON ) { // backwards... fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum); } else fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum); for (i=0 ; i<w->numpoints ; i++) { fprintf (pf,"("); WriteFloat (pf, w->points[i][0]); WriteFloat (pf, w->points[i][1]); WriteFloat (pf, w->points[i][2]); fprintf (pf,") "); } fprintf (pf,"\n"); } } if (p->nodes[0] == node) p = p->next[0]; else p = p->next[1]; } }
static void WritePortalFile_r (node_t *node) { int i; portal_t *p; winding_t *w; plane_t *pl, plane2; if (!node->contents) { WritePortalFile_r (node->children[0]); WritePortalFile_r (node->children[1]); return; } if (node->contents == BSP_CONTENTS_SOLID) return; for (p = node->portals ; p ; ) { w = p->winding; // LordHavoc: transparent water support if (w && p->nodes[0] == node && PortalSidesVisible (p)) { // write out to the file // sometimes planes get turned around when they are very near // the changeover point between different axis. interpret the // plane the same way vis will, and flip the side orders if needed pl = &mapplanes[p->planenum]; PlaneFromWinding (w, &plane2); if ( DotProduct (pl->normal, plane2.normal) < 0.99 ) // backwards... fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum); else fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum); // Vic: proper float output for (i=0 ; i<w->numpoints ; i++) { fprintf (pf, "("); WriteFloatToPortalFile (w->points[i][0]); fprintf (pf, " "); WriteFloatToPortalFile (w->points[i][1]); fprintf (pf, " "); WriteFloatToPortalFile (w->points[i][2]); fprintf (pf, ")"); fprintf (pf, i == w->numpoints-1 ? "\n" : " "); } } if (p->nodes[0] == node) p = p->next[0]; else p = p->next[1]; } }
static void WritePortalFile_r(node_t *node) { int i; portal_t *p; winding_t *w; plane_t *pl, plane2; if (!node->contents) { WritePortalFile_r(node->children[0]); WritePortalFile_r(node->children[1]); return; } if (node->contents == CONTENTS_SOLID) return; for (p = node->portals; p;) { w = p->winding; if (w && p->nodes[0] == node && SameContent(p->nodes[0]->contents, p->nodes[1]->contents)) { /* * sometimes planes get turned around when they are very near * the changeover point between different axis. interpret the * plane the same way vis will, and flip the side orders if needed */ pl = &pPlanes[p->planenum]; PlaneFromWinding(w, &plane2); if (DotProduct(pl->normal, plane2.normal) < 1.0 - ANGLEEPSILON) { /* backwards... */ fprintf(PortalFile, "%i %i %i ", w->numpoints, p->nodes[1]->visleafnum, p->nodes[0]->visleafnum); } else fprintf(PortalFile, "%i %i %i ", w->numpoints, p->nodes[0]->visleafnum, p->nodes[1]->visleafnum); for (i = 0; i < w->numpoints; i++) { fprintf(PortalFile, "("); WriteFloat(w->points[i][0]); WriteFloat(w->points[i][1]); WriteFloat(w->points[i][2]); fprintf(PortalFile, ") "); } fprintf(PortalFile, "\n"); } if (p->nodes[0] == node) p = p->next[0]; else p = p->next[1]; } }
void CheckLeafPortalConsistancy (node_t *node) { int side, side2; portal_t *p, *p2; dplane_t plane, plane2; int i; winding_t *w; float dist; side = side2 = 0; // quiet compiler warning for (p = node->portals ; p ; p = p->next[side]) { if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) side = 1; else Error ("CutNodePortals_r: mislinked portal"); CheckWindingInNode (p->winding, node); CheckWindingArea (p->winding); // check that the side orders are correct plane = p->plane; PlaneFromWinding (p->winding, &plane2); for (p2 = node->portals ; p2 ; p2 = p2->next[side2]) { if (p2->nodes[0] == node) side2 = 0; else if (p2->nodes[1] == node) side2 = 1; else Error ("CutNodePortals_r: mislinked portal"); w = p2->winding; for (i=0 ; i<w->numpoints ; i++) { dist = DotProduct (w->points[i], plane.normal) - plane.dist; if ( (side == 0 && dist < -1) || (side == 1 && dist > 1) ) { printf ("WARNING: portal siding direction is wrong\n"); return; } } } } }
static void CheckLeafPortalConsistancy(node_t *node) { int side, side2; portal_t *p, *p2; plane_t plane, plane2; int i; winding_t *w; vec_t dist; side = side2 = 0; // quiet compiler warning for (p = node->portals; p; p = p->next[side]) { if (p->nodes[0] == node) side = 0; else if (p->nodes[1] == node) side = 1; else Message(msgError, errMislinkedPortal); CheckWindingInNode(p->winding, node); CheckWindingArea(p->winding); // check that the side orders are correct plane = pPlanes[p->planenum]; PlaneFromWinding(p->winding, &plane2); for (p2 = node->portals; p2; p2 = p2->next[side2]) { if (p2->nodes[0] == node) side2 = 0; else if (p2->nodes[1] == node) side2 = 1; else Message(msgError, errMislinkedPortal); w = p2->winding; for (i = 0; i < w->numpoints; i++) { dist = DotProduct(w->points[i], plane.normal) - plane.dist; if ((side == 0 && dist < -1) || (side == 1 && dist > 1)) { Message(msgWarning, warnBadPortalDirection); return; } } } } }
/* ============ 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); }
/* ============ 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); }
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); }
/* * @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); }
/* ================== CheckWinding Check for possible errors ================== */ void CheckWinding( winding_t *w ) { int i, j; vec_t *p1, *p2; vec_t d, edgedist; vec3_t dir, edgenormal; plane_t facenormal; PlaneFromWinding ( w, &facenormal ); if (w->numpoints < 3) { printf( "CheckWinding: too few points to form a triangle at %f %f %f\n", w->points[0][0], w->points[0][1], w->points[0][2] ); w->numpoints = 0; return; } // try repeatedly if an error is corrected // (fixing one may expose another) do { for( i = 0; i < w->numpoints; i++ ) { p1 = w->points[i]; p2 = w->points[(i + 1) % w->numpoints]; for( j = 0; j < 3; j++ ) if( p1[j] >= BOGUS_RANGE || p1[j] <= -BOGUS_RANGE ) Error( "CheckWinding: BOGUS_RANGE: %f %f %f\n", p1[0], p1[1], p1[2] ); // check the point is on the face plane d = DotProduct( p1, facenormal.normal ) - facenormal.dist; if( d < -WINDING_EPSILON || d > WINDING_EPSILON ) { printf( "CheckWinding: point off plane at %f %f %f, attempting to fix\n", p1[0], p1[1], p1[2] ); VectorMA(p1, -d, facenormal.normal, p1); break; } // check the edge isn't degenerate VectorSubtract( p2, p1, dir ); if( VectorLength( dir ) < WINDING_EPSILON ) { printf( "CheckWinding: healing degenerate edge at %f %f %f\n", p2[0], p2[1], p2[2] ); for (j = i + 1;j < w->numpoints;j++) VectorCopy(w->points[j - 1], w->points[j]); w->numpoints--; break; } // calculate edge plane to check for concavity CrossProduct( facenormal.normal, dir, edgenormal ); VectorNormalize( edgenormal ); edgedist = DotProduct( p1, edgenormal ); // all other points must be on front side for( j = 0; j < w->numpoints; j++ ) { d = DotProduct( w->points[j], edgenormal ); if( d > edgedist + WINDING_EPSILON ) { printf( "CheckWinding: non-convex polygon at %f %f %f, attempting to heal\n", w->points[j][0], w->points[j][1], w->points[j][2] ); VectorMA(w->points[j], -d, edgenormal, w->points[j]); break; } } if (j < w->numpoints) break; } } while (i < w->numpoints); }