]> git.mxchange.org Git - flightgear.git/blob - Airports/genapt.cxx
Optimizations from Norman Vine.
[flightgear.git] / Airports / genapt.cxx
1 //
2 // genapt.cxx -- generate airport scenery from the given definition file
3 //
4 // Written by Curtis Olson, started September 1998.
5 //
6 // Copyright (C) 1998  Curtis L. Olson  - curt@me.umn.edu
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 //
22 // $Id$
23 // (Log is kept at end of this file)
24
25
26 #include <string>        // Standard C++ string library
27 #include <vector>
28 #include "Include/fg_stl_config.h"
29
30 #ifdef NEEDNAMESPACESTD
31 using namespace std;
32 #endif
33
34 #ifdef __BORLANDC__
35 #  define exception c_exception
36 #endif
37 #include <math.h>
38
39 #include <Debug/logstream.hxx>
40 // #include <Include/fg_types.h>
41 #include <Math/fg_geodesy.hxx>
42 #include <Math/mat3.h>
43 #include <Math/point3d.hxx>
44 #include <Math/polar3d.hxx>
45 #include <Misc/fgstream.hxx>
46 #include <Objects/material.hxx>
47
48 // #include <gpc/gpc.h>
49
50 #include "genapt.hxx"
51
52
53 typedef vector < Point3D > container;
54 typedef container::iterator iterator;
55 typedef container::const_iterator const_iterator;
56
57
58 #define FG_APT_BASE_TEX_CONSTANT 2000.0
59
60 // Calculate texture coordinates for a given point.
61 static Point3D calc_tex_coords(double *node, const Point3D& ref) {
62     Point3D cp;
63     Point3D pp;
64
65     cp = Point3D( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
66
67     pp = fgCartToPolar3d(cp);
68
69     pp.setx( fmod(FG_APT_BASE_TEX_CONSTANT * pp.x(), 10.0) );
70     pp.sety( fmod(FG_APT_BASE_TEX_CONSTANT * pp.y(), 10.0) );
71
72     if ( pp.x() < 0.0 ) {
73         pp.setx( pp.x() + 10.0 );
74     }
75
76     if ( pp.y() < 0.0 ) {
77         pp.sety( pp.y() + 10.0 );
78     }
79
80     return(pp);
81 }
82
83
84 // generate the actual base area for the airport
85 static void
86 gen_base( const Point3D& average, const container& perimeter, fgTILE *t)
87 {
88     GLint display_list;
89     Point3D cart, cart_trans, tex;
90     MAT3vec normal;
91     double dist, max_dist, temp;
92     int center_num, i;
93
94     fgFRAGMENT fragment;
95
96     max_dist = 0.0;
97
98     FG_LOG( FG_TERRAIN, FG_INFO, 
99             "generating airport base for size = " << perimeter.size() );
100
101     fragment.init();
102     fragment.tile_ptr = t;
103
104     // find airport base material in the properties list
105     if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
106         FG_LOG( FG_TERRAIN, FG_ALERT, 
107                 "Ack! unknown material name = " << APT_BASE_MATERIAL 
108                 << " in fgAptGenerat()" );
109     }
110
111     FG_LOG( FG_TERRAIN, FG_INFO, 
112             " tile center = " 
113             << t->center.x() << " " << t->center.y() << " " << t->center.z() );
114     FG_LOG( FG_TERRAIN, FG_INFO, 
115             " airport center = "
116             << average.x() << " " << average.y() << " " << average.z() );
117     fragment.center = average;
118
119     normal[0] = average.x();
120     normal[1] = average.y();
121     normal[2] = average.z();
122     MAT3_NORMALIZE_VEC(normal, temp);
123     
124     display_list = xglGenLists(1);
125     xglNewList(display_list, GL_COMPILE);
126     xglBegin(GL_TRIANGLE_FAN);
127
128     // first point center of fan
129     cart_trans = average - t->center;
130     t->nodes[t->ncount][0] = cart_trans.x();
131     t->nodes[t->ncount][1] = cart_trans.y();
132     t->nodes[t->ncount][2] = cart_trans.z();
133     center_num = t->ncount;
134     t->ncount++;
135
136     tex = calc_tex_coords( t->nodes[t->ncount-1], t->center );
137     xglTexCoord2f(tex.x(), tex.y());
138     xglNormal3dv(normal);
139     xglVertex3dv(t->nodes[t->ncount-1]);
140
141     // first point on perimeter
142     const_iterator current = perimeter.begin();
143     cart = fgGeodToCart( *current );
144     cart_trans = cart - t->center;
145     t->nodes[t->ncount][0] = cart_trans.x();
146     t->nodes[t->ncount][1] = cart_trans.y();
147     t->nodes[t->ncount][2] = cart_trans.z();
148     t->ncount++;
149
150     i = 1;
151     tex = calc_tex_coords( t->nodes[i], t->center );
152     dist = cart.distance3Dsquared(average);
153     if ( dist > max_dist ) {
154         max_dist = dist;
155     }
156     xglTexCoord2f(tex.x(), tex.y());
157     xglVertex3dv(t->nodes[i]);
158     ++current;
159     ++i;
160
161     const_iterator last = perimeter.end();
162     for ( ; current != last; ++current ) {
163         cart = fgGeodToCart( *current );
164         cart_trans = cart - t->center;
165         t->nodes[t->ncount][0] = cart_trans.x();
166         t->nodes[t->ncount][1] = cart_trans.y();
167         t->nodes[t->ncount][2] = cart_trans.z();
168         t->ncount++;
169         fragment.add_face(center_num, i - 1, i);
170
171         tex = calc_tex_coords( t->nodes[i], t->center );
172         dist = cart.distance3Dsquared(average);
173         if ( dist > max_dist ) {
174             max_dist = dist;
175         }
176         xglTexCoord2f(tex.x(), tex.y());
177         xglVertex3dv(t->nodes[i]);
178         i++;
179     }
180
181     // last point (first point in perimeter list)
182     current = perimeter.begin();
183     cart = fgGeodToCart( *current );
184     cart_trans = cart - t->center;
185     fragment.add_face(center_num, i - 1, 1);
186
187     tex = calc_tex_coords( t->nodes[1], t->center );
188     xglTexCoord2f(tex.x(), tex.y());
189     xglVertex3dv(t->nodes[1]);
190
191     xglEnd();
192     xglEndList();
193
194     fragment.bounding_radius = sqrt(max_dist);
195     fragment.display_list = display_list;
196
197     t->fragment_list.push_back(fragment);
198 }
199
200
201 // Load a .apt file and register the GL fragments with the
202 // corresponding tile
203 int
204 fgAptGenerate(const string& path, fgTILE *tile)
205 {
206     string token;
207     string apt_id, apt_name;
208     char c;
209     int i = 1;
210
211     // face list (this indexes into the master tile vertex list)
212     container perimeter;
213     Point3D p, average;
214     double avex = 0.0, avey = 0.0, avez = 0.0;
215     int size;
216
217     // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
218     // gpc_vertex_list perimeter_2d;
219
220     fg_gzifstream in( path );
221     if ( !in ) {
222         // exit immediately assuming an airport file for this tile
223         // doesn't exist.
224         return 0;
225     }
226
227     apt_id = "";
228
229     // read in each line of the file
230     in >> skipcomment;
231     while ( ! in.eof() )
232     {
233         in >> token;
234
235         if ( token == "a" ) {
236             // airport info record (start of airport)
237
238             if ( apt_id != "" ) {
239                 // we have just finished reading and airport record.
240                 // process the info
241                 gen_base(average, perimeter, tile);
242             }
243
244             FG_LOG( FG_TERRAIN, FG_INFO, "Reading airport record" );
245             in >> apt_id;
246             apt_name = "";
247             i = 1;
248             avex = avey = avez = 0.0;
249             perimeter.erase( perimeter.begin(), perimeter.end() );
250             // skip to end of line.
251             while ( in.get(c) && c != '\n' ) {
252                 apt_name += c;
253             }
254             FG_LOG( FG_TERRAIN, FG_INFO, 
255                     "\tID = " << apt_id << "  Name = " << apt_name );
256         } else if ( token == "p" ) {
257             // airport area bounding polygon coordinate.  These
258             // specify a convex hull that should already have been cut
259             // out of the base terrain.  The points are given in
260             // counter clockwise order and are specified in lon/lat
261             // degrees.
262             in >> p;
263             avex += tile->nodes[i][0];
264             avey += tile->nodes[i][1];
265             avez += tile->nodes[i][2];
266             perimeter.push_back(p);
267             ++i;
268         } else if ( token == "r" ) {
269             // runway record
270             // skip for now
271             while ( in.get(c) && c != '\n' );
272         }
273
274         in >> skipcomment;
275     }
276
277     if ( apt_id != "" ) {
278         // we have just finished reading and airport record.
279         // process the info
280         size = perimeter.size();
281         average = Point3D( avex / (double)size + tile->center.x(),
282                            avey / (double)size + tile->center.y(),
283                            avez / (double)size + tile->center.z() );
284
285         gen_base(average, perimeter, tile);
286     }
287
288     return 1;
289 }
290
291
292 // $Log$
293 // Revision 1.12  1999/02/01 21:08:33  curt
294 // Optimizations from Norman Vine.
295 //
296 // Revision 1.11  1998/11/23 21:48:09  curt
297 // Borland portability tweaks.
298 //
299 // Revision 1.10  1998/11/07 19:07:06  curt
300 // Enable release builds using the --without-logging option to the configure
301 // script.  Also a couple log message cleanups, plus some C to C++ comment
302 // conversion.
303 //
304 // Revision 1.9  1998/11/06 21:17:32  curt
305 // Converted to new logstream debugging facility.  This allows release
306 // builds with no messages at all (and no performance impact) by using
307 // the -DFG_NDEBUG flag.
308 //
309 // Revision 1.8  1998/11/06 14:46:59  curt
310 // Changes to track Bernie's updates to fgstream.
311 //
312 // Revision 1.7  1998/10/20 18:26:06  curt
313 // Updates to point3d.hxx
314 //
315 // Revision 1.6  1998/10/18 01:17:16  curt
316 // Point3D tweaks.
317 //
318 // Revision 1.5  1998/10/16 23:27:14  curt
319 // C++-ifying.
320 //
321 // Revision 1.4  1998/10/16 00:51:46  curt
322 // Converted to Point3D class.
323 //
324 // Revision 1.3  1998/09/21 20:55:00  curt
325 // Used the cartesian form of the airport area coordinates to determine the
326 // center.
327 //
328 // Revision 1.2  1998/09/14 12:44:30  curt
329 // Don't recalculate perimeter points since it is not likely that they will match
330 // exactly with the previously calculated points, which will leave an ugly gap
331 // around the airport area.
332 //
333 // Revision 1.1  1998/09/14 02:14:01  curt
334 // Initial revision of genapt.[ch]xx for generating airport scenery.
335 //