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:
commit
b9c39fd2ab
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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; };
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user