From 8f321140256d835adb0d0779eedef732b4cda1d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 9 Nov 2017 18:26:27 +0100 Subject: [PATCH] segfault fix --- apps/openmw/engine.cpp | 9 ++-- apps/openmw/engine.hpp | 3 +- apps/openmw/mwinput/inputmanagerimp.cpp | 26 ++-------- apps/openmw/mwinput/inputmanagerimp.hpp | 4 +- apps/openmw/mwrender/renderingmanager.cpp | 62 +++++++++++++++-------- apps/openmw/mwrender/renderingmanager.hpp | 2 +- 6 files changed, 56 insertions(+), 50 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 3e5ab7ce6..499158fd4 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -484,7 +484,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) else gameControllerdb = ""; //if it doesn't exist, pass in an empty string - MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, keybinderUser, keybinderUserExists, gameControllerdb, mGrab); + MWInput::InputManager* input = new MWInput::InputManager (mWindow, mViewer, mScreenCaptureHandler, mScreenCaptureOperation, keybinderUser, keybinderUserExists, gameControllerdb, mGrab); mEnvironment.setInputManager (input); std::string myguiResources = (mResDir / "mygui").string(); @@ -641,8 +641,11 @@ void OMW::Engine::go() settingspath = loadSettings (settings); - mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(), - Settings::Manager::getString("screenshot format", "General"))); + mScreenCaptureOperation = new WriteScreenshotToFileOperation(mCfgMgr.getUserDataPath().string(), + Settings::Manager::getString("screenshot format", "General")); + + mScreenCaptureHandler = new osgViewer::ScreenCaptureHandler(mScreenCaptureOperation); + mViewer->addEventHandler(mScreenCaptureHandler); mEnvironment.setFrameRateLimit(Settings::Manager::getFloat("framerate limit", "Video")); diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index bf144bfed..3cbd4b6e7 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -7,7 +7,7 @@ #include #include - +#include #include "mwbase/environment.hpp" @@ -82,6 +82,7 @@ namespace OMW boost::filesystem::path mResDir; osg::ref_ptr mViewer; osg::ref_ptr mScreenCaptureHandler; + osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation; std::string mCellName; std::vector mContentFiles; bool mSkipMenu; diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index cd2e8408b..e1c85744e 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -37,12 +37,14 @@ namespace MWInput SDL_Window* window, osg::ref_ptr viewer, osg::ref_ptr screenCaptureHandler, + osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation, const std::string& userFile, bool userFileExists, const std::string& controllerBindingsFile, bool grab) : mWindow(window) , mWindowVisible(true) , mViewer(viewer) , mScreenCaptureHandler(screenCaptureHandler) + , mScreenCaptureOperation(screenCaptureOperation) , mJoystickLastUsed(false) , mPlayer(NULL) , mInputManager(NULL) @@ -1027,29 +1029,7 @@ namespace MWInput { osg::ref_ptr screenshot (new osg::Image); MWBase::Environment::get().getWorld()->screenshot360(screenshot.get()); -(*mScreenCaptureHandler->getCaptureOperation()) (*(screenshot.get()),0); - -/* - osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("jpg"); - - if (!readerwriter) - { - std::cerr << "Error: Unable to write 360 degree screenshot, can't find a jpg ReaderWriter" << std::endl; - return; - } - - std::ofstream outfile; - outfile.open("test.jpg"); - - osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*screenshot, outfile); - - if (!result.success()) - { - outfile << "Error: Unable to write screenshot: " << result.message() << " code " << result.status() << std::endl; - return; - } - - outfile.close(); */ + (*mScreenCaptureOperation) (*(screenshot.get()),0); } void InputManager::toggleInventory() diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 07b43d0ac..5d3e88eab 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -4,6 +4,7 @@ #include "../mwgui/mode.hpp" #include +#include #include #include @@ -14,7 +15,6 @@ #include "../mwbase/inputmanager.hpp" - namespace MWWorld { class Player; @@ -74,6 +74,7 @@ namespace MWInput SDL_Window* window, osg::ref_ptr viewer, osg::ref_ptr screenCaptureHandler, + osgViewer::ScreenCaptureHandler::CaptureOperation *screenCaptureOperation, const std::string& userFile, bool userFileExists, const std::string& controllerBindingsFile, bool grab); @@ -158,6 +159,7 @@ namespace MWInput bool mWindowVisible; osg::ref_ptr mViewer; osg::ref_ptr mScreenCaptureHandler; + osgViewer::ScreenCaptureHandler::CaptureOperation *mScreenCaptureOperation; bool mJoystickLastUsed; MWWorld::Player* mPlayer; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 4ea602f3f..a08e7a0a2 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -625,6 +625,13 @@ namespace MWRender class SphericalScreenshot { public: + typedef enum + { + MAPPING_CYLINDRICAL = 0, + MAPPING_SPHERICAL, + MAPPING_SMALL_PLANET + } SphericalScreenshotMapping; + SphericalScreenshot(int size) { mSize = size; @@ -638,13 +645,26 @@ namespace MWRender return mImages[index].get(); } - void create(osg::Image *dest, int w, int h) + void create(osg::Image *dest, int w, int h, SphericalScreenshotMapping mapping) { dest->allocateImage(w,h,mImages[0]->r(),mImages[0]->getPixelFormat(),mImages[0]->getDataType()); for (int j = 0; j < h; ++j) for (int i = 0; i < w; ++i) - dest->setColor(getColorByDirection(sphericalCoords(i / ((float) w), j / ((float) h))),i,j); + { + osg::Vec3d coords; + osg::Vec2d normalizedXY = osg::Vec2d(i / ((float) w), j / ((float) h)); + + switch (mapping) + { + case MAPPING_CYLINDRICAL: coords = cylindricalCoords(normalizedXY.x(),normalizedXY.y()); break; + case MAPPING_SPHERICAL: coords = sphericalCoords(normalizedXY.x(),normalizedXY.y()); break; + case MAPPING_SMALL_PLANET: coords = smallPlanetCoords(normalizedXY.x(),normalizedXY.y()); break; + default: break; + } + + dest->setColor(getColorByDirection(coords),i,j); + } } osg::Vec3d cylindricalCoords(double x, double y) @@ -682,18 +702,18 @@ namespace MWRender osg::Vec4 getColorByDirection(osg::Vec3d d) { + // for details see OpenGL 4.4 specification page 241 + double x, y; - double ma; // see OpenGL 4.4 specification page 241 + double ma; int side; double ax, ay, az; - ax = d.x() > 0 ? d.x() : -d.x(); + ax = d.x() > 0 ? d.x() : -d.x(); // abs behaves weirdly for some reason ay = d.y() > 0 ? d.y() : -d.y(); az = d.z() > 0 ? d.z() : -d.z(); - if (ax > ay) - { if (ax > az) { side = d.x() > 0 ? 1 : 3; @@ -704,9 +724,7 @@ namespace MWRender side = d.z() > 0 ? 5 : 4; ma = az; } - } else - { if (ay > az) { side = d.y() > 0 ? 0 : 2; @@ -717,12 +735,11 @@ namespace MWRender side = d.z() > 0 ? 5 : 4; ma = az; } - } switch (side) { - case 0: x = d.x(); y = d.z(); break; - case 1: x = -d.y(); y = d.z(); break; + case 0: x = d.x(); y = d.z(); break; + case 1: x = -d.y(); y = d.z(); break; case 2: x = -d.x(); y = d.z(); break; case 3: x = d.y(); y = d.z(); break; case 4: x = d.x(); y = d.y(); break; @@ -745,8 +762,10 @@ namespace MWRender void RenderingManager::screenshot360(osg::Image* image) { - int w = 1024; - SphericalScreenshot s(w); + int cubeWidth = 1024; + int screenshotWidth = 1600; + int screenshotHeight = 1280; + SphericalScreenshot s(cubeWidth); osg::Vec3 directions[6] = { osg::Vec3(0,0,-1), @@ -766,18 +785,18 @@ namespace MWRender for (int i = 0; i < 6; i++) // for each cube side { osg::Image *sideImage = s.getImage(i); - screenshot(sideImage,w,w,directions[i]); + screenshot(sideImage,cubeWidth,cubeWidth,directions[i],true); } if (mCamera->isFirstPerson()) mPlayerAnimation->getObjectRoot()->setNodeMask(1); - s.create(image,1600,1600); + s.create(image,screenshotWidth,screenshotHeight,SphericalScreenshot::MAPPING_SPHERICAL); mFieldOfView = fovBackup; } - void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Vec3 direction) + void RenderingManager::screenshot(osg::Image *image, int w, int h, osg::Vec3 direction, bool disableWaterEffects) { osg::ref_ptr rttCamera (new osg::Camera); rttCamera->setNodeMask(Mask_RenderToTexture); @@ -786,9 +805,7 @@ namespace MWRender rttCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF); rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT, osg::Camera::PIXEL_BUFFER_RTT); rttCamera->setProjectionMatrixAsPerspective(mFieldOfView, w/float(h), mNearClip, mViewDistance); - rttCamera->setViewMatrix( - mViewer->getCamera()->getViewMatrix() * osg::Matrixd::rotate(osg::Vec3(0,0,-1),direction) - ); + rttCamera->setViewMatrix(mViewer->getCamera()->getViewMatrix() * osg::Matrixd::rotate(osg::Vec3(0,0,-1),direction)); rttCamera->setViewport(0, 0, w, h); @@ -816,13 +833,16 @@ namespace MWRender // at the time this function is called we are in the middle of a frame, // so out of order calls are necessary to get a correct frameNumber for the next frame. // refer to the advance() and frame() order in Engine::go() - mWater->setEffectsEnabled(false); + + if (disableWaterEffects) + mWater->setEffectsEnabled(false); mViewer->eventTraversal(); mViewer->updateTraversal(); mViewer->renderingTraversals(); - mWater->setEffectsEnabled(true); + if (disableWaterEffects) + mWater->setEffectsEnabled(true); callback->waitTillDone(); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index e6e2e1c0a..cb0723397 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -125,7 +125,7 @@ namespace MWRender 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, osg::Vec3 direction=osg::Vec3(0,0,-1)); + void screenshot(osg::Image* image, int w, int h, osg::Vec3 direction=osg::Vec3(0,0,-1), bool disableWaterEffects=false); void screenshot360(osg::Image* image); struct RayResult