2 // getapt.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.
23 // (Log is kept at end of this file)
26 #include <string> // Standard C++ string library
28 #include "Include/fg_stl_config.h"
30 #ifdef NEEDNAMESPACESTD
34 #include <Debug/fg_debug.h>
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>
43 // #include <gpc/gpc.h>
48 typedef vector < Point3D > container;
49 typedef container::iterator iterator;
50 typedef container::const_iterator const_iterator;
54 // Calculate distance between to Point3D's
55 static double calc_dist(const Point3D& p1, const Point3D& p2) {
60 return sqrt(x*x + y*y + z*z);
65 #define FG_APT_BASE_TEX_CONSTANT 2000.0
67 // Calculate texture coordinates for a given point.
68 static Point3D calc_tex_coords(double *node, const Point3D& ref) {
72 cp = Point3D( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
74 pp = fgCartToPolar3d(cp);
76 pp.setx( fmod(FG_APT_BASE_TEX_CONSTANT * pp.x(), 10.0) );
77 pp.sety( fmod(FG_APT_BASE_TEX_CONSTANT * pp.y(), 10.0) );
80 pp.setx( pp.x() + 10.0 );
84 pp.sety( pp.y() + 10.0 );
91 // generate the actual base area for the airport
93 gen_base( const Point3D& average, const container& perimeter, fgTILE *t)
96 Point3D cart, cart_trans, tex;
98 double dist, max_dist, temp;
105 cout << "generating airport base for size = " << perimeter.size() << "\n";
108 fragment.tile_ptr = t;
110 // find airport base material in the properties list
111 if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
112 fgPrintf( FG_TERRAIN, FG_ALERT,
113 "Ack! unknown material name = %s in fgAptGenerat()\n",
117 printf(" tile center = %.2f %.2f %.2f\n",
118 t->center.x(), t->center.y(), t->center.z() );
119 printf(" airport center = %.2f %.2f %.2f\n",
120 average.x(), average.y(), average.z());
121 fragment.center = average;
123 normal[0] = average.x();
124 normal[1] = average.y();
125 normal[2] = average.z();
126 MAT3_NORMALIZE_VEC(normal, temp);
128 display_list = xglGenLists(1);
129 xglNewList(display_list, GL_COMPILE);
130 xglBegin(GL_TRIANGLE_FAN);
132 // first point center of fan
133 cart_trans = average - t->center;
134 t->nodes[t->ncount][0] = cart_trans.x();
135 t->nodes[t->ncount][1] = cart_trans.y();
136 t->nodes[t->ncount][2] = cart_trans.z();
137 center_num = t->ncount;
140 tex = calc_tex_coords( t->nodes[t->ncount-1], t->center );
141 xglTexCoord2f(tex.x(), tex.y());
142 xglNormal3dv(normal);
143 xglVertex3dv(t->nodes[t->ncount-1]);
145 // first point on perimeter
146 const_iterator current = perimeter.begin();
147 cart = fgGeodToCart( *current );
148 cart_trans = cart - t->center;
149 t->nodes[t->ncount][0] = cart_trans.x();
150 t->nodes[t->ncount][1] = cart_trans.y();
151 t->nodes[t->ncount][2] = cart_trans.z();
155 tex = calc_tex_coords( t->nodes[i], t->center );
156 dist = distance3D(average, cart);
157 if ( dist > max_dist ) {
160 xglTexCoord2f(tex.x(), tex.y());
161 xglVertex3dv(t->nodes[i]);
165 const_iterator last = perimeter.end();
166 for ( ; current != last; ++current ) {
167 cart = fgGeodToCart( *current );
168 cart_trans = cart - t->center;
169 t->nodes[t->ncount][0] = cart_trans.x();
170 t->nodes[t->ncount][1] = cart_trans.y();
171 t->nodes[t->ncount][2] = cart_trans.z();
173 fragment.add_face(center_num, i - 1, i);
175 tex = calc_tex_coords( t->nodes[i], t->center );
176 dist = distance3D(average, cart);
177 if ( dist > max_dist ) {
180 xglTexCoord2f(tex.x(), tex.y());
181 xglVertex3dv(t->nodes[i]);
185 // last point (first point in perimeter list)
186 current = perimeter.begin();
187 cart = fgGeodToCart( *current );
188 cart_trans = cart - t->center;
189 fragment.add_face(center_num, i - 1, 1);
191 tex = calc_tex_coords( t->nodes[1], t->center );
192 xglTexCoord2f(tex.x(), tex.y());
193 xglVertex3dv(t->nodes[1]);
198 fragment.bounding_radius = max_dist;
199 fragment.display_list = display_list;
201 t->fragment_list.push_back(fragment);
205 // Load a .apt file and register the GL fragments with the
206 // corresponding tile
208 fgAptGenerate(const string& path, fgTILE *tile)
211 string apt_id, apt_name;
215 // face list (this indexes into the master tile vertex list)
218 double avex = 0.0, avey = 0.0, avez = 0.0;
221 // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
222 // gpc_vertex_list perimeter_2d;
224 fg_gzifstream in( path );
226 // exit immediately assuming an airport file for this tile
233 // read in each line of the file
237 in.stream() >> token;
239 if ( token == "a" ) {
240 // airport info record (start of airport)
242 if ( apt_id != "" ) {
243 // we have just finished reading and airport record.
245 gen_base(average, perimeter, tile);
248 cout << "Reading airport record\n";
249 in.stream() >> apt_id;
252 avex = avey = avez = 0.0;
253 perimeter.erase( perimeter.begin(), perimeter.end() );
254 // skip to end of line.
255 while ( in.get(c) && c != '\n' ) {
258 cout << "\tID = " + apt_id + " Name = " + apt_name + "\n";
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
266 avex += tile->nodes[i][0];
267 avey += tile->nodes[i][1];
268 avez += tile->nodes[i][2];
269 perimeter.push_back(p);
271 } else if ( token == "r" ) {
274 while ( in.get(c) && c != '\n' );
277 // airports.insert(a);
281 if ( apt_id != "" ) {
282 // we have just finished reading and airport record.
284 size = perimeter.size();
285 average = Point3D( avex / (double)size + tile->center.x(),
286 avey / (double)size + tile->center.y(),
287 avez / (double)size + tile->center.z() );
289 gen_base(average, perimeter, tile);
297 // Revision 1.6 1998/10/18 01:17:16 curt
300 // Revision 1.5 1998/10/16 23:27:14 curt
303 // Revision 1.4 1998/10/16 00:51:46 curt
304 // Converted to Point3D class.
306 // Revision 1.3 1998/09/21 20:55:00 curt
307 // Used the cartesian form of the airport area coordinates to determine the
310 // Revision 1.2 1998/09/14 12:44:30 curt
311 // Don't recalculate perimeter points since it is not likely that they will match
312 // exactly with the previously calculated points, which will leave an ugly gap
313 // around the airport area.
315 // Revision 1.1 1998/09/14 02:14:01 curt
316 // Initial revision of genapt.[ch]xx for generating airport scenery.