From 427762b074451a066d314e719ced0c6204e6f898 Mon Sep 17 00:00:00 2001 From: curt Date: Tue, 23 Mar 1999 22:02:03 +0000 Subject: [PATCH] Worked on creating data to output ... normals, bounding spheres, etc. --- GenOutput/genobj.cxx | 284 +++++++++++++++++++++++++++++++++++++++---- GenOutput/genobj.hxx | 79 ++++++++++-- Main/construct.cxx | 13 +- 3 files changed, 341 insertions(+), 35 deletions(-) diff --git a/GenOutput/genobj.cxx b/GenOutput/genobj.cxx index 634765d1d..06c5a0799 100644 --- a/GenOutput/genobj.cxx +++ b/GenOutput/genobj.cxx @@ -23,14 +23,130 @@ // (Log is kept at end of this file) +#include + +#include +#include + #include "genobj.hxx" -// Calculate the global bounding sphere from all the input points. -// Center is the average of the points. -static void calc_gbs( const trinode_list& nodelist, Point3D *center, - double *radius ) -{ +// build the wgs-84 point list +void FGGenOutput::gen_wgs84_points() { + cout << "calculating wgs84 point" << endl; + Point3D geod, radians, cart; + + const_point_list_iterator current = geod_nodes.begin(); + const_point_list_iterator last = geod_nodes.end(); + + for ( ; current != last; ++current ) { + geod = *current; + + // convert to radians + radians = Point3D( geod.x() * DEG_TO_RAD, + geod.y() * DEG_TO_RAD, + geod.z() ); + + cart = fgGeodToCart(radians); + // cout << cart << endl; + wgs84_nodes.push_back(cart); + } +} + + +// 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. +void FGGenOutput::gen_node_ele_lookup_table() { + belongs_to ele_list; + ele_list.erase( ele_list.begin(), ele_list.end() ); + + // initialize reverse_ele_lookup structure by creating an empty + // list for each point + 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 + 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; + } +} + + +// caclulate the normal for the specified triangle face +Point3D FGGenOutput::calc_normal( int i ) { + double v1[3], v2[3], normal[3]; + double temp; + + 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 +void FGGenOutput::gen_face_normals() { + // traverse triangle structure building the face normal table + + cout << "calculating face normals" << endl; + + for ( int i = 0; i < (int)tri_elements.size(); i++ ) { + // cout << calc_normal( i ) << endl; + face_normals.push_back( calc_normal( i ) ); + } + +} + + +// calculate the normals for each point in wgs84_nodes +void FGGenOutput::gen_normals() { + Point3D normal; + cout << "caculating node normals" << endl; + + // for each node + for ( int i = 0; i < (int)wgs84_nodes.size(); ++i ) { + belongs_to tri_list = reverse_ele_lookup[i]; + + belongs_to_iterator current = tri_list.begin(); + belongs_to_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 ); + } +} + + +// calculate the global bounding sphere. Center is the average of the +// points. +void FGGenOutput::calc_gbs() { double x = 0; double y = 0; double z = 0; @@ -38,8 +154,8 @@ static void calc_gbs( const trinode_list& nodelist, Point3D *center, double dist_squared; double radius_squared = 0; - const_trinode_list_iterator current = nodelist.begin(); - const_trinode_list_iterator last = nodelist.end(); + const_point_list_iterator current = wgs84_nodes.begin(); + const_point_list_iterator last = wgs84_nodes.end(); for ( ; current != last; ++current ) { x += current->x(); @@ -47,39 +163,163 @@ static void calc_gbs( const trinode_list& nodelist, Point3D *center, z += current->z(); } - x /= nodelist.size(); - y /= nodelist.size(); - z /= nodelist.size(); + x /= wgs84_nodes.size(); + y /= wgs84_nodes.size(); + z /= wgs84_nodes.size(); - *center = Point3D(x, y, z); + gbs_center = Point3D(x, y, z); - current = nodelist.begin(); + current = wgs84_nodes.begin(); for ( ; current != last; ++current ) { - dist_squared = center->distance3Dsquared(*current); + dist_squared = gbs_center.distance3Dsquared(*current); if ( dist_squared > radius_squared ) { radius_squared = dist_squared; } } - *radius = sqrt(radius_squared); + gbs_radius = sqrt(radius_squared); } -// generate the flight gear format from the triangulation -int fgGenOutput( const FGTriangle& t ) { - Point3D gbs; - double gradius; - +// build the necessary output structures based on the triangulation +// data +int FGGenOutput::build( const FGTriangle& t ) { FGTriNodes trinodes = t.get_out_nodes(); - trinode_list nodelist = trinodes.get_node_list(); - calc_gbs( nodelist, &gbs, &gradius ); - cout << "center = " << gbs << " radius = " << gradius << endl; + // copy the geodetic node list into this class + geod_nodes = trinodes.get_node_list(); + + // copy the triangle list into this class + tri_elements = t.get_elelist(); + + // generate the point list in wgs-84 coordinates + gen_wgs84_points(); + + // calculate the global bounding sphere + calc_gbs(); + cout << "center = " << gbs_center << " radius = " << gbs_radius << endl; + + // build the node -> element (triangle) reverse lookup table + gen_node_ele_lookup_table(); + + // build the face normal list + gen_face_normals(); + + // calculate the normals for each point in wgs84_nodes + gen_normals(); + + return 1; +} + + +// caclulate the bounding sphere for the specified triangle face +void FGGenOutput::calc_bounding_sphere( int i, Point3D *center, + double *radius ) { + Point3D c( 0.0 ); + + 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() ]; + + c = p1 + p2 + p3; + c /= 3; + + double dist_squared; + double max_squared = 0; + + dist_squared = c.distance3Dsquared(p1); + if ( dist_squared > max_squared ) { + max_squared = dist_squared; + } + + dist_squared = c.distance3Dsquared(p2); + if ( dist_squared > max_squared ) { + max_squared = dist_squared; + } + + dist_squared = c.distance3Dsquared(p3); + if ( dist_squared > max_squared ) { + max_squared = dist_squared; + } + + *center = c; + *radius = sqrt(max_squared); +} + + +// write out the fgfs scenery file +int FGGenOutput::write( const string& path ) { + Point3D p; + + FILE *fp; + if ( (fp = fopen( path.c_str(), "w" )) == NULL ) { + cout << "ERROR: opening " << path << " for writing!" << endl; + exit(-1); + } + + // write headers + fprintf(fp, "# FGFS Scenery Version %s\n", FG_SCENERY_FILE_FORMAT); + + time_t calendar_time = time(NULL); + struct tm *local_tm; + local_tm = localtime( &calendar_time ); + char time_str[256]; + strftime( time_str, 256, "%a %b %d %H:%M:%S %Z %Y", local_tm); + fprintf(fp, "# Created %s\n", time_str ); + fprintf(fp, "\n"); + + // write global bounding spher + fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n", + gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius); + fprintf(fp, "\n"); + + // write nodes + fprintf(fp, "# vertex list\n"); + 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 ) { + p = *w_current - gbs_center; + fprintf(fp, "v %.5f %.5f %.5f\n", p.x(), p.y(), p.z()); + } + fprintf(fp, "\n"); + + // write vertex normals + fprintf(fp, "# vertex normal list\n"); + const_point_list_iterator n_current = point_normals.begin(); + const_point_list_iterator n_last = point_normals.end(); + for ( ; n_current != n_last; ++n_current ) { + p = *n_current; + fprintf(fp, "vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z()); + } + fprintf(fp, "\n"); + + // write triangles + Point3D center; + double radius; + fprintf(fp, "# triangle list\n"); + fprintf(fp, "\n"); + const_triele_list_iterator t_current = tri_elements.begin(); + const_triele_list_iterator t_last = tri_elements.end(); + int counter = 0; + for ( ; t_current != t_last; ++t_current ) { + calc_bounding_sphere( counter, ¢er, &radius ); + fprintf(fp, "# usemtl desert1\n"); + fprintf(fp, "# bs %.2f %.2f %.2f %.2f\n", + center.x(), center.y(), center.z(), radius); + fprintf(fp, "f %d %d %d\n", + t_current->get_n1(), t_current->get_n2(), t_current->get_n3()); + fprintf(fp, "\n"); + ++counter; + } + return 1; } // $Log$ +// Revision 1.2 1999/03/23 22:02:03 curt +// Worked on creating data to output ... normals, bounding spheres, etc. +// // Revision 1.1 1999/03/22 23:51:51 curt // Initial revision. // diff --git a/GenOutput/genobj.hxx b/GenOutput/genobj.hxx index 76ce3aee2..7afb3076d 100644 --- a/GenOutput/genobj.hxx +++ b/GenOutput/genobj.hxx @@ -32,38 +32,93 @@ #endif +#include #include #include -typedef vector < Point3D > wgs84_node_list; -typedef wgs84_node_list::iterator wgs84_node_list_iterator; -typedef wgs84_node_list::const_iterator const_wgs84_node_list_iterator; +typedef vector < int > belongs_to; +typedef belongs_to::iterator belongs_to_iterator; +typedef belongs_to::const_iterator belongs_to_tripoly_iterator; + +typedef vector < belongs_to > belongs_to_list; +typedef belongs_to_list::iterator belongs_to_list_iterator; +typedef belongs_to_list::const_iterator belongs_to_list_tripoly_iterator; -typedef vector < Point3D > normal_list; -typedef normal_list::iterator normal_list_iterator; -typedef normal_list::const_iterator const_normal_list_iterator; class FGGenOutput { private: - wgs84_node_list wgs84_nodes; - normal_list normals; + // node list in geodetic coordinats + point_list geod_nodes; + + // node list in cartesian coords (wgs84 model) + point_list wgs84_nodes; + + // 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; + + // triangles (by index into point list) + triele_list tri_elements; + + // for each node, a list of triangle indices that contain this node + belongs_to_list reverse_ele_lookup; + + // global bounding sphere + Point3D gbs_center; + double gbs_radius; + + // build the wgs-84 point list + void gen_wgs84_points(); + + // 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. + void gen_node_ele_lookup_table(); + + // calculate the normals for each point in wgs84_nodes + void gen_normals(); + + // build the face normal list + void gen_face_normals(); + + // caclulate the normal for the specified triangle face + Point3D calc_normal( int i ); + + // calculate the global bounding sphere. Center is the average of + // the points. + void calc_gbs(); + + // caclulate the bounding sphere for the specified triangle face + void calc_bounding_sphere( int i, Point3D *center, double *radius ); public: - -}; + // Constructor && Destructor + inline FGGenOutput() { } + inline ~FGGenOutput() { } + + // build the necessary output structures based on the + // triangulation data + int build( const FGTriangle& t ); -// generate the flight gear format from the triangulation -int fgGenOutput( const FGTriangle& t ); + // write out the fgfs scenery file + int write( const string& path ); +}; #endif // _GENOBJ_HXX // $Log$ +// Revision 1.3 1999/03/23 22:02:04 curt +// Worked on creating data to output ... normals, bounding spheres, etc. +// // Revision 1.2 1999/03/23 17:44:49 curt // Beginning work on generating output scenery. // diff --git a/Main/construct.cxx b/Main/construct.cxx index 629df1918..23899f797 100644 --- a/Main/construct.cxx +++ b/Main/construct.cxx @@ -156,6 +156,13 @@ void do_triangulate( const FGArray& array, const FGClipper& clipper, } +// generate the flight gear scenery file +void do_output( const FGTriangle& t, FGGenOutput& output ) { + output.build( t ); + output.write( "output" ); +} + + main(int argc, char **argv) { fitnode_list fit_list; double lon, lat; @@ -188,11 +195,15 @@ main(int argc, char **argv) { do_triangulate( array, clipper, t ); // generate the output - fgGenOutput( t ); + FGGenOutput output; + do_output( t, output ); } // $Log$ +// Revision 1.8 1999/03/23 22:02:17 curt +// Worked on creating data to output ... normals, bounding spheres, etc. +// // Revision 1.7 1999/03/22 23:48:29 curt // Added GenOutput/ // -- 2.39.5