]> git.mxchange.org Git - flightgear.git/blob - src/Airports/genapt.cxx
Code reorganization.
[flightgear.git] / src / 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 <simgear/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 <simgear/logstream.hxx>
40 #include <simgear/fg_geodesy.hxx>
41 #include <simgear/mat3.h>
42 #include <simgear/point3d.hxx>
43 #include <simgear/polar3d.hxx>
44 #include <simgear/fgstream.hxx>
45
46 #include <Objects/materialmgr.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(const Point3D& 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, FGTileEntry *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     xglVertex3d(t->nodes[t->ncount-1][0],
143                 t->nodes[t->ncount-1][1],
144                 t->nodes[t->ncount-1][2]);
145
146     // first point on perimeter
147     const_iterator current = perimeter.begin();
148     cart = fgGeodToCart( *current );
149     cart_trans = cart - t->center;
150     t->nodes[t->ncount][0] = cart_trans.x();
151     t->nodes[t->ncount][1] = cart_trans.y();
152     t->nodes[t->ncount][2] = cart_trans.z();
153     t->ncount++;
154
155     i = 1;
156     tex = calc_tex_coords( t->nodes[i], t->center );
157     dist = cart.distance3Dsquared(average);
158     if ( dist > max_dist ) {
159         max_dist = dist;
160     }
161     xglTexCoord2f(tex.x(), tex.y());
162     xglVertex3dv(t->nodes[i].get_n());
163     ++current;
164     ++i;
165
166     const_iterator last = perimeter.end();
167     for ( ; current != last; ++current ) {
168         cart = fgGeodToCart( *current );
169         cart_trans = cart - t->center;
170         t->nodes[t->ncount][0] = cart_trans.x();
171         t->nodes[t->ncount][1] = cart_trans.y();
172         t->nodes[t->ncount][2] = cart_trans.z();
173         t->ncount++;
174         fragment.add_face(center_num, i - 1, i);
175
176         tex = calc_tex_coords( t->nodes[i], t->center );
177         dist = cart.distance3Dsquared(average);
178         if ( dist > max_dist ) {
179             max_dist = dist;
180         }
181         xglTexCoord2f(tex.x(), tex.y());
182         xglVertex3dv(t->nodes[i].get_n());
183         i++;
184     }
185
186     // last point (first point in perimeter list)
187     current = perimeter.begin();
188     cart = fgGeodToCart( *current );
189     cart_trans = cart - t->center;
190     fragment.add_face(center_num, i - 1, 1);
191
192     tex = calc_tex_coords( t->nodes[1], t->center );
193     xglTexCoord2f(tex.x(), tex.y());
194     xglVertex3dv(t->nodes[1].get_n());
195
196     xglEnd();
197     xglEndList();
198
199     fragment.bounding_radius = sqrt(max_dist);
200     // fragment.display_list = display_list;
201
202     t->fragment_list.push_back(fragment);
203 }
204
205
206 // Load a .apt file and register the GL fragments with the
207 // corresponding tile
208 int
209 fgAptGenerate(const string& path, FGTileEntry *tile)
210 {
211     string token;
212     string apt_id, apt_name;
213     char c;
214     int i = 1;
215
216     // face list (this indexes into the master tile vertex list)
217     container perimeter;
218     Point3D p, average;
219     double avex = 0.0, avey = 0.0, avez = 0.0;
220     int size;
221
222     // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
223     // gpc_vertex_list perimeter_2d;
224
225     fg_gzifstream in( path );
226     if ( !in.is_open() ) {
227         // return immediately assuming an airport file for this tile
228         // doesn't exist.
229         return 0;
230     }
231
232     apt_id = "";
233
234     // read in each line of the file
235     in >> skipcomment;
236     while ( ! in.eof() )
237     {
238         in >> token;
239
240         if ( token == "a" ) {
241             // airport info record (start of airport)
242
243             if ( apt_id.length() > 0 ) {
244                 // we have just finished reading and airport record.
245                 // process the info
246                 gen_base(average, perimeter, tile);
247             }
248
249             FG_LOG( FG_TERRAIN, FG_INFO, "Reading airport record" );
250             in >> apt_id;
251             apt_name = "";
252             i = 1;
253             avex = avey = avez = 0.0;
254             perimeter.erase( perimeter.begin(), perimeter.end() );
255             // skip to end of line.
256             while ( in.get(c) && c != '\n' ) {
257                 apt_name += c;
258             }
259             FG_LOG( FG_TERRAIN, FG_INFO, 
260                     "\tID = " << apt_id << "  Name = " << apt_name );
261         } else if ( token == "p" ) {
262             // airport area bounding polygon coordinate.  These
263             // specify a convex hull that should already have been cut
264             // out of the base terrain.  The points are given in
265             // counter clockwise order and are specified in lon/lat
266             // degrees.
267             in >> p;
268             avex += tile->nodes[i][0];
269             avey += tile->nodes[i][1];
270             avez += tile->nodes[i][2];
271             perimeter.push_back(p);
272             ++i;
273         } else if ( token == "r" ) {
274             // runway record
275             // skip for now
276             while ( in.get(c) && c != '\n' );
277         }
278
279         in >> skipcomment;
280     }
281
282     if ( apt_id.length() > 0 ) {
283         // we have just finished reading and airport record.
284         // process the info
285         size = perimeter.size();
286         average = Point3D( avex / (double)size + tile->center.x(),
287                            avey / (double)size + tile->center.y(),
288                            avez / (double)size + tile->center.z() );
289
290         gen_base(average, perimeter, tile);
291     }
292
293     return 1;
294 }
295
296