]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/prtfile.c
q3map2: fix dangling pointer dereference
[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         if ( fabs( v - Q_rint( v ) ) < 0.001 ) {
60                 fprintf( f,"%i ",(int)Q_rint( v ) );
61         }
62         else{
63                 fprintf( f,"%f ",v );
64         }
65 }
66
67 /*
68    =================
69    WritePortalFile_r
70    =================
71  */
72 void WritePortalFile_r( node_t *node ){
73         int i, s;
74         portal_t    *p;
75         winding_t   *w;
76         vec3_t normal;
77         vec_t dist;
78
79         // decision node
80         if ( node->planenum != PLANENUM_LEAF ) {
81                 WritePortalFile_r( node->children[0] );
82                 WritePortalFile_r( node->children[1] );
83                 return;
84         }
85
86         if ( node->opaque ) {
87                 return;
88         }
89
90         for ( p = node->portals ; p ; p = p->next[s] )
91         {
92                 w = p->winding;
93                 s = ( p->nodes[1] == node );
94                 if ( w && p->nodes[0] == node ) {
95                         if ( !PortalPassable( p ) ) {
96                                 continue;
97                         }
98                         // write out to the file
99
100                         // sometimes planes get turned around when they are very near
101                         // the changeover point between different axis.  interpret the
102                         // plane the same way vis will, and flip the side orders if needed
103                         // FIXME: is this still relevent?
104                         WindingPlane( w, normal, &dist );
105                         if ( DotProduct( p->plane.normal, normal ) < 0.99 ) { // 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
112                         /* ydnar: added this change to make antiportals work */
113                         if ( p->compileFlags & C_HINT ) {
114                                 fprintf( pf, "1 " );
115                         }
116                         else{
117                                 fprintf( pf, "0 " );
118                         }
119
120                         /* write the winding */
121                         for ( i = 0 ; i < w->numpoints ; i++ )
122                         {
123                                 fprintf( pf,"(" );
124                                 WriteFloat( pf, w->p[i][0] );
125                                 WriteFloat( pf, w->p[i][1] );
126                                 WriteFloat( pf, w->p[i][2] );
127                                 fprintf( pf,") " );
128                         }
129                         fprintf( pf,"\n" );
130                 }
131         }
132
133 }
134
135 /*
136    =================
137    WriteFaceFile_r
138    =================
139  */
140 void WriteFaceFile_r( node_t *node ){
141         int i, s;
142         portal_t    *p;
143         winding_t   *w;
144
145         // decision node
146         if ( node->planenum != PLANENUM_LEAF ) {
147                 WriteFaceFile_r( node->children[0] );
148                 WriteFaceFile_r( node->children[1] );
149                 return;
150         }
151
152         if ( node->opaque ) {
153                 return;
154         }
155
156         for ( p = node->portals ; p ; p = p->next[s] )
157         {
158                 w = p->winding;
159                 s = ( p->nodes[1] == node );
160                 if ( w ) {
161                         if ( PortalPassable( p ) ) {
162                                 continue;
163                         }
164                         // write out to the file
165
166                         if ( p->nodes[0] == node ) {
167                                 fprintf( pf,"%i %i ",w->numpoints, p->nodes[0]->cluster );
168                                 for ( i = 0 ; i < w->numpoints ; i++ )
169                                 {
170                                         fprintf( pf,"(" );
171                                         WriteFloat( pf, w->p[i][0] );
172                                         WriteFloat( pf, w->p[i][1] );
173                                         WriteFloat( pf, w->p[i][2] );
174                                         fprintf( pf,") " );
175                                 }
176                                 fprintf( pf,"\n" );
177                         }
178                         else
179                         {
180                                 fprintf( pf,"%i %i ",w->numpoints, p->nodes[1]->cluster );
181                                 for ( i = w->numpoints - 1; i >= 0; i-- )
182                                 {
183                                         fprintf( pf,"(" );
184                                         WriteFloat( pf, w->p[i][0] );
185                                         WriteFloat( pf, w->p[i][1] );
186                                         WriteFloat( pf, w->p[i][2] );
187                                         fprintf( pf,") " );
188                                 }
189                                 fprintf( pf,"\n" );
190                         }
191                 }
192         }
193 }
194
195 /*
196    ================
197    NumberLeafs_r
198    ================
199  */
200 void NumberLeafs_r( node_t *node ){
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                         if ( PortalPassable( p ) ) {
227                                 num_visportals++;
228                         }
229                         else{
230                                 num_solidfaces++;
231                         }
232                         p = p->next[0];
233                 }
234                 else
235                 {
236                         if ( !PortalPassable( p ) ) {
237                                 num_solidfaces++;
238                         }
239                         p = p->next[1];
240                 }
241         }
242 }
243
244
245 /*
246    ================
247    NumberClusters
248    ================
249  */
250 void NumberClusters( tree_t *tree ) {
251         num_visclusters = 0;
252         num_visportals = 0;
253         num_solidfaces = 0;
254
255         Sys_FPrintf( SYS_VRB,"--- NumberClusters ---\n" );
256
257         // set the cluster field in every leaf and count the total number of portals
258         NumberLeafs_r( tree->headnode );
259
260         Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
261         Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
262         Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
263 }
264
265 /*
266    ================
267    WritePortalFile
268    ================
269  */
270 void WritePortalFile( tree_t *tree ){
271         char filename[1024];
272
273         Sys_FPrintf( SYS_VRB,"--- WritePortalFile ---\n" );
274
275         // write the file
276         sprintf( filename, "%s.prt", source );
277         Sys_Printf( "writing %s\n", filename );
278         pf = fopen( filename, "w" );
279         if ( !pf ) {
280                 Error( "Error opening %s", filename );
281         }
282
283         fprintf( pf, "%s\n", PORTALFILE );
284         fprintf( pf, "%i\n", num_visclusters );
285         fprintf( pf, "%i\n", num_visportals );
286         fprintf( pf, "%i\n", num_solidfaces );
287
288         WritePortalFile_r( tree->headnode );
289         WriteFaceFile_r( tree->headnode );
290
291         fclose( pf );
292 }