--- /dev/null
+/*\r
+Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
+For a list of contributors, see the accompanying CONTRIBUTORS file.\r
+\r
+This file is part of GtkRadiant.\r
+\r
+GtkRadiant is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2 of the License, or\r
+(at your option) any later version.\r
+\r
+GtkRadiant is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GtkRadiant; if not, write to the Free Software\r
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
+*/\r
+\r
+#include "qbsp.h"\r
+\r
+/*\r
+==============================================================================\r
+\r
+PORTAL FILE GENERATION\r
+\r
+Save out name.prt for qvis to read\r
+==============================================================================\r
+*/\r
+\r
+\r
+#define PORTALFILE "PRT1"\r
+\r
+FILE *pf;\r
+int num_visclusters; // clusters the player can be in\r
+int num_visportals;\r
+\r
+void WriteFloat (FILE *f, vec_t v)\r
+{\r
+ if ( fabs(v - Q_rint(v)) < 0.001 )\r
+ fprintf (f,"%i ",(int)Q_rint(v));\r
+ else\r
+ fprintf (f,"%f ",v);\r
+}\r
+\r
+/*\r
+=================\r
+WritePortalFile_r\r
+=================\r
+*/\r
+void WritePortalFile_r (node_t *node)\r
+{\r
+ int i, s; \r
+ portal_t *p;\r
+ winding_t *w;\r
+ vec3_t normal;\r
+ vec_t dist;\r
+\r
+ // decision node\r
+ if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)\r
+ {\r
+ WritePortalFile_r (node->children[0]);\r
+ WritePortalFile_r (node->children[1]);\r
+ return;\r
+ }\r
+ \r
+ if (node->contents & CONTENTS_SOLID)\r
+ return;\r
+\r
+ for (p = node->portals ; p ; p=p->next[s])\r
+ {\r
+ w = p->winding;\r
+ s = (p->nodes[1] == node);\r
+ if (w && p->nodes[0] == node)\r
+ {\r
+ if (!Portal_VisFlood (p))\r
+ continue;\r
+ // write out to the file\r
+ \r
+ // sometimes planes get turned around when they are very near\r
+ // the changeover point between different axis. interpret the\r
+ // plane the same way vis will, and flip the side orders if needed\r
+ // FIXME: is this still relevent?\r
+ WindingPlane (w, normal, &dist);\r
+ if ( DotProduct (p->plane.normal, normal) < 0.99 )\r
+ { // backwards...\r
+ fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);\r
+ }\r
+ else\r
+ fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);\r
+ for (i=0 ; i<w->numpoints ; i++)\r
+ {\r
+ fprintf (pf,"(");\r
+ WriteFloat (pf, w->p[i][0]);\r
+ WriteFloat (pf, w->p[i][1]);\r
+ WriteFloat (pf, w->p[i][2]);\r
+ fprintf (pf,") ");\r
+ }\r
+ fprintf (pf,"\n");\r
+ }\r
+ }\r
+\r
+}\r
+\r
+/*\r
+================\r
+FillLeafNumbers_r\r
+\r
+All of the leafs under node will have the same cluster\r
+================\r
+*/\r
+void FillLeafNumbers_r (node_t *node, int num)\r
+{\r
+ if (node->planenum == PLANENUM_LEAF)\r
+ {\r
+ if (node->contents & CONTENTS_SOLID)\r
+ node->cluster = -1;\r
+ else\r
+ node->cluster = num;\r
+ return;\r
+ }\r
+ node->cluster = num;\r
+ FillLeafNumbers_r (node->children[0], num);\r
+ FillLeafNumbers_r (node->children[1], num);\r
+}\r
+\r
+/*\r
+================\r
+NumberLeafs_r\r
+================\r
+*/\r
+void NumberLeafs_r (node_t *node)\r
+{\r
+ portal_t *p;\r
+\r
+ if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)\r
+ { // decision node\r
+ node->cluster = -99;\r
+ NumberLeafs_r (node->children[0]);\r
+ NumberLeafs_r (node->children[1]);\r
+ return;\r
+ }\r
+ \r
+ // either a leaf or a detail cluster\r
+\r
+ if ( node->contents & CONTENTS_SOLID )\r
+ { // solid block, viewpoint never inside\r
+ node->cluster = -1;\r
+ return;\r
+ }\r
+\r
+ FillLeafNumbers_r (node, num_visclusters);\r
+ num_visclusters++;\r
+\r
+ // count the portals\r
+ for (p = node->portals ; p ; )\r
+ {\r
+ if (p->nodes[0] == node) // only write out from first leaf\r
+ {\r
+ if (Portal_VisFlood (p))\r
+ num_visportals++;\r
+ p = p->next[0];\r
+ }\r
+ else\r
+ p = p->next[1]; \r
+ }\r
+\r
+}\r
+\r
+\r
+/*\r
+================\r
+CreateVisPortals_r\r
+================\r
+*/\r
+void CreateVisPortals_r (node_t *node)\r
+{\r
+ // stop as soon as we get to a detail_seperator, which\r
+ // means that everything below is in a single cluster\r
+ if (node->planenum == PLANENUM_LEAF || node->detail_seperator )\r
+ return;\r
+\r
+ MakeNodePortal (node);\r
+ SplitNodePortals (node);\r
+\r
+ CreateVisPortals_r (node->children[0]);\r
+ CreateVisPortals_r (node->children[1]);\r
+}\r
+\r
+/*\r
+================\r
+FinishVisPortals_r\r
+================\r
+*/\r
+void FinishVisPortals2_r (node_t *node)\r
+{\r
+ if (node->planenum == PLANENUM_LEAF)\r
+ return;\r
+\r
+ MakeNodePortal (node);\r
+ SplitNodePortals (node);\r
+\r
+ FinishVisPortals2_r (node->children[0]);\r
+ FinishVisPortals2_r (node->children[1]);\r
+}\r
+\r
+void FinishVisPortals_r (node_t *node)\r
+{\r
+ if (node->planenum == PLANENUM_LEAF)\r
+ return;\r
+\r
+ if (node->detail_seperator)\r
+ {\r
+ FinishVisPortals2_r (node);\r
+ return;\r
+ }\r
+\r
+ FinishVisPortals_r (node->children[0]);\r
+ FinishVisPortals_r (node->children[1]);\r
+}\r
+\r
+\r
+int clusterleaf;\r
+void SaveClusters_r (node_t *node)\r
+{\r
+ if (node->planenum == PLANENUM_LEAF)\r
+ {\r
+ dleafs[clusterleaf++].cluster = node->cluster;\r
+ return;\r
+ }\r
+ SaveClusters_r (node->children[0]);\r
+ SaveClusters_r (node->children[1]);\r
+}\r
+\r
+/*\r
+================\r
+WritePortalFile\r
+================\r
+*/\r
+void WritePortalFile (tree_t *tree)\r
+{\r
+ char filename[1024];\r
+ node_t *headnode;\r
+\r
+ Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n");\r
+\r
+ headnode = tree->headnode;\r
+ num_visclusters = 0;\r
+ num_visportals = 0;\r
+\r
+ FreeTreePortals_r (headnode);\r
+\r
+ MakeHeadnodePortals (tree);\r
+\r
+ CreateVisPortals_r (headnode);\r
+\r
+// set the cluster field in every leaf and count the total number of portals\r
+\r
+ NumberLeafs_r (headnode);\r
+ \r
+// write the file\r
+ sprintf (filename, "%s.prt", source);\r
+ Sys_Printf ("writing %s\n", filename);\r
+ pf = fopen (filename, "w");\r
+ if (!pf)\r
+ Error ("Error opening %s", filename);\r
+ \r
+ fprintf (pf, "%s\n", PORTALFILE);\r
+ fprintf (pf, "%i\n", num_visclusters);\r
+ fprintf (pf, "%i\n", num_visportals);\r
+\r
+ Sys_FPrintf( SYS_VRB, "%5i visclusters\n", num_visclusters);\r
+ Sys_FPrintf( SYS_VRB, "%5i visportals\n", num_visportals);\r
+\r
+ WritePortalFile_r (headnode);\r
+\r
+ fclose (pf);\r
+\r
+ // we need to store the clusters out now because ordering\r
+ // issues made us do this after writebsp...\r
+ clusterleaf = 1;\r
+ SaveClusters_r (headnode);\r
+}\r
+\r