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