initial
[divverent/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 /*
67 =================
68 WritePortalFile_r
69 =================
70 */
71 void WritePortalFile_r (node_t *node)
72 {
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                 {
96                         if (!PortalPassable(p))
97                                 continue;
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 )
106                         {       // backwards...
107                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
108                         }
109                         else
110                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
111                         
112                         /* ydnar: added this change to make antiportals work */
113                         if( p->compileFlags & C_HINT )
114                                 fprintf( pf, "1 " );
115                         else
116                                 fprintf( pf, "0 " );
117                         
118                         /* write the winding */
119                         for (i=0 ; i<w->numpoints ; i++)
120                         {
121                                 fprintf (pf,"(");
122                                 WriteFloat (pf, w->p[i][0]);
123                                 WriteFloat (pf, w->p[i][1]);
124                                 WriteFloat (pf, w->p[i][2]);
125                                 fprintf (pf,") ");
126                         }
127                         fprintf (pf,"\n");
128                 }
129         }
130
131 }
132
133 /*
134 =================
135 WriteFaceFile_r
136 =================
137 */
138 void WriteFaceFile_r (node_t *node)
139 {
140         int                     i, s;   
141         portal_t        *p;
142         winding_t       *w;
143
144         // decision node
145         if (node->planenum != PLANENUM_LEAF) {
146                 WriteFaceFile_r (node->children[0]);
147                 WriteFaceFile_r (node->children[1]);
148                 return;
149         }
150         
151         if (node->opaque) {
152                 return;
153         }
154
155         for (p = node->portals ; p ; p=p->next[s])
156         {
157                 w = p->winding;
158                 s = (p->nodes[1] == node);
159                 if (w)
160                 {
161                         if (PortalPassable(p))
162                                 continue;
163                         // write out to the file
164
165                         if (p->nodes[0] == node)
166                         {
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 {
202         portal_t        *p;
203
204         if ( node->planenum != PLANENUM_LEAF ) {
205                 // decision node
206                 node->cluster = -99;
207                 NumberLeafs_r (node->children[0]);
208                 NumberLeafs_r (node->children[1]);
209                 return;
210         }
211         
212         node->area = -1;
213
214         if ( node->opaque ) {
215                 // solid block, viewpoint never inside
216                 node->cluster = -1;
217                 return;
218         }
219
220         node->cluster = num_visclusters;
221         num_visclusters++;
222
223         // count the portals
224         for (p = node->portals ; p ; )
225         {
226                 if (p->nodes[0] == node)                // only write out from first leaf
227                 {
228                         if (PortalPassable(p))
229                                 num_visportals++;
230                         else
231                                 num_solidfaces++;
232                         p = p->next[0];
233                 }
234                 else
235                 {
236                         if (!PortalPassable(p))
237                                 num_solidfaces++;
238                         p = p->next[1];         
239                 }
240         }
241 }
242
243
244 /*
245 ================
246 NumberClusters
247 ================
248 */
249 void NumberClusters(tree_t *tree) {
250         num_visclusters = 0;
251         num_visportals = 0;
252         num_solidfaces = 0;
253
254         Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
255         
256         // set the cluster field in every leaf and count the total number of portals
257         NumberLeafs_r (tree->headnode);
258
259         Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
260         Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
261         Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
262 }
263
264 /*
265 ================
266 WritePortalFile
267 ================
268 */
269 void WritePortalFile (tree_t *tree)
270 {
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         fprintf (pf, "%s\n", PORTALFILE);
283         fprintf (pf, "%i\n", num_visclusters);
284         fprintf (pf, "%i\n", num_visportals);
285         fprintf (pf, "%i\n", num_solidfaces);
286
287         WritePortalFile_r(tree->headnode);
288         WriteFaceFile_r(tree->headnode);
289
290         fclose (pf);
291 }
292