2000-02-09 19:51:45 +00:00
|
|
|
// genobj.hxx -- Generate the flight gear "obj" file format from the
|
|
|
|
// triangle output
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started March 1999.
|
|
|
|
//
|
2004-11-19 22:25:49 +00:00
|
|
|
// Copyright (C) 1999 Curtis L. Olson - http://www.flightgear.org/~curt
|
2000-02-09 19:51:45 +00:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
2007-11-08 22:14:02 +01:00
|
|
|
// $Id: genobj.cxx,v 1.26 2004-11-19 22:25:49 curt Exp $
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
2001-07-31 20:14:54 +00:00
|
|
|
#include <simgear/compiler.h>
|
2001-01-05 00:05:02 +00:00
|
|
|
#include <simgear/io/sg_binobj.hxx>
|
2010-07-31 19:21:59 +02:00
|
|
|
#include <simgear/math/SGGeometry.hxx>
|
2000-02-16 22:01:47 +00:00
|
|
|
#include <simgear/misc/texcoord.hxx>
|
2000-02-09 19:51:45 +00:00
|
|
|
|
2001-06-22 19:28:29 +00:00
|
|
|
#include <Output/output.hxx>
|
2007-11-09 12:46:25 +01:00
|
|
|
#include <Clipper/priorities.hxx>
|
2000-02-09 19:51:45 +00:00
|
|
|
|
2001-04-24 21:10:27 +00:00
|
|
|
#include <Osgb36/osgbtc.hxx>
|
2001-04-25 15:06:17 +00:00
|
|
|
#include <Osgb36/uk.hxx>
|
2000-05-30 21:11:15 +00:00
|
|
|
|
2000-02-09 19:51:45 +00:00
|
|
|
#include "genobj.hxx"
|
|
|
|
|
2008-08-08 12:17:43 +02:00
|
|
|
using std::cout;
|
|
|
|
using std::endl;
|
2010-07-31 19:21:59 +02:00
|
|
|
using std::string;
|
2000-05-30 21:11:15 +00:00
|
|
|
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
// calculate the global bounding sphere. Center is the center of the
|
|
|
|
// tile and zero elevation
|
2003-03-13 21:20:46 +00:00
|
|
|
void TGGenOutput::calc_gbs( TGConstruct& c ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
point_list wgs84_nodes = c.get_wgs84_nodes();
|
2010-07-31 19:21:59 +02:00
|
|
|
SGSphered d;
|
|
|
|
for ( int i = 0; i < wgs84_nodes.size(); ++i ) {
|
|
|
|
d.expandBy(wgs84_nodes[ i ].toSGVec3d());
|
2000-02-09 19:51:45 +00:00
|
|
|
}
|
2010-07-31 19:21:59 +02:00
|
|
|
|
|
|
|
gbs_center = d.getCenter();
|
|
|
|
gbs_radius = d.getRadius();
|
2000-02-09 19:51:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define FG_STANDARD_TEXTURE_DIMENSION 1000.0 // meters
|
|
|
|
|
|
|
|
// traverse the specified fan and attempt to calculate "none
|
|
|
|
// stretching" texture coordinates
|
2003-03-13 21:20:46 +00:00
|
|
|
int_list TGGenOutput::calc_tex_coords( TGConstruct& c, point_list geod_nodes,
|
2000-02-09 19:51:45 +00:00
|
|
|
int_list fan )
|
|
|
|
{
|
|
|
|
// cout << "calculating texture coordinates for a specific fan of size = "
|
|
|
|
// << fan.size() << endl;
|
|
|
|
|
2000-12-13 20:06:36 +00:00
|
|
|
SGBucket b = c.get_bucket();
|
2000-02-09 19:51:45 +00:00
|
|
|
double clat = b.get_center_lat();
|
2001-03-24 03:34:04 +00:00
|
|
|
double clat_rad = clat * SGD_DEGREES_TO_RADIANS;
|
2000-02-09 19:51:45 +00:00
|
|
|
double cos_lat = cos( clat_rad );
|
2001-03-24 03:34:04 +00:00
|
|
|
double local_radius = cos_lat * SG_EQUATORIAL_RADIUS_M;
|
2001-03-25 12:10:21 +00:00
|
|
|
double local_perimeter = 2.0 * local_radius * SGD_PI;
|
2000-02-09 19:51:45 +00:00
|
|
|
double degree_width = local_perimeter / 360.0;
|
|
|
|
|
|
|
|
// cout << "clat = " << clat << endl;
|
|
|
|
// cout << "clat (radians) = " << clat_rad << endl;
|
|
|
|
// cout << "cos(lat) = " << cos_lat << endl;
|
|
|
|
// cout << "local_radius = " << local_radius << endl;
|
|
|
|
// cout << "local_perimeter = " << local_perimeter << endl;
|
|
|
|
// cout << "degree_width = " << degree_width << endl;
|
|
|
|
|
2001-03-25 12:10:21 +00:00
|
|
|
double perimeter = 2.0 * SG_EQUATORIAL_RADIUS_M * SG_DPI;
|
2000-02-09 19:51:45 +00:00
|
|
|
double degree_height = perimeter / 360.0;
|
|
|
|
// cout << "degree_height = " << degree_height << endl;
|
|
|
|
|
|
|
|
// find min/max of fan
|
|
|
|
Point3D min, max, p, t;
|
|
|
|
bool first = true;
|
|
|
|
|
|
|
|
for ( int i = 0; i < (int)fan.size(); ++i ) {
|
|
|
|
p = geod_nodes[ fan[i] ];
|
|
|
|
t.setx( p.x() * ( degree_width / FG_STANDARD_TEXTURE_DIMENSION ) );
|
|
|
|
t.sety( p.y() * ( degree_height / FG_STANDARD_TEXTURE_DIMENSION ) );
|
|
|
|
|
|
|
|
if ( first ) {
|
|
|
|
min = max = t;
|
|
|
|
first = false;
|
|
|
|
} else {
|
|
|
|
if ( t.x() < min.x() ) {
|
|
|
|
min.setx( t.x() );
|
|
|
|
}
|
|
|
|
if ( t.y() < min.y() ) {
|
|
|
|
min.sety( t.y() );
|
|
|
|
}
|
|
|
|
if ( t.x() > max.x() ) {
|
|
|
|
max.setx( t.x() );
|
|
|
|
}
|
|
|
|
if ( t.y() > max.y() ) {
|
|
|
|
max.sety( t.y() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
min.setx( (double)( (int)min.x() - 1 ) );
|
|
|
|
min.sety( (double)( (int)min.y() - 1 ) );
|
|
|
|
// cout << "found min = " << min << endl;
|
|
|
|
|
|
|
|
// generate tex_list
|
|
|
|
Point3D shifted_t;
|
|
|
|
int index;
|
|
|
|
int_list tex;
|
|
|
|
tex.clear();
|
|
|
|
for ( int i = 0; i < (int)fan.size(); ++i ) {
|
|
|
|
p = geod_nodes[ fan[i] ];
|
|
|
|
t.setx( p.x() * ( degree_width / FG_STANDARD_TEXTURE_DIMENSION ) );
|
|
|
|
t.sety( p.y() * ( degree_height / FG_STANDARD_TEXTURE_DIMENSION ) );
|
|
|
|
shifted_t = t - min;
|
2001-03-23 23:18:18 +00:00
|
|
|
if ( shifted_t.x() < SG_EPSILON ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
shifted_t.setx( 0.0 );
|
|
|
|
}
|
2001-03-23 23:18:18 +00:00
|
|
|
if ( shifted_t.y() < SG_EPSILON ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
shifted_t.sety( 0.0 );
|
|
|
|
}
|
|
|
|
shifted_t.setz( 0.0 );
|
|
|
|
// cout << "shifted_t = " << shifted_t << endl;
|
|
|
|
index = tex_coords.unique_add( shifted_t );
|
|
|
|
tex.push_back( index );
|
|
|
|
}
|
|
|
|
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// build the necessary output structures based on the triangulation
|
|
|
|
// data
|
2003-03-13 21:20:46 +00:00
|
|
|
int TGGenOutput::build( TGConstruct& c ) {
|
2010-10-02 10:25:36 +02:00
|
|
|
int i, j, k;
|
2000-05-30 21:11:15 +00:00
|
|
|
|
2003-02-26 20:25:29 +00:00
|
|
|
TGTriNodes trinodes = c.get_tri_nodes();
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
// copy the geodetic node list into this class
|
|
|
|
geod_nodes = trinodes.get_node_list();
|
|
|
|
|
|
|
|
// copy the triangle list into this class
|
|
|
|
tri_elements = c.get_tri_elements();
|
|
|
|
|
|
|
|
// build the trifan list
|
|
|
|
cout << "total triangles = " << tri_elements.size() << endl;
|
2003-02-26 20:36:15 +00:00
|
|
|
TGGenFans f;
|
2003-03-13 21:20:46 +00:00
|
|
|
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
triele_list area_tris;
|
|
|
|
area_tris.erase( area_tris.begin(), area_tris.end() );
|
|
|
|
|
|
|
|
const_triele_list_iterator t_current = tri_elements.begin();
|
|
|
|
const_triele_list_iterator t_last = tri_elements.end();
|
|
|
|
for ( ; t_current != t_last; ++t_current ) {
|
|
|
|
if ( (int)t_current->get_attribute() == i ) {
|
|
|
|
area_tris.push_back( *t_current );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( (int)area_tris.size() > 0 ) {
|
|
|
|
cout << "generating fans for area = " << i << endl;
|
|
|
|
fans[i] = f.greedy_build( area_tris );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// build the texture coordinate list and make a parallel structure
|
|
|
|
// to the fan list for pointers into the texture list
|
|
|
|
cout << "calculating texture coordinates" << endl;
|
2003-08-19 02:29:44 +00:00
|
|
|
cout << "c.get_useUKGrid() = " << c.get_useUKGrid() << endl;
|
2000-02-09 19:51:45 +00:00
|
|
|
tex_coords.clear();
|
2010-10-02 10:25:36 +02:00
|
|
|
std::vector < SGGeod > convGeodNodes;
|
|
|
|
for ( k = 0; k < geod_nodes.size(); k++ ) {
|
|
|
|
Point3D node = geod_nodes[k];
|
|
|
|
convGeodNodes.push_back( SGGeod::fromDegM( node.x(), node.y(), node.z() ) );
|
|
|
|
}
|
2003-03-13 21:20:46 +00:00
|
|
|
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
2003-08-19 02:29:44 +00:00
|
|
|
// cout << " area = " << i << endl;
|
2000-05-30 21:11:15 +00:00
|
|
|
for ( j = 0; j < (int)fans[i].size(); ++j ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
// int_list t_list = calc_tex_coords( c, geod_nodes, fans[i][j] );
|
|
|
|
// cout << fans[i][j].size() << " === "
|
|
|
|
// << t_list.size() << endl;
|
2001-04-24 21:10:27 +00:00
|
|
|
SGBucket b = c.get_bucket();
|
|
|
|
Point3D ourPosition;
|
|
|
|
|
2004-04-26 16:17:45 +00:00
|
|
|
ourPosition.setlon(b.get_chunk_lon());
|
|
|
|
ourPosition.setlat(b.get_chunk_lat());
|
2001-04-24 21:10:27 +00:00
|
|
|
|
2010-07-31 19:21:59 +02:00
|
|
|
int_list ti_list;
|
|
|
|
ti_list.clear();
|
2001-04-24 21:10:27 +00:00
|
|
|
//dcl - here read the flag to check if we are building UK grid
|
|
|
|
//If so - check if the bucket is within the UK lat & lon
|
2001-07-31 20:14:54 +00:00
|
|
|
if( (c.get_useUKGrid()) && (isInUK(ourPosition)) ) {
|
2010-07-31 19:21:59 +02:00
|
|
|
point_list tp_list;
|
2001-04-24 21:10:27 +00:00
|
|
|
tp_list = UK_calc_tex_coords( b, geod_nodes, fans[i][j], 1.0 );
|
2010-10-02 10:25:36 +02:00
|
|
|
for ( k = 0; k < (int)tp_list.size(); ++k ) {
|
2010-07-31 19:21:59 +02:00
|
|
|
// cout << " tc = " << tp_list[k] << endl;
|
|
|
|
int index = tex_coords.simple_add( tp_list[k] );
|
|
|
|
ti_list.push_back( index );
|
|
|
|
}
|
2001-07-31 20:14:54 +00:00
|
|
|
} else {
|
2010-07-31 19:21:59 +02:00
|
|
|
std::vector< SGVec2f > tp_list = sgCalcTexCoords( b, convGeodNodes, fans[i][j] );
|
2010-10-02 10:06:34 +02:00
|
|
|
for ( k = 0; k < (int)tp_list.size(); ++k ) {
|
|
|
|
SGVec2f tc = tp_list[k];
|
2010-07-31 19:21:59 +02:00
|
|
|
// SG_LOG(SG_GENERAL, SG_DEBUG, "base_tc = " << tc);
|
|
|
|
int index = tex_coords.simple_add( Point3D( tc.x(), tc.y(), 0 ) );
|
|
|
|
ti_list.push_back( index );
|
|
|
|
}
|
2001-07-31 20:14:54 +00:00
|
|
|
}
|
2001-04-24 21:10:27 +00:00
|
|
|
|
2000-02-09 19:51:45 +00:00
|
|
|
textures[i].push_back( ti_list );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// calculate the global bounding sphere
|
|
|
|
calc_gbs( c );
|
|
|
|
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-02 10:25:36 +02:00
|
|
|
// calculate the bounding sphere for a list of triangle faces
|
2003-03-13 21:20:46 +00:00
|
|
|
void TGGenOutput::calc_group_bounding_sphere( TGConstruct& c,
|
2000-05-08 17:25:09 +00:00
|
|
|
const opt_list& fans,
|
2000-02-09 19:51:45 +00:00
|
|
|
Point3D *center, double *radius )
|
|
|
|
{
|
|
|
|
cout << "calculate group bounding sphere for " << fans.size() << " fans."
|
|
|
|
<< endl;
|
|
|
|
|
|
|
|
point_list wgs84_nodes = c.get_wgs84_nodes();
|
|
|
|
|
|
|
|
// generate a list of unique points from the triangle list
|
2003-02-26 20:25:29 +00:00
|
|
|
TGTriNodes nodes;
|
2000-02-09 19:51:45 +00:00
|
|
|
|
2000-05-08 17:25:09 +00:00
|
|
|
const_opt_list_iterator f_current = fans.begin();
|
|
|
|
const_opt_list_iterator f_last = fans.end();
|
2000-02-09 19:51:45 +00:00
|
|
|
for ( ; f_current != f_last; ++f_current ) {
|
|
|
|
const_int_list_iterator i_current = f_current->begin();
|
|
|
|
const_int_list_iterator i_last = f_current->end();
|
|
|
|
for ( ; i_current != i_last; ++i_current ) {
|
|
|
|
Point3D p1 = wgs84_nodes[ *i_current ];
|
|
|
|
nodes.unique_add(p1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// find average of point list
|
|
|
|
*center = Point3D( 0.0 );
|
|
|
|
point_list points = nodes.get_node_list();
|
|
|
|
// cout << "found " << points.size() << " unique nodes" << endl;
|
|
|
|
point_list_iterator p_current = points.begin();
|
|
|
|
point_list_iterator p_last = points.end();
|
|
|
|
for ( ; p_current != p_last; ++p_current ) {
|
|
|
|
*center += *p_current;
|
|
|
|
}
|
|
|
|
*center /= points.size();
|
|
|
|
|
|
|
|
// find max radius
|
|
|
|
double dist_squared;
|
|
|
|
double max_squared = 0;
|
|
|
|
|
|
|
|
p_current = points.begin();
|
|
|
|
p_last = points.end();
|
|
|
|
for ( ; p_current != p_last; ++p_current ) {
|
|
|
|
dist_squared = (*center).distance3Dsquared(*p_current);
|
|
|
|
if ( dist_squared > max_squared ) {
|
|
|
|
max_squared = dist_squared;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*radius = sqrt(max_squared);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-02 10:06:34 +02:00
|
|
|
// calculate the bounding sphere for the specified triangle face
|
2003-03-13 21:20:46 +00:00
|
|
|
void TGGenOutput::calc_bounding_sphere( TGConstruct& c, const TGTriEle& t,
|
2000-02-09 19:51:45 +00:00
|
|
|
Point3D *center, double *radius )
|
|
|
|
{
|
|
|
|
point_list wgs84_nodes = c.get_wgs84_nodes();
|
|
|
|
|
|
|
|
*center = Point3D( 0.0 );
|
|
|
|
|
|
|
|
Point3D p1 = wgs84_nodes[ t.get_n1() ];
|
|
|
|
Point3D p2 = wgs84_nodes[ t.get_n2() ];
|
|
|
|
Point3D p3 = wgs84_nodes[ t.get_n3() ];
|
|
|
|
|
|
|
|
*center = p1 + p2 + p3;
|
|
|
|
*center /= 3;
|
|
|
|
|
|
|
|
double dist_squared;
|
|
|
|
double max_squared = 0;
|
|
|
|
|
|
|
|
dist_squared = (*center).distance3Dsquared(p1);
|
|
|
|
if ( dist_squared > max_squared ) {
|
|
|
|
max_squared = dist_squared;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist_squared = (*center).distance3Dsquared(p2);
|
|
|
|
if ( dist_squared > max_squared ) {
|
|
|
|
max_squared = dist_squared;
|
|
|
|
}
|
|
|
|
|
|
|
|
dist_squared = (*center).distance3Dsquared(p3);
|
|
|
|
if ( dist_squared > max_squared ) {
|
|
|
|
max_squared = dist_squared;
|
|
|
|
}
|
|
|
|
|
|
|
|
*radius = sqrt(max_squared);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-01-05 00:05:02 +00:00
|
|
|
#if 0
|
2000-02-09 19:51:45 +00:00
|
|
|
// write out the fgfs scenery file
|
2003-03-13 21:20:46 +00:00
|
|
|
int TGGenOutput::write_orig( TGConstruct &c ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
Point3D p;
|
2000-05-30 21:11:15 +00:00
|
|
|
int i;
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
string base = c.get_output_base();
|
2000-12-13 20:06:36 +00:00
|
|
|
SGBucket b = c.get_bucket();
|
2000-02-09 19:51:45 +00:00
|
|
|
|
2004-07-30 20:02:20 +00:00
|
|
|
string dir = base + b.gen_base_path();
|
2000-05-30 21:11:15 +00:00
|
|
|
|
Contributed by Bruce Finney:
The following files have been changed to enable the latest Terragear CVS
to compile with MSVC++ 5.0
.\construct\clipper\clipper.cxx
for( int i - lots of places
.\construct\genoutput\genobj.cxx
fix directory logic for windows, line 320 and following
.\construct\main\main.cxx
windows does not have an opendir function
added code for windows directory functions
disabled the mem allocation limit code - windows does not
have similar functions
for ( int i - several places
.\construct\match\match.cxx
moved the definition of file and command outside of the ifdef line 420
.\lib\e00\e00.cxx
for( int i - several places
.\lib\e00\e00.cxx
use simgear/compiler.h constructs
.\lib\geometry\contour_tree.hxx
removed a cout statement
.\lib\geometry\poly_support.cxx
added float.h changed 1.0e+999 to DBL_MAX, windows doesn't go that big
lots of for ( int i changes
lines 193 and 208 no != operator defined - changed logic
line 801 flag should be int, not bool, get_hole_flag returns int
.\lib\landcover\landcover.cxx
.\lib\landcover\landcover.hxx
add include simgear/compiler.h
see comments
.\lib\optimize\genfans.cxx
function canonify added return at end, windows complains
added using std for cout and endl
.\lib\optimize\genstrips.cxx
function tgGenStrips no return value, moved by_node into outer scope
fix for ( int i ...
.\lib\poly2tri\construct.c
added include <memory.h> for windows
remove unused variables lines 435 & 437
.\lib\poly2tri\misc.c
added HAVE_SYS_TIME_H logic for sys/time.h include file
added logic to uses windows functions for time and rand
.\lib\poly2tri\monotone.c
added include <memory.h> for windows
lines 286-288 remove unused variables
.\lib\poly2tri\tri.c
remove sys/time.h - no time functions called
added include <memory.h> for windows
.\lib\polygon\polygon.cxx
function polygon_to_tristrip will not compile I don't think the
logic is complete, no returned data added if else endif around
function and polygon_to_tristrip_old, renamed _old function.
Search of code reveals that function is not called by anyone.
.\lib\polygon\superpoly.cxx
changed include <superpoly.hxx> to "superpoly.hxx"
.\lib\polygon\superpoly.hxx
add include <windows.h> for windows before include <gl.h>
needed for definitions used in Microsoft version of opengl
.\lib\shapelib\dbfopen.c
added include files for windows
lines 195-197 271-272 515-517 removed unused variables
.\lib\shapelib\shpopen.c
added #include <stdlib.h> for malloc() and friends
added include files for windows
line 279 527 813 1127 removed unused variables
line 827 cast result to int
.\lib\win32\mkdir.cpp
documented function, remove debug lines
.\prep\demraw2ascii\main.c
lines 46-50 remove unused variables
.\prep\demraw2ascii\rawdem.c
line 47 changed logic to compile with MSVC
line 244-256 set real constants to float, windows complains with
double constants
.\prep\genairports\build.cxx
lots of for ( int i changes
.\prep\genairports\main.cxx
fix mkdir logic for windows
.\prep\genairports\output.cxx
added using std cout endl
lots of for ( int i changes
fix mkdir logic for windows
.\prep\genairports\runway.cxx
for ( int i changes
lines 117-118 161-162 remove default values for function parameters
.\prep\gshhs\main.cxx
added using std cout
.\prep\shapefile\noaa_decode.cxx
.\prep\shapefile\shape_decode.cxx
added using std for cout
lines 45-49 moved unused variables inside #if 0 block
2000-11-25 19:39:46 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
fg_mkdir( dir.c_str() );
|
2000-05-30 21:11:15 +00:00
|
|
|
#else
|
2000-02-09 19:51:45 +00:00
|
|
|
string command = "mkdir -p " + dir;
|
|
|
|
system(command.c_str());
|
2000-05-30 21:11:15 +00:00
|
|
|
#endif
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
string file = dir + "/" + b.gen_index_str();
|
|
|
|
cout << "Output file = " << file << endl;
|
|
|
|
|
|
|
|
FILE *fp;
|
|
|
|
if ( (fp = fopen( file.c_str(), "w" )) == NULL ) {
|
|
|
|
cout << "ERROR: opening " << file << " for writing!" << endl;
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// write headers
|
|
|
|
fprintf(fp, "# FGFS Scenery\n");
|
|
|
|
fprintf(fp, "# 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 sphere
|
|
|
|
fprintf(fp, "# gbs %.5f %.5f %.5f %.2f\n",
|
|
|
|
gbs_center.x(), gbs_center.y(), gbs_center.z(), gbs_radius);
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
|
|
|
// write nodes
|
|
|
|
point_list wgs84_nodes = c.get_wgs84_nodes();
|
2000-11-22 20:41:22 +00:00
|
|
|
cout << "writing nodes = " << wgs84_nodes.size() << endl;
|
2000-02-09 19:51:45 +00:00
|
|
|
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
|
|
|
|
point_list point_normals = c.get_point_normals();
|
2000-11-22 20:41:22 +00:00
|
|
|
cout << "writing normals = " << point_normals.size() << endl;
|
2000-02-09 19:51:45 +00:00
|
|
|
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 texture coordinates
|
|
|
|
point_list tex_coord_list = tex_coords.get_node_list();
|
|
|
|
fprintf(fp, "# texture coordinate list\n");
|
2000-05-30 21:11:15 +00:00
|
|
|
for ( i = 0; i < (int)tex_coord_list.size(); ++i ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
p = tex_coord_list[i];
|
|
|
|
fprintf(fp, "vt %.5f %.5f\n", p.x(), p.y());
|
|
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
|
|
|
// write triangles (grouped by type for now)
|
|
|
|
Point3D center;
|
|
|
|
double radius;
|
|
|
|
fprintf(fp, "# triangle groups\n");
|
|
|
|
fprintf(fp, "\n");
|
|
|
|
|
|
|
|
int total_tris = 0;
|
2003-03-13 21:20:46 +00:00
|
|
|
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
2000-02-09 19:51:45 +00:00
|
|
|
if ( (int)fans[i].size() > 0 ) {
|
|
|
|
string attr_name = get_area_name( (AreaType)i );
|
|
|
|
calc_group_bounding_sphere( c, fans[i], ¢er, &radius );
|
|
|
|
cout << "writing " << (int)fans[i].size() << " fans for "
|
|
|
|
<< attr_name << endl;
|
|
|
|
|
|
|
|
fprintf(fp, "# usemtl %s\n", attr_name.c_str() );
|
|
|
|
fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
|
|
|
|
center.x(), center.y(), center.z(), radius);
|
|
|
|
|
|
|
|
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
|
|
|
|
fprintf( fp, "tf" );
|
|
|
|
total_tris += fans[i][j].size() - 2;
|
|
|
|
for ( int k = 0; k < (int)fans[i][j].size(); ++k ) {
|
|
|
|
fprintf( fp, " %d/%d", fans[i][j][k], textures[i][j][k] );
|
|
|
|
}
|
|
|
|
fprintf( fp, "\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
fprintf( fp, "\n" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cout << "wrote " << total_tris << " tris to output file" << endl;
|
|
|
|
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
command = "gzip --force --best " + file;
|
|
|
|
system(command.c_str());
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2001-01-05 00:05:02 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// write out the fgfs scenery file
|
2003-03-13 21:20:46 +00:00
|
|
|
int TGGenOutput::write( TGConstruct &c ) {
|
2001-01-05 00:05:02 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
// Assemble all the data into the final format
|
|
|
|
|
|
|
|
SGBucket b = c.get_bucket();
|
2004-07-30 20:02:20 +00:00
|
|
|
string base = c.get_output_base();
|
2001-01-05 00:05:02 +00:00
|
|
|
string name = b.gen_index_str();
|
2001-06-22 19:28:29 +00:00
|
|
|
name += ".btg";
|
2001-01-05 00:05:02 +00:00
|
|
|
|
2010-07-31 19:21:59 +02:00
|
|
|
std::vector< SGVec3d > wgs84_nodes;
|
|
|
|
for ( i = 0; i < c.get_wgs84_nodes().size(); i++ ) {
|
|
|
|
Point3D node = c.get_wgs84_nodes()[i];
|
|
|
|
wgs84_nodes.push_back( node.toSGVec3d() );
|
|
|
|
}
|
|
|
|
std::vector< SGVec3f > normals;
|
|
|
|
for ( i = 0; i < c.get_point_normals().size(); i++ ) {
|
|
|
|
Point3D node = c.get_point_normals()[i];
|
|
|
|
normals.push_back( node.toSGVec3f() );
|
|
|
|
}
|
2001-01-05 00:05:02 +00:00
|
|
|
cout << "dumping normals = " << normals.size() << endl;
|
|
|
|
/* for ( i = 0; i < (int)normals.size(); ++i ) {
|
|
|
|
Point3D p = normals[i];
|
|
|
|
printf("vn %.5f %.5f %.5f\n", p.x(), p.y(), p.z());
|
|
|
|
} */
|
2010-07-31 19:21:59 +02:00
|
|
|
std::vector< SGVec2f > texcoords;
|
|
|
|
for ( i = 0; i < tex_coords.get_node_list().size(); i++ ) {
|
|
|
|
Point3D node = tex_coords.get_node_list()[i];
|
|
|
|
texcoords.push_back( node.toSGVec2f() );
|
|
|
|
}
|
2001-01-05 00:05:02 +00:00
|
|
|
|
|
|
|
// allocate and initialize triangle group structures
|
|
|
|
group_list tris_v; group_list tris_tc; string_list tri_materials;
|
|
|
|
tris_v.clear(); tris_tc.clear(); tri_materials.clear();
|
|
|
|
|
|
|
|
group_list strips_v; group_list strips_tc; string_list strip_materials;
|
|
|
|
strips_v.clear(); strips_tc.clear(); strip_materials.clear();
|
|
|
|
|
|
|
|
group_list fans_v; group_list fans_tc; string_list fan_materials;
|
|
|
|
fans_v.clear(); fans_tc.clear(); fan_materials.clear();
|
|
|
|
|
2003-03-13 21:20:46 +00:00
|
|
|
for ( i = 0; i < TG_MAX_AREA_TYPES; ++i ) {
|
2001-01-05 00:05:02 +00:00
|
|
|
if ( (int)fans[i].size() > 0 ) {
|
|
|
|
cout << "creating " << fans[i].size() << " fans of type "
|
|
|
|
<< i << endl;
|
|
|
|
string attr_name = get_area_name( (AreaType)i );
|
|
|
|
|
|
|
|
int_list vs, tcs;
|
|
|
|
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
|
|
|
|
vs.clear(); tcs.clear();
|
|
|
|
for ( int k = 0; k < (int)fans[i][j].size(); ++k ) {
|
|
|
|
vs.push_back( fans[i][j][k] );
|
|
|
|
tcs.push_back( textures[i][j][k] );
|
|
|
|
}
|
|
|
|
fans_v.push_back( vs );
|
|
|
|
fans_tc.push_back( tcs );
|
|
|
|
fan_materials.push_back( attr_name );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-01-06 04:31:57 +00:00
|
|
|
SGBinObject obj;
|
|
|
|
|
|
|
|
obj.set_gbs_center( gbs_center );
|
|
|
|
obj.set_gbs_radius( gbs_radius );
|
|
|
|
obj.set_wgs84_nodes( wgs84_nodes );
|
|
|
|
obj.set_normals( normals );
|
|
|
|
obj.set_texcoords( texcoords );
|
|
|
|
obj.set_tris_v( tris_v );
|
|
|
|
obj.set_tris_tc( tris_tc );
|
|
|
|
obj.set_tri_materials( tri_materials );
|
|
|
|
obj.set_strips_v( strips_v );
|
|
|
|
obj.set_strips_tc( strips_tc );
|
|
|
|
obj.set_strip_materials( strip_materials );
|
|
|
|
obj.set_fans_v( fans_v );
|
|
|
|
obj.set_fans_tc( fans_tc );
|
|
|
|
obj.set_fan_materials( fan_materials );
|
|
|
|
|
|
|
|
obj.write_bin( base, name, b );
|
2001-01-05 00:05:02 +00:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2000-02-09 19:51:45 +00:00
|
|
|
|
|
|
|
|