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) {
|
OrthophotoRef Orthophoto::fromBucket(const SGBucket& bucket, const PathList& scenery_paths) {
|
||||||
|
|
||||||
const std::string bucket_path = bucket.gen_base_path();
|
const std::string bucket_path = bucket.gen_base_path();
|
||||||
|
|
||||||
for (const auto& scenery_path : scenery_paths) {
|
for (const auto& scenery_path : scenery_paths) {
|
||||||
SGPath path = scenery_path / "Orthophotos" / bucket_path / std::to_string(bucket.gen_index());
|
SGPath path = scenery_path / "Orthophotos" / bucket_path / std::to_string(bucket.gen_index());
|
||||||
|
|
||||||
path.concat(".png");
|
SGPath dds_path = path;
|
||||||
if (path.exists()) {
|
dds_path.concat(".dds");
|
||||||
ImageRef image = osgDB::readRefImageFile(path.str());
|
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) {
|
if (!image) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
image->flipVertical();
|
image->flipVertical();
|
||||||
OrthophotoBounds bbox = OrthophotoBounds::fromBucket(bucket);
|
const Texture2DRef texture = textureFromImage(image);
|
||||||
return new Orthophoto(image, bbox);
|
const OrthophotoBounds bbox = OrthophotoBounds::fromBucket(bucket);
|
||||||
|
return new Orthophoto(texture, bbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handy image cropping function from osgEarth
|
Orthophoto::Orthophoto(const std::vector<OrthophotoRef>& orthophotos) {
|
||||||
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;
|
|
||||||
|
|
||||||
//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) {
|
for (const auto& orthophoto : orthophotos) {
|
||||||
prelim_bbox.expandToInclude(orthophoto->getBbox());
|
_bbox.expandToInclude(orthophoto->getBbox());
|
||||||
}
|
}
|
||||||
|
|
||||||
const OrthophotoRef& some_orthophoto = orthophotos[0];
|
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 OrthophotoBounds& some_bbox = some_orthophoto->getBbox();
|
||||||
const double degs_to_pixels = some_image->s() / some_bbox.getWidth();
|
const double degs_to_pixels = some_image->s() / some_bbox.getWidth();
|
||||||
|
|
||||||
const int total_width = degs_to_pixels * prelim_bbox.getWidth();
|
const int total_width = degs_to_pixels * _bbox.getWidth();
|
||||||
const int total_height = degs_to_pixels * prelim_bbox.getHeight();
|
const int total_height = degs_to_pixels * _bbox.getHeight();
|
||||||
|
|
||||||
const int depth = some_image->r();
|
const int depth = some_image->r();
|
||||||
GLenum pixel_format = some_image->getPixelFormat();
|
GLenum pixel_format = some_image->getPixelFormat();
|
||||||
GLenum data_type = some_image->getDataType();
|
GLenum data_type = some_image->getDataType();
|
||||||
int packing = some_image->getPacking();
|
int packing = some_image->getPacking();
|
||||||
|
|
||||||
ImageRef prelim_image = new osg::Image();
|
ImageRef composite_image = new osg::Image();
|
||||||
prelim_image->allocateImage(total_width, total_height, depth, pixel_format, data_type, packing);
|
composite_image->allocateImage(total_width, total_height, depth, pixel_format, data_type, packing);
|
||||||
|
|
||||||
for (const auto& orthophoto : orthophotos) {
|
for (const auto& orthophoto : orthophotos) {
|
||||||
|
|
||||||
const OrthophotoBounds& bounds = orthophoto->getBbox();
|
const OrthophotoBounds& bounds = orthophoto->getBbox();
|
||||||
const int width = degs_to_pixels * bounds.getWidth();
|
const int width = degs_to_pixels * bounds.getWidth();
|
||||||
const int height = degs_to_pixels * bounds.getHeight();
|
const int height = degs_to_pixels * bounds.getHeight();
|
||||||
const int s_offset = degs_to_pixels * prelim_bbox.getLonOffset(bounds);
|
const int s_offset = degs_to_pixels * _bbox.getLonOffset(bounds);
|
||||||
const int t_offset = degs_to_pixels * prelim_bbox.getLatOffset(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
|
// 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);
|
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;
|
_texture = textureFromImage(composite_image);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OrthophotoManager* OrthophotoManager::instance() {
|
OrthophotoManager* OrthophotoManager::instance() {
|
||||||
@ -397,8 +352,10 @@ namespace simgear {
|
|||||||
|
|
||||||
if (orthophotos.size() == 0) {
|
if (orthophotos.size() == 0) {
|
||||||
return nullptr;
|
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 {
|
namespace simgear {
|
||||||
|
|
||||||
using ImageRef = osg::ref_ptr<osg::Image>;
|
using ImageRef = osg::ref_ptr<osg::Image>;
|
||||||
|
using Texture2DRef = osg::ref_ptr<osg::Texture2D>;
|
||||||
|
|
||||||
class Orthophoto;
|
class Orthophoto;
|
||||||
using OrthophotoRef = osg::ref_ptr<Orthophoto>;
|
using OrthophotoRef = osg::ref_ptr<Orthophoto>;
|
||||||
@ -73,16 +74,16 @@ namespace simgear {
|
|||||||
|
|
||||||
class Orthophoto : public osg::Referenced {
|
class Orthophoto : public osg::Referenced {
|
||||||
private:
|
private:
|
||||||
ImageRef _image;
|
Texture2DRef _texture;
|
||||||
OrthophotoBounds _bbox;
|
OrthophotoBounds _bbox;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static OrthophotoRef fromBucket(const SGBucket& bucket, const PathList& scenery_paths);
|
static OrthophotoRef fromBucket(const SGBucket& bucket, const PathList& scenery_paths);
|
||||||
|
|
||||||
Orthophoto(const ImageRef& image, const OrthophotoBounds& bbox) { _image = image; _bbox = bbox; }
|
Orthophoto(const Texture2DRef& texture, const OrthophotoBounds& bbox) { _texture = texture; _bbox = bbox; }
|
||||||
Orthophoto(const std::vector<OrthophotoRef>& orthophotos, const OrthophotoBounds& needed_bbox);
|
Orthophoto(const std::vector<OrthophotoRef>& orthophotos);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Texture2D> getTexture();
|
Texture2DRef getTexture() const { return _texture; };
|
||||||
OrthophotoBounds getBbox() const { return _bbox; };
|
OrthophotoBounds getBbox() const { return _bbox; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user