Merge /p/flightgear-photoscenery/simgear/ branch next-photoscenery-r6 into next

https://sourceforge.net/p/flightgear/simgear/merge-requests/88/
This commit is contained in:
xDraconian 2020-12-12 23:13:37 +00:00
commit b9c39fd2ab
2 changed files with 55 additions and 97 deletions

View File

@ -209,140 +209,95 @@ namespace simgear {
}
}
Texture2DRef textureFromImage(const ImageRef& image) {
Texture2DRef texture = new osg::Texture2D(image);
texture->setWrap(osg::Texture::WrapParameter::WRAP_S, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WrapParameter::WRAP_T, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WrapParameter::WRAP_R, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
return texture;
}
OrthophotoRef Orthophoto::fromBucket(const SGBucket& bucket, const PathList& scenery_paths) {
const std::string bucket_path = bucket.gen_base_path();
for (const auto& scenery_path : scenery_paths) {
SGPath path = scenery_path / "Orthophotos" / bucket_path / std::to_string(bucket.gen_index());
path.concat(".png");
if (path.exists()) {
ImageRef image = osgDB::readRefImageFile(path.str());
SGPath dds_path = path;
dds_path.concat(".dds");
if (dds_path.exists()) {
ImageRef image = osgDB::readRefImageFile(dds_path.str());
if (!image) {
return nullptr;
}
const Texture2DRef texture = textureFromImage(image);
const OrthophotoBounds bbox = OrthophotoBounds::fromBucket(bucket);
return new Orthophoto(texture, bbox);
}
SGPath png_path = path;
png_path.concat(".png");
if (png_path.exists()) {
ImageRef image = osgDB::readRefImageFile(png_path.str());
if (!image) {
return nullptr;
}
image->flipVertical();
OrthophotoBounds bbox = OrthophotoBounds::fromBucket(bucket);
return new Orthophoto(image, bbox);
const Texture2DRef texture = textureFromImage(image);
const OrthophotoBounds bbox = OrthophotoBounds::fromBucket(bucket);
return new Orthophoto(texture, bbox);
}
}
return nullptr;
}
// Handy image cropping function from osgEarth
osg::Image* cropImage(const osg::Image* image,
double src_minx, double src_miny, double src_maxx, double src_maxy,
double &dst_minx, double &dst_miny, double &dst_maxx, double &dst_maxy) {
if ( image == 0L )
return 0L;
Orthophoto::Orthophoto(const std::vector<OrthophotoRef>& orthophotos) {
//Compute the desired cropping rectangle
int windowX = osg::clampBetween( (int)floor( (dst_minx - src_minx) / (src_maxx - src_minx) * (double)image->s()), 0, image->s()-1);
int windowY = osg::clampBetween( (int)floor( (dst_miny - src_miny) / (src_maxy - src_miny) * (double)image->t()), 0, image->t()-1);
int windowWidth = osg::clampBetween( (int)ceil( (dst_maxx - src_minx) / (src_maxx - src_minx) * (double)image->s()) - windowX, 0, image->s());
int windowHeight = osg::clampBetween( (int)ceil( (dst_maxy - src_miny) / (src_maxy - src_miny) * (double)image->t()) - windowY, 0, image->t());
if (windowX + windowWidth > image->s())
{
windowWidth = image->s() - windowX;
}
if (windowY + windowHeight > image->t())
{
windowHeight = image->t() - windowY;
}
if ((windowWidth * windowHeight) == 0)
{
return NULL;
}
//Compute the actual bounds of the area we are computing
double res_s = (src_maxx - src_minx) / (double)image->s();
double res_t = (src_maxy - src_miny) / (double)image->t();
dst_minx = src_minx + (double)windowX * res_s;
dst_miny = src_miny + (double)windowY * res_t;
dst_maxx = dst_minx + (double)windowWidth * res_s;
dst_maxy = dst_miny + (double)windowHeight * res_t;
//OE_NOTICE << "Copying from " << windowX << ", " << windowY << ", " << windowWidth << ", " << windowHeight << std::endl;
//Allocate the croppped image
osg::Image* cropped = new osg::Image;
cropped->allocateImage(windowWidth, windowHeight, image->r(), image->getPixelFormat(), image->getDataType());
cropped->setInternalTextureFormat( image->getInternalTextureFormat() );
for (int layer=0; layer<image->r(); ++layer)
{
for (int src_row = windowY, dst_row=0; dst_row < windowHeight; src_row++, dst_row++)
{
if (src_row > image->t()-1) SG_LOG(SG_OSG, SG_INFO, "HeightBroke");
const void* src_data = image->data(windowX, src_row, layer);
void* dst_data = cropped->data(0, dst_row, layer);
memcpy( dst_data, src_data, cropped->getRowSizeInBytes());
}
}
return cropped;
}
Orthophoto::Orthophoto(const std::vector<OrthophotoRef>& orthophotos, const OrthophotoBounds& needed_bbox) {
OrthophotoBounds prelim_bbox;
for (const auto& orthophoto : orthophotos) {
prelim_bbox.expandToInclude(orthophoto->getBbox());
_bbox.expandToInclude(orthophoto->getBbox());
}
const OrthophotoRef& some_orthophoto = orthophotos[0];
const ImageRef& some_image = some_orthophoto->_image;
const ImageRef& some_image = some_orthophoto->_texture->getImage();
const OrthophotoBounds& some_bbox = some_orthophoto->getBbox();
const double degs_to_pixels = some_image->s() / some_bbox.getWidth();
const int total_width = degs_to_pixels * prelim_bbox.getWidth();
const int total_height = degs_to_pixels * prelim_bbox.getHeight();
const int total_width = degs_to_pixels * _bbox.getWidth();
const int total_height = degs_to_pixels * _bbox.getHeight();
const int depth = some_image->r();
GLenum pixel_format = some_image->getPixelFormat();
GLenum data_type = some_image->getDataType();
int packing = some_image->getPacking();
ImageRef prelim_image = new osg::Image();
prelim_image->allocateImage(total_width, total_height, depth, pixel_format, data_type, packing);
ImageRef composite_image = new osg::Image();
composite_image->allocateImage(total_width, total_height, depth, pixel_format, data_type, packing);
for (const auto& orthophoto : orthophotos) {
const OrthophotoBounds& bounds = orthophoto->getBbox();
const int width = degs_to_pixels * bounds.getWidth();
const int height = degs_to_pixels * bounds.getHeight();
const int s_offset = degs_to_pixels * prelim_bbox.getLonOffset(bounds);
const int t_offset = degs_to_pixels * prelim_bbox.getLatOffset(bounds);
const int s_offset = degs_to_pixels * _bbox.getLonOffset(bounds);
const int t_offset = degs_to_pixels * _bbox.getLatOffset(bounds);
// Make a deep copy of the orthophoto's image so that we don't modify the original when scaling
ImageRef sub_image = new osg::Image(*orthophoto->_image, osg::CopyOp::DEEP_COPY_ALL);
ImageRef sub_image = new osg::Image(*orthophoto->_texture->getImage(), osg::CopyOp::DEEP_COPY_ALL);
if (sub_image->getPixelFormat() != pixel_format) {
SG_LOG(SG_OSG, SG_ALERT, "Pixel format mismatch. Not creating part of composite orthophoto.");
continue;
}
sub_image->scaleImage(width, height, depth);
prelim_image->copySubImage(s_offset, t_offset, 0, sub_image);
composite_image->copySubImage(s_offset, t_offset, 0, sub_image);
}
double x_min = prelim_bbox.getLonOffset(needed_bbox) * degs_to_pixels;
double y_min = prelim_bbox.getLatOffset(needed_bbox) * degs_to_pixels;
double x_max = x_min + needed_bbox.getWidth() * degs_to_pixels;
double y_max = y_min + needed_bbox.getHeight() * degs_to_pixels;
_image = cropImage(prelim_image, 0.0, 0.0, total_width, total_height, x_min, y_min, x_max, y_max);
_bbox = needed_bbox; // Theoretically, it would be good to adjust from how the bounds have changed from cropping
}
osg::ref_ptr<osg::Texture2D> Orthophoto::getTexture() {
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D(_image);
texture->setWrap(osg::Texture::WrapParameter::WRAP_S, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WrapParameter::WRAP_T, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WrapParameter::WRAP_R, osg::Texture::WrapMode::CLAMP_TO_EDGE);
texture->setMaxAnisotropy(SGSceneFeatures::instance()->getTextureFilter());
return texture;
_texture = textureFromImage(composite_image);
}
OrthophotoManager* OrthophotoManager::instance() {
@ -397,8 +352,10 @@ namespace simgear {
if (orthophotos.size() == 0) {
return nullptr;
} else if (orthophotos.size() == 1) {
return orthophotos[0];
} else {
return new Orthophoto(orthophotos);
}
return new Orthophoto(orthophotos, needed_bounds);
}
}

View File

@ -40,6 +40,7 @@
namespace simgear {
using ImageRef = osg::ref_ptr<osg::Image>;
using Texture2DRef = osg::ref_ptr<osg::Texture2D>;
class Orthophoto;
using OrthophotoRef = osg::ref_ptr<Orthophoto>;
@ -73,16 +74,16 @@ namespace simgear {
class Orthophoto : public osg::Referenced {
private:
ImageRef _image;
Texture2DRef _texture;
OrthophotoBounds _bbox;
public:
static OrthophotoRef fromBucket(const SGBucket& bucket, const PathList& scenery_paths);
Orthophoto(const ImageRef& image, const OrthophotoBounds& bbox) { _image = image; _bbox = bbox; }
Orthophoto(const std::vector<OrthophotoRef>& orthophotos, const OrthophotoBounds& needed_bbox);
Orthophoto(const Texture2DRef& texture, const OrthophotoBounds& bbox) { _texture = texture; _bbox = bbox; }
Orthophoto(const std::vector<OrthophotoRef>& orthophotos);
osg::ref_ptr<osg::Texture2D> getTexture();
Texture2DRef getTexture() const { return _texture; };
OrthophotoBounds getBbox() const { return _bbox; };
};