]> git.mxchange.org Git - flightgear.git/blob - Simulator/Airports/genapt.cxx
Initial revision.
[flightgear.git] / Simulator / 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
24
25 #include <Include/compiler.h>
26
27 #include STL_STRING
28 #include <vector>
29
30 #ifdef __BORLANDC__
31 #  define exception c_exception
32 #endif
33 #include <math.h>
34
35 #ifdef FG_HAVE_NATIVE_SGI_COMPILERS
36 #  include <strings.h>
37 #endif
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 FG_USING_STD(string);
53 FG_USING_STD(vector);
54
55
56 typedef vector < Point3D > container;
57 typedef container::iterator iterator;
58 typedef container::const_iterator const_iterator;
59
60
61 #define FG_APT_BASE_TEX_CONSTANT 2000.0
62
63 // Calculate texture coordinates for a given point.
64 static Point3D calc_tex_coords(double *node, const Point3D& ref) {
65     Point3D cp;
66     Point3D pp;
67
68     cp = Point3D( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
69
70     pp = fgCartToPolar3d(cp);
71
72     pp.setx( fmod(FG_APT_BASE_TEX_CONSTANT * pp.x(), 10.0) );
73     pp.sety( fmod(FG_APT_BASE_TEX_CONSTANT * pp.y(), 10.0) );
74
75     if ( pp.x() < 0.0 ) {
76         pp.setx( pp.x() + 10.0 );
77     }
78
79     if ( pp.y() < 0.0 ) {
80         pp.sety( pp.y() + 10.0 );
81     }
82
83     return(pp);
84 }
85
86
87 // generate the actual base area for the airport
88 static void
89 gen_base( const Point3D& average, const container& perimeter, fgTILE *t)
90 {
91     GLint display_list;
92     Point3D cart, cart_trans, tex;
93     MAT3vec normal;
94     double dist, max_dist, temp;
95     int center_num, i;
96
97     fgFRAGMENT fragment;
98
99     max_dist = 0.0;
100
101     FG_LOG( FG_TERRAIN, FG_INFO, 
102             "generating airport base for size = " << perimeter.size() );
103
104     fragment.init();
105     fragment.tile_ptr = t;
106
107     // find airport base material in the properties list
108     if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
109         FG_LOG( FG_TERRAIN, FG_ALERT, 
110                 "Ack! unknown material name = " << APT_BASE_MATERIAL 
111                 << " in fgAptGenerat()" );
112     }
113
114     FG_LOG( FG_TERRAIN, FG_INFO, 
115             " tile center = " 
116             << t->center.x() << " " << t->center.y() << " " << t->center.z() );
117     FG_LOG( FG_TERRAIN, FG_INFO, 
118             " airport center = "
119             << average.x() << " " << average.y() << " " << average.z() );
120     fragment.center = average;
121
122     normal[0] = average.x();
123     normal[1] = average.y();
124     normal[2] = average.z();
125     MAT3_NORMALIZE_VEC(normal, temp);
126     
127     display_list = xglGenLists(1);
128     xglNewList(display_list, GL_COMPILE);
129     xglBegin(GL_TRIANGLE_FAN);
130
131     // first point center of fan
132     cart_trans = average - t->center;
133     t->nodes[t->ncount][0] = cart_trans.x();
134     t->nodes[t->ncount][1] = cart_trans.y();
135     t->nodes[t->ncount][2] = cart_trans.z();
136     center_num = t->ncount;
137     t->ncount++;
138
139     tex = calc_tex_coords( t->nodes[t->ncount-1], t->center );
140     xglTexCoord2f(tex.x(), tex.y());
141     xglNormal3dv(normal);
142     xglVertex3dv(t->nodes[t->ncount-1]);
143
144     // first point on perimeter
145     const_iterator current = perimeter.begin();
146     cart = fgGeodToCart( *current );
147     cart_trans = cart - t->center;
148     t->nodes[t->ncount][0] = cart_trans.x();
149     t->nodes[t->ncount][1] = cart_trans.y();
150     t->nodes[t->ncount][2] = cart_trans.z();
151     t->ncount++;
152
153     i = 1;
154     tex = calc_tex_coords( t->nodes[i], t->center );
155     dist = cart.distance3Dsquared(average);
156     if ( dist > max_dist ) {
157         max_dist = dist;
158     }
159     xglTexCoord2f(tex.x(), tex.y());
160     xglVertex3dv(t->nodes[i]);
161     ++current;
162     ++i;
163
164     const_iterator last = perimeter.end();
165     for ( ; current != last; ++current ) {
166         cart = fgGeodToCart( *current );
167         cart_trans = cart - t->center;
168         t->nodes[t->ncount][0] = cart_trans.x();
169         t->nodes[t->ncount][1] = cart_trans.y();
170         t->nodes[t->ncount][2] = cart_trans.z();
171         t->ncount++;
172         fragment.add_face(center_num, i - 1, i);
173
174         tex = calc_tex_coords( t->nodes[i], t->center );
175         dist = cart.distance3Dsquared(average);
176         if ( dist > max_dist ) {
177             max_dist = dist;
178         }
179         xglTexCoord2f(tex.x(), tex.y());
180         xglVertex3dv(t->nodes[i]);
181         i++;
182     }
183
184     // last point (first point in perimeter list)
185     current = perimeter.begin();
186     cart = fgGeodToCart( *current );
187     cart_trans = cart - t->center;
188     fragment.add_face(center_num, i - 1, 1);
189
190     tex = calc_tex_coords( t->nodes[1], t->center );
191     xglTexCoord2f(tex.x(), tex.y());
192     xglVertex3dv(t->nodes[1]);
193
194     xglEnd();
195     xglEndList();
196
197     fragment.bounding_radius = sqrt(max_dist);
198     fragment.display_list = display_list;
199
200     t->fragment_list.push_back(fragment);
201 }
202
203
204 // Load a .apt file and register the GL fragments with the
205 // corresponding tile
206 int
207 fgAptGenerate(const string& path, fgTILE *tile)
208 {
209     string token;
210     string apt_id, apt_name;
211     char c;
212     int i = 1;
213
214     // face list (this indexes into the master tile vertex list)
215     container perimeter;
216     Point3D p, average;
217     double avex = 0.0, avey = 0.0, avez = 0.0;
218     int size;
219
220     // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
221     // gpc_vertex_list perimeter_2d;
222
223     fg_gzifstream in( path );
224     if ( !in ) {
225         // exit immediately assuming an airport file for this tile
226         // doesn't exist.
227         return 0;
228     }
229
230     apt_id = "";
231
232     // read in each line of the file
233     in >> skipcomment;
234     while ( ! in.eof() )
235     {
236         in >> token;
237
238         if ( token == "a" ) {
239             // airport info record (start of airport)
240
241             if ( apt_id.length() > 0 ) {
242                 // we have just finished reading and airport record.
243                 // process the info
244                 gen_base(average, perimeter, tile);
245             }
246
247             FG_LOG( FG_TERRAIN, FG_INFO, "Reading airport record" );
248             in >> apt_id;
249             apt_name = "";
250             i = 1;
251             avex = avey = avez = 0.0;
252             perimeter.erase( perimeter.begin(), perimeter.end() );
253             // skip to end of line.
254             while ( in.get(c) && c != '\n' ) {
255                 apt_name += c;
256             }
257             FG_LOG( FG_TERRAIN, FG_INFO, 
258                     "\tID = " << apt_id << "  Name = " << apt_name );
259         } else if ( token == "p" ) {
260             // airport area bounding polygon coordinate.  These
261             // specify a convex hull that should already have been cut
262             // out of the base terrain.  The points are given in
263             // counter clockwise order and are specified in lon/lat
264             // degrees.
265             in >> p;
266             avex += tile->nodes[i][0];
267             avey += tile->nodes[i][1];
268             avez += tile->nodes[i][2];
269             perimeter.push_back(p);
270             ++i;
271         } else if ( token == "r" ) {
272             // runway record
273             // skip for now
274             while ( in.get(c) && c != '\n' );
275         }
276
277         in >> skipcomment;
278     }
279
280     if ( apt_id.length() > 0 ) {
281         // we have just finished reading and airport record.
282         // process the info
283         size = perimeter.size();
284         average = Point3D( avex / (double)size + tile->center.x(),
285                            avey / (double)size + tile->center.y(),
286                            avez / (double)size + tile->center.z() );
287
288         gen_base(average, perimeter, tile);
289     }
290
291     return 1;
292 }
293
294