prtfile.c (6245B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 #include "qbsp.h" 24 25 /* 26 ============================================================================== 27 28 PORTAL FILE GENERATION 29 30 Save out name.prt for qvis to read 31 ============================================================================== 32 */ 33 34 35 #define PORTALFILE "PRT1" 36 37 FILE *pf; 38 int num_visclusters; // clusters the player can be in 39 int num_visportals; 40 41 void WriteFloat2 (FILE *f, vec_t v) 42 { 43 if ( fabs(v - Q_rint(v)) < 0.001 ) 44 fprintf (f,"%i ",(int)Q_rint(v)); 45 else 46 fprintf (f,"%f ",v); 47 } 48 49 /* 50 ================= 51 WritePortalFile_r 52 ================= 53 */ 54 void WritePortalFile_r (node_t *node) 55 { 56 int i, s; 57 portal_t *p; 58 winding_t *w; 59 vec3_t normal; 60 vec_t dist; 61 62 // decision node 63 if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) 64 { 65 WritePortalFile_r (node->children[0]); 66 WritePortalFile_r (node->children[1]); 67 return; 68 } 69 70 if (node->contents & CONTENTS_SOLID) 71 return; 72 73 for (p = node->portals ; p ; p=p->next[s]) 74 { 75 w = p->winding; 76 s = (p->nodes[1] == node); 77 if (w && p->nodes[0] == node) 78 { 79 if (!Portal_VisFlood (p)) 80 continue; 81 // write out to the file 82 83 // sometimes planes get turned around when they are very near 84 // the changeover point between different axis. interpret the 85 // plane the same way vis will, and flip the side orders if needed 86 // FIXME: is this still relevent? 87 WindingPlane (w, normal, &dist); 88 if ( DotProduct (p->plane.normal, normal) < 0.99 ) 89 { // backwards... 90 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); 91 } 92 else 93 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster); 94 for (i=0 ; i<w->numpoints ; i++) 95 { 96 fprintf (pf,"("); 97 WriteFloat2 (pf, w->p[i][0]); 98 WriteFloat2 (pf, w->p[i][1]); 99 WriteFloat2 (pf, w->p[i][2]); 100 fprintf (pf,") "); 101 } 102 fprintf (pf,"\n"); 103 } 104 } 105 106 } 107 108 /* 109 ================ 110 FillLeafNumbers_r 111 112 All of the leafs under node will have the same cluster 113 ================ 114 */ 115 void FillLeafNumbers_r (node_t *node, int num) 116 { 117 if (node->planenum == PLANENUM_LEAF) 118 { 119 if (node->contents & CONTENTS_SOLID) 120 node->cluster = -1; 121 else 122 node->cluster = num; 123 return; 124 } 125 node->cluster = num; 126 FillLeafNumbers_r (node->children[0], num); 127 FillLeafNumbers_r (node->children[1], num); 128 } 129 130 /* 131 ================ 132 NumberLeafs_r 133 ================ 134 */ 135 void NumberLeafs_r (node_t *node) 136 { 137 portal_t *p; 138 139 if (node->planenum != PLANENUM_LEAF && !node->detail_seperator) 140 { // decision node 141 node->cluster = -99; 142 NumberLeafs_r (node->children[0]); 143 NumberLeafs_r (node->children[1]); 144 return; 145 } 146 147 // either a leaf or a detail cluster 148 149 if ( node->contents & CONTENTS_SOLID ) 150 { // solid block, viewpoint never inside 151 node->cluster = -1; 152 return; 153 } 154 155 FillLeafNumbers_r (node, num_visclusters); 156 num_visclusters++; 157 158 // count the portals 159 for (p = node->portals ; p ; ) 160 { 161 if (p->nodes[0] == node) // only write out from first leaf 162 { 163 if (Portal_VisFlood (p)) 164 num_visportals++; 165 p = p->next[0]; 166 } 167 else 168 p = p->next[1]; 169 } 170 171 } 172 173 174 /* 175 ================ 176 CreateVisPortals_r 177 ================ 178 */ 179 void CreateVisPortals_r (node_t *node) 180 { 181 // stop as soon as we get to a detail_seperator, which 182 // means that everything below is in a single cluster 183 if (node->planenum == PLANENUM_LEAF || node->detail_seperator ) 184 return; 185 186 MakeNodePortal (node); 187 SplitNodePortals (node); 188 189 CreateVisPortals_r (node->children[0]); 190 CreateVisPortals_r (node->children[1]); 191 } 192 193 /* 194 ================ 195 FinishVisPortals_r 196 ================ 197 */ 198 void FinishVisPortals2_r (node_t *node) 199 { 200 if (node->planenum == PLANENUM_LEAF) 201 return; 202 203 MakeNodePortal (node); 204 SplitNodePortals (node); 205 206 FinishVisPortals2_r (node->children[0]); 207 FinishVisPortals2_r (node->children[1]); 208 } 209 210 void FinishVisPortals_r (node_t *node) 211 { 212 if (node->planenum == PLANENUM_LEAF) 213 return; 214 215 if (node->detail_seperator) 216 { 217 FinishVisPortals2_r (node); 218 return; 219 } 220 221 FinishVisPortals_r (node->children[0]); 222 FinishVisPortals_r (node->children[1]); 223 } 224 225 226 int clusterleaf; 227 void SaveClusters_r (node_t *node) 228 { 229 if (node->planenum == PLANENUM_LEAF) 230 { 231 dleafs[clusterleaf++].cluster = node->cluster; 232 return; 233 } 234 SaveClusters_r (node->children[0]); 235 SaveClusters_r (node->children[1]); 236 } 237 238 /* 239 ================ 240 WritePortalFile 241 ================ 242 */ 243 void WritePortalFile (tree_t *tree) 244 { 245 char filename[1024]; 246 node_t *headnode; 247 248 qprintf ("--- WritePortalFile ---\n"); 249 250 headnode = tree->headnode; 251 num_visclusters = 0; 252 num_visportals = 0; 253 254 Tree_FreePortals_r (headnode); 255 256 MakeHeadnodePortals (tree); 257 258 CreateVisPortals_r (headnode); 259 260 // set the cluster field in every leaf and count the total number of portals 261 262 NumberLeafs_r (headnode); 263 264 // write the file 265 sprintf (filename, "%s.prt", source); 266 printf ("writing %s\n", filename); 267 pf = fopen (filename, "w"); 268 if (!pf) 269 Error ("Error opening %s", filename); 270 271 fprintf (pf, "%s\n", PORTALFILE); 272 fprintf (pf, "%i\n", num_visclusters); 273 fprintf (pf, "%i\n", num_visportals); 274 275 qprintf ("%5i visclusters\n", num_visclusters); 276 qprintf ("%5i visportals\n", num_visportals); 277 278 WritePortalFile_r (headnode); 279 280 fclose (pf); 281 282 // we need to store the clusters out now because ordering 283 // issues made us do this after writebsp... 284 clusterleaf = 1; 285 SaveClusters_r (headnode); 286 } 287