]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/bsp/qbsp3/prtfile.c
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / tools / quake2 / extra / bsp / qbsp3 / prtfile.c
1 /*
2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
4
5 This file is part of Quake 2 Tools source code.
6
7 Quake 2 Tools 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 2 Tools 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 Quake 2 Tools source code; 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 WriteFloat (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                                 WriteFloat (pf, w->p[i][0]);
98                                 WriteFloat (pf, w->p[i][1]);
99                                 WriteFloat (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         FreeTreePortals_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