- Fixed brushexport2 output float-format (Shaderman)
[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 #define LINE_BUF 1000
28 #define 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         if(fabs(*p - ceil(*p)) < MAX_ROUND_ERROR)
52                 *p = static_cast<float>(ceil(*p));
53
54         if(fabs(*p - floor(*p)) < MAX_ROUND_ERROR)
55                 *p = static_cast<float>(floor(*p));
56 }
57
58 bool CBspPortal::Build(char *def, unsigned int pointCnt, bool bInverse)
59 {
60         char *c = def;
61         unsigned int n;
62
63         point_count = pointCnt;
64
65         if(point_count < 3)
66                 return false;
67
68         point = new CBspPoint[point_count];
69
70         for(n = 0; n < point_count; n++)
71         {
72                 for(; *c != 0 && *c != '('; c++);
73
74                 if(*c == 0)
75                         return false;
76
77                 c++;
78
79                 int x;
80                 if(bInverse)
81                         x = point_count - n - 1;
82                 else
83                         x = n;
84
85                 sscanf(c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2]);
86
87                 ClampFloat(&point[x].p[0]);
88                 ClampFloat(&point[x].p[1]);
89                 ClampFloat(&point[x].p[2]);
90         }
91
92         return true;
93 }
94
95 CPortals::CPortals()
96 {
97         memset(this, 0, sizeof(CPortals));
98 }
99
100 CPortals::~CPortals()
101 {
102         Purge();
103 }
104
105 void CPortals::Purge()
106 {
107         if(node)
108                 delete[] node;
109         node = NULL;
110         node_count = 0;
111 }
112
113 void CPortals::Load()
114 {
115         char buf[LINE_BUF+1];
116
117         memset(buf, 0, LINE_BUF + 1);
118         
119         Purge();
120
121         globalOutputStream() << MSG_PREFIX "Loading portal file " << fn << ".\n";
122
123         FILE *in;
124
125         in = fopen(fn, "rt");
126
127         if(in == NULL)
128         {
129                 globalOutputStream() << "  ERROR - could not open file.\n";
130
131                 return;
132         }
133
134         if(!fgets(buf, LINE_BUF, in))
135         {
136                 fclose(in);
137
138                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
139
140                 return;
141         }
142
143         if(strncmp("PRT1", buf, 4) != 0)
144         {
145                 fclose(in);
146
147                 globalOutputStream() << "  ERROR - File header indicates wrong file type (should be \"PRT1\").\n";
148
149                 return;
150         }
151
152         if(!fgets(buf, LINE_BUF, in))
153         {
154                 fclose(in);
155
156                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
157
158                 return;
159         }
160
161         sscanf(buf, "%u", &node_count);
162
163         if(node_count > 0xFFFF)
164         {
165                 fclose(in);
166
167                 node_count = 0;
168
169                 globalOutputStream() << "  ERROR - Extreme number of nodes, aborting.\n";
170
171                 return;
172         }
173
174         if(!fgets(buf, LINE_BUF, in))
175         {
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         {
190                 fclose(in);
191
192                 node_count = 0;
193
194                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
195
196                 return;
197         }
198
199         unsigned int p_count2;
200         sscanf(buf, "%u", &p_count2);
201
202         node = new CBspNode[node_count];
203
204         unsigned int i;
205         for(i = 0; i < p_count; i++)
206         {
207                 if(!fgets(buf, LINE_BUF, in))
208                 {
209                         fclose(in);
210
211                         node_count = 0;
212
213                         globalOutputStream() << "  ERROR - File ended prematurely.\n";
214
215                         return;
216                 }
217
218                 unsigned int dummy, node1, node2;
219                 sscanf(buf, "%u %u %u", &dummy, &node1, &node2);
220
221                 node[node1].portal_count++;
222                 node[node2].portal_count++;
223         }
224
225         for(i = 0; i < p_count2; i++)
226         {
227                 if(!fgets(buf, LINE_BUF, in))
228                 {
229                         fclose(in);
230
231                         node_count = 0;
232
233                         globalOutputStream() << "  ERROR - File ended prematurely.\n";
234
235                         return;
236                 }
237
238                 unsigned int dummy, node1;
239                 sscanf(buf, "%u %u", &dummy, &node1);
240
241                 node[node1].portal_count++;
242         }
243
244         for(i = 0; i < node_count; i++)
245                 node[i].portal = new CBspPortal[node[i].portal_count];
246
247         fclose(in);
248
249         in = fopen(fn, "rt");
250
251         fgets(buf, LINE_BUF, in);
252         fgets(buf, LINE_BUF, in);
253         fgets(buf, LINE_BUF, in);
254         fgets(buf, LINE_BUF, in);
255
256         unsigned int n;
257         for(n = 0; n < p_count; n++)
258         {
259                 if(!fgets(buf, LINE_BUF, in))
260                 {
261                         fclose(in);
262
263                         Purge();
264
265                         globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n";
266
267                         return;
268                 }
269
270                 unsigned int pCount, node1, node2;
271                 sscanf(buf, "%u %u %u", &pCount, &node1, &node2);
272
273                 if(!node[node1].AddPortal(buf, pCount, false))
274                 {
275                         fclose(in);
276
277                         Purge();
278
279                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
280
281                         return;
282                 }
283
284                 if(!node[node2].AddPortal(buf, pCount, true))
285                 {
286                         fclose(in);
287
288                         Purge();
289
290                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
291
292                         return;
293                 }
294         }
295
296  for(n = 0; n < p_count2; n++)
297         {
298                 if(!fgets(buf, LINE_BUF, in))
299                 {
300                         fclose(in);
301
302                         Purge();
303
304                         globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n";
305
306                         return;
307                 }
308
309                 unsigned int pCount, node1;
310                 sscanf(buf, "%u %u", &pCount, &node1);
311
312                 if(!node[node1].AddPortal(buf, pCount, false))
313                 {
314                         fclose(in);
315
316                         Purge();
317
318                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
319
320                         return;
321                 }
322         }
323
324         fclose(in);
325 }
326
327 CBspNode::CBspNode()
328 {
329         portal = NULL;
330         portal_count = 0;
331         portal_next = 0;
332 }
333
334 CBspNode::~CBspNode()
335 {
336         if(portal != NULL)
337                 delete[] portal;
338 }
339
340 bool CBspNode::AddPortal(char *def, unsigned int pointCnt, bool bInverse)
341 {
342         return portal[portal_next++].Build(def, pointCnt, bInverse);
343 }