mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 01:56:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			590 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			590 lines
		
	
	
	
		
			22 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "scenewidget.hpp"
 | 
						|
 | 
						|
#include <chrono>
 | 
						|
#include <exception>
 | 
						|
#include <thread>
 | 
						|
 | 
						|
#include <QLayout>
 | 
						|
#include <QMouseEvent>
 | 
						|
#include <QSurfaceFormat>
 | 
						|
 | 
						|
#include <apps/opencs/model/prefs/category.hpp>
 | 
						|
#include <apps/opencs/model/prefs/setting.hpp>
 | 
						|
#include <apps/opencs/view/render/lightingbright.hpp>
 | 
						|
#include <apps/opencs/view/render/lightingday.hpp>
 | 
						|
#include <apps/opencs/view/render/lightingnight.hpp>
 | 
						|
 | 
						|
#include <extern/osgQt/CompositeOsgRenderer.hpp>
 | 
						|
#include <extern/osgQt/osgQOpenGLWidget.hpp>
 | 
						|
 | 
						|
#include <osg/Array>
 | 
						|
#include <osg/Camera>
 | 
						|
#include <osg/DisplaySettings>
 | 
						|
#include <osg/GL>
 | 
						|
#include <osg/Geometry>
 | 
						|
#include <osg/GraphicsContext>
 | 
						|
#include <osg/Group>
 | 
						|
#include <osg/LightModel>
 | 
						|
#include <osg/Material>
 | 
						|
#include <osg/Matrix>
 | 
						|
#include <osg/PrimitiveSet>
 | 
						|
#include <osg/StateAttribute>
 | 
						|
#include <osg/StateSet>
 | 
						|
#include <osg/Transform>
 | 
						|
#include <osg/Vec3>
 | 
						|
#include <osg/Vec4>
 | 
						|
#include <osg/Vec4ub>
 | 
						|
#include <osg/View>
 | 
						|
#include <osg/Viewport>
 | 
						|
 | 
						|
#include <osgGA/EventQueue>
 | 
						|
#include <osgGA/GUIEventAdapter>
 | 
						|
 | 
						|
#include <osgViewer/GraphicsWindow>
 | 
						|
#include <osgViewer/View>
 | 
						|
#include <osgViewer/ViewerBase>
 | 
						|
#include <osgViewer/ViewerEventHandlers>
 | 
						|
 | 
						|
#include <components/debug/debuglog.hpp>
 | 
						|
#include <components/resource/resourcesystem.hpp>
 | 
						|
#include <components/resource/scenemanager.hpp>
 | 
						|
#include <components/sceneutil/glextensions.hpp>
 | 
						|
#include <components/sceneutil/lightmanager.hpp>
 | 
						|
 | 
						|
#include "../widget/scenetoolmode.hpp"
 | 
						|
 | 
						|
#include "../../model/prefs/shortcut.hpp"
 | 
						|
#include "../../model/prefs/state.hpp"
 | 
						|
 | 
						|
#include "cameracontroller.hpp"
 | 
						|
#include "lighting.hpp"
 | 
						|
#include "mask.hpp"
 | 
						|
 | 
						|
