2 // genapt.cxx -- generate airport scenery from the given definition file
4 // Written by Curtis Olson, started September 1998.
6 // Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
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.
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.
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.
25 #include <simgear/compiler.h>
31 # define exception c_exception
35 #ifdef FG_HAVE_NATIVE_SGI_COMPILERS
40 #include <simgear/xgl/xgl.h>
44 #include <simgear/debug/logstream.hxx>
45 #include <simgear/math/fg_geodesy.hxx>
46 #include <simgear/math/point3d.hxx>
47 #include <simgear/math/polar3d.hxx>
48 #include <simgear/misc/fgstream.hxx>
50 #include <Objects/materialmgr.hxx>
58 typedef vector < Point3D > container;
59 typedef container::iterator iterator;
60 typedef container::const_iterator const_iterator;
63 #define FG_APT_BASE_TEX_CONSTANT 2000.0
65 // Calculate texture coordinates for a given point.
66 static Point3D calc_tex_coords(const Point3D& node, const Point3D& ref) {
70 cp = Point3D( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
72 pp = fgCartToPolar3d(cp);
74 pp.setx( fmod(FG_APT_BASE_TEX_CONSTANT * pp.x(), 10.0) );
75 pp.sety( fmod(FG_APT_BASE_TEX_CONSTANT * pp.y(), 10.0) );
78 pp.setx( pp.x() + 10.0 );
82 pp.sety( pp.y() + 10.0 );
89 // generate the actual base area for the airport
91 gen_base( const Point3D& average, const container& perimeter, FGTileEntry *t)
94 Point3D cart, cart_trans, tex;
96 double dist, max_dist;
103 FG_LOG( FG_TERRAIN, FG_INFO,
104 "generating airport base for size = " << perimeter.size() );
107 fragment.tile_ptr = t;
109 // find airport base material in the properties list
110 if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
111 FG_LOG( FG_TERRAIN, FG_ALERT,
112 "Ack! unknown material name = " << APT_BASE_MATERIAL
113 << " in fgAptGenerat()" );
116 FG_LOG( FG_TERRAIN, FG_INFO,
118 << t->center.x() << " " << t->center.y() << " " << t->center.z() );
119 FG_LOG( FG_TERRAIN, FG_INFO,
121 << average.x() << " " << average.y() << " " << average.z() );
122 fragment.center = average;
124 sgSetVec3( normal, average.x(), average.y(), average.z() );
125 sgNormalizeVec3( normal );
127 display_list = xglGenLists(1);
128 xglNewList(display_list, GL_COMPILE);
129 xglBegin(GL_TRIANGLE_FAN);
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;
139 tex = calc_tex_coords( t->nodes[t->ncount-1], t->center );
140 xglTexCoord2f(tex.x(), tex.y());
141 xglNormal3fv(normal);
142 xglVertex3d(t->nodes[t->ncount-1][0],
143 t->nodes[t->ncount-1][1],
144 t->nodes[t->ncount-1][2]);
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();
156 tex = calc_tex_coords( t->nodes[i], t->center );
157 dist = cart.distance3Dsquared(average);
158 if ( dist > max_dist ) {
161 xglTexCoord2f(tex.x(), tex.y());
162 xglVertex3dv(t->nodes[i].get_n());
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();
174 fragment.add_face(center_num, i - 1, i);
176 tex = calc_tex_coords( t->nodes[i], t->center );
177 dist = cart.distance3Dsquared(average);
178 if ( dist > max_dist ) {
181 xglTexCoord2f(tex.x(), tex.y());
182 xglVertex3dv(t->nodes[i].get_n());
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);
192 tex = calc_tex_coords( t->nodes[1], t->center );
193 xglTexCoord2f(tex.x(), tex.y());
194 xglVertex3dv(t->nodes[1].get_n());
199 fragment.bounding_radius = sqrt(max_dist);
200 // fragment.display_list = display_list;
202 t->fragment_list.push_back(fragment);
206 // Load a .apt file and register the GL fragments with the
207 // corresponding tile
209 fgAptGenerate(const string& path, FGTileEntry *tile)
212 string apt_id, apt_name;
216 // face list (this indexes into the master tile vertex list)
219 double avex = 0.0, avey = 0.0, avez = 0.0;
222 // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
223 // gpc_vertex_list perimeter_2d;
225 fg_gzifstream in( path );
226 if ( !in.is_open() ) {
227 // return immediately assuming an airport file for this tile
234 // read in each line of the file
240 if ( token == "a" ) {
241 // airport info record (start of airport)
243 if ( apt_id.length() > 0 ) {
244 // we have just finished reading and airport record.
246 gen_base(average, perimeter, tile);
249 FG_LOG( FG_TERRAIN, FG_INFO, "Reading airport record" );
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' ) {
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
268 avex += tile->nodes[i][0];
269 avey += tile->nodes[i][1];
270 avez += tile->nodes[i][2];
271 perimeter.push_back(p);
273 } else if ( token == "r" ) {
276 while ( in.get(c) && c != '\n' );
282 if ( apt_id.length() > 0 ) {
283 // we have just finished reading and airport record.
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() );
290 gen_base(average, perimeter, tile);