]> git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/q2map/prtfile.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / q2map / prtfile.c
diff --git a/tools/quake2/q2map/prtfile.c b/tools/quake2/q2map/prtfile.c
new file mode 100644 (file)
index 0000000..c88e039
--- /dev/null
@@ -0,0 +1,286 @@
+/*\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