_farplanedist now ignores C_SKY leafs
[xonotic/netradiant.git] / tools / quake3 / q3map2 / prtfile.c
1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6 This file is part of GtkRadiant.
7
8 GtkRadiant is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 GtkRadiant is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GtkRadiant; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22 ----------------------------------------------------------------------------------
23
24 This code has been altered significantly from its original form, to support
25 several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27 ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define PRTFILE_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41 /*
42 ==============================================================================
43
44 PORTAL FILE GENERATION
45
46 Save out name.prt for qvis to read
47 ==============================================================================
48 */
49
50
51 #define PORTALFILE      "PRT1"
52
53 FILE    *pf;
54 int             num_visclusters;                                // clusters the player can be in
55 int             num_visportals;
56 int             num_solidfaces;
57
58 void WriteFloat (FILE *f, vec_t v)
59 {
60         if ( fabs(v - Q_rint(v)) < 0.001 )
61                 fprintf (f,"%i ",(int)Q_rint(v));
62         else
63                 fprintf (f,"%f ",v);
64 }
65
66 void CountVisportals_r(node_t *node)
67 {
68         int                     s;      
69         portal_t        *p;
70         winding_t       *w;
71
72         // decision node
73         if (node->planenum != PLANENUM_LEAF) {
74                 CountVisportals_r (node->children[0]);
75                 CountVisportals_r (node->children[1]);
76                 return;
77         }
78         
79         if (node->opaque) {
80                 return;
81         }
82
83         for (p = node->portals ; p ; p=p->next[s])
84         {
85                 w = p->winding;
86                 s = (p->nodes[1] == node);
87                 if (w && p->nodes[0] == node)
88                 {
89                         if (!PortalPassable(p))
90                                 continue;
91                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
92                                 continue;
93                         ++num_visportals;
94                 }
95         }
96 }
97
98 /*
99 =================
100 WritePortalFile_r
101 =================
102 */
103 void WritePortalFile_r (node_t *node)
104 {
105         int                     i, s, flags;
106         portal_t        *p;
107         winding_t       *w;
108         vec3_t          normal;
109         vec_t           dist;
110
111         // decision node
112         if (node->planenum != PLANENUM_LEAF) {
113                 WritePortalFile_r (node->children[0]);
114                 WritePortalFile_r (node->children[1]);
115                 return;
116         }
117         
118         if (node->opaque) {
119                 return;
120         }
121
122         for (p = node->portals ; p ; p=p->next[s])
123         {
124                 w = p->winding;
125                 s = (p->nodes[1] == node);
126                 if (w && p->nodes[0] == node)
127                 {
128                         if (!PortalPassable(p))
129                                 continue;
130                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
131                                 continue;
132                         --num_visportals;
133                         // write out to the file
134                         
135                         // sometimes planes get turned around when they are very near
136                         // the changeover point between different axis.  interpret the
137                         // plane the same way vis will, and flip the side orders if needed
138                         // FIXME: is this still relevent?
139                         WindingPlane (w, normal, &dist);
140
141                         if ( DotProduct (p->plane.normal, normal) < 0.99 )
142                         {       // backwards...
143                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
144                         }
145                         else
146                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
147
148                         flags = 0;
149                         
150                         /* ydnar: added this change to make antiportals work */
151                         if( p->compileFlags & C_HINT )
152                                 flags |= 1;
153
154                         /* divVerent: I want farplanedist to not kill skybox. So... */
155                         if( p->compileFlags & C_SKY )
156                                 flags |= 2;
157
158                         fprintf( pf, "%d ", flags );
159                         
160                         /* write the winding */
161                         for (i=0 ; i<w->numpoints ; i++)
162                         {
163                                 fprintf (pf,"(");
164                                 WriteFloat (pf, w->p[i][0]);
165                                 WriteFloat (pf, w->p[i][1]);
166                                 WriteFloat (pf, w->p[i][2]);
167                                 fprintf (pf,") ");
168                         }
169                         fprintf (pf,"\n");
170                 }
171         }
172
173 }
174
175 void CountSolidFaces_r (node_t *node)
176 {
177         int                     s;      
178         portal_t        *p;
179         winding_t       *w;
180
181         // decision node
182         if (node->planenum != PLANENUM_LEAF) {
183                 CountSolidFaces_r (node->children[0]);
184                 CountSolidFaces_r (node->children[1]);
185                 return;
186         }
187         
188         if (node->opaque) {
189                 return;
190         }
191
192         for (p = node->portals ; p ; p=p->next[s])
193         {
194                 w = p->winding;
195                 s = (p->nodes[1] == node);
196                 if (w)
197                 {
198                         if (PortalPassable(p))
199                                 continue;
200                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
201                                 continue;
202                         // write out to the file
203
204                         ++num_solidfaces;
205                 }
206         }
207 }
208
209 /*
210 =================
211 WriteFaceFile_r
212 =================
213 */
214 void WriteFaceFile_r (node_t *node)
215 {
216         int                     i, s;   
217         portal_t        *p;
218         winding_t       *w;
219
220         // decision node
221         if (node->planenum != PLANENUM_LEAF) {
222                 WriteFaceFile_r (node->children[0]);
223                 WriteFaceFile_r (node->children[1]);
224                 return;
225         }
226         
227         if (node->opaque) {
228                 return;
229         }
230
231         for (p = node->portals ; p ; p=p->next[s])
232         {
233                 w = p->winding;
234                 s = (p->nodes[1] == node);
235                 if (w)
236                 {
237                         if (PortalPassable(p))
238                                 continue;
239                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
240                                 continue;
241                         // write out to the file
242
243                         if (p->nodes[0] == node)
244                         {
245                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
246                                 for (i=0 ; i<w->numpoints ; i++)
247                                 {
248                                         fprintf (pf,"(");
249                                         WriteFloat (pf, w->p[i][0]);
250                                         WriteFloat (pf, w->p[i][1]);
251                                         WriteFloat (pf, w->p[i][2]);
252                                         fprintf (pf,") ");
253                                 }
254                                 fprintf (pf,"\n");
255                         }
256                         else
257                         {
258                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
259                                 for (i = w->numpoints-1; i >= 0; i--)
260                                 {
261                                         fprintf (pf,"(");
262                                         WriteFloat (pf, w->p[i][0]);
263                                         WriteFloat (pf, w->p[i][1]);
264                                         WriteFloat (pf, w->p[i][2]);
265                                         fprintf (pf,") ");
266                                 }
267                                 fprintf (pf,"\n");
268                         }
269                 }
270         }
271 }
272
273 /*
274 ================
275 NumberLeafs_r
276 ================
277 */
278 void NumberLeafs_r (node_t *node, int c)
279 {
280 #if 0
281         portal_t        *p;
282 #endif
283         if ( node->planenum != PLANENUM_LEAF ) {
284                 // decision node
285                 node->cluster = -99;
286
287                 if(node->has_structural_children)
288                 {
289 #if 0
290                         if(c >= 0)
291                                 Sys_FPrintf (SYS_ERR,"THIS CANNOT HAPPEN\n");
292 #endif
293                         NumberLeafs_r (node->children[0], c);
294                         NumberLeafs_r (node->children[1], c);
295                 }
296                 else
297                 {
298                         if(c < 0)
299                                 c = num_visclusters++;
300                         NumberLeafs_r (node->children[0], c);
301                         NumberLeafs_r (node->children[1], c);
302                 }
303                 return;
304         }
305         
306         node->area = -1;
307
308         if ( node->opaque ) {
309                 // solid block, viewpoint never inside
310                 node->cluster = -1;
311                 return;
312         }
313
314         if(c < 0)
315                 c = num_visclusters++;
316         
317         node->cluster = c;
318
319 #if 0
320         // count the portals
321         for (p = node->portals ; p ; )
322         {
323                 if (p->nodes[0] == node)                // only write out from first leaf
324                 {
325                         if (PortalPassable(p))
326                                 num_visportals++;
327                         else
328                                 num_solidfaces++;
329                         p = p->next[0];
330                 }
331                 else
332                 {
333                         if (!PortalPassable(p))
334                                 num_solidfaces++;
335                         p = p->next[1];         
336                 }
337         }
338 #endif
339 }
340
341
342 /*
343 ================
344 NumberClusters
345 ================
346 */
347 void NumberClusters(tree_t *tree) {
348         num_visclusters = 0;
349         num_visportals = 0;
350         num_solidfaces = 0;
351
352         Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
353         
354         // set the cluster field in every leaf and count the total number of portals
355         NumberLeafs_r (tree->headnode, -1);
356         CountVisportals_r (tree->headnode);
357         CountSolidFaces_r (tree->headnode);
358
359         Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
360         Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
361         Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
362 }
363
364 /*
365 ================
366 WritePortalFile
367 ================
368 */
369 void WritePortalFile (tree_t *tree)
370 {
371         char    filename[1024];
372
373         Sys_FPrintf (SYS_VRB,"--- WritePortalFile ---\n");
374         
375         // write the file
376         sprintf (filename, "%s.prt", source);
377         Sys_Printf ("writing %s\n", filename);
378         pf = fopen (filename, "w");
379         if (!pf)
380                 Error ("Error opening %s", filename);
381                 
382         fprintf (pf, "%s\n", PORTALFILE);
383         fprintf (pf, "%i\n", num_visclusters);
384         fprintf (pf, "%i\n", num_visportals);
385         fprintf (pf, "%i\n", num_solidfaces);
386
387         WritePortalFile_r(tree->headnode);
388         WriteFaceFile_r(tree->headnode);
389
390         fclose (pf);
391 }
392