WS30: Initial photoscenery work
Hack for hackathon
This commit is contained in:
parent
6ea99e43f1
commit
7a7b26e75d
@ -230,6 +230,53 @@ std::string SGBucket::gen_vpb_base() const {
|
|||||||
return raw_path;
|
return raw_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SGBucket::gen_vpb_subtile(int level, int x, int y) const {
|
||||||
|
// long int index;
|
||||||
|
int top_lon, top_lat, main_lon, main_lat;
|
||||||
|
char hem, pole;
|
||||||
|
char raw_path[256];
|
||||||
|
|
||||||
|
top_lon = lon / 10;
|
||||||
|
main_lon = lon;
|
||||||
|
if ( (lon < 0) && (top_lon * 10 != lon) ) {
|
||||||
|
top_lon -= 1;
|
||||||
|
}
|
||||||
|
top_lon *= 10;
|
||||||
|
if ( top_lon >= 0 ) {
|
||||||
|
hem = 'e';
|
||||||
|
} else {
|
||||||
|
hem = 'w';
|
||||||
|
top_lon *= -1;
|
||||||
|
}
|
||||||
|
if ( main_lon < 0 ) {
|
||||||
|
main_lon *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
top_lat = lat / 10;
|
||||||
|
main_lat = lat;
|
||||||
|
if ( (lat < 0) && (top_lat * 10 != lat) ) {
|
||||||
|
top_lat -= 1;
|
||||||
|
}
|
||||||
|
top_lat *= 10;
|
||||||
|
if ( top_lat >= 0 ) {
|
||||||
|
pole = 'n';
|
||||||
|
} else {
|
||||||
|
pole = 's';
|
||||||
|
top_lat *= -1;
|
||||||
|
}
|
||||||
|
if ( main_lat < 0 ) {
|
||||||
|
main_lat *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
::snprintf(raw_path, 256, "%c%03d%c%02d/%c%03d%c%02d/ws_%c%03d%c%02d_root_L0_X0_Y0/ws_%c%03d%c%02d_L%d_X%d_Y%d_subtile",
|
||||||
|
hem, top_lon, pole, top_lat,
|
||||||
|
hem, main_lon, pole, main_lat,
|
||||||
|
hem, main_lon, pole, main_lat,
|
||||||
|
hem, main_lon, pole, main_lat,
|
||||||
|
level, x, y);
|
||||||
|
|
||||||
|
return raw_path;
|
||||||
|
}
|
||||||
// Build the path name for this bucket
|
// Build the path name for this bucket
|
||||||
std::string SGBucket::gen_base_path() const {
|
std::string SGBucket::gen_base_path() const {
|
||||||
// long int index;
|
// long int index;
|
||||||
|
@ -215,6 +215,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
std::string gen_vpb_base() const;
|
std::string gen_vpb_base() const;
|
||||||
std::string gen_vpb_base_alt() const;
|
std::string gen_vpb_base_alt() const;
|
||||||
|
std::string gen_vpb_subtile(int level, int x, int y) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the center lon of a tile.
|
* @return the center lon of a tile.
|
||||||
|
@ -1027,9 +1027,9 @@ struct OSGOptimizePolicy : public OptimizeModelPolicy {
|
|||||||
// Top level. This is likely to have the default GeometryTechnique already assigned which we need to replace with our own
|
// Top level. This is likely to have the default GeometryTechnique already assigned which we need to replace with our own
|
||||||
terrain->setSampleRatio(features->getVPBSampleRatio());
|
terrain->setSampleRatio(features->getVPBSampleRatio());
|
||||||
terrain->setVerticalScale(features->getVPBVerticalScale());
|
terrain->setVerticalScale(features->getVPBVerticalScale());
|
||||||
terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt));
|
terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt, fileName));
|
||||||
if (terrainTile != NULL) {
|
if (terrainTile != NULL) {
|
||||||
terrainTile->setTerrainTechnique(new VPBTechnique(sgopt));
|
terrainTile->setTerrainTechnique(new VPBTechnique(sgopt, fileName));
|
||||||
terrainTile->setDirty(true);
|
terrainTile->setDirty(true);
|
||||||
} else {
|
} else {
|
||||||
SG_LOG(SG_TERRAIN, SG_ALERT, "VPB TerrainTile not found");
|
SG_LOG(SG_TERRAIN, SG_ALERT, "VPB TerrainTile not found");
|
||||||
@ -1039,7 +1039,7 @@ struct OSGOptimizePolicy : public OptimizeModelPolicy {
|
|||||||
terrain = new osgTerrain::Terrain;
|
terrain = new osgTerrain::Terrain;
|
||||||
terrain->setSampleRatio(features->getVPBSampleRatio());
|
terrain->setSampleRatio(features->getVPBSampleRatio());
|
||||||
terrain->setVerticalScale(features->getVPBVerticalScale());
|
terrain->setVerticalScale(features->getVPBVerticalScale());
|
||||||
terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt));
|
terrain->setTerrainTechniquePrototype(new VPBTechnique(sgopt, fileName));
|
||||||
|
|
||||||
// if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it.
|
// if CoordinateSystemNode is present copy it's contents into the Terrain, and discard it.
|
||||||
osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(optimized.get());
|
osg::CoordinateSystemNode* csn = findTopMostNodeOfType<osg::CoordinateSystemNode>(optimized.get());
|
||||||
|
@ -56,7 +56,8 @@
|
|||||||
using namespace osgTerrain;
|
using namespace osgTerrain;
|
||||||
using namespace simgear;
|
using namespace simgear;
|
||||||
|
|
||||||
VPBTechnique::VPBTechnique()
|
VPBTechnique::VPBTechnique():
|
||||||
|
_fileName("")
|
||||||
{
|
{
|
||||||
setFilterBias(0);
|
setFilterBias(0);
|
||||||
setFilterWidth(0.1);
|
setFilterWidth(0.1);
|
||||||
@ -64,17 +65,20 @@ VPBTechnique::VPBTechnique()
|
|||||||
_randomObjectsConstraintGroup = new osg::Group();
|
_randomObjectsConstraintGroup = new osg::Group();
|
||||||
}
|
}
|
||||||
|
|
||||||
VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options)
|
VPBTechnique::VPBTechnique(const SGReaderWriterOptions* options, const string& fileName):
|
||||||
|
_fileName(fileName)
|
||||||
{
|
{
|
||||||
setFilterBias(0);
|
setFilterBias(0);
|
||||||
setFilterWidth(0.1);
|
setFilterWidth(0.1);
|
||||||
setFilterMatrixAs(GAUSSIAN);
|
setFilterMatrixAs(GAUSSIAN);
|
||||||
setOptions(options);
|
setOptions(options);
|
||||||
_randomObjectsConstraintGroup = new osg::Group();
|
_randomObjectsConstraintGroup = new osg::Group();
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "VPBTechnique for " << _fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
VPBTechnique::VPBTechnique(const VPBTechnique& gt,const osg::CopyOp& copyop):
|
VPBTechnique::VPBTechnique(const VPBTechnique& gt,const osg::CopyOp& copyop):
|
||||||
TerrainTechnique(gt,copyop)
|
TerrainTechnique(gt,copyop),
|
||||||
|
_fileName(gt._fileName)
|
||||||
{
|
{
|
||||||
setFilterBias(gt._filterBias);
|
setFilterBias(gt._filterBias);
|
||||||
setFilterWidth(gt._filterWidth);
|
setFilterWidth(gt._filterWidth);
|
||||||
@ -1279,55 +1283,91 @@ void VPBTechnique::generateGeometry(BufferData& buffer, Locator* masterLocator,
|
|||||||
|
|
||||||
void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator)
|
void VPBTechnique::applyColorLayers(BufferData& buffer, Locator* masterLocator)
|
||||||
{
|
{
|
||||||
SGMaterialLibPtr matlib = _options->getMaterialLib();
|
|
||||||
if (!matlib) return;
|
|
||||||
|
|
||||||
osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
|
const SGPropertyNode* propertyNode = _options->getPropertyNode().get();
|
||||||
if (!colorLayer) return;
|
bool photoScenery = false;
|
||||||
|
|
||||||
osg::Image* image = colorLayer->getImage();
|
if (propertyNode) {
|
||||||
if (!image || ! image->valid()) return;
|
photoScenery = _options->getPropertyNode()->getBoolValue("/sim/rendering/photoscenery/enabled");
|
||||||
|
|
||||||
// First time generating this texture, so process to change landclass IDs to texure indexes.
|
|
||||||
SGPropertyNode_ptr landEffectProp;
|
|
||||||
|
|
||||||
const SGGeod loc = computeCenterGeod(buffer, masterLocator);
|
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "Applying VPB material " << loc);
|
|
||||||
|
|
||||||
SGMaterialCache::Atlas atlas = matlib->generateMatCache(loc, _options)->getAtlas();
|
|
||||||
SGMaterialCache::AtlasIndex atlasIndex = atlas.index;
|
|
||||||
|
|
||||||
// Set the "g" color channel to an index into the atlas index.
|
|
||||||
for (unsigned int s = 0; s < (unsigned int) image->s(); s++) {
|
|
||||||
for (unsigned int t = 0; t < (unsigned int) image->t(); t++) {
|
|
||||||
osg::Vec4d c = image->getColor(s, t);
|
|
||||||
int i = int(round(c.x() * 255.0));
|
|
||||||
c.set(c.x(), (double) (atlasIndex[i] / 255.0), c.z(), c.w() );
|
|
||||||
image->setColor(c, s, t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SG_LOG(SG_TERRAIN, SG_DEBUG, "VPB Image level:" << _terrainTile->getTileID().level << " " << image->s() << "x" << image->t() << " mipmaps:" << image->getNumMipmapLevels() << " format:" << image->getInternalTextureFormat());
|
if (photoScenery) {
|
||||||
|
|
||||||
osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D;
|
// Firstly, we need to work out the texture file we want to load. Fortunately this follows the same
|
||||||
texture2D->setImage(image);
|
// naming convention as the VPB scenery itself.
|
||||||
texture2D->setMaxAnisotropy(16.0f);
|
auto tileID = _terrainTile->getTileID();
|
||||||
texture2D->setResizeNonPowerOfTwoHint(false);
|
SG_LOG(SG_TERRAIN, SG_ALERT, "Using Photoscenery for " << tileID.level << " X" << tileID.x << " Y" << tileID.y);
|
||||||
|
|
||||||
// Use mipmaps only in the minimization case because on magnification this results
|
const osg::Vec3d world = buffer._transform->getMatrix().getTrans();
|
||||||
// in bad interpolation of boundaries between landclasses
|
const SGGeod loc = SGGeod::fromCart(toSG(world));
|
||||||
texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_NEAREST);
|
const SGBucket bucket = SGBucket(loc);
|
||||||
texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
|
|
||||||
|
|
||||||
texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
|
// Bit of a hack - we assume the Orthophotos are in the same FG_SCENERY top level as the .osgb tiles.
|
||||||
texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
|
string base = _fileName.substr(0, _fileName.find("vpb"));
|
||||||
|
SGPath orthotexture = SGPath(base);
|
||||||
|
orthotexture.append("Orthophotos");
|
||||||
|
orthotexture.append(bucket.gen_vpb_subtile(tileID.level, tileID.x, tileID.y) + ".dds");
|
||||||
|
SG_LOG(SG_TERRAIN, SG_ALERT, "Using " << orthotexture);
|
||||||
|
|
||||||
osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet();
|
if (orthotexture.exists()) {
|
||||||
stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON);
|
osg::Texture2D* texture = SGLoadTexture2D(SGPath(orthotexture), _options, false, false);
|
||||||
stateset->setTextureAttributeAndModes(1, atlas.image, osg::StateAttribute::ON);
|
osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet();
|
||||||
stateset->setTextureAttributeAndModes(2, atlas.dimensions, osg::StateAttribute::ON);
|
stateset->setTextureAttributeAndModes(0, texture);
|
||||||
stateset->setTextureAttributeAndModes(3, atlas.diffuse, osg::StateAttribute::ON);
|
} else {
|
||||||
stateset->setTextureAttributeAndModes(4, atlas.specular, osg::StateAttribute::ON);
|
SG_LOG(SG_TERRAIN, SG_ALERT, "Unable to find " << orthotexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
SGMaterialLibPtr matlib = _options->getMaterialLib();
|
||||||
|
if (!matlib) return;
|
||||||
|
|
||||||
|
osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0);
|
||||||
|
if (!colorLayer) return;
|
||||||
|
|
||||||
|
osg::Image* image = colorLayer->getImage();
|
||||||
|
if (!image || ! image->valid()) return;
|
||||||
|
|
||||||
|
// First time generating this texture, so process to change landclass IDs to texure indexes.
|
||||||
|
SGPropertyNode_ptr landEffectProp;
|
||||||
|
|
||||||
|
const SGGeod loc = computeCenterGeod(buffer, masterLocator);
|
||||||
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "Applying VPB material " << loc);
|
||||||
|
|
||||||
|
SGMaterialCache::Atlas atlas = matlib->generateMatCache(loc, _options)->getAtlas();
|
||||||
|
SGMaterialCache::AtlasIndex atlasIndex = atlas.index;
|
||||||
|
|
||||||
|
// Set the "g" color channel to an index into the atlas index.
|
||||||
|
for (unsigned int s = 0; s < (unsigned int) image->s(); s++) {
|
||||||
|
for (unsigned int t = 0; t < (unsigned int) image->t(); t++) {
|
||||||
|
osg::Vec4d c = image->getColor(s, t);
|
||||||
|
int i = int(round(c.x() * 255.0));
|
||||||
|
c.set(c.x(), (double) (atlasIndex[i] / 255.0), c.z(), c.w() );
|
||||||
|
image->setColor(c, s, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SG_LOG(SG_TERRAIN, SG_DEBUG, "VPB Image level:" << _terrainTile->getTileID().level << " " << image->s() << "x" << image->t() << " mipmaps:" << image->getNumMipmapLevels() << " format:" << image->getInternalTextureFormat());
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D;
|
||||||
|
texture2D->setImage(image);
|
||||||
|
texture2D->setMaxAnisotropy(16.0f);
|
||||||
|
texture2D->setResizeNonPowerOfTwoHint(false);
|
||||||
|
|
||||||
|
// Use mipmaps only in the minimization case because on magnification this results
|
||||||
|
// in bad interpolation of boundaries between landclasses
|
||||||
|
texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_NEAREST);
|
||||||
|
texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
|
||||||
|
|
||||||
|
texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
|
||||||
|
texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
osg::StateSet* stateset = buffer._landGeode->getOrCreateStateSet();
|
||||||
|
stateset->setTextureAttributeAndModes(0, texture2D, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttributeAndModes(1, atlas.image, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttributeAndModes(2, atlas.dimensions, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttributeAndModes(3, atlas.diffuse, osg::StateAttribute::ON);
|
||||||
|
stateset->setTextureAttributeAndModes(4, atlas.specular, osg::StateAttribute::ON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double VPBTechnique::det2(const osg::Vec2d a, const osg::Vec2d b)
|
double VPBTechnique::det2(const osg::Vec2d a, const osg::Vec2d b)
|
||||||
|
@ -45,7 +45,7 @@ class VPBTechnique : public TerrainTechnique
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
VPBTechnique();
|
VPBTechnique();
|
||||||
VPBTechnique(const SGReaderWriterOptions* options);
|
VPBTechnique(const SGReaderWriterOptions* options, const string& fileName);
|
||||||
|
|
||||||
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
|
||||||
VPBTechnique(const VPBTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
|
VPBTechnique(const VPBTechnique&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
|
||||||
@ -199,6 +199,7 @@ class VPBTechnique : public TerrainTechnique
|
|||||||
osg::Matrix3 _filterMatrix;
|
osg::Matrix3 _filterMatrix;
|
||||||
osg::ref_ptr<osg::Uniform> _filterMatrixUniform;
|
osg::ref_ptr<osg::Uniform> _filterMatrixUniform;
|
||||||
osg::ref_ptr<SGReaderWriterOptions> _options;
|
osg::ref_ptr<SGReaderWriterOptions> _options;
|
||||||
|
const string& _fileName;
|
||||||
osg::ref_ptr<osg::Group> _randomObjectsConstraintGroup;
|
osg::ref_ptr<osg::Group> _randomObjectsConstraintGroup;
|
||||||
|
|
||||||
inline static osg::ref_ptr<osg::Group> _elevationConstraintGroup = new osg::Group();
|
inline static osg::ref_ptr<osg::Group> _elevationConstraintGroup = new osg::Group();
|
||||||
|
Loading…
Reference in New Issue
Block a user