#include "bsplib.h" #include "const.h" /* ============================================================================== Portal file generation Save out name.prt for qvis to read ============================================================================== */ #define PORTALFILE "PRT1" file_t *pf; int num_visclusters; // clusters the player can be in int num_visportals; void WriteFloat (file_t *f, vec_t v) { if ( fabs(v - floor(v + 0.5)) < 0.001 ) FS_Printf(f,"%i ",(int)floor(v + 0.5)); else FS_Printf(f,"%f ",v); } /* ================= WritePortalFile_r ================= */ void WritePortalFile_r (node_t *node) { int i, s; portal_t *p; winding_t *w; vec3_t normal; vec_t dist; // decision node if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) { WritePortalFile_r (node->children[0]); WritePortalFile_r (node->children[1]); return; } if (node->contents & CONTENTS_SOLID) return; for (p = node->portals ; p ; p=p->next[s]) { w = p->winding; s = (p->nodes[1] == node); if (w && p->nodes[0] == node) { if (!Portal_VisFlood (p)) continue; // 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 // FIXME: is this still relevent? WindingPlane (w, normal, &dist); if ( DotProduct (p->plane.normal, normal) < 0.99 ) { // backwards... FS_Printf(pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); } else FS_Printf(pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster); for (i=0 ; inumpoints ; i++) { FS_Printf (pf,"( "); WriteFloat (pf, w->p[i][0]); WriteFloat (pf, w->p[i][1]); WriteFloat (pf, w->p[i][2]); FS_Printf (pf,") "); } FS_Printf(pf,"\n"); } } } /* ================ FillLeafNumbers_r All of the leafs under node will have the same cluster ================ */ void FillLeafNumbers_r (node_t *node, int num) { if (node->planenum == PLANENUM_LEAF) { if (node->contents & CONTENTS_SOLID) node->cluster = -1; else node->cluster = num; return; } node->cluster = num; FillLeafNumbers_r (node->children[0], num); FillLeafNumbers_r (node->children[1], num); } /* ================ NumberLeafs_r ================ */ void NumberLeafs_r (node_t *node) { portal_t *p; if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) { // decision node node->cluster = -99; NumberLeafs_r (node->children[0]); NumberLeafs_r (node->children[1]); return; } // either a leaf or a detail cluster if ( node->contents & CONTENTS_SOLID ) { // solid block, viewpoint never inside node->cluster = -1; return; } FillLeafNumbers_r (node, num_visclusters); num_visclusters++; // count the portals for (p = node->portals ; p ; ) { if (p->nodes[0] == node) // only write out from first leaf { if (Portal_VisFlood (p)) num_visportals++; p = p->next[0]; } else p = p->next[1]; } } /* ================ CreateVisPortals_r ================ */ void CreateVisPortals_r (node_t *node) { // stop as soon as we get to a detail_seperator, which // means that everything below is in a single cluster if (node->planenum == PLANENUM_LEAF || node->detail_seperator ) return; MakeNodePortal (node); SplitNodePortals (node); CreateVisPortals_r (node->children[0]); CreateVisPortals_r (node->children[1]); } /* ================ FinishVisPortals_r ================ */ void FinishVisPortals2_r (node_t *node) { if (node->planenum == PLANENUM_LEAF) return; MakeNodePortal (node); SplitNodePortals (node); FinishVisPortals2_r (node->children[0]); FinishVisPortals2_r (node->children[1]); } void FinishVisPortals_r (node_t *node) { if (node->planenum == PLANENUM_LEAF) return; if (node->detail_seperator) { FinishVisPortals2_r (node); return; } FinishVisPortals_r (node->children[0]); FinishVisPortals_r (node->children[1]); } int clusterleaf; void SaveClusters_r (node_t *node) { if (node->planenum == PLANENUM_LEAF) { dleafs[clusterleaf++].cluster = node->cluster; return; } SaveClusters_r (node->children[0]); SaveClusters_r (node->children[1]); } /* ================ WritePortalFile ================ */ void WritePortalFile (tree_t *tree) { char path[MAX_SYSPATH]; node_t *headnode; Msg("--- WritePortalFile ---\n"); headnode = tree->headnode; num_visclusters = 0; num_visportals = 0; FreeTreePortals_r (headnode); MakeHeadnodePortals (tree); CreateVisPortals_r (headnode); // set the cluster field in every leaf and count the total number of portals NumberLeafs_r (headnode); // write the file com.sprintf (path, "maps/%s.prt", gs_filename ); pf = FS_Open(path, "w" ); if (!pf) Sys_Error ("Error opening %s", path); FS_Printf (pf, "%s\n", PORTALFILE); FS_Printf (pf, "%i\n", num_visclusters); FS_Printf (pf, "%i\n", num_visportals); MsgDev( D_INFO, "%5i visclusters\n", num_visclusters ); MsgDev( D_INFO, "%5i visportals\n", num_visportals ); WritePortalFile_r( headnode ); FS_Close( pf ); // we need to store the clusters out now because ordering // issues made us do this after writebsp... clusterleaf = 1; SaveClusters_r (headnode); }