bucket: Make no bucket cross the 0 and 180 deg longitude border.
Change the bucket tiling at the poles not to cross the 0deg longitude and not to cross the 180deg longitude line. This lets some special cases disappear for the buckets as well as for the hierarchical level of detail spt loader. Also change the last degree tiles from spanning 360 degrees to 12 degrees. Before we had 8 nested rings which neither helps scenery paging nor culling. With that change the chunks are about the same order of size than any other tile. Also the tile shapes are much more friendly for culling and paging. Also in presence of the current scenery, this polar tiles contain as of today just totally broken geometry which tells me that also the scenery generation process did not like these rings for the tile shapes. The impact on the current scenery is low. With this change the polar regions do no longer load the tiles that are available in the current scenery builds. The last degree tiles are broken in this scenery version anyway. The next degree that is changed will really loose some tiles that were sensible as of today. All these areas are replaced with sea tiles by the old paging structure. So, you will have at least ground below you when you fly there. A hopefully comming soon scenery rebuild will use this new tiling structure and thus will be the first one providing closed polar caps.
This commit is contained in:
parent
7489771ad2
commit
08351e0df2
@ -224,17 +224,6 @@ std::string SGBucket::gen_base_path() const {
|
||||
|
||||
// return width of the tile in degrees
|
||||
double SGBucket::get_width() const {
|
||||
if (lon==-180 && (lat==-89 || lat==88) ) {
|
||||
/* Normally the tile at 180W in 88N and 89S
|
||||
* would cover 184W to 176W and the next
|
||||
* on the east side starts at 176W.
|
||||
* To correct, make this a special tile
|
||||
* from 180W to 176W with 4 degrees width
|
||||
* instead of the normal 8 degrees at
|
||||
* that latitude.
|
||||
*/
|
||||
return 4.0;
|
||||
}
|
||||
return sg_bucket_span( get_center_lat() );
|
||||
}
|
||||
|
||||
|
@ -57,9 +57,7 @@
|
||||
// return the horizontal tile span factor based on latitude
|
||||
static double sg_bucket_span( double l ) {
|
||||
if ( l >= 89.0 ) {
|
||||
return 360.0;
|
||||
} else if ( l >= 88.0 ) {
|
||||
return 8.0;
|
||||
return 12.0;
|
||||
} else if ( l >= 86.0 ) {
|
||||
return 4.0;
|
||||
} else if ( l >= 83.0 ) {
|
||||
@ -80,12 +78,10 @@ static double sg_bucket_span( double l ) {
|
||||
return 1.0;
|
||||
} else if ( l >= -86.0 ) {
|
||||
return 2.0;
|
||||
} else if ( l >= -88.0 ) {
|
||||
return 4.0;
|
||||
} else if ( l >= -89.0 ) {
|
||||
return 8.0;
|
||||
return 4.0;
|
||||
} else {
|
||||
return 360.0;
|
||||
return 12.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,10 @@ namespace simgear {
|
||||
|
||||
#define Elements(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
// 3*5*3 * 8 = 360
|
||||
static const unsigned _lonFactors[] = { 3, 5, 3, 2, 2, 2, /* sub degree */ 2, 2, 2 };
|
||||
// 5*3*3 * 4 = 180
|
||||
static const unsigned _latFactors[] = { 5, 3, 3, 2, 2, /* sub degree */ 2, 2, 2, 1 };
|
||||
// 2*5*3*3 * 4 = 360
|
||||
static const unsigned _lonFactors[] = { 2, 5, 3, 3, 2, 2, /* sub degree */ 2, 2, 2 };
|
||||
// 3*3*5 * 4 = 180
|
||||
static const unsigned _latFactors[] = { 3, 5, 1, 3, 2, 2, /* sub degree */ 2, 2, 2 };
|
||||
|
||||
static unsigned product(const unsigned* factors, unsigned count)
|
||||
{
|
||||
@ -50,13 +50,10 @@ static unsigned product(const unsigned* factors, unsigned count)
|
||||
/// bits which matches the SGBuckets maximum tile resolution.
|
||||
///
|
||||
/// Notable /design/ decision:
|
||||
/// * The longitude maps to the interval [0,360[ which appears to be
|
||||
/// counter productive for the file/directory names and the
|
||||
/// texture coordinates which map [-180,180[.
|
||||
/// The reason is that the buckets at 89deg longitude are 8deg
|
||||
/// latitude width. So there is a bunch of buckets that range from
|
||||
/// [176, -184[ longitude. So the wrap happens at 0deg instead
|
||||
/// of 180deg since we have a cut edge for all latitudes.
|
||||
/// * The longitude maps to the interval [-180,180[.
|
||||
/// The latitude maps to the interval [-90,90].
|
||||
/// This works now that the tiles do no longer cut
|
||||
/// neither the 180deg nor the 0deg boundary.
|
||||
/// * This is not meant to be an API class for simgear. This is
|
||||
/// just an internal tool that I would like to keep in the SPT loader.
|
||||
/// But I want to have coverage somehow tested with the usual unit
|
||||
@ -142,6 +139,20 @@ public:
|
||||
return SGBucket(_offsetToLongitudeDeg(offset), _offsetToLatitudeDeg(_offset[1]));
|
||||
}
|
||||
|
||||
BucketBox getParentBox(unsigned level) const
|
||||
{
|
||||
BucketBox box;
|
||||
unsigned plon = product(_lonFactors + level, Elements(_lonFactors) - level);
|
||||
unsigned plat = product(_latFactors + level, Elements(_latFactors) - level);
|
||||
box._offset[0] = _offset[0] - _offset[0] % plon;
|
||||
box._offset[0] = _normalizeLongitude(box._offset[0]);
|
||||
box._offset[1] = _offset[1] - _offset[1] % plat;
|
||||
box._size[0] = plon;
|
||||
box._size[1] = plat;
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
BucketBox getSubBoxHeight(unsigned j, unsigned level) const
|
||||
{
|
||||
assert(0 < level);
|
||||
@ -283,22 +294,22 @@ public:
|
||||
SGGeod p00 = _offsetToGeod(x0, y0, 0);
|
||||
SGVec3f v00 = SGVec3f::fromGeod(p00);
|
||||
SGVec3f n00 = SGQuatf::fromLonLat(p00).backTransform(SGVec3f(0, 0, -1));
|
||||
SGVec2f t00(x0*1.0/(360*8) + 0.5, y0*1.0/(180*8));
|
||||
SGVec2f t00(x0*1.0/(360*8), y0*1.0/(180*8));
|
||||
|
||||
SGGeod p10 = _offsetToGeod(x1, y0, 0);
|
||||
SGVec3f v10 = SGVec3f::fromGeod(p10);
|
||||
SGVec3f n10 = SGQuatf::fromLonLat(p10).backTransform(SGVec3f(0, 0, -1));
|
||||
SGVec2f t10(x1*1.0/(360*8) + 0.5, y0*1.0/(180*8));
|
||||
SGVec2f t10(x1*1.0/(360*8), y0*1.0/(180*8));
|
||||
|
||||
SGGeod p11 = _offsetToGeod(x1, y1, 0);
|
||||
SGVec3f v11 = SGVec3f::fromGeod(p11);
|
||||
SGVec3f n11 = SGQuatf::fromLonLat(p11).backTransform(SGVec3f(0, 0, -1));
|
||||
SGVec2f t11(x1*1.0/(360*8) + 0.5, y1*1.0/(180*8));
|
||||
SGVec2f t11(x1*1.0/(360*8), y1*1.0/(180*8));
|
||||
|
||||
SGGeod p01 = _offsetToGeod(x0, y1, 0);
|
||||
SGVec3f v01 = SGVec3f::fromGeod(p01);
|
||||
SGVec3f n01 = SGQuatf::fromLonLat(p01).backTransform(SGVec3f(0, 0, -1));
|
||||
SGVec2f t01(x0*1.0/(360*8) + 0.5, y1*1.0/(180*8));
|
||||
SGVec2f t01(x0*1.0/(360*8), y1*1.0/(180*8));
|
||||
|
||||
if (y0 != 0) {
|
||||
points[numPoints] = v00;
|
||||
@ -341,17 +352,11 @@ private:
|
||||
|
||||
static unsigned _longitudeDegToOffset(double lon)
|
||||
{
|
||||
lon = SGMiscd::normalizePeriodic(0, 360, lon);
|
||||
unsigned offset = (unsigned)(8*lon + 0.5);
|
||||
unsigned offset = (unsigned)(8*(lon + 180) + 0.5);
|
||||
return _normalizeLongitude(offset);
|
||||
}
|
||||
static double _offsetToLongitudeDeg(unsigned offset)
|
||||
{
|
||||
if (180*8 <= offset)
|
||||
return offset*0.125 - 360;
|
||||
else
|
||||
return offset*0.125;
|
||||
}
|
||||
{ return offset*0.125 - 180; }
|
||||
|
||||
static unsigned _latitudeDegToOffset(double lat)
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ ReaderWriterSPT::readNode(const std::string& fileName, const osgDB::Options* opt
|
||||
// The file name without path and without the spt extension
|
||||
std::string strippedFileName = osgDB::getStrippedName(fileName);
|
||||
if (strippedFileName == "earth")
|
||||
return createTree(BucketBox(0, -90, 360, 180), options, true);
|
||||
return createTree(BucketBox(-180, -90, 360, 180), options, true);
|
||||
|
||||
std::stringstream ss(strippedFileName);
|
||||
BucketBox bucketBox;
|
||||
|
Loading…
Reference in New Issue
Block a user