]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/cportals.cpp
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / contrib / bobtoolz / cportals.cpp
1 /*
2    BobToolz plugin for GtkRadiant
3    Copyright (C) 2001 Gordon Biggans
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this library; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "CPortals.h"
21
22 #include <string.h>
23 #include <math.h>
24
25 #include "misc.h"
26
27 const int LINE_BUF = 1000;
28 const char *MSG_PREFIX = "bobToolz plugin: ";
29
30 // these classes are far less of a mess than my code was,
31 // thanq to G.DeWan 4 the prtview source on which it was based
32
33 CBspPortal::CBspPortal()
34 {
35     memset(this, 0, sizeof(CBspPortal));
36 }
37
38 CBspPortal::~CBspPortal()
39 {
40     delete[] point;
41 }
42
43 void ClampFloat(float *p)
44 {
45     double i;
46     double frac = modf(*p, &i);
47
48     if (!frac) {
49         return;
50     }
51
52     if (fabs(*p - ceil(*p)) < MAX_ROUND_ERROR) {
53         *p = static_cast<float>( ceil(*p));
54     }
55
56     if (fabs(*p - floor(*p)) < MAX_ROUND_ERROR) {
57         *p = static_cast<float>( floor(*p));
58     }
59 }
60
61 bool CBspPortal::Build(char *def, unsigned int pointCnt, bool bInverse)
62 {
63     char *c = def;
64     unsigned int n;
65
66     point_count = pointCnt;
67
68     if (point_count < 3) {
69         return false;
70     }
71
72     point = new CBspPoint[point_count];
73
74     for (n = 0; n < point_count; n++) {
75         for (; *c != 0 && *c != '('; c++) {}
76
77         if (*c == 0) {
78             return false;
79         }
80
81         c++;
82
83         int x;
84         if (bInverse) {
85             x = point_count - n - 1;
86         } else {
87             x = n;
88         }
89
90         sscanf(c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2]);
91
92         ClampFloat(&point[x].p[0]);
93         ClampFloat(&point[x].p[1]);
94         ClampFloat(&point[x].p[2]);
95     }
96
97     return true;
98 }
99
100 CPortals::CPortals()
101 {
102     memset(this, 0, sizeof(CPortals));
103 }
104
105 CPortals::~CPortals()
106 {
107     Purge();
108 }
109
110 void CPortals::Purge()
111 {
112     if (node) {
113         delete[] node;
114     }
115     node = NULL;
116     node_count = 0;
117 }
118
119 void CPortals::Load()
120 {
121     char buf[LINE_BUF + 1];
122
123     memset(buf, 0, LINE_BUF + 1);
124
125     Purge();
126
127     globalOutputStream() << MSG_PREFIX << "Loading portal file " << fn << ".\n";
128
129     FILE *in;
130
131     in = fopen(fn, "rt");
132
133     if (in == NULL) {
134         globalOutputStream() << "  ERROR - could not open file.\n";
135
136         return;
137     }
138
139     if (!fgets(buf, LINE_BUF, in)) {
140         fclose(in);
141
142         globalOutputStream() << "  ERROR - File ended prematurely.\n";
143
144         return;
145     }
146
147     if (strncmp("PRT1", buf, 4) != 0) {
148         fclose(in);
149
150         globalOutputStream() << "  ERROR - File header indicates wrong file type (should be \"PRT1\").\n";
151
152         return;
153     }
154
155     if (!fgets(buf, LINE_BUF, in)) {
156         fclose(in);
157
158         globalOutputStream() << "  ERROR - File ended prematurely.\n";
159
160         return;
161     }
162
163     sscanf(buf, "%u", &node_count);
164
165     if (node_count > 0xFFFF) {
166         fclose(in);
167
168         node_count = 0;
169
170         globalOutputStream() << "  ERROR - Extreme number of nodes, aborting.\n";
171
172         return;
173     }
174
175     if (!fgets(buf, LINE_BUF, in)) {
176         fclose(in);
177
178         node_count = 0;
179
180         globalOutputStream() << "  ERROR - File ended prematurely.\n";
181
182         return;
183     }
184
185     unsigned int p_count;
186     sscanf(buf, "%u", &p_count);
187
188     if (!fgets(buf, LINE_BUF, in)) {
189         fclose(in);
190
191         node_count = 0;
192
193         globalOutputStream() << "  ERROR - File ended prematurely.\n";
194
195         return;
196     }
197
198     unsigned int p_count2;
199     sscanf(buf, "%u", &p_count2);
200
201     node = new CBspNode[node_count];
202
203     unsigned int i;
204     for (i = 0; i < p_count; i++) {
205         if (!fgets(buf, LINE_BUF, in)) {
206             fclose(in);
207
208             node_count = 0;
209
210             globalOutputStream() << "  ERROR - File ended prematurely.\n";
211
212             return;
213         }
214
215         unsigned int dummy, node1, node2;
216         sscanf(buf, "%u %u %u", &dummy, &node1, &node2);
217
218         node[node1].portal_count++;
219         node[node2].portal_count++;
220     }
221
222     for (i = 0; i < p_count2; i++) {
223         if (!fgets(buf, LINE_BUF, in)) {
224             fclose(in);
225
226             node_count = 0;
227
228             globalOutputStream() << "  ERROR - File ended prematurely.\n";
229
230             return;
231         }
232
233         unsigned int dummy, node1;
234         sscanf(buf, "%u %u", &dummy, &node1);
235
236         node[node1].portal_count++;
237     }
238
239     for (i = 0; i < node_count; i++) {
240         node[i].portal = new CBspPortal[node[i].portal_count];
241     }
242
243     fclose(in);
244
245     in = fopen(fn, "rt");
246
247     fgets(buf, LINE_BUF, in);
248     fgets(buf, LINE_BUF, in);
249     fgets(buf, LINE_BUF, in);
250     fgets(buf, LINE_BUF, in);
251
252     unsigned int n;
253     for (n = 0; n < p_count; n++) {
254         if (!fgets(buf, LINE_BUF, in)) {
255             fclose(in);
256
257             Purge();
258
259             globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of "
260                                  << p_count << ".\n";
261
262             return;
263         }
264
265         unsigned int pCount, node1, node2;
266         sscanf(buf, "%u %u %u", &pCount, &node1, &node2);
267
268         if (!node[node1].AddPortal(buf, pCount, false)) {
269             fclose(in);
270
271             Purge();
272
273             globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count
274                                  << " is not formatted correctly.\n";
275
276             return;
277         }
278
279         if (!node[node2].AddPortal(buf, pCount, true)) {
280             fclose(in);
281
282             Purge();
283
284             globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count
285                                  << " is not formatted correctly.\n";
286
287             return;
288         }
289     }
290
291     for (n = 0; n < p_count2; n++) {
292         if (!fgets(buf, LINE_BUF, in)) {
293             fclose(in);
294
295             Purge();
296
297             globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of "
298                                  << p_count << ".\n";
299
300             return;
301         }
302
303         unsigned int pCount, node1;
304         sscanf(buf, "%u %u", &pCount, &node1);
305
306         if (!node[node1].AddPortal(buf, pCount, false)) {
307             fclose(in);
308
309             Purge();
310
311             globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count
312                                  << " is not formatted correctly.\n";
313
314             return;
315         }
316     }
317
318     fclose(in);
319 }
320
321 CBspNode::CBspNode()
322 {
323     portal = NULL;
324     portal_count = 0;
325     portal_next = 0;
326 }
327
328 CBspNode::~CBspNode()
329 {
330     if (portal != NULL) {
331         delete[] portal;
332     }
333 }
334
335 bool CBspNode::AddPortal(char *def, unsigned int pointCnt, bool bInverse)
336 {
337     return portal[portal_next++].Build(def, pointCnt, bInverse);
338 }