Added an explanation of what this code does.

This commit is contained in:
curt 2000-12-01 22:13:41 +00:00
parent 806083cb25
commit fb0916be0f

View File

@ -22,12 +22,130 @@
// $Id$
/* The following is an explanation of our somewhat conveluted and
tricky texture scaling/offset scheme:
MAX_TEX_COORD is a value I arrived at by trial and error for my
voodoo2/3 video card. If you use texture coordinates that are too
big, you quickly start getting into round off problems and the texture
jumps and moves relative to the polygon.
The point of all of this code is that I wanted to be able to define
this size in meters of a texture and have it be applied seamlessly to
the terrain. I wanted to be able to change the defined size (in
meters) of textures at run time. In other words I want to be able to
scale the textures at run time and still have them seamlessly tile
together across fans.
The problem is that I have to pregenerate all the texture coordinates
when I create the scenery, and I didn't want to burn CPU doing this
again when I load the scenery at run time.
It ended up taking me a lot of thought, a lot of trial and error, and
a lot of fiddling around to come up with a scheme that worked.
----------
Ok, so think about what needs to be done to have the texture tile
across a series of triangles and fans ...
Basically you want to use some function of lon/lat mod your max
texture coordinate size to calculate the texture coordinate of each
vertex. This should result in nice tiling across distinct triangles
and fans.
Pretend our MAX_TEX_COORD = 4.0 and half of this is 2.0
Imagine the following two adjacent polygons with the "X" component of
the initial texture coordinate based on longitude (Note they are drawn
spaced apart, but in reality the two polygons are adjacent):
7.0 8.6 8.6 9.0
*-----* *------*
| | | |
Now, this exceeds our MAX_TEX_COORD of 4.0 so we have to scale these
texture coordinates by some integer value. Let's say we always want
to minimize the tex coordinates to minimize rounding error so we will
offset the first polygon by 7.0 and the second by 8.0:
0.0 --- 1.6 and 0.6 --- 1.0
Our tiling is maintianed becuase the coordinates are continous (mod
1.0) and we still get the double repeat across both polygons.
We want to be able to scale these values by an arbitrary constant and
still have proper tiling.
Let's try doubling the coordinates:
0.0 --- 3.2 and 1.2 --- 2.0
Everything still tiles nicely (because the coordinates are continuous
mod 1.0) and the texture is now repeated 4x across the two polygons.
Before it was repeated 2x.
Let's try halving the coordinates:
0.0 --- 0.8 and 0.3 --- 0.5
Ooop! We lost continuity in texture coordinate space ... no we will
have a visual discontinuity in the texture tiling!
Ok, so we need some other scheme to keep our texture coordinates
smaller than MAX_TEX_COORD that preserves continuity in texture
space. <Deep breath> let's try the scheme that I have coded up that
you are asking about ... <fingers crossed> :-)
Going way back to the top before we shifted the texture coordinates.
tmin for the first polygon is 7.0, this is then adjusted to:
(int)(tmin.x() / HALF_MAX_TEX_COORD) ) * HALF_MAX_TEX_COORD
= (int)(7.0/2.0) * 2.0 = 3.0 * 2.0 = 6.0
The two texture coordinates are offset by 6.0 which yields 1.0 -- 2.6
tmin for the second polygon is 8.6 which is adjusted to:
(int)(tmin.x() / HALF_MAX_TEX_COORD) ) * HALF_MAX_TEX_COORD
= (int)( 8.6 / 2.0 ) * 2.0 = 4.0 * 2.0 = 8.0
The offset for the second polygon is 8.0 which yields 0.6 --- 1.0
So now we have:
1.0 --- 2.6 and 0.6 --- 1.0
This still tiles nicely and strethes our texture across completely, so
far we haven't done any damage.
Now let's double the coordinates:
2.0 --- 5.2 and 1.2 --- 2.0
The texture is repeated 4x as it should be and is still continuous.
How about halfing the coordinates. This is where the first scheme
broke down. Halving the coordinates yields
0.5 --- 1.3 and 0.3 --- 0.5
Woohoo, we still have texture space continuity (mod 1.0) and the
texture is repeated 1x.
Note, it took me almost as long to re-figure this out and write this
explanation as it did to figure out the scheme originally. I better
enter this in the official comments in case I forget again. :-)
*/
#include "texcoord.hxx"
#define FG_STANDARD_TEXTURE_DIMENSION 1000.0 // meters
#define MAX_TEX_COORD 8.0
#define HALF_MAX_TEX_COORD ( MAX_TEX_COORD / 2.0 )
#define HALF_MAX_TEX_COORD ( MAX_TEX_COORD * 0.5 )
// return the basic unshifted/unmoded texture coordinate for a lat/lon
@ -113,14 +231,12 @@ point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
double dy = fabs( tmax.y() - tmin.y() );
// cout << "dx = " << dx << " dy = " << dy << endl;
bool do_shift = false;
// Point3D mod_shift;
if ( (dx > HALF_MAX_TEX_COORD) || (dy > HALF_MAX_TEX_COORD) ) {
// structure is too big, we'll just have to shift it so that
// tmin = (0,0). This messes up subsequent texture scaling,
// but is the best we can do.
// cout << "SHIFTING" << endl;
do_shift = true;
if ( tmin.x() < 0 ) {
tmin.setx( (double)( (int)tmin.x() - 1 ) );
} else {
@ -193,7 +309,6 @@ point_list calc_tex_coords( const FGBucket& b, const point_list& geod_nodes,
t = basic_tex_coord( p, degree_width, degree_height, scale );
// cout << "second t = " << t << endl;
// if ( do_shift ) {
adjusted_t = t - tmin;
#if 0
} else {