Start of support for precalculating texture coordinates.
Try to avoid a situation where you cycle between too many nodes and two few nodes with just a single increment of error level.
This commit is contained in:
parent
28ee2efbf9
commit
c062fe49c4
5 changed files with 127 additions and 30 deletions
|
@ -60,6 +60,70 @@ void FGGenOutput::calc_gbs( FGConstruct& c ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define FG_TEX_CONSTANT 69.0
|
||||||
|
|
||||||
|
// traverse the specified fan and attempt to calculate "none
|
||||||
|
// stretching" texture coordinates
|
||||||
|
int_list FGGenOutput::calc_tex_coords( point_list geod_nodes, int_list fan ) {
|
||||||
|
// cout << "calculating texture coordinates for a specific fan of size = "
|
||||||
|
// << fan.size() << 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() * FG_TEX_CONSTANT );
|
||||||
|
t.sety( p.y() * FG_TEX_CONSTANT );
|
||||||
|
|
||||||
|
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() * FG_TEX_CONSTANT );
|
||||||
|
t.sety( p.y() * FG_TEX_CONSTANT );
|
||||||
|
shifted_t = t - min;
|
||||||
|
if ( shifted_t.x() < FG_EPSILON ) {
|
||||||
|
shifted_t.setx( 0.0 );
|
||||||
|
}
|
||||||
|
if ( shifted_t.y() < FG_EPSILON ) {
|
||||||
|
shifted_t.sety( 0.0 );
|
||||||
|
}
|
||||||
|
shifted_t.setz( 0.0 );
|
||||||
|
index = tex_coords.unique_add( shifted_t );
|
||||||
|
tex.push_back( index );
|
||||||
|
}
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// build the necessary output structures based on the triangulation
|
// build the necessary output structures based on the triangulation
|
||||||
// data
|
// data
|
||||||
int FGGenOutput::build( FGConstruct& c ) {
|
int FGGenOutput::build( FGConstruct& c ) {
|
||||||
|
@ -92,6 +156,20 @@ int FGGenOutput::build( FGConstruct& c ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
tex_coords.clear();
|
||||||
|
|
||||||
|
for ( int i = 0; i < FG_MAX_AREA_TYPES; ++i ) {
|
||||||
|
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
|
||||||
|
int_list t_list = calc_tex_coords( geod_nodes, fans[i][j] );
|
||||||
|
// cout << fans[i][j].size() << " === "
|
||||||
|
// << t_list.size() << endl;
|
||||||
|
textures[i].push_back( t_list );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// calculate the global bounding sphere
|
// calculate the global bounding sphere
|
||||||
calc_gbs( c );
|
calc_gbs( c );
|
||||||
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
|
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
|
||||||
|
@ -247,6 +325,14 @@ int FGGenOutput::write( FGConstruct &c ) {
|
||||||
}
|
}
|
||||||
fprintf(fp, "\n");
|
fprintf(fp, "\n");
|
||||||
|
|
||||||
|
// write texture coordinates
|
||||||
|
point_list tex_coord_list = tex_coords.get_node_list();
|
||||||
|
for ( int i = 0; i < (int)tex_coord_list.size(); ++i ) {
|
||||||
|
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)
|
// write triangles (grouped by type for now)
|
||||||
Point3D center;
|
Point3D center;
|
||||||
double radius;
|
double radius;
|
||||||
|
@ -265,33 +351,13 @@ int FGGenOutput::write( FGConstruct &c ) {
|
||||||
fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
|
fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
|
||||||
center.x(), center.y(), center.z(), radius);
|
center.x(), center.y(), center.z(), radius);
|
||||||
|
|
||||||
fan_list_iterator f_current = fans[i].begin();
|
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
|
||||||
fan_list_iterator f_last = fans[i].end();
|
|
||||||
for ( ; f_current != f_last; ++f_current ) {
|
|
||||||
fprintf( fp, "tf" );
|
fprintf( fp, "tf" );
|
||||||
total_tris += f_current->size() - 2;
|
total_tris += fans[i][j].size() - 2;
|
||||||
int_list_iterator i_current = f_current->begin();
|
for ( int k = 0; k < (int)fans[i][j].size(); ++k ) {
|
||||||
int_list_iterator i_last = f_current->end();
|
fprintf( fp, " %d/%d", fans[i][j][k], textures[i][j][k] );
|
||||||
for ( ; i_current != i_last; ++i_current ) {
|
|
||||||
fprintf( fp, " %d", *i_current );
|
|
||||||
}
|
}
|
||||||
fprintf( fp, "\n" );
|
fprintf( fp, "\n" );
|
||||||
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
int_list_iterator i_current = f_current->begin();
|
|
||||||
int_list_iterator i_last = f_current->end();
|
|
||||||
int center = *i_current;
|
|
||||||
++i_current;
|
|
||||||
int n2 = *i_current;
|
|
||||||
++i_current;
|
|
||||||
for ( ; i_current != i_last; ++i_current ) {
|
|
||||||
int n3 = *i_current;
|
|
||||||
fprintf( fp, "f %d %d %d\n", center, n2, n3 );
|
|
||||||
n2 = n3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf( fp, "\n" );
|
fprintf( fp, "\n" );
|
||||||
|
|
|
@ -48,6 +48,10 @@ FG_USING_STD(string);
|
||||||
FG_USING_STD(vector);
|
FG_USING_STD(vector);
|
||||||
|
|
||||||
|
|
||||||
|
typedef vector < int_list > tex_list;
|
||||||
|
typedef tex_list::iterator tex_list_iterator;
|
||||||
|
typedef tex_list::const_iterator const_tex_list_iterator;
|
||||||
|
|
||||||
class FGGenOutput {
|
class FGGenOutput {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,9 +62,15 @@ private:
|
||||||
// triangles (by index into point list)
|
// triangles (by index into point list)
|
||||||
triele_list tri_elements;
|
triele_list tri_elements;
|
||||||
|
|
||||||
|
// texture coordinates
|
||||||
|
FGTriNodes tex_coords;
|
||||||
|
|
||||||
// fan list
|
// fan list
|
||||||
fan_list fans[FG_MAX_AREA_TYPES];
|
fan_list fans[FG_MAX_AREA_TYPES];
|
||||||
|
|
||||||
|
// textures pointer list
|
||||||
|
tex_list textures[FG_MAX_AREA_TYPES];
|
||||||
|
|
||||||
// global bounding sphere
|
// global bounding sphere
|
||||||
Point3D gbs_center;
|
Point3D gbs_center;
|
||||||
double gbs_radius;
|
double gbs_radius;
|
||||||
|
@ -77,6 +87,10 @@ private:
|
||||||
void calc_bounding_sphere( FGConstruct& c, const FGTriEle& t,
|
void calc_bounding_sphere( FGConstruct& c, const FGTriEle& t,
|
||||||
Point3D *center, double *radius );
|
Point3D *center, double *radius );
|
||||||
|
|
||||||
|
// traverse the specified fan and attempt to calculate "none
|
||||||
|
// stretching" texture coordinates
|
||||||
|
int_list calc_tex_coords( point_list geod_nodes, int_list fan );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Constructor && Destructor
|
// Constructor && Destructor
|
||||||
|
|
|
@ -341,6 +341,9 @@ void construct_tile( FGConstruct& c ) {
|
||||||
// arbitrarily complex tiles.
|
// arbitrarily complex tiles.
|
||||||
|
|
||||||
bool acceptable = false;
|
bool acceptable = false;
|
||||||
|
bool growing = false;
|
||||||
|
bool shrinking = false;
|
||||||
|
|
||||||
double error = 200.0;
|
double error = 200.0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -371,8 +374,14 @@ void construct_tile( FGConstruct& c ) {
|
||||||
cout << "produced too few nodes ..." << endl;
|
cout << "produced too few nodes ..." << endl;
|
||||||
|
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
|
growing = true;
|
||||||
|
|
||||||
|
if ( shrinking ) {
|
||||||
|
error /= 1.25;
|
||||||
|
shrinking = false;
|
||||||
|
} else {
|
||||||
error /= 1.5;
|
error /= 1.5;
|
||||||
|
}
|
||||||
cout << "Setting error to " << error << " and retrying fit."
|
cout << "Setting error to " << error << " and retrying fit."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
@ -383,8 +392,15 @@ void construct_tile( FGConstruct& c ) {
|
||||||
cout << "produced too many nodes ..." << endl;
|
cout << "produced too many nodes ..." << endl;
|
||||||
|
|
||||||
acceptable = false;
|
acceptable = false;
|
||||||
|
shrinking = true;
|
||||||
|
|
||||||
|
if ( growing ) {
|
||||||
|
error *= 1.25;
|
||||||
|
growing = false;
|
||||||
|
} else {
|
||||||
error *= 1.5;
|
error *= 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
cout << "Setting error to " << error << " and retrying fit."
|
cout << "Setting error to " << error << " and retrying fit."
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,10 +117,10 @@ main(int argc, char **argv) {
|
||||||
FGBucket tmp1( 0.0, 0.0 );
|
FGBucket tmp1( 0.0, 0.0 );
|
||||||
|
|
||||||
double dy = tmp1.get_height();
|
double dy = tmp1.get_height();
|
||||||
lat = 44.25 + dy * 0.5;
|
lat = 68.75 + dy * 0.5;
|
||||||
|
|
||||||
bool start_lon = true;
|
bool start_lon = true;
|
||||||
lon = -85.75 + (1.0/16.0);
|
lon = -152.9 /* + (1.0/16.0) */;
|
||||||
|
|
||||||
while ( lat <= 90.0 ) {
|
while ( lat <= 90.0 ) {
|
||||||
FGBucket tmp2( 0.0, lat );
|
FGBucket tmp2( 0.0, lat );
|
||||||
|
|
|
@ -413,9 +413,10 @@ int FGTriangle::run_triangulate( int pass ) {
|
||||||
if ( pass == 1 ) {
|
if ( pass == 1 ) {
|
||||||
// use a quality value of 10 (q10) meaning no interior
|
// use a quality value of 10 (q10) meaning no interior
|
||||||
// triangle angles less than 10 degrees
|
// triangle angles less than 10 degrees
|
||||||
|
// tri_options = "pczAen";
|
||||||
tri_options = "pczq10Aen";
|
tri_options = "pczq10Aen";
|
||||||
// string tri_options = "pzAen";
|
// // string tri_options = "pzAen";
|
||||||
// string tri_options = "pczq15S400Aen";
|
// // string tri_options = "pczq15S400Aen";
|
||||||
} else if ( pass == 2 ) {
|
} else if ( pass == 2 ) {
|
||||||
// no new points on boundary (Y), no internal segment
|
// no new points on boundary (Y), no internal segment
|
||||||
// splitting (YY), no quality refinement ()
|
// splitting (YY), no quality refinement ()
|
||||||
|
|
Loading…
Reference in a new issue