Ogre Version: : 13.4
Operating System: : Linux Fedora 35
Render System: :OpenGL 3+
I have an application with a main window based on ApplicationContextQt that is working fine.
At some point, i want to create a top down image of the scene without changing the current context (point of view, viewport...)
=> for that purpose i want to temporarly create a texture i'll be rendering into and then do what i need to with the resulting image (export, process...).
I ended up with the following code :
Code: Select all
void capture(
Ogre::SceneManager* scene_manager,
const std::string& id,
double x,
double y,
double z,
double head,
double pitch,
double roll,
double size_y,
double size_z,
double near_clip,
double far_clip,
double scale_mpp,
Ogre::PixelFormat pixel_format,
const Ogre::ColourValue& clear_color,
std::function<void(const Ogre::PixelBox&)> use_data)
{
auto* cam = scene_manager->createCamera(fmt::format("{}_camera", id));
cam->setProjectionType(Ogre::ProjectionType::PT_ORTHOGRAPHIC);
cam->setNearClipDistance(near_clip);
cam->setFarClipDistance(far_clip);
cam->setAutoAspectRatio(false);
cam->setOrthoWindow(size_y, size_z);
const auto tex_width = int(size_y / scale_mpp);
const auto tex_height = int(size_z / scale_mpp);
auto* node = scene_manager->getRootSceneNode()->createChildSceneNode();
node->attachObject(cam);
// place camera in world RD-convetion
// note that ogre camera look towards -Z, while RD-conv is to gaze along X
node->setPosition(SimOgreCommon::GeoHelpers::rdXYZ_to_ogre(x, y, z));
node->setOrientation(
SimOgreCommon::GeoHelpers::rdHPR_to_ogre(head, pitch, roll) *
Ogre::Quaternion{-Ogre::Degree(90.0), Ogre::Vector3::UNIT_Y});
Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().createManual(
fmt::format("{}_tex", id),
Resource3dDatabase::getComputationDefault(),
Ogre::TEX_TYPE_2D,
tex_width,
tex_height,
0,
pixel_format,
Ogre::TU_RENDERTARGET);
Ogre::HardwarePixelBufferSharedPtr buffer = tex->getBuffer();
auto* renderer = buffer->getRenderTarget();
auto* viewport = renderer->addViewport(cam);
viewport->setAutoUpdated(false);
viewport->setClearEveryFrame(true);
viewport->setBackgroundColour(clear_color);
viewport->setOverlaysEnabled(false);
viewport->setShadowsEnabled(false);
// render
viewport->update();
// transfer buffer from gpu to cpu: lock buffer to read into it
{
buffer->lock(Ogre::HardwareBuffer::LockOptions::HBL_READ_ONLY);
const Ogre::PixelBox& pixel_box = buffer->getCurrentLock();
use_data(pixel_box);
buffer->unlock();
}
// clean up
scene_manager->getRootSceneNode()->removeAndDestroyChild(node);
scene_manager->destroyCamera(cam);
}
note:
the detail of following methods is not relevant here:
'SimOgreCommon::GeoHelpers::rdXYZ_to_ogre' -> returns a vector3
'SimOgreCommon::GeoHelpers::rdHPR_to_ogre' -> returns a quaternion
'Resource3dDatabase::getComputationDefault' -> returns a string that refers to a resource group that was previously created
As an example, I use following lambda as 'use_data' function:
Code: Select all
[&](const Ogre::PixelBox& pixel_box) {
QImage img{
static_cast<Ogre::uint8*>(pixel_box.data),
int(pixel_box.getWidth()),
int(pixel_box.getHeight()),
QImage::Format_ARGB32};
img.save(QString::fromStdString(filepath), nullptr);
});
This method is ok in term of generating the data i want.
My concern is that i can't call my 'capture' method twice with the same id :
The second time i get following exception :
Code: Select all
terminate called after throwing an instance of 'Ogre::ItemIdentityException'
what(): ItemIdentityException: Texture with the name agent_capture_tex already exists. in ResourceManager::add at /xxxxxxxx/ogre-13.4.0/OgreMain/src/OgreResourceManager.cpp (line 152)
To my understanding the texture is not deleted when the "capure function" ends. correct?
What shall i do to release it?
I tried to Ogre::TextureManager::getSingleton().remove(fmt::format("{}_tex", id));
at the end of "capture function" but i still get the exception.
Of course i can have specific id for ech call to the "capture function" but i'm concerned by the fact that the texture is not released while i don't need it any longer.