patches by jal: fix some warnings, and spawnflags 64 on misc_model to not smooth...
[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 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;   
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                         /* ydnar: added this change to make antiportals work */
149                         if( p->compileFlags & C_HINT )
150                                 fprintf( pf, "1 " );
151                         else
152                                 fprintf( pf, "0 " );
153                         
154                         /* write the winding */
155                         for (i=0 ; i<w->numpoints ; i++)
156                         {
157                                 fprintf (pf,"(");
158                                 WriteFloat (pf, w->p[i][0]);
159                                 WriteFloat (pf, w->p[i][1]);
160                                 WriteFloat (pf, w->p[i][2]);
161                                 fprintf (pf,") ");
162                         }
163                         fprintf (pf,"\n");
164                 }
165         }
166
167 }
168
169 void CountSolidFaces_r (node_t *node)
170 {
171         int                     s;      
172         portal_t        *p;
173         winding_t       *w;
174
175         // decision node
176         if (node->planenum != PLANENUM_LEAF) {
177                 CountSolidFaces_r (node->children[0]);
178                 CountSolidFaces_r (node->children[1]);
179                 return;
180         }
181         
182         if (node->opaque) {
183                 return;
184         }
185
186         for (p = node->portals ; p ; p=p->next[s])
187         {
188                 w = p->winding;
189                 s = (p->nodes[1] == node);
190                 if (w)
191                 {
192                         if (PortalPassable(p))
193                                 continue;
194                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
195                                 continue;
196                         // write out to the file
197
198                         ++num_solidfaces;
199                 }
200         }
201 }
202
203 /*
204 =================
205 WriteFaceFile_r
206 =================
207 */
208 void WriteFaceFile_r (node_t *node)
209 {
210         int                     i, s;   
211         portal_t        *p;
212         winding_t       *w;
213
214         // decision node
215         if (node->planenum != PLANENUM_LEAF) {
216                 WriteFaceFile_r (node->children[0]);
217                 WriteFaceFile_r (node->children[1]);
218                 return;
219         }
220         
221         if (node->opaque) {
222                 return;
223         }
224
225         for (p = node->portals ; p ; p=p->next[s])
226         {
227                 w = p->winding;
228                 s = (p->nodes[1] == node);
229                 if (w)
230                 {
231                         if (PortalPassable(p))
232                                 continue;
233                         if(p->nodes[0]->cluster == p->nodes[1]->cluster)
234                                 continue;
235                         // write out to the file
236
237                         if (p->nodes[0] == node)
238                         {
239                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
240                                 for (i=0 ; i<w->numpoints ; i++)
241                                 {
242                                         fprintf (pf,"(");
243                                         WriteFloat (pf, w->p[i][0]);
244                                         WriteFloat (pf, w->p[i][1]);
245                                         WriteFloat (pf, w->p[i][2]);
246                                         fprintf (pf,") ");
247                                 }
248                                 fprintf (pf,"\n");
249                         }
250                         else
251                         {
252                                 fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
253                                 for (i = w->numpoints-1; i >= 0; i--)
254                                 {
255                                         fprintf (pf,"(");
256                                         WriteFloat (pf, w->p[i][0]);
257                                         WriteFloat (pf, w->p[i][1]);
258                                         WriteFloat (pf, w->p[i][2]);
259                                         fprintf (pf,") ");
260                                 }
261                                 fprintf (pf,"\n");
262                         }
263                 }
264         }
265 }
266
267 /*
268 ================
269 NumberLeafs_r
270 ================
271 */
272 void NumberLeafs_r (node_t *node, int c)
273 {
274 #if 0
275         portal_t        *p;
276 #endif
277         if ( node->planenum != PLANENUM_LEAF ) {
278                 // decision node
279                 node->cluster = -99;
280
281                 if(node->has_structural_children)
282                 {
283 #if 0
284                         if(c >= 0)
285                                 Sys_FPrintf (SYS_ERR,"THIS CANNOT HAPPEN\n");
286 #endif
287                         NumberLeafs_r (node->children[0], c);
288                         NumberLeafs_r (node->children[1], c);
289                 }
290                 else
291                 {
292                         if(c < 0)
293                                 c = num_visclusters++;
294                         NumberLeafs_r (node->children[0], c);
295                         NumberLeafs_r (node->children[1], c);
296                 }
297                 return;
298         }
299         
300         node->area = -1;
301
302         if ( node->opaque ) {
303                 // solid block, viewpoint never inside
304                 node->cluster = -1;
305                 return;
306         }
307
308         if(c < 0)
309                 c = num_visclusters++;
310         
311         node->cluster = c;
312
313 #if 0
314         // count the portals
315         for (p = node->portals ; p ; )
316         {
317                 if (p->nodes[0] == node)                // only write out from first leaf
318                 {
319                         if (PortalPassable(p))
320                                 num_visportals++;
321                         else
322                                 num_solidfaces++;
323                         p = p->next[0];
324                 }
325                 else
326                 {
327                         if (!PortalPassable(p))
328                                 num_solidfaces++;
329                         p = p->next[1];         
330                 }
331         }
332 #endif
333 }
334
335
336 /*
337 ================
338 NumberClusters
339 ================
340 */
341 void NumberClusters(tree_t *tree) {
342         num_visclusters = 0;
343         num_visportals = 0;
344         num_solidfaces = 0;
345
346         Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
347         
348         // set the cluster field in every leaf and count the total number of portals
349         NumberLeafs_r (tree->headnode, -1);
350         CountVisportals_r (tree->headnode);
351         CountSolidFaces_r (tree->headnode);
352
353         Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
354         Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
355         Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
356 }
357
358 /*
359 ================
360 WritePortalFile
361 ================
362 */
363 void WritePortalFile (tree_t *tree)
364 {
365         char    filename[1024];
366
367         Sys_FPrintf (SYS_VRB,"--- WritePortalFile ---\n");
368         
369         // write the file
370         sprintf (filename, "%s.prt", source);
371         Sys_Printf ("writing %s\n", filename);
372         pf = fopen (filename, "w");
373         if (!pf)
374                 Error ("Error opening %s", filename);
375                 
376         fprintf (pf, "%s\n", PORTALFILE);
377         fprintf (pf, "%i\n", num_visclusters);
378         fprintf (pf, "%i\n", num_visportals);
379         fprintf (pf, "%i\n", num_solidfaces);
380
381         WritePortalFile_r(tree->headnode);
382         WriteFaceFile_r(tree->headnode);
383
384         fclose (pf);
385 }
386