]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/q2map/prtfile.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake2 / q2map / prtfile.c
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 */\r
21 \r
22 #include "qbsp.h"\r
23 \r
24 /*\r
25 ==============================================================================\r
26 \r
27 PORTAL FILE GENERATION\r
28 \r
29 Save out name.prt for qvis to read\r
30 ==============================================================================\r
31 */\r
32 \r
33 \r
34 #define PORTALFILE      "PRT1"\r
35 \r
36 FILE    *pf;\r
37 int             num_visclusters;                                // clusters the player can be in\r
38 int             num_visportals;\r
39 \r
40 void WriteFloat (FILE *f, vec_t v)\r
41 {\r
42         if ( fabs(v - Q_rint(v)) < 0.001 )\r
43                 fprintf (f,"%i ",(int)Q_rint(v));\r
44         else\r
45                 fprintf (f,"%f ",v);\r
46 }\r
47 \r
48 /*\r
49 =================\r
50 WritePortalFile_r\r
51 =================\r
52 */\r
53 void WritePortalFile_r (node_t *node)\r
54 {\r
55         int                     i, s;   \r
56         portal_t        *p;\r
57         winding_t       *w;\r
58         vec3_t          normal;\r
59         vec_t           dist;\r
60 \r
61         // decision node\r
62         if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)\r
63         {\r
64                 WritePortalFile_r (node->children[0]);\r
65                 WritePortalFile_r (node->children[1]);\r
66                 return;\r
67         }\r
68         \r
69         if (node->contents & CONTENTS_SOLID)\r
70                 return;\r
71 \r
72         for (p = node->portals ; p ; p=p->next[s])\r
73         {\r
74                 w = p->winding;\r
75                 s = (p->nodes[1] == node);\r
76                 if (w && p->nodes[0] == node)\r
77                 {\r
78                         if (!Portal_VisFlood (p))\r
79                                 continue;\r
80                 // write out to the file\r
81                 \r
82                 // sometimes planes get turned around when they are very near\r
83                 // the changeover point between different axis.  interpret the\r
84                 // plane the same way vis will, and flip the side orders if needed\r
85                         // FIXME: is this still relevent?\r
86                         WindingPlane (w, normal, &dist);\r
87                         if ( DotProduct (p->plane.normal, normal) < 0.99 )\r
88                         {       // backwards...\r
89                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);\r
90                         }\r
91                         else\r
92                                 fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);\r
93                         for (i=0 ; i<w->numpoints ; i++)\r
94                         {\r
95                                 fprintf (pf,"(");\r
96                                 WriteFloat (pf, w->p[i][0]);\r
97                                 WriteFloat (pf, w->p[i][1]);\r
98                                 WriteFloat (pf, w->p[i][2]);\r
99                                 fprintf (pf,") ");\r
100                         }\r
101                         fprintf (pf,"\n");\r
102                 }\r
103         }\r
104 \r
105 }\r
106 \r
107 /*\r
108 ================\r
109 FillLeafNumbers_r\r
110 \r
111 All of the leafs under node will have the same cluster\r
112 ================\r
113 */\r
114 void FillLeafNumbers_r (node_t *node, int num)\r
115 {\r
116         if (node->planenum == PLANENUM_LEAF)\r
117         {\r
118                 if (node->contents & CONTENTS_SOLID)\r
119                         node->cluster = -1;\r
120                 else\r
121                         node->cluster = num;\r
122                 return;\r
123         }\r
124         node->cluster = num;\r
125         FillLeafNumbers_r (node->children[0], num);\r
126         FillLeafNumbers_r (node->children[1], num);\r
127 }\r
128 \r
129 /*\r
130 ================\r
131 NumberLeafs_r\r
132 ================\r
133 */\r
134 void NumberLeafs_r (node_t *node)\r
135 {\r
136         portal_t        *p;\r
137 \r
138         if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)\r
139         {       // decision node\r
140                 node->cluster = -99;\r
141                 NumberLeafs_r (node->children[0]);\r
142                 NumberLeafs_r (node->children[1]);\r
143                 return;\r
144         }\r
145         \r
146         // either a leaf or a detail cluster\r
147 \r
148         if ( node->contents & CONTENTS_SOLID )\r
149         {       // solid block, viewpoint never inside\r
150                 node->cluster = -1;\r
151                 return;\r
152         }\r
153 \r
154         FillLeafNumbers_r (node, num_visclusters);\r
155         num_visclusters++;\r
156 \r
157         // count the portals\r
158         for (p = node->portals ; p ; )\r
159         {\r
160                 if (p->nodes[0] == node)                // only write out from first leaf\r
161                 {\r
162                         if (Portal_VisFlood (p))\r
163                                 num_visportals++;\r
164                         p = p->next[0];\r
165                 }\r
166                 else\r
167                         p = p->next[1];         \r
168         }\r
169 \r
170 }\r
171 \r
172 \r
173 /*\r
174 ================\r
175 CreateVisPortals_r\r
176 ================\r
177 */\r
178 void CreateVisPortals_r (node_t *node)\r
179 {\r
180         // stop as soon as we get to a detail_seperator, which\r
181         // means that everything below is in a single cluster\r
182         if (node->planenum == PLANENUM_LEAF || node->detail_seperator )\r
183                 return;\r
184 \r
185         MakeNodePortal (node);\r
186         SplitNodePortals (node);\r
187 \r
188         CreateVisPortals_r (node->children[0]);\r
189         CreateVisPortals_r (node->children[1]);\r
190 }\r
191 \r
192 /*\r
193 ================\r
194 FinishVisPortals_r\r
195 ================\r
196 */\r
197 void FinishVisPortals2_r (node_t *node)\r
198 {\r
199         if (node->planenum == PLANENUM_LEAF)\r
200                 return;\r
201 \r
202         MakeNodePortal (node);\r
203         SplitNodePortals (node);\r
204 \r
205         FinishVisPortals2_r (node->children[0]);\r
206         FinishVisPortals2_r (node->children[1]);\r
207 }\r
208 \r
209 void FinishVisPortals_r (node_t *node)\r
210 {\r
211         if (node->planenum == PLANENUM_LEAF)\r
212                 return;\r
213 \r
214         if (node->detail_seperator)\r
215         {\r
216                 FinishVisPortals2_r (node);\r
217                 return;\r
218         }\r
219 \r
220         FinishVisPortals_r (node->children[0]);\r
221         FinishVisPortals_r (node->children[1]);\r
222 }\r
223 \r
224 \r
225 int             clusterleaf;\r
226 void SaveClusters_r (node_t *node)\r
227 {\r
228         if (node->planenum == PLANENUM_LEAF)\r
229         {\r
230                 dleafs[clusterleaf++].cluster = node->cluster;\r
231                 return;\r
232         }\r
233         SaveClusters_r (node->children[0]);\r
234         SaveClusters_r (node->children[1]);\r
235 }\r
236 \r
237 /*\r
238 ================\r
239 WritePortalFile\r
240 ================\r
241 */\r
242 void WritePortalFile (tree_t *tree)\r
243 {\r
244         char    filename[1024];\r
245         node_t *headnode;\r
246 \r
247         Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n");\r
248 \r
249         headnode = tree->headnode;\r
250         num_visclusters = 0;\r
251         num_visportals = 0;\r
252 \r
253         FreeTreePortals_r (headnode);\r
254 \r
255         MakeHeadnodePortals (tree);\r
256 \r
257         CreateVisPortals_r (headnode);\r
258 \r
259 // set the cluster field in every leaf and count the total number of portals\r
260 \r
261         NumberLeafs_r (headnode);\r
262         \r
263 // write the file\r
264         sprintf (filename, "%s.prt", source);\r
265         Sys_Printf ("writing %s\n", filename);\r
266         pf = fopen (filename, "w");\r
267         if (!pf)\r
268                 Error ("Error opening %s", filename);\r
269                 \r
270         fprintf (pf, "%s\n", PORTALFILE);\r
271         fprintf (pf, "%i\n", num_visclusters);\r
272         fprintf (pf, "%i\n", num_visportals);\r
273 \r
274         Sys_FPrintf( SYS_VRB, "%5i visclusters\n", num_visclusters);\r
275         Sys_FPrintf( SYS_VRB, "%5i visportals\n", num_visportals);\r
276 \r
277         WritePortalFile_r (headnode);\r
278 \r
279         fclose (pf);\r
280 \r
281         // we need to store the clusters out now because ordering\r
282         // issues made us do this after writebsp...\r
283         clusterleaf = 1;\r
284         SaveClusters_r (headnode);\r
285 }\r
286 \r