1
0
Fork 0

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:
curt 1999-05-12 02:09:02 +00:00
parent 28ee2efbf9
commit c062fe49c4
5 changed files with 127 additions and 30 deletions

View file

@ -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
// data
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
calc_gbs( c );
cout << "center = " << gbs_center << " radius = " << gbs_radius << endl;
@ -247,6 +325,14 @@ int FGGenOutput::write( FGConstruct &c ) {
}
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)
Point3D center;
double radius;
@ -265,33 +351,13 @@ int FGGenOutput::write( FGConstruct &c ) {
fprintf(fp, "# bs %.4f %.4f %.4f %.2f\n",
center.x(), center.y(), center.z(), radius);
fan_list_iterator f_current = fans[i].begin();
fan_list_iterator f_last = fans[i].end();
for ( ; f_current != f_last; ++f_current ) {
for ( int j = 0; j < (int)fans[i].size(); ++j ) {
fprintf( fp, "tf" );
total_tris += f_current->size() - 2;
int_list_iterator i_current = f_current->begin();
int_list_iterator i_last = f_current->end();
for ( ; i_current != i_last; ++i_current ) {
fprintf( fp, " %d", *i_current );
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" );
#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" );

View file

@ -48,6 +48,10 @@ FG_USING_STD(string);
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 {
private:
@ -58,9 +62,15 @@ private:
// triangles (by index into point list)
triele_list tri_elements;
// texture coordinates
FGTriNodes tex_coords;
// fan list
fan_list fans[FG_MAX_AREA_TYPES];
// textures pointer list
tex_list textures[FG_MAX_AREA_TYPES];
// global bounding sphere
Point3D gbs_center;
double gbs_radius;
@ -77,6 +87,10 @@ private:
void calc_bounding_sphere( FGConstruct& c, const FGTriEle& t,
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:
// Constructor && Destructor

View file

@ -341,6 +341,9 @@ void construct_tile( FGConstruct& c ) {
// arbitrarily complex tiles.
bool acceptable = false;
bool growing = false;
bool shrinking = false;
double error = 200.0;
int count = 0;
@ -371,8 +374,14 @@ void construct_tile( FGConstruct& c ) {
cout << "produced too few nodes ..." << endl;
acceptable = false;
growing = true;
error /= 1.5;
if ( shrinking ) {
error /= 1.25;
shrinking = false;
} else {
error /= 1.5;
}
cout << "Setting error to " << error << " and retrying fit."
<< endl;
}
@ -383,8 +392,15 @@ void construct_tile( FGConstruct& c ) {
cout << "produced too many nodes ..." << endl;
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."
<< endl;
}

View file

@ -117,10 +117,10 @@ main(int argc, char **argv) {
FGBucket tmp1( 0.0, 0.0 );
double dy = tmp1.get_height();
lat = 44.25 + dy * 0.5;
lat = 68.75 + dy * 0.5;
bool start_lon = true;
lon = -85.75 + (1.0/16.0);
lon = -152.9 /* + (1.0/16.0) */;
while ( lat <= 90.0 ) {
FGBucket tmp2( 0.0, lat );

View file

@ -413,9 +413,10 @@ int FGTriangle::run_triangulate( int pass ) {
if ( pass == 1 ) {
// use a quality value of 10 (q10) meaning no interior
// triangle angles less than 10 degrees
// tri_options = "pczAen";
tri_options = "pczq10Aen";
// string tri_options = "pzAen";
// string tri_options = "pczq15S400Aen";
// // string tri_options = "pzAen";
// // string tri_options = "pczq15S400Aen";
} else if ( pass == 2 ) {
// no new points on boundary (Y), no internal segment
// splitting (YY), no quality refinement ()