]> git.mxchange.org Git - flightgear.git/blob - Airports/genapt.cxx
Point3D tweaks.
[flightgear.git] / Airports / genapt.cxx
1 //
2 // getapt.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 // (Log is kept at end of this file)
24
25
26 #include <string>        // Standard C++ string library
27 #include <vector>
28 #include "Include/fg_stl_config.h"
29
30 #ifdef NEEDNAMESPACESTD
31 using namespace std;
32 #endif
33
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>
42
43 // #include <gpc/gpc.h>
44
45 #include "genapt.hxx"
46
47
48 typedef vector < Point3D > container;
49 typedef container::iterator iterator;
50 typedef container::const_iterator const_iterator;
51
52
53 /*
54 // Calculate distance between to Point3D's
55 static double calc_dist(const Point3D& p1, const Point3D& p2) {
56     double x, y, z;
57     x = p1.x() - p2.x();
58     y = p1.y() - p2.y();
59     z = p1.z() - p2.z();
60     return sqrt(x*x + y*y + z*z);
61 }
62 */
63
64
65 #define FG_APT_BASE_TEX_CONSTANT 2000.0
66
67 // Calculate texture coordinates for a given point.
68 static Point3D calc_tex_coords(double *node, const Point3D& ref) {
69     Point3D cp;
70     Point3D pp;
71
72     cp = Point3D( node[0] + ref.x(), node[1] + ref.y(), node[2] + ref.z() );
73
74     pp = fgCartToPolar3d(cp);
75
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) );
78
79     if ( pp.x() < 0.0 ) {
80         pp.setx( pp.x() + 10.0 );
81     }
82
83     if ( pp.y() < 0.0 ) {
84         pp.sety( pp.y() + 10.0 );
85     }
86
87     return(pp);
88 }
89
90
91 // generate the actual base area for the airport
92 static void
93 gen_base( const Point3D& average, const container& perimeter, fgTILE *t)
94 {
95     GLint display_list;
96     Point3D cart, cart_trans, tex;
97     MAT3vec normal;
98     double dist, max_dist, temp;
99     int center_num, i;
100
101     fgFRAGMENT fragment;
102
103     max_dist = 0.0;
104
105     cout << "generating airport base for size = " << perimeter.size() << "\n";
106
107     fragment.init();
108     fragment.tile_ptr = t;
109
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",
114                   APT_BASE_MATERIAL );
115     }
116
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;
122
123     normal[0] = average.x();
124     normal[1] = average.y();
125     normal[2] = average.z();
126     MAT3_NORMALIZE_VEC(normal, temp);
127     
128     display_list = xglGenLists(1);
129     xglNewList(display_list, GL_COMPILE);
130     xglBegin(GL_TRIANGLE_FAN);
131
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;
138     t->ncount++;
139
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]);
144
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();
152     t->ncount++;
153
154     i = 1;
155     tex = calc_tex_coords( t->nodes[i], t->center );
156     dist = distance3D(average, cart);
157     if ( dist > max_dist ) {
158         max_dist = dist;
159     }
160     xglTexCoord2f(tex.x(), tex.y());
161     xglVertex3dv(t->nodes[i]);
162     ++current;
163     ++i;
164
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();
172         t->ncount++;
173         fragment.add_face(center_num, i - 1, i);
174
175         tex = calc_tex_coords( t->nodes[i], t->center );
176         dist = distance3D(average, cart);
177         if ( dist > max_dist ) {
178             max_dist = dist;
179         }
180         xglTexCoord2f(tex.x(), tex.y());
181         xglVertex3dv(t->nodes[i]);
182         i++;
183     }
184
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);
190
191     tex = calc_tex_coords( t->nodes[1], t->center );
192     xglTexCoord2f(tex.x(), tex.y());
193     xglVertex3dv(t->nodes[1]);
194
195     xglEnd();
196     xglEndList();
197
198     fragment.bounding_radius = max_dist;
199     fragment.display_list = display_list;
200
201     t->fragment_list.push_back(fragment);
202 }
203
204
205 // Load a .apt file and register the GL fragments with the
206 // corresponding tile
207 int
208 fgAptGenerate(const string& path, fgTILE *tile)
209 {
210     string token;
211     string apt_id, apt_name;
212     char c;
213     int i = 1;
214
215     // face list (this indexes into the master tile vertex list)
216     container perimeter;
217     Point3D p, average;
218     double avex = 0.0, avey = 0.0, avez = 0.0;
219     int size;
220
221     // gpc_vertex p_2d, list_2d[MAX_PERIMETER];
222     // gpc_vertex_list perimeter_2d;
223
224     fg_gzifstream in( path );
225     if ( !in ) {
226         // exit immediately assuming an airport file for this tile
227         // doesn't exist.
228         return 0;
229     }
230
231     apt_id = "";
232
233     // read in each line of the file
234     in.eat_comments();
235     while ( ! in.eof() )
236     {
237         in.stream() >> token;
238
239         if ( token == "a" ) {
240             // airport info record (start of airport)
241
242             if ( apt_id != "" ) {
243                 // we have just finished reading and airport record.
244                 // process the info
245                 gen_base(average, perimeter, tile);
246             }
247
248             cout << "Reading airport record\n";
249             in.stream() >> apt_id;
250             apt_name = "";
251             i = 1;
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' ) {
256                 apt_name += c;
257             }
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
264             // degrees.
265             in.stream() >> 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         // airports.insert(a);
278         in.eat_comments();
279     }
280
281     if ( apt_id != "" ) {
282         // we have just finished reading and airport record.
283         // process the info
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() );
288
289         gen_base(average, perimeter, tile);
290     }
291
292     return 1;
293 }
294
295
296 // $Log$
297 // Revision 1.6  1998/10/18 01:17:16  curt
298 // Point3D tweaks.
299 //
300 // Revision 1.5  1998/10/16 23:27:14  curt
301 // C++-ifying.
302 //
303 // Revision 1.4  1998/10/16 00:51:46  curt
304 // Converted to Point3D class.
305 //
306 // Revision 1.3  1998/09/21 20:55:00  curt
307 // Used the cartesian form of the airport area coordinates to determine the
308 // center.
309 //
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.
314 //
315 // Revision 1.1  1998/09/14 02:14:01  curt
316 // Initial revision of genapt.[ch]xx for generating airport scenery.
317 //
318 //
319