From 5308916996748685255ff6aa29cf0734e98ec942 Mon Sep 17 00:00:00 2001 From: curt Date: Sun, 2 May 1999 22:10:51 +0000 Subject: [PATCH] Added construct.[ch]xx as a data repository class to hold all the data that needs to be passed back and forth during the scenery assembly. --- Tools/Construct/Main/Makefile.am | 1 + Tools/Construct/Main/construct.hxx | 163 +++++++++++++++++++++++++++ Tools/Construct/Main/main.cxx | 170 ++++++++++++++++++++++++++--- 3 files changed, 316 insertions(+), 18 deletions(-) create mode 100644 Tools/Construct/Main/construct.hxx diff --git a/Tools/Construct/Main/Makefile.am b/Tools/Construct/Main/Makefile.am index caeb4bce1..fe38511be 100644 --- a/Tools/Construct/Main/Makefile.am +++ b/Tools/Construct/Main/Makefile.am @@ -7,6 +7,7 @@ construct_LDADD = \ $(top_builddir)/Tools/Construct/Clipper/libClipper.a \ $(top_builddir)/Tools/Construct/GenOutput/libGenOutput.a \ $(top_builddir)/Tools/Construct/Combine/libCombine.a \ + $(top_builddir)/Tools/Construct/Match/libMatch.a \ $(top_builddir)/Tools/Construct/Triangulate/libTriangulate.a \ $(top_builddir)/Tools/Lib/Polygon/libPolygon.a \ $(top_builddir)/Tools/Lib/Triangle/libTriangle.a \ diff --git a/Tools/Construct/Main/construct.hxx b/Tools/Construct/Main/construct.hxx new file mode 100644 index 000000000..d7bf83153 --- /dev/null +++ b/Tools/Construct/Main/construct.hxx @@ -0,0 +1,163 @@ +// construct.hxx -- Class to manage the primary data used in the +// construction process +// +// Written by Curtis Olson, started May 1999. +// +// Copyright (C) 1999 Curtis L. Olson - curt@flightgear.org +// +// 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$ + + +#ifndef _CONSTRUCT_HXX +#define _CONSTRUCT_HXX + + +#ifndef __cplusplus +# error This library requires C++ +#endif + + +#include + +#include STL_STRING + +#include + +#include +#include +#include +#include + +FG_USING_STD(string); + + +typedef vector < int_list > belongs_to_list; +typedef belongs_to_list::iterator belongs_to_list_iterator; +typedef belongs_to_list::const_iterator belongs_to_list_tripoly_iterator; + + +class FGConstruct { + +private: + + // paths + string work_base; + string output_base; + + // detail level constraints + int min_nodes; + int max_nodes; + + // this bucket + FGBucket bucket; + + // clipped polygons (gpc format) + FGgpcPolyList clipped_polys; + + // raw node list (after triangulation) + FGTriNodes tri_nodes; + + // node list in geodetic coords (with fixed elevation) + point_list geod_nodes; + + // node list in cartesian coords (wgs84 model) + point_list wgs84_nodes; + + // triangle elements (after triangulation) + triele_list tri_elements; + + // edge segments (after triangulation) + FGTriSegments tri_segs; + + // for each node, a list of triangle indices that contain this node + belongs_to_list reverse_ele_lookup; + + // face normal list (for flat shading) + point_list face_normals; + + // normal list (for each point) in cart coords (for smooth + // shading) + point_list point_normals; + +public: + + // Constructor + FGConstruct(); + + // Destructor + ~FGConstruct(); + + // paths + inline string get_work_base() const { return work_base; } + inline void set_work_base( const string s ) { work_base = s; } + inline string get_output_base() const { return output_base; } + inline void set_output_base( const string s ) { output_base = s; } + + // detail level constraints + inline int get_min_nodes() const { return min_nodes; } + inline void set_min_nodes( const int n ) { min_nodes = n; } + inline int get_max_nodes() const { return max_nodes; } + inline void set_max_nodes( const int n ) { max_nodes = n; } + + // this bucket + inline FGBucket get_bucket() const { return bucket; } + inline void set_bucket( const FGBucket b ) { bucket = b; } + + // clipped polygons + inline FGgpcPolyList get_clipped_polys() const { return clipped_polys; } + inline void set_clipped_polys( FGgpcPolyList p ) { clipped_polys = p; } + + // node list (after triangulation) + inline FGTriNodes get_tri_nodes() const { return tri_nodes; } + inline void set_tri_nodes( FGTriNodes n ) { tri_nodes = n; } + + // triangle elements (after triangulation) + inline triele_list get_tri_elements() const { return tri_elements; } + inline void set_tri_elements( triele_list e ) { tri_elements = e; } + + // edge segments (after triangulation) + inline FGTriSegments get_tri_segs() const { return tri_segs; } + inline void set_tri_segs( FGTriSegments s ) { tri_segs = s; } + + // node list in geodetic coords (with fixed elevation) + inline point_list get_geod_nodes() const { return geod_nodes; } + inline void set_geod_nodes( point_list n ) { geod_nodes = n; } + + // node list in cartesian coords (wgs84 model) + inline point_list get_wgs84_nodes() const { return wgs84_nodes; } + inline void set_wgs84_nodes( point_list n ) { wgs84_nodes = n; } + + // for each node, a list of triangle indices that contain this node + inline belongs_to_list get_reverse_ele_lookup() const { + return reverse_ele_lookup; + } + inline void set_reverse_ele_lookup( belongs_to_list r ) { + reverse_ele_lookup = r; + } + + // face normal list (for flat shading) + inline point_list get_face_normals() const { return face_normals; } + inline void set_face_normals( point_list n ) { face_normals = n; } + + // normal list (for each point) in cart coords (for smooth + // shading) + inline point_list get_point_normals() const { return point_normals; } + inline void set_point_normals( point_list n ) { point_normals = n; } +}; + + +#endif // _CONSTRUCT_HXX diff --git a/Tools/Construct/Main/main.cxx b/Tools/Construct/Main/main.cxx index 357797806..267d71d45 100644 --- a/Tools/Construct/Main/main.cxx +++ b/Tools/Construct/Main/main.cxx @@ -26,11 +26,13 @@ #include #include +#include #include #include #include #include +#include #include #include "construct.hxx" @@ -163,42 +165,158 @@ void do_triangulate( FGConstruct& c, const FGArray& array, } -// build the wgs-84 point list -static point_list gen_wgs84_points( FGConstruct& c, const FGArray& array ) { +// build the wgs-84 point list (and fix the elevations of the geodetic +// nodes) +static void fix_point_heights( FGConstruct& c, const FGArray& array ) { + point_list geod_nodes; point_list wgs84_nodes; - cout << "calculating wgs84 point" << endl; - Point3D geod, radians, cart; - point_list geod_nodes = c.get_tri_nodes().get_node_list(); - const_point_list_iterator current = geod_nodes.begin(); - const_point_list_iterator last = geod_nodes.end(); + cout << "fixing node heights and generating wgs84 list" << endl; + Point3D geod, radians, cart; - double real_z; + point_list raw_nodes = c.get_tri_nodes().get_node_list(); + point_list_iterator current = raw_nodes.begin(); + point_list_iterator last = raw_nodes.end(); for ( ; current != last; ++current ) { geod = *current; - real_z = array.interpolate_altitude( geod.x() * 3600.0, - geod.y() * 3600.0 ); + geod.setz( array.interpolate_altitude( geod.x() * 3600.0, + geod.y() * 3600.0 ) ); // convert to radians radians = Point3D( geod.x() * DEG_TO_RAD, geod.y() * DEG_TO_RAD, - real_z ); + geod.z() ); cart = fgGeodToCart(radians); // cout << cart << endl; + + geod_nodes.push_back(geod); wgs84_nodes.push_back(cart); } - return wgs84_nodes; + c.set_geod_nodes( geod_nodes ); + c.set_wgs84_nodes( wgs84_nodes ); +} + + +// build the node -> element (triangle) reverse lookup table. there +// is an entry for each point containing a list of all the triangles +// that share that point. +static belongs_to_list gen_node_ele_lookup_table( FGConstruct& c ) { + belongs_to_list reverse_ele_lookup; + reverse_ele_lookup.clear(); + + int_list ele_list; + ele_list.clear(); + + // initialize reverse_ele_lookup structure by creating an empty + // list for each point + point_list wgs84_nodes = c.get_wgs84_nodes(); + const_point_list_iterator w_current = wgs84_nodes.begin(); + const_point_list_iterator w_last = wgs84_nodes.end(); + for ( ; w_current != w_last; ++w_current ) { + reverse_ele_lookup.push_back( ele_list ); + } + + // traverse triangle structure building reverse lookup table + triele_list tri_elements = c.get_tri_elements(); + const_triele_list_iterator current = tri_elements.begin(); + const_triele_list_iterator last = tri_elements.end(); + int counter = 0; + for ( ; current != last; ++current ) { + reverse_ele_lookup[ current->get_n1() ].push_back( counter ); + reverse_ele_lookup[ current->get_n2() ].push_back( counter ); + reverse_ele_lookup[ current->get_n3() ].push_back( counter ); + ++counter; + } + + return reverse_ele_lookup; +} + + +// caclulate the normal for the specified triangle face +static Point3D calc_normal( FGConstruct& c, int i ) { + double v1[3], v2[3], normal[3]; + double temp; + + point_list wgs84_nodes = c.get_wgs84_nodes(); + triele_list tri_elements = c.get_tri_elements(); + + Point3D p1 = wgs84_nodes[ tri_elements[i].get_n1() ]; + Point3D p2 = wgs84_nodes[ tri_elements[i].get_n2() ]; + Point3D p3 = wgs84_nodes[ tri_elements[i].get_n3() ]; + + v1[0] = p2.x() - p1.x(); v1[1] = p2.y() - p1.y(); v1[2] = p2.z() - p1.z(); + v2[0] = p3.x() - p1.x(); v2[1] = p3.y() - p1.y(); v2[2] = p3.z() - p1.z(); + + MAT3cross_product(normal, v1, v2); + MAT3_NORMALIZE_VEC(normal,temp); + + return Point3D( normal[0], normal[1], normal[2] ); +} + + +// build the face normal list +static point_list gen_face_normals( FGConstruct& c ) { + point_list face_normals; + + // traverse triangle structure building the face normal table + + cout << "calculating face normals" << endl; + + triele_list tri_elements = c.get_tri_elements(); + for ( int i = 0; i < (int)tri_elements.size(); i++ ) { + // cout << calc_normal( i ) << endl; + face_normals.push_back( calc_normal( c, i ) ); + } + + return face_normals; +} + + +// calculate the normals for each point in wgs84_nodes +static point_list gen_point_normals( FGConstruct& c ) { + point_list point_normals; + + Point3D normal; + cout << "caculating node normals" << endl; + + point_list wgs84_nodes = c.get_wgs84_nodes(); + belongs_to_list reverse_ele_lookup = c.get_reverse_ele_lookup(); + point_list face_normals = c.get_face_normals(); + + // for each node + for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) { + int_list tri_list = reverse_ele_lookup[i]; + + int_list_iterator current = tri_list.begin(); + int_list_iterator last = tri_list.end(); + + Point3D average( 0.0 ); + + // for each triangle that shares this node + for ( ; current != last; ++current ) { + normal = face_normals[ *current ]; + average += normal; + // cout << normal << endl; + } + + average /= tri_list.size(); + // cout << "average = " << average << endl; + + point_normals.push_back( average ); + } + + return point_normals; } // generate the flight gear scenery file void do_output( FGConstruct& c, const FGTriangle& t, const FGArray& array, FGGenOutput& output ) { - output.build( c, array ); + output.build( c ); output.write( c ); } @@ -267,10 +385,26 @@ void construct_tile( FGConstruct& c ) { // save the results of the triangulation c.set_tri_nodes( t.get_out_nodes() ); c.set_tri_elements( t.get_elelist() ); + c.set_tri_segs( t.get_out_segs() ); // calculate wgs84 (cartesian) form of node list - c.set_wgs84_nodes( gen_wgs84_points( c, array ) ); + fix_point_heights( c, array ); + // build the node -> element (triangle) reverse lookup table + c.set_reverse_ele_lookup( gen_node_ele_lookup_table( c ) ); + + // build the face normal list + c.set_face_normals( gen_face_normals( c ) ); + + // calculate the normals for each point in wgs84_nodes + c.set_point_normals( gen_point_normals( c ) ); + + // match tile edges with any neighbor tiles that have already been + // generated + FGMatch m; + m.extract_shared( c ); + m.write_shared( c ); + // generate the output FGGenOutput output; do_output( c, t, array, output ); @@ -296,11 +430,11 @@ main(int argc, char **argv) { c.set_min_nodes( 50 ); c.set_max_nodes( (int)(FG_MAX_NODES * 0.8) ); - // lon = -146.248360; lat = 61.133950; // PAVD (Valdez, AK) + lon = -146.248360; lat = 61.133950; // PAVD (Valdez, AK) // lon = -110.664244; lat = 33.352890; // P13 // lon = -93.211389; lat = 45.145000; // KANE // lon = -92.486188; lat = 44.590190; // KRGK - // lon = -89.744682312011719; lat= 29.314495086669922; + // lon = -89.7446823; lat= 29.314495; // lon = -122.488090; lat = 42.743183; // 64S // lon = -114.861097; lat = 35.947480; // 61B // lon = -112.012175; lat = 41.195944; // KOGD @@ -312,14 +446,14 @@ main(int argc, char **argv) { // lon = -92.5; lat = 47.5; // Marsh test (northern MN) // lon = -111.977773; lat = 40.788388; // KSLC // lon = -121.914; lat = 42.5655; // TEST (Oregon SW of Crater) - lon = -76.201239; lat = 36.894606; // KORF (Norfolk, Virginia) + // lon = -76.201239; lat = 36.894606; // KORF (Norfolk, Virginia) double min_x = lon - 3; double min_y = lat - 1; FGBucket b_min( min_x, min_y ); FGBucket b_max( lon + 3, lat + 1 ); - FGBucket b_start(1662962L); + FGBucket b_start(566777L); bool do_tile = false; // FGBucket b_omit(-1L); -- 2.39.5