Write savegame screenshot

c++11
scrawl 10 years ago
parent 24551c7bab
commit 2a85a22dba

@ -23,6 +23,7 @@ namespace osg
{
class Vec3f;
class Quat;
class Image;
}
namespace Loading
@ -438,7 +439,7 @@ namespace MWBase
virtual void reattachPlayerCamera() = 0;
/// \todo this does not belong here
virtual void screenshot (Ogre::Image& image, int w, int h) = 0;
virtual void screenshot (osg::Image* image, int w, int h) = 0;
/// Find default position inside exterior cell specified by name
/// \return false if exterior with given name not exists, true otherwise

@ -379,6 +379,65 @@ namespace MWRender
mWater->setHeight(height);
}
class NotifyDrawCompletedCallback : public osg::Camera::DrawCallback
{
public:
virtual void operator () (osg::RenderInfo& renderInfo) const
{
mCondition.signal();
}
mutable OpenThreads::Condition mCondition;
};
void RenderingManager::screenshot(osg::Image *image, int w, int h)
{
int oldCullMask = mViewer->getCamera()->getCullMask();
mViewer->getCamera()->setCullMask(oldCullMask & (~Mask_GUI));
osg::ref_ptr<osg::Camera> rttCamera (new osg::Camera);
rttCamera->setNodeMask(Mask_RenderToTexture);
rttCamera->attach(osg::Camera::COLOR_BUFFER, image);
rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT);
rttCamera->setClearColor(mViewer->getCamera()->getClearColor());
rttCamera->setClearMask(mViewer->getCamera()->getClearMask());
rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance);
rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix());
rttCamera->setViewport(0, 0, w, h);
rttCamera->setGraphicsContext(mViewer->getCamera()->getGraphicsContext());
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
texture->setInternalFormat(GL_RGB);
texture->setTextureSize(w, h);
texture->setResizeNonPowerOfTwoHint(false);
rttCamera->attach(osg::Camera::COLOR_BUFFER, texture);
image->setDataType(GL_UNSIGNED_BYTE);
image->setPixelFormat(texture->getInternalFormat());
rttCamera->addChild(mLightRoot);
mRootNode->addChild(rttCamera);
mViewer->frame();
// The draw needs to complete before we can copy back our image.
osg::ref_ptr<NotifyDrawCompletedCallback> callback (new NotifyDrawCompletedCallback);
rttCamera->setFinalDrawCallback(callback);
OpenThreads::Mutex m;
m.lock();
callback->mCondition.wait(&m);
m.unlock();
rttCamera->removeChildren(0, rttCamera->getNumChildren());
rttCamera->setGraphicsContext(NULL);
mRootNode->removeChild(rttCamera);
mViewer->getCamera()->setCullMask(oldCullMask);
}
void RenderingManager::getCameraToViewportRay(float nX, float nY, osg::Vec3f &origin, osg::Vec3f &dest)
{
osg::Matrix viewProj = mViewer->getCamera()->getViewMatrix() * mViewer->getCamera()->getProjectionMatrix();

@ -82,6 +82,9 @@ namespace MWRender
void setWaterEnabled(bool enabled);
void setWaterHeight(float level);
/// Take a screenshot of w*h onto the given image, not including the GUI.
void screenshot(osg::Image* image, int w, int h);
/// Return the object under the mouse cursor / crosshair position, given by nX and nY normalized screen coordinates,
/// where (0,0) is the top left corner.
MWWorld::Ptr getFacedObject(const float nX, const float nY, float maxDistance, bool ignorePlayer);

@ -10,7 +10,9 @@
#include <components/settings/settings.hpp>
#include <OgreImage.h>
#include <osg/Image>
#include <osgDB/Registry>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp>
@ -179,14 +181,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot
profile.mTimePlayed = mTimePlayed;
profile.mDescription = description;
/*
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
Ogre::Image screenshot;
world.screenshot(screenshot, screenshotW, screenshotH);
Ogre::DataStreamPtr encoded = screenshot.encode("jpg");
profile.mScreenshot.resize(encoded->size());
encoded->read(&profile.mScreenshot[0], encoded->size());
*/
writeScreenshot(profile.mScreenshot);
if (!slot)
slot = getCurrentCharacter()->createSlot (profile);
@ -572,3 +567,31 @@ bool MWState::StateManager::verifyProfile(const ESM::SavedGame& profile) const
}
return true;
}
void MWState::StateManager::writeScreenshot(std::vector<char> &imageData) const
{
int screenshotW = 259*2, screenshotH = 133*2; // *2 to get some nice antialiasing
osg::ref_ptr<osg::Image> screenshot (new osg::Image);
MWBase::Environment::get().getWorld()->screenshot(screenshot.get(), screenshotW, screenshotH);
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg");
if (!readerwriter)
{
std::cerr << "Unable to write screenshot, can't find a jpg ReaderWriter" << std::endl;
return;
}
std::ostringstream ostream;
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*screenshot, ostream);
if (!result.success())
{
std::cerr << "Unable to write screenshot: " << result.message() << std::endl;
return;
}
std::string data = ostream.str();
imageData = std::vector<char>(data.begin(), data.end());
}

@ -25,6 +25,8 @@ namespace MWState
bool verifyProfile (const ESM::SavedGame& profile) const;
void writeScreenshot (std::vector<char>& imageData) const;
std::map<int, int> buildContentFileIndexMap (const ESM::ESMReader& reader) const;
public:

@ -2128,9 +2128,9 @@ namespace MWWorld
return mRendering->getAnimation(ptr);
}
void World::screenshot(Ogre::Image &image, int w, int h)
void World::screenshot(osg::Image* image, int w, int h)
{
//mRendering->screenshot(image, w, h);
mRendering->screenshot(image, w, h);
}
void World::activateDoor(const MWWorld::Ptr& door)

@ -524,7 +524,7 @@ namespace MWWorld
virtual void reattachPlayerCamera();
/// \todo this does not belong here
virtual void screenshot (Ogre::Image& image, int w, int h);
virtual void screenshot (osg::Image* image, int w, int h);
/// Find center of exterior cell above land surface
/// \return false if exterior with given name not exists, true otherwise

Loading…
Cancel
Save