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