]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/prtfile.c
eol style
[xonotic/netradiant.git] / tools / quake3 / q3map2 / 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
23 This code has been altered significantly from its original form, to support
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."
25
26 ------------------------------------------------------------------------------- */
27
28
29
30 /* marker */
31 #define PRTFILE_C
32
33
34
35 /* dependencies */
36 #include "q3map2.h"
37
38
39
40 /*
41 ==============================================================================
42
43 PORTAL FILE GENERATION
44
45 Save out name.prt for qvis to read
46 ==============================================================================
47 */
48
49
50 #define PORTALFILE      "PRT1"
51
52 FILE    *pf;
53 int             num_visclusters;                                // clusters the player can be in
54 int             num_visportals;
55 int             num_solidfaces;
56
57 void WriteFloat (FILE *f, vec_t v)
58 {
59         if ( fabs(v - Q_rint(v)) < 0.001 )
60                 fprintf (f,"%i ",(int)Q_rint(v));
61         else
62                 fprintf (f,"%f ",v);
63 }
64
65 /*
66 =================
67 WritePortalFile_r
68 =================
69 */
70 void WritePortalFile_r (node_t *node)
71 {
72         int                     i, s;   
73         portal_t        *p;
74         winding_t       *w;
75         vec3_t          normal;
76         vec_t           dist;
77
78         // decision node
79         if (node->planenum != PLANENUM_LEAF) {
80                 WritePortalFile_r (node->children[0]);
81                 WritePortalFile_r (node->children[1]);
82                 return;
83         }
84         
85         if (node->opaque) {
86                 return;
87         }
88
89         for (p = node->portals ; p ; p=p->next[s])
90         {
91                 w = p->winding;
92                 s = (p->nodes[1] == node);
93                 if (w && p->nodes[0] == node)
94                 {
95                         if (!PortalPassable(p))
96                                 continue;
97                         // write out to the file
98                         
99                         // sometimes planes get turned around when they are very near
100                         // the changeover point between different axis.  interpret the
101                         // plane the same way vis will, and flip the side orders if needed
102                         // FIXME: is this still relevent?
103                         WindingPlane (w, normal, &dist);
104                         if ( DotProduct (p->plane.normal, normal) < 0.99 )
105                         {       // backwards...
106                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
107                         }
108                         else
109                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
110                         
111                         /* ydnar: added this change to make antiportals work */
112                         if( p->compileFlags & C_HINT )
113                                 fprintf( pf, "1 " );
114                         else
115                                 fprintf( pf, "0 " );
116                         
117                         /* write the winding */
118                         for (i=0 ; i<w->numpoints ; i++)
119                         {
120                                 fprintf (pf,"(");
121                                 WriteFloat (pf, w->p[i][0]);
122                                 WriteFloat (pf, w->p[i][1]);
123                                 WriteFloat (pf, w->p[i][2]);
124                                 fprintf (pf,") ");
125                         }
126                         fprintf (pf,"\n");
127                 }
128         }
129
130 }
131
132 /*
133 =================
134 WriteFaceFile_r
135 =================
136 */
137 void WriteFaceFile_r (node_t *node)
138 {
139         int                     i, s;   
140         portal_t        *p;
141         winding_t       *w;
142
143         // decision node
144         if (node->planenum != PLANENUM_LEAF) {
145                 WriteFaceFile_r (node->children[0]);
146                 WriteFaceFile_r (node->children[1]);
147                 return;
148         }
149         
150         if (node->opaque) {
151                 return;
152         }
153
154         for (p = node->portals ; p ; p=p->next[s])
155         {
156                 w = p->winding;
157                 s = (p->nodes[1] == node);
158                 if (w)
159                 {
160                         if (PortalPassable(p))
161                                 continue;
162                         // write out to the file
163
164                         if (p->nodes[0] == node)
165                         {
166                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
167                                 for (i=0 ; i<w->numpoints ; i++)
168                                 {
169                                         fprintf (pf,"(");
170                                         WriteFloat (pf, w->p[i][0]);
171                                         WriteFloat (pf, w->p[i][1]);
172                                         WriteFloat (pf, w->p[i][2]);
173                                         fprintf (pf,") ");
174                                 }
175                                 fprintf (pf,"\n");
176                         }
177                         else
178                         {
179                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
180                                 for (i = w->numpoints-1; i >= 0; i--)
181                                 {
182                                         fprintf (pf,"(");
183                                         WriteFloat (pf, w->p[i][0]);
184                                         WriteFloat (pf, w->p[i][1]);
185                                         WriteFloat (pf, w->p[i][2]);
186                                         fprintf (pf,") ");
187                                 }
188                                 fprintf (pf,"\n");
189                         }
190                 }
191         }
192 }
193
194 /*
195 ================
196 NumberLeafs_r
197 ================
198 */
199 void NumberLeafs_r (node_t *node)
200 {
201         portal_t        *p;
202
203         if ( node->planenum != PLANENUM_LEAF ) {
204                 // decision node
205                 node->cluster = -99;
206                 NumberLeafs_r (node->children[0]);
207                 NumberLeafs_r (node->children[1]);
208                 return;
209         }
210         
211         node->area = -1;
212
213         if ( node->opaque ) {
214                 // solid block, viewpoint never inside
215                 node->cluster = -1;
216                 return;
217         }
218
219         node->cluster = num_visclusters;
220         num_visclusters++;
221
222         // count the portals
223         for (p = node->portals ; p ; )
224         {
225                 if (p->nodes[0] == node)                // only write out from first leaf
226                 {
227                         if (PortalPassable(p))
228                                 num_visportals++;
229                         else
230                                 num_solidfaces++;
231                         p = p->next[0];
232                 }
233                 else
234                 {
235                         if (!PortalPassable(p))
236                                 num_solidfaces++;
237                         p = p->next[1];         
238                 }
239         }
240 }
241
242
243 /*
244 ================
245 NumberClusters
246 ================
247 */
248 void NumberClusters(tree_t *tree) {
249         num_visclusters = 0;
250         num_visportals = 0;
251         num_solidfaces = 0;
252
253         Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
254         
255         // set the cluster field in every leaf and count the total number of portals
256         NumberLeafs_r (tree->headnode);
257
258         Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
259         Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
260         Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
261 }
262
263 /*
264 ================
265 WritePortalFile
266 ================
267 */
268 void WritePortalFile (tree_t *tree)
269 {
270         char    filename[1024];
271
272         Sys_FPrintf (SYS_VRB,"--- WritePortalFile ---\n");
273         
274         // write the file
275         sprintf (filename, "%s.prt", source);
276         Sys_Printf ("writing %s\n", filename);
277         pf = fopen (filename, "w");
278         if (!pf)
279                 Error ("Error opening %s", filename);
280                 
281         fprintf (pf, "%s\n", PORTALFILE);
282         fprintf (pf, "%i\n", num_visclusters);
283         fprintf (pf, "%i\n", num_visportals);
284         fprintf (pf, "%i\n", num_solidfaces);
285
286         WritePortalFile_r(tree->headnode);
287         WriteFaceFile_r(tree->headnode);
288
289         fclose (pf);
290 }
291