namespace CSVRender
 | 
						|
{
 | 
						|
 | 
						|
    RenderWidget::RenderWidget(QWidget* parent, Qt::WindowFlags f)
 | 
						|
        : QWidget(parent, f)
 | 
						|
        , mRootNode(nullptr)
 | 
						|
    {
 | 
						|
        mView = new osgViewer::View;
 | 
						|
        updateCameraParameters(width() / static_cast<double>(height()));
 | 
						|
 | 
						|
        mWidget = new osgQOpenGLWidget(this);
 | 
						|
 | 
						|
        mRenderer = mWidget->getCompositeViewer();
 | 
						|
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> window
 | 
						|
            = new osgViewer::GraphicsWindowEmbedded(0, 0, width(), height());
 | 
						|
        mWidget->setGraphicsWindowEmbedded(window);
 | 
						|
 | 
						|
        mRenderer->setRealizeOperation(new SceneUtil::GetGLExtensionsOperation());
 | 
						|
 | 
						|
        int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
 | 
						|
        mRenderer->setRunMaxFrameRate(frameRateLimit);
 | 
						|
        mRenderer->setUseConfigureAffinity(false);
 | 
						|
 | 
						|
        QLayout* layout = new QHBoxLayout(this);
 | 
						|
        layout->setContentsMargins(0, 0, 0, 0);
 | 
						|
        layout->addWidget(mWidget);
 | 
						|
        setLayout(layout);
 | 
						|
 | 
						|
        mView->getCamera()->setGraphicsContext(window);
 | 
						|
 | 
						|
        osg::ref_ptr<SceneUtil::LightManager> lightMgr = new SceneUtil::LightManager;
 | 
						|
        lightMgr->setStartLight(1);
 | 
						|
        lightMgr->setLightingMask(Mask_Lighting);
 | 
						|
        mRootNode = std::move(lightMgr);
 | 
						|
 | 
						|
        mView->getCamera()->setViewport(new osg::Viewport(0, 0, width(), height()));
 | 
						|
 | 
						|
        mView->getCamera()->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
 | 
						|
        mView->getCamera()->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
 | 
						|
        osg::ref_ptr<osg::Material> defaultMat(new osg::Material);
 | 
						|
        defaultMat->setColorMode(osg::Material::OFF);
 | 
						|
        defaultMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 1, 1));
 | 
						|
        defaultMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(1, 1, 1, 1));
 | 
						|
        defaultMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
 | 
						|
        mView->getCamera()->getOrCreateStateSet()->setAttribute(defaultMat);
 | 
						|
 | 
						|
        mView->setSceneData(mRootNode);
 | 
						|
 | 
						|
        // Add ability to signal osg to show its statistics for debugging purposes
 | 
						|
        mView->addEventHandler(new osgViewer::StatsHandler);
 | 
						|
 | 
						|
        mRenderer->addView(mView);
 | 
						|
        mRenderer->setDone(false);
 | 
						|
    }
 | 
						|
 | 
						|
    RenderWidget::~RenderWidget()
 | 
						|
    {
 | 
						|
        try
 | 
						|
        {
 | 
						|
            mRenderer->removeView(mView);
 | 
						|
        }
 | 
						|
        catch (const std::exception& e)
 | 
						|
        {
 | 
						|
            Log(Debug::Error) << "Error in the destructor: " << e.what();
 | 
						|
        }
 | 
						|
        delete mWidget;
 | 
						|
    }
 | 
						|
 | 
						|
    void RenderWidget::flagAsModified()
 | 
						|
    {
 | 
						|
        mView->requestRedraw();
 | 
						|
    }
 | 
						|
 | 
						|
    void RenderWidget::setVisibilityMask(unsigned int mask)
 | 
						|
    {
 | 
						|
        mView->getCamera()->setCullMask(mask | Mask_ParticleSystem | Mask_Lighting);
 | 
						|
    }
 | 
						|
 | 
						|
    osg::Camera* RenderWidget::getCamera()
 | 
						|
    {
 | 
						|
        return mView->getCamera();
 | 
						|
    }
 | 
						|
 | 
						|
    void RenderWidget::toggleRenderStats()
 | 
						|
    {
 | 
						|
        osgViewer::GraphicsWindow* window
 | 
						|
            = static_cast<osgViewer::GraphicsWindow*>(mView->getCamera()->getGraphicsContext());
 | 
						|
 | 
						|
        window->getEventQueue()->keyPress(osgGA::GUIEventAdapter::KEY_S);
 | 
						|
        window->getEventQueue()->keyRelease(osgGA::GUIEventAdapter::KEY_S);
 | 
						|
    }
 | 
						|
 | 
						|
    // ---------------------------------------------------
 | 
						|
 | 
						|
    SceneWidget::SceneWidget(std::shared_ptr<Resource::ResourceSystem> resourceSystem, QWidget* parent,
 | 
						|
        Qt::WindowFlags f, bool retrieveInput)
 | 
						|
        : RenderWidget(parent, f)
 | 
						|
        , mResourceSystem(std::move(resourceSystem))
 | 
						|
        , mLighting(nullptr)
 | 
						|
        , mHasDefaultAmbient(false)
 | 
						|
        , mIsExterior(true)
 | 
						|
        , mPrevMouseX(0)
 | 
						|
        , mPrevMouseY(0)
 | 
						|
        , mCamPositionSet(false)
 | 
						|
    {
 | 
						|
        mFreeCamControl = new FreeCameraController(this);
 | 
						|
        mOrbitCamControl = new OrbitCameraController(this);
 | 
						|
        mCurrentCamControl = mFreeCamControl;
 | 
						|
 | 
						|
        mOrbitCamControl->setPickingMask(Mask_Reference | Mask_Terrain);
 | 
						|
 | 
						|
        mOrbitCamControl->setConstRoll(CSMPrefs::get()["3D Scene Input"]["navi-orbit-const-roll"].isTrue());
 | 
						|
 | 
						|
        // set up gradient view or configured clear color
 | 
						|
        QColor bgColour = CSMPrefs::get()["Rendering"]["scene-day-background-colour"].toColor();
 | 
						|
 | 
						|
        if (CSMPrefs::get()["Rendering"]["scene-use-gradient"].isTrue())
 | 
						|
        {
 | 
						|
            QColor gradientColour = CSMPrefs::get()["Rendering"]["scene-day-gradient-colour"].toColor();
 | 
						|
            mGradientCamera = createGradientCamera(bgColour, gradientColour);
 | 
						|
 | 
						|
            mView->getCamera()->setClearMask(0);
 | 
						|
            mView->getCamera()->addChild(mGradientCamera.get());
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            mView->getCamera()->setClearColor(osg::Vec4(bgColour.redF(), bgColour.greenF(), bgColour.blueF(), 1.0f));
 | 
						|
        }
 | 
						|
 | 
						|
        // we handle lighting manually
 | 
						|
        mView->setLightingMode(osgViewer::View::NO_LIGHT);
 | 
						|
 | 
						|
        setLighting(&mLightingDay);
 | 
						|
 | 
						|
        mResourceSystem->getSceneManager()->setParticleSystemMask(Mask_ParticleSystem);
 | 
						|
 | 
						|
        // Recieve mouse move event even if mouse button is not pressed
 | 
						|
        setMouseTracking(true);
 | 
						|
        setFocusPolicy(Qt::ClickFocus);
 | 
						|
 | 
						|
        connect(&CSMPrefs::State::get(), &CSMPrefs::State::settingChanged, this, &SceneWidget::settingChanged);
 | 
						|
 | 
						|
        // TODO update this outside of the constructor where virtual methods can be used
 | 
						|
        if (retrieveInput)
 | 
						|
        {
 | 
						|
            CSMPrefs::get()["3D Scene Input"].update();
 | 
						|
            CSMPrefs::get()["Tooltips"].update();
 | 
						|
        }
 | 
						|
 | 
						|
        connect(mRenderer, &CompositeOsgRenderer::simulationUpdated, this, &SceneWidget::update);
 | 
						|
 | 
						|
        // Shortcuts
 | 
						|
        CSMPrefs::Shortcut* focusToolbarShortcut = new CSMPrefs::Shortcut("scene-focus-toolbar", this);
 | 
						|
        connect(
 | 
						|
            focusToolbarShortcut, qOverload<>(&CSMPrefs::Shortcut::activated), this, &SceneWidget::focusToolbarRequest);
 | 
						|
 | 
						|
        CSMPrefs::Shortcut* renderStatsShortcut = new CSMPrefs::Shortcut("scene-render-stats", this);
 | 
						|
        connect(
 | 
						|
            renderStatsShortcut, qOverload<>(&CSMPrefs::Shortcut::activated), this, &SceneWidget::toggleRenderStats);
 | 
						|
    }
 | 
						|
 | 
						|
    SceneWidget::~SceneWidget()
 | 
						|
    {
 | 
						|
        // Since we're holding on to the resources past the existence of this graphics context, we'll need to manually
 | 
						|
        // release the created objects
 | 
						|
        mResourceSystem->releaseGLObjects(mView->getCamera()->getGraphicsContext()->getState());
 | 
						|
    }
 | 
						|
 | 
						|
    osg::ref_ptr<osg::Geometry> SceneWidget::createGradientRectangle(QColor& bgColour, QColor& gradientColour)
 | 
						|
    {
 | 
						|
        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
 | 
						|
 | 
						|
        osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
 | 
						|
 | 
						|
        vertices->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
 | 
						|
        vertices->push_back(osg::Vec3(1.0f, 0.0f, -1.0f));
 | 
						|
        vertices->push_back(osg::Vec3(0.0f, 1.0f, -1.0f));
 | 
						|
        vertices->push_back(osg::Vec3(1.0f, 1.0f, -1.0f));
 | 
						|
 | 
						|
        geometry->setVertexArray(vertices);
 | 
						|
 | 
						|
        osg::ref_ptr<osg::DrawElementsUShort> primitives = new osg::DrawElementsUShort(osg::PrimitiveSet::TRIANGLES, 0);
 | 
						|
 | 
						|
        // triangle 1
 | 
						|
        primitives->push_back(0);
 | 
						|
        primitives->push_back(1);
 | 
						|
        primitives->push_back(2);
 | 
						|
 | 
						|
        // triangle 2
 | 
						|
        primitives->push_back(2);
 | 
						|
        primitives->push_back(1);
 | 
						|
        primitives->push_back(3);
 | 
						|
 | 
						|
        geometry->addPrimitiveSet(primitives);
 | 
						|
 | 
						|
        osg::ref_ptr<osg::Vec4ubArray> colours = new osg::Vec4ubArray;
 | 
						|
        colours->push_back(osg::Vec4ub(gradientColour.red(), gradientColour.green(), gradientColour.blue(), 1.0f));
 | 
						|
        colours->push_back(osg::Vec4ub(gradientColour.red(), gradientColour.green(), gradientColour.blue(), 1.0f));
 | 
						|
        colours->push_back(osg::Vec4ub(bgColour.red(), bgColour.green(), bgColour.blue(), 1.0f));
 | 
						|
        colours->push_back(osg::Vec4ub(bgColour.red(), bgColour.green(), bgColour.blue(), 1.0f));
 | 
						|
 | 
						|
        geometry->setColorArray(colours, osg::Array::BIND_PER_VERTEX);
 | 
						|
 | 
						|
        geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
 | 
						|
        geometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
 | 
						|
 | 
						|
        return geometry;
 | 
						|
    }
 | 
						|
 | 
						|
    osg::ref_ptr<osg::Camera> SceneWidget::createGradientCamera(QColor& bgColour, QColor& gradientColour)
 | 
						|
    {
 | 
						|
        osg::ref_ptr<osg::Camera> camera = new osg::Camera();
 | 
						|
        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
 | 
						|
        camera->setProjectionMatrix(osg::Matrix::ortho2D(0, 1.0f, 0, 1.0f));
 | 
						|
        camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
 | 
						|
        camera->setViewMatrix(osg::Matrix::identity());
 | 
						|
 | 
						|
        camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 | 
						|
        camera->setAllowEventFocus(false);
 | 
						|
 | 
						|
        // draw subgraph before main camera view.
 | 
						|
        camera->setRenderOrder(osg::Camera::PRE_RENDER);
 | 
						|
 | 
						|
        camera->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
 | 
						|
 | 
						|
        osg::ref_ptr<osg::Geometry> gradientQuad = createGradientRectangle(bgColour, gradientColour);
 | 
						|
 | 
						|
        camera->addChild(std::move(gradientQuad));
 | 
						|
        return camera;
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::updateGradientCamera(QColor& bgColour, QColor& gradientColour)
 | 
						|
    {
 | 
						|
        osg::ref_ptr<osg::Geometry> gradientRect = createGradientRectangle(bgColour, gradientColour);
 | 
						|
        // Replaces previous rectangle
 | 
						|
        mGradientCamera->setChild(0, gradientRect.get());
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::setLighting(Lighting* lighting)
 | 
						|
    {
 | 
						|
        if (mLighting)
 | 
						|
            mLighting->deactivate();
 | 
						|
 | 
						|
        mLighting = lighting;
 | 
						|
        mLighting->activate(mRootNode, mIsExterior);
 | 
						|
 | 
						|
        osg::Vec4f ambient = mLighting->getAmbientColour(mHasDefaultAmbient ? &mDefaultAmbient : nullptr);
 | 
						|
        setAmbient(ambient);
 | 
						|
 | 
						|
        flagAsModified();
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::setAmbient(const osg::Vec4f& ambient)
 | 
						|
    {
 | 
						|
        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
 | 
						|
        osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel;
 | 
						|
        lightmodel->setAmbientIntensity(ambient);
 | 
						|
        stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
 | 
						|
        stateset->setMode(GL_LIGHT0, osg::StateAttribute::ON);
 | 
						|
        stateset->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
 | 
						|
        mRootNode->setStateSet(stateset);
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::selectLightingMode(const std::string& mode)
 | 
						|
    {
 | 
						|
        QColor backgroundColour;
 | 
						|
        QColor gradientColour;
 | 
						|
        if (mode == "day")
 | 
						|
        {
 | 
						|
            backgroundColour = CSMPrefs::get()["Rendering"]["scene-day-background-colour"].toColor();
 | 
						|
            gradientColour = CSMPrefs::get()["Rendering"]["scene-day-gradient-colour"].toColor();
 | 
						|
            setLighting(&mLightingDay);
 | 
						|
        }
 | 
						|
        else if (mode == "night")
 | 
						|
        {
 | 
						|
            backgroundColour = CSMPrefs::get()["Rendering"]["scene-night-background-colour"].toColor();
 | 
						|
            gradientColour = CSMPrefs::get()["Rendering"]["scene-night-gradient-colour"].toColor();
 | 
						|
            setLighting(&mLightingNight);
 | 
						|
        }
 | 
						|
        else if (mode == "bright")
 | 
						|
        {
 | 
						|
            backgroundColour = CSMPrefs::get()["Rendering"]["scene-bright-background-colour"].toColor();
 | 
						|
            gradientColour = CSMPrefs::get()["Rendering"]["scene-bright-gradient-colour"].toColor();
 | 
						|
            setLighting(&mLightingBright);
 | 
						|
        }
 | 
						|
        if (CSMPrefs::get()["Rendering"]["scene-use-gradient"].isTrue())
 | 
						|
        {
 | 
						|
            if (mGradientCamera.get() != nullptr)
 | 
						|
            {
 | 
						|
                // we can go ahead and update since this camera still exists
 | 
						|
                updateGradientCamera(backgroundColour, gradientColour);
 | 
						|
 | 
						|
                if (!mView->getCamera()->containsNode(mGradientCamera.get()))
 | 
						|
                {
 | 
						|
                    // need to re-attach the gradient camera
 | 
						|
                    mView->getCamera()->setClearMask(0);
 | 
						|
                    mView->getCamera()->addChild(mGradientCamera.get());
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                // need to create the gradient camera
 | 
						|
                mGradientCamera = createGradientCamera(backgroundColour, gradientColour);
 | 
						|
                mView->getCamera()->setClearMask(0);
 | 
						|
                mView->getCamera()->addChild(mGradientCamera.get());
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            // Fall back to using the clear color for the camera
 | 
						|
            mView->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 | 
						|
            mView->getCamera()->setClearColor(
 | 
						|
                osg::Vec4(backgroundColour.redF(), backgroundColour.greenF(), backgroundColour.blueF(), 1.0f));
 | 
						|
            if (mGradientCamera.get() != nullptr && mView->getCamera()->containsNode(mGradientCamera.get()))
 | 
						|
            {
 | 
						|
                // Remove the child to prevent the gradient from rendering
 | 
						|
                mView->getCamera()->removeChild(mGradientCamera.get());
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    CSVWidget::SceneToolMode* SceneWidget::makeLightingSelector(CSVWidget::SceneToolbar* parent)
 | 
						|
    {
 | 
						|
        CSVWidget::SceneToolMode* tool = new CSVWidget::SceneToolMode(parent, "Lighting Mode");
 | 
						|
 | 
						|
        /// \todo replace icons
 | 
						|
        tool->addButton(":scenetoolbar/day", "day",
 | 
						|
            "Day"
 | 
						|
            "<ul><li>Cell specific ambient in interiors</li>"
 | 
						|
            "<li>Low ambient in exteriors</li>"
 | 
						|
            "<li>Strong directional light source</li>"
 | 
						|
            "<li>This mode closely resembles day time in-game</li></ul>");
 | 
						|
        tool->addButton(":scenetoolbar/night", "night",
 | 
						|
            "Night"
 | 
						|
            "<ul><li>Cell specific ambient in interiors</li>"
 | 
						|
            "<li>Low ambient in exteriors</li>"
 | 
						|
            "<li>Weak directional light source</li>"
 | 
						|
            "<li>This mode closely resembles night time in-game</li></ul>");
 | 
						|
        tool->addButton(":scenetoolbar/bright", "bright",
 | 
						|
            "Bright"
 | 
						|
            "<ul><li>Maximum ambient</li>"
 | 
						|
            "<li>Strong directional light source</li></ul>");
 | 
						|
 | 
						|
        connect(tool, &CSVWidget::SceneToolMode::modeChanged, this, &SceneWidget::selectLightingMode);
 | 
						|
 | 
						|
        return tool;
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::setDefaultAmbient(const osg::Vec4f& colour)
 | 
						|
    {
 | 
						|
        mDefaultAmbient = colour;
 | 
						|
        mHasDefaultAmbient = true;
 | 
						|
 | 
						|
        setAmbient(mLighting->getAmbientColour(&mDefaultAmbient));
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::setExterior(bool isExterior)
 | 
						|
    {
 | 
						|
        mIsExterior = isExterior;
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::mouseMoveEvent(QMouseEvent* event)
 | 
						|
    {
 | 
						|
        mCurrentCamControl->handleMouseMoveEvent(event->x() - mPrevMouseX, event->y() - mPrevMouseY);
 | 
						|
 | 
						|
        mPrevMouseX = event->x();
 | 
						|
        mPrevMouseY = event->y();
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::wheelEvent(QWheelEvent* event)
 | 
						|
    {
 | 
						|
        mCurrentCamControl->handleMouseScrollEvent(event->angleDelta().y());
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::update(double dt)
 | 
						|
    {
 | 
						|
        if (mCamPositionSet)
 | 
						|
        {
 | 
						|
            mCurrentCamControl->update(dt);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            mCurrentCamControl->setup(mRootNode, Mask_Reference | Mask_Terrain, CameraController::WorldUp);
 | 
						|
            mCamPositionSet = true;
 | 
						|
        }
 | 
						|
 | 
						|
        if (mSelectionMarkerNode)
 | 
						|
        {
 | 
						|
            osg::MatrixList worldMats = mSelectionMarkerNode->getWorldMatrices();
 | 
						|
            if (!worldMats.empty())
 | 
						|
            {
 | 
						|
                osg::Matrixd markerWorldMat = worldMats[0];
 | 
						|
 | 
						|
                osg::Vec3f eye, _;
 | 
						|
                mView->getCamera()->getViewMatrix().getLookAt(eye, _, _);
 | 
						|
                osg::Vec3f cameraLocalPos = eye * osg::Matrixd::inverse(markerWorldMat);
 | 
						|
 | 
						|
                bool isInFrontRightQuadrant = (cameraLocalPos.x() > 0.1f) && (cameraLocalPos.y() > 0.1f);
 | 
						|
                bool isSignificantlyBehind = (cameraLocalPos.x() < 1.f) && (cameraLocalPos.y() < 1.f);
 | 
						|
 | 
						|
                if (!isInFrontRightQuadrant && isSignificantlyBehind)
 | 
						|
                {
 | 
						|
                    osg::Quat current = mSelectionMarkerNode->getAttitude();
 | 
						|
                    mSelectionMarkerNode->setAttitude(current * osg::Quat(osg::PI, osg::Vec3f(0, 0, 1)));
 | 
						|
                }
 | 
						|
 | 
						|
                float distance = (markerWorldMat.getTrans() - eye).length();
 | 
						|
                float scale = std::max(distance / 75.0f, 1.0f);
 | 
						|
                mSelectionMarkerNode->setScale(osg::Vec3(scale, scale, scale));
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::settingChanged(const CSMPrefs::Setting* setting)
 | 
						|
    {
 | 
						|
        if (*setting == "3D Scene Input/p-navi-free-sensitivity")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setCameraSensitivity(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/p-navi-orbit-sensitivity")
 | 
						|
        {
 | 
						|
            mOrbitCamControl->setCameraSensitivity(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/p-navi-free-invert")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setInverted(setting->isTrue());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/p-navi-orbit-invert")
 | 
						|
        {
 | 
						|
            mOrbitCamControl->setInverted(setting->isTrue());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/s-navi-sensitivity")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setSecondaryMovementMultiplier(setting->toDouble());
 | 
						|
            mOrbitCamControl->setSecondaryMovementMultiplier(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-wheel-factor")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setWheelMovementMultiplier(setting->toDouble());
 | 
						|
            mOrbitCamControl->setWheelMovementMultiplier(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-free-lin-speed")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setLinearSpeed(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-free-rot-speed")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setRotationalSpeed(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-free-speed-mult")
 | 
						|
        {
 | 
						|
            mFreeCamControl->setSpeedMultiplier(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-orbit-rot-speed")
 | 
						|
        {
 | 
						|
            mOrbitCamControl->setOrbitSpeed(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-orbit-speed-mult")
 | 
						|
        {
 | 
						|
            mOrbitCamControl->setOrbitSpeedMultiplier(setting->toDouble());
 | 
						|
        }
 | 
						|
        else if (*setting == "3D Scene Input/navi-orbit-const-roll")
 | 
						|
        {
 | 
						|
            mOrbitCamControl->setConstRoll(setting->isTrue());
 | 
						|
        }
 | 
						|
        else if (*setting == "Rendering/framerate-limit")
 | 
						|
        {
 | 
						|
            mRenderer->setRunMaxFrameRate(setting->toInt());
 | 
						|
        }
 | 
						|
        else if (*setting == "Rendering/camera-fov" || *setting == "Rendering/camera-ortho"
 | 
						|
            || *setting == "Rendering/camera-ortho-size")
 | 
						|
        {
 | 
						|
            updateCameraParameters();
 | 
						|
        }
 | 
						|
        else if (*setting == "Rendering/scene-day-night-switch-nodes")
 | 
						|
        {
 | 
						|
            if (mLighting)
 | 
						|
                setLighting(mLighting);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void RenderWidget::updateCameraParameters(double overrideAspect)
 | 
						|
    {
 | 
						|
        const float nearDist = 1.0;
 | 
						|
        const float farDist = 1000.0;
 | 
						|
 | 
						|
        if (CSMPrefs::get()["Rendering"]["camera-ortho"].isTrue())
 | 
						|
        {
 | 
						|
            const float size = CSMPrefs::get()["Rendering"]["camera-ortho-size"].toInt();
 | 
						|
            const float aspect = overrideAspect >= 0.0 ? overrideAspect : (width() / static_cast<double>(height()));
 | 
						|
            const float halfH = size * 10.0;
 | 
						|
            const float halfW = halfH * aspect;
 | 
						|
 | 
						|
            mView->getCamera()->setProjectionMatrixAsOrtho(-halfW, halfW, -halfH, halfH, nearDist, farDist);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            mView->getCamera()->setProjectionMatrixAsPerspective(CSMPrefs::get()["Rendering"]["camera-fov"].toInt(),
 | 
						|
                static_cast<double>(width()) / static_cast<double>(height()), nearDist, farDist);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    void SceneWidget::selectNavigationMode(const std::string& mode)
 | 
						|
    {
 | 
						|
        if (mode == "1st")
 | 
						|
        {
 | 
						|
            mCurrentCamControl->setCamera(nullptr);
 | 
						|
            mCurrentCamControl = mFreeCamControl;
 | 
						|
            mFreeCamControl->setCamera(getCamera());
 | 
						|
            mFreeCamControl->fixUpAxis(CameraController::WorldUp);
 | 
						|
        }
 | 
						|
        else if (mode == "free")
 | 
						|
        {
 | 
						|
            mCurrentCamControl->setCamera(nullptr);
 | 
						|
            mCurrentCamControl = mFreeCamControl;
 | 
						|
            mFreeCamControl->setCamera(getCamera());
 | 
						|
            mFreeCamControl->unfixUpAxis();
 | 
						|
        }
 | 
						|
        else if (mode == "orbit")
 | 
						|
        {
 | 
						|
            mCurrentCamControl->setCamera(nullptr);
 | 
						|
            mCurrentCamControl = mOrbitCamControl;
 | 
						|
            mOrbitCamControl->setCamera(getCamera());
 | 
						|
            mOrbitCamControl->reset();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 |