]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/cportals.cpp
Merge commit '830125fad042fad35dc029b6eb57c8156ad7e176'
[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         memset( this, 0, sizeof( CBspPortal ) );
35 }
36
37 CBspPortal::~CBspPortal(){
38         delete[] point;
39 }
40
41 void ClampFloat( float* p ){
42         double i;
43         double frac = modf( *p, &i );
44
45         if ( !frac ) {
46                 return;
47         }
48
49         if ( fabs( *p - ceil( *p ) ) < MAX_ROUND_ERROR ) {
50                 *p = static_cast<float>( ceil( *p ) );
51         }
52
53         if ( fabs( *p - floor( *p ) ) < MAX_ROUND_ERROR ) {
54                 *p = static_cast<float>( floor( *p ) );
55         }
56 }
57
58 bool CBspPortal::Build( char *def, unsigned int pointCnt, bool bInverse ){
59         char *c = def;
60         unsigned int n;
61
62         point_count = pointCnt;
63
64         if ( point_count < 3 ) {
65                 return false;
66         }
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
78                 c++;
79
80                 int x;
81                 if ( bInverse ) {
82                         x = point_count - n - 1;
83                 }
84                 else{
85                         x = n;
86                 }
87
88                 sscanf( c, "%f %f %f", &point[x].p[0], &point[x].p[1], &point[x].p[2] );
89
90                 ClampFloat( &point[x].p[0] );
91                 ClampFloat( &point[x].p[1] );
92                 ClampFloat( &point[x].p[2] );
93         }
94
95         return true;
96 }
97
98 CPortals::CPortals(){
99         memset( this, 0, sizeof( CPortals ) );
100 }
101
102 CPortals::~CPortals(){
103         Purge();
104 }
105
106 void CPortals::Purge(){
107         if ( node ) {
108                 delete[] node;
109         }
110         node = NULL;
111         node_count = 0;
112 }
113
114 void CPortals::Load(){
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                 globalOutputStream() << "  ERROR - could not open file.\n";
129
130                 return;
131         }
132
133         if ( !fgets( buf, LINE_BUF, in ) ) {
134                 fclose( in );
135
136                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
137
138                 return;
139         }
140
141         if ( strncmp( "PRT1", buf, 4 ) != 0 ) {
142                 fclose( in );
143
144                 globalOutputStream() << "  ERROR - File header indicates wrong file type (should be \"PRT1\").\n";
145
146                 return;
147         }
148
149         if ( !fgets( buf, LINE_BUF, in ) ) {
150                 fclose( in );
151
152                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
153
154                 return;
155         }
156
157         sscanf( buf, "%u", &node_count );
158
159         if ( node_count > 0xFFFF ) {
160                 fclose( in );
161
162                 node_count = 0;
163
164                 globalOutputStream() << "  ERROR - Extreme number of nodes, aborting.\n";
165
166                 return;
167         }
168
169         if ( !fgets( buf, LINE_BUF, in ) ) {
170                 fclose( in );
171
172                 node_count = 0;
173
174                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
175
176                 return;
177         }
178
179         unsigned int p_count;
180         sscanf( buf, "%u", &p_count );
181
182         if ( !fgets( buf, LINE_BUF, in ) ) {
183                 fclose( in );
184
185                 node_count = 0;
186
187                 globalOutputStream() << "  ERROR - File ended prematurely.\n";
188
189                 return;
190         }
191
192         unsigned int p_count2;
193         sscanf( buf, "%u", &p_count2 );
194
195         node = new CBspNode[node_count];
196
197         unsigned int i;
198         for ( i = 0; i < p_count; i++ )
199         {
200                 if ( !fgets( buf, LINE_BUF, in ) ) {
201                         fclose( in );
202
203                         node_count = 0;
204
205                         globalOutputStream() << "  ERROR - File ended prematurely.\n";
206
207                         return;
208                 }
209
210                 unsigned int dummy, node1, node2;
211                 sscanf( buf, "%u %u %u", &dummy, &node1, &node2 );
212
213                 node[node1].portal_count++;
214                 node[node2].portal_count++;
215         }
216
217         for ( i = 0; i < p_count2; i++ )
218         {
219                 if ( !fgets( buf, LINE_BUF, in ) ) {
220                         fclose( in );
221
222                         node_count = 0;
223
224                         globalOutputStream() << "  ERROR - File ended prematurely.\n";
225
226                         return;
227                 }
228
229                 unsigned int dummy, node1;
230                 sscanf( buf, "%u %u", &dummy, &node1 );
231
232                 node[node1].portal_count++;
233         }
234
235         for ( i = 0; i < node_count; i++ )
236                 node[i].portal = new CBspPortal[node[i].portal_count];
237
238         fclose( in );
239
240         in = fopen( fn, "rt" );
241
242         fgets( buf, LINE_BUF, in );
243         fgets( buf, LINE_BUF, in );
244         fgets( buf, LINE_BUF, in );
245         fgets( buf, LINE_BUF, in );
246
247         unsigned int n;
248         for ( n = 0; n < p_count; n++ )
249         {
250                 if ( !fgets( buf, LINE_BUF, in ) ) {
251                         fclose( in );
252
253                         Purge();
254
255                         globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n";
256
257                         return;
258                 }
259
260                 unsigned int pCount, node1, node2;
261                 sscanf( buf, "%u %u %u", &pCount, &node1, &node2 );
262
263                 if ( !node[node1].AddPortal( buf, pCount, false ) ) {
264                         fclose( in );
265
266                         Purge();
267
268                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
269
270                         return;
271                 }
272
273                 if ( !node[node2].AddPortal( buf, pCount, true ) ) {
274                         fclose( in );
275
276                         Purge();
277
278                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
279
280                         return;
281                 }
282         }
283
284         for ( n = 0; n < p_count2; n++ )
285         {
286                 if ( !fgets( buf, LINE_BUF, in ) ) {
287                         fclose( in );
288
289                         Purge();
290
291                         globalOutputStream() << "  ERROR - Could not find information for portal number " << n + 1 << " of " << p_count << ".\n";
292
293                         return;
294                 }
295
296                 unsigned int pCount, node1;
297                 sscanf( buf, "%u %u", &pCount, &node1 );
298
299                 if ( !node[node1].AddPortal( buf, pCount, false ) ) {
300                         fclose( in );
301
302                         Purge();
303
304                         globalOutputStream() << "  ERROR - Information for portal number " << n + 1 << " of " << p_count << " is not formatted correctly.\n";
305
306                         return;
307                 }
308         }
309
310         fclose( in );
311 }
312
313 CBspNode::CBspNode(){
314         portal = NULL;
315         portal_count = 0;
316         portal_next = 0;
317 }
318
319 CBspNode::~CBspNode(){
320         if ( portal != NULL ) {
321                 delete[] portal;
322         }
323 }
324
325 bool CBspNode::AddPortal( char *def, unsigned int pointCnt, bool bInverse ){
326         return portal[portal_next++].Build( def, pointCnt, bInverse );
327 }