1
0
Fork 0
flightgear/Airports/genapt.cxx
curt acae3186db Don't recalculate perimeter points since it is not likely that they will match
exactly with the previously calculated points, which will leave an ugly gap
around the airport area.
1998-09-14 12:44:30 +00:00

367 lines
9.6 KiB
C++

//
// getapt.cxx -- generate airport scenery from the given definition file
//
// Written by Curtis Olson, started September 1998.
//
// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
// (Log is kept at end of this file)
#include <string> // Standard C++ string library
#include <vector>
#include "Include/fg_stl_config.h"
#ifdef NEEDNAMESPACESTD
using namespace std;
#endif
#include <Debug/fg_debug.h>
#include <Include/fg_types.h>
#include <Math/fg_geodesy.h>
#include <Math/mat3.h>
#include <Math/polar3d.hxx>
#include <Misc/fgstream.hxx>
#include <Objects/material.hxx>
// #include <gpc/gpc.h>
#include "genapt.hxx"
typedef vector < fgPoint3d > container;
typedef container::iterator iterator;
typedef container::const_iterator const_iterator;
// Calculate distance between to fgPoint3d's
static double calc_dist(const fgPoint3d& p1, const fgPoint3d& p2) {
double x, y, z;
x = p1.x - p2.x;
y = p1.y - p2.y;
z = p1.z - p2.z;
return sqrt(x*x + y*y + z*z);
}
// convert a geodetic point lon(degrees), lat(degrees), elev(meter) to a
// cartesian point
static fgPoint3d geod_to_cart(fgPoint3d geod) {
fgPoint3d cart;
fgPoint3d geoc;
double sl_radius;
// printf("A geodetic point is (%.2f, %.2f, %.2f)\n", geod[0],
// geod[1], geod[2]);
geoc.lon = geod.lon*DEG_TO_RAD;
fgGeodToGeoc(geod.lat*DEG_TO_RAD, geod.radius, &sl_radius, &geoc.lat);
// printf("A geocentric point is (%.2f, %.2f, %.2f)\n", gc_lon,
// gc_lat, sl_radius+geod[2]); */
geoc.radius = sl_radius + geod.radius;
cart = fgPolarToCart3d(geoc);
// printf("A cart point is (%.8f, %.8f, %.8f)\n", cp.x, cp.y, cp.z);
return cart;
}
#define FG_APT_BASE_TEX_CONSTANT 2000.0
#ifdef OLD_TEX_COORDS
// Calculate texture coordinates for a given point.
static fgPoint3d
calc_tex_coords(const fgPoint3d& p) {
fgPoint3d tex;
cout << "Texture coordinates = " <<
FG_APT_BASE_TEX_CONSTANT * p.lon << " " <<
FG_APT_BASE_TEX_CONSTANT * p.lat << "\n";
tex.x = fmod(FG_APT_BASE_TEX_CONSTANT * p.lon, 10.0);
tex.y = fmod(FG_APT_BASE_TEX_CONSTANT * p.lat, 10.0);
if ( tex.x < 0.0 ) {
tex.x += 10.0;
}
if ( tex.y < 0.0 ) {
tex.y += 10.0;
}
cout << "Texture coordinates = " << tex.x << " " << tex.y << "\n";
return tex;
}
#endif
// Calculate texture coordinates for a given point.
static fgPoint3d calc_tex_coords(double *node, fgPoint3d *ref) {
fgPoint3d cp;
fgPoint3d pp;
cp.x = node[0] + ref->x;
cp.y = node[1] + ref->y;
cp.z = node[2] + ref->z;
pp = fgCartToPolar3d(cp);
pp.lon = fmod(FG_APT_BASE_TEX_CONSTANT * pp.lon, 10.0);
pp.lat = fmod(FG_APT_BASE_TEX_CONSTANT * pp.lat, 10.0);
if ( pp.lon < 0.0 ) {
pp.lon += 10.0;
}
if ( pp.lat < 0.0 ) {
pp.lat += 10.0;
}
return(pp);
}
// generate the actual base area for the airport
static void
gen_base( const fgPoint3d& average, const container& perimeter, fgTILE *t)
{
GLint display_list;
fgPoint3d ave_cart, cart, cart_trans, tex;
MAT3vec normal;
double dist, max_dist, temp;
int center_num, i;
fgFRAGMENT fragment;
max_dist = 0.0;
cout << "generating airport base for size = " << perimeter.size() << "\n";
fragment.init();
fragment.tile_ptr = t;
// find airport base material in the properties list
if ( ! material_mgr.find( APT_BASE_MATERIAL, fragment.material_ptr )) {
fgPrintf( FG_TERRAIN, FG_ALERT,
"Ack! unknown material name = %s in fgAptGenerat()\n",
APT_BASE_MATERIAL );
}
ave_cart = geod_to_cart( average );
printf(" tile center = %.2f %.2f %.2f\n",
t->center.x, t->center.y, t->center.z);
printf(" airport center = %.2f %.2f %.2f\n",
average.x, average.y, average.z);
printf(" airport center = %.2f %.2f %.2f\n",
ave_cart.x, ave_cart.y, ave_cart.z);
fragment.center.x = ave_cart.x;
fragment.center.y = ave_cart.y;
fragment.center.z = ave_cart.z;
normal[0] = ave_cart.x;
normal[1] = ave_cart.y;
normal[2] = ave_cart.z;
MAT3_NORMALIZE_VEC(normal, temp);
display_list = xglGenLists(1);
xglNewList(display_list, GL_COMPILE);
xglBegin(GL_TRIANGLE_FAN);
// first point center of fan
cart_trans.x = ave_cart.x - t->center.x;
cart_trans.y = ave_cart.y - t->center.y;
cart_trans.z = ave_cart.z - t->center.z;
t->nodes[t->ncount][0] = cart_trans.x;
t->nodes[t->ncount][1] = cart_trans.y;
t->nodes[t->ncount][2] = cart_trans.z;
center_num = t->ncount;
t->ncount++;
tex = calc_tex_coords( t->nodes[t->ncount-1], &(t->center) );
xglTexCoord2f(tex.x, tex.y);
xglNormal3dv(normal);
xglVertex3dv(t->nodes[t->ncount-1]);
// first point on perimeter
iterator current = perimeter.begin();
cart = geod_to_cart( *current );
cart_trans.x = cart.x - t->center.x;
cart_trans.y = cart.y - t->center.y;
cart_trans.z = cart.z - t->center.z;
t->nodes[t->ncount][0] = cart_trans.x;
t->nodes[t->ncount][1] = cart_trans.y;
t->nodes[t->ncount][2] = cart_trans.z;
t->ncount++;
i = 1;
tex = calc_tex_coords( t->nodes[i], &(t->center) );
dist = calc_dist(ave_cart, cart);
if ( dist > max_dist ) {
max_dist = dist;
}
xglTexCoord2f(tex.x, tex.y);
xglVertex3dv(t->nodes[i]);
++current;
++i;
const_iterator last = perimeter.end();
for ( ; current != last; ++current ) {
cart = geod_to_cart( *current );
cart_trans.x = cart.x - t->center.x;
cart_trans.y = cart.y - t->center.y;
cart_trans.z = cart.z - t->center.z;
t->nodes[t->ncount][0] = cart_trans.x;
t->nodes[t->ncount][1] = cart_trans.y;
t->nodes[t->ncount][2] = cart_trans.z;
t->ncount++;
fragment.add_face(center_num, i - 1, i);
tex = calc_tex_coords( t->nodes[i], &(t->center) );
dist = calc_dist(ave_cart, cart);
if ( dist > max_dist ) {
max_dist = dist;
}
xglTexCoord2f(tex.x, tex.y);
xglVertex3dv(t->nodes[i]);
i++;
}
// last point (first point in perimeter list)
current = perimeter.begin();
cart = geod_to_cart( *current );
cart_trans.x = cart.x - t->center.x;
cart_trans.y = cart.y - t->center.y;
cart_trans.z = cart.z - t->center.z;
fragment.add_face(center_num, i - 1, 1);
tex = calc_tex_coords( t->nodes[1], &(t->center) );
xglTexCoord2f(tex.x, tex.y);
xglVertex3dv(t->nodes[1]);
xglEnd();
xglEndList();
fragment.bounding_radius = max_dist;
fragment.display_list = display_list;
t->fragment_list.push_back(fragment);
}
// Load a .apt file and register the GL fragments with the
// corresponding tile
int
fgAptGenerate(const string& path, fgTILE *tile)
{
string token;
string apt_id, apt_name;
char c;
// face list (this indexes into the master tile vertex list)
container perimeter;
fgPoint3d p, average;
int size;
// gpc_vertex p_2d, list_2d[MAX_PERIMETER];
// gpc_vertex_list perimeter_2d;
fg_gzifstream in( path );
if ( !in ) {
// exit immediately assuming an airport file for this tile
// doesn't exist.
return 0;
}
apt_id = "";
// read in each line of the file
in.eat_comments();
while ( ! in.eof() )
{
in.stream() >> token;
if ( token == "a" ) {
// airport info record (start of airport)
if ( apt_id != "" ) {
// we have just finished reading and airport record.
// process the info
gen_base(average, perimeter, tile);
}
cout << "Reading airport record\n";
in.stream() >> apt_id;
apt_name = "";
average.lon = average.lat = average.radius = 0.0;
perimeter.erase( perimeter.begin(), perimeter.end() );
// skip to end of line.
while ( in.get(c) && c != '\n' ) {
apt_name += c;
}
cout << "\tID = " + apt_id + " Name = " + apt_name + "\n";
} else if ( token == "p" ) {
// airport area bounding polygon coordinate. These
// specify a convex hull that should already have been cut
// out of the base terrain. The points are given in
// counter clockwise order and are specified in lon/lat
// degrees.
in.stream() >> p.lon >> p.lat >> p.radius;
average.lon += p.lon;
average.lat += p.lat;
average.radius += p.radius;
perimeter.push_back(p);
} else if ( token == "r" ) {
// runway record
// skip for now
while ( in.get(c) && c != '\n' );
}
// airports.insert(a);
in.eat_comments();
}
if ( apt_id != "" ) {
// we have just finished reading and airport record.
// process the info
size = perimeter.size();
average.lon /= (double)size;
average.lat /= (double)size;
average.radius /= (double)size;
gen_base(average, perimeter, tile);
}
return 1;
}
// $Log$
// Revision 1.2 1998/09/14 12:44:30 curt
// Don't recalculate perimeter points since it is not likely that they will match
// exactly with the previously calculated points, which will leave an ugly gap
// around the airport area.
//
// Revision 1.1 1998/09/14 02:14:01 curt
// Initial revision of genapt.[ch]xx for generating airport scenery.
//
//