2011-10-20 15:02:19 -04:00
|
|
|
#include "renderingmanager.hpp"
|
|
|
|
|
2017-02-15 20:57:12 +01:00
|
|
|
#include <cstdlib>
|
2015-08-21 22:00:08 +12:00
|
|
|
#include <limits>
|
2011-10-20 18:15:30 -04:00
|
|
|
|
2021-06-01 12:15:25 -07:00
|
|
|
#include <osg/ClipControl>
|
2015-05-24 03:36:34 +02:00
|
|
|
#include <osg/ComputeBoundsVisitor>
|
2015-04-21 23:27:26 +02:00
|
|
|
#include <osg/Fog>
|
2015-04-12 15:34:50 +02:00
|
|
|
#include <osg/Group>
|
|
|
|
#include <osg/Light>
|
|
|
|
#include <osg/LightModel>
|
2017-02-01 03:18:17 +01:00
|
|
|
#include <osg/Material>
|
2015-06-01 17:02:44 +02:00
|
|
|
#include <osg/PolygonMode>
|
2015-05-24 03:36:34 +02:00
|
|
|
#include <osg/UserDataContainer>
|
2011-10-20 18:15:30 -04:00
|
|
|
|
2015-05-24 03:36:34 +02:00
|
|
|
#include <osgUtil/LineSegmentIntersector>
|
2015-05-03 18:16:54 +02:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
#include <osgViewer/Viewer>
|
2013-07-29 02:32:08 +02:00
|
|
|
|
2020-04-22 15:57:24 +02:00
|
|
|
#include <components/nifosg/nifloader.hpp>
|
2020-04-22 13:34:19 +02:00
|
|
|
|
2018-08-14 23:05:43 +04:00
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
|
2022-04-04 22:51:23 +02:00
|
|
|
#include <components/stereo/multiview.hpp>
|
|
|
|
#include <components/stereo/stereomanager.hpp>
|
|
|
|
|
2016-02-05 23:03:53 +01:00
|
|
|
#include <components/resource/imagemanager.hpp>
|
2017-02-09 03:32:40 +01:00
|
|
|
#include <components/resource/keyframemanager.hpp>
|
2015-04-22 19:08:56 +02:00
|
|
|
#include <components/resource/resourcesystem.hpp>
|
2021-01-08 19:33:51 +04:00
|
|
|
|
2020-12-18 00:02:51 +00:00
|
|
|
#include <components/shader/removedalphafunc.hpp>
|
2017-11-15 15:20:59 +01:00
|
|
|
#include <components/shader/shadermanager.hpp>
|
2015-04-22 19:08:56 +02:00
|
|
|
|
2023-05-20 22:23:09 +02:00
|
|
|
#include <components/settings/values.hpp>
|
2015-04-21 23:27:26 +02:00
|
|
|
|
2023-05-19 14:29:01 -07:00
|
|
|
#include <components/sceneutil/cullsafeboundsvisitor.hpp>
|
2021-11-21 02:25:05 +00:00
|
|
|
#include <components/sceneutil/depth.hpp>
|
2015-04-12 15:34:50 +02:00
|
|
|
#include <components/sceneutil/lightmanager.hpp>
|
2015-11-20 21:57:04 +01:00
|
|
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
2022-06-06 22:40:38 +02:00
|
|
|
#include <components/sceneutil/rtt.hpp>
|
2017-11-08 01:44:49 +00:00
|
|
|
#include <components/sceneutil/shadow.hpp>
|
2015-04-14 17:29:12 +02:00
|
|
|
#include <components/sceneutil/statesetupdater.hpp>
|
2022-04-04 22:51:23 +02:00
|
|
|
#include <components/sceneutil/visitor.hpp>
|
2016-02-09 01:02:40 +01:00
|
|
|
#include <components/sceneutil/workqueue.hpp>
|
2017-02-01 03:00:33 +01:00
|
|
|
#include <components/sceneutil/writescene.hpp>
|
2015-04-14 15:55:56 +02:00
|
|
|
|
2022-05-14 22:53:53 -07:00
|
|
|
#include <components/misc/constants.hpp>
|
|
|
|
|
2017-03-09 03:49:40 +01:00
|
|
|
#include <components/terrain/quadtreeworld.hpp>
|
2015-06-03 01:18:36 +02:00
|
|
|
#include <components/terrain/terraingrid.hpp>
|
|
|
|
|
2022-01-22 15:58:41 +01:00
|
|
|
#include <components/esm3/loadcell.hpp>
|
2023-01-22 23:40:55 +01:00
|
|
|
#include <components/esm4/loadcell.hpp>
|
2013-08-16 13:01:52 +02:00
|
|
|
|
2022-08-28 16:26:11 +02:00
|
|
|
#include <components/debug/debugdraw.hpp>
|
2018-04-07 16:11:23 +03:00
|
|
|
#include <components/detournavigator/navigator.hpp>
|
2022-08-12 00:09:49 +02:00
|
|
|
#include <components/detournavigator/navmeshcacheitem.hpp>
|
2018-04-07 16:11:23 +03:00
|
|
|
|
2015-11-03 02:17:42 +01:00
|
|
|
#include "../mwworld/cellstore.hpp"
|
2018-06-16 10:18:04 +04:00
|
|
|
#include "../mwworld/class.hpp"
|
2021-10-29 16:47:17 +04:00
|
|
|
#include "../mwworld/groundcoverstore.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
#include "../mwgui/postprocessorhud.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
|
2021-04-03 22:25:13 -07:00
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
|
|
|
|
#include "../mwbase/environment.hpp"
|
2022-05-13 18:58:00 -07:00
|
|
|
#include "../mwbase/windowmanager.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
#include "../mwbase/world.hpp"
|
2015-11-01 22:09:02 +01:00
|
|
|
|
2015-04-14 15:55:56 +02:00
|
|
|
#include "actorspaths.hpp"
|
2015-05-21 23:54:39 +02:00
|
|
|
#include "camera.hpp"
|
2015-04-19 17:55:56 +02:00
|
|
|
#include "effectmanager.hpp"
|
2020-06-07 10:35:33 +04:00
|
|
|
#include "fogmanager.hpp"
|
2020-01-12 11:42:47 +04:00
|
|
|
#include "groundcover.hpp"
|
2018-04-07 16:11:23 +03:00
|
|
|
#include "navmesh.hpp"
|
2015-05-01 18:21:50 +02:00
|
|
|
#include "npcanimation.hpp"
|
2020-04-20 18:47:14 +02:00
|
|
|
#include "objectpaging.hpp"
|
2015-05-04 17:41:30 +02:00
|
|
|
#include "pathgrid.hpp"
|
2015-06-03 01:18:36 +02:00
|
|
|
#include "postprocessor.hpp"
|
2019-11-27 23:45:01 +01:00
|
|
|
#include "recastmesh.hpp"
|
2021-01-08 19:33:51 +04:00
|
|
|
#include "screenshotmanager.hpp"
|
2020-01-12 11:42:47 +04:00
|
|
|
#include "sky.hpp"
|
2021-06-01 12:15:25 -07:00
|
|
|
#include "terrainstorage.hpp"
|
2022-06-26 16:42:29 +02:00
|
|
|
#include "vismask.hpp"
|
2021-06-01 12:15:25 -07:00
|
|
|
#include "water.hpp"
|
2017-09-21 03:08:45 -07:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
namespace MWRender
|
2012-03-08 10:46:34 +04:00
|
|
|
{
|
2022-04-04 22:51:23 +02:00
|
|
|
class PerViewUniformStateUpdater final : public SceneUtil::StateSetUpdater
|
|
|
|
{
|
|
|
|
public:
|
2022-06-29 18:15:12 -07:00
|
|
|
PerViewUniformStateUpdater(Resource::SceneManager* sceneManager)
|
|
|
|
: mSceneManager(sceneManager)
|
2022-04-04 22:51:23 +02:00
|
|
|
{
|
2022-06-29 18:15:12 -07:00
|
|
|
mOpaqueTextureUnit = mSceneManager->getShaderManager().reserveGlobalTextureUnits(
|
|
|
|
Shader::ShaderManager::Slot::OpaqueDepthTexture);
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void setDefaults(osg::StateSet* stateset) override
|
|
|
|
{
|
|
|
|
stateset->addUniform(new osg::Uniform("projectionMatrix", osg::Matrixf{}));
|
2022-06-06 22:40:38 +02:00
|
|
|
if (mSkyRTT)
|
|
|
|
stateset->addUniform(new osg::Uniform("sky", mSkyTextureUnit));
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
|
|
|
|
{
|
2023-01-28 10:40:24 -08:00
|
|
|
stateset->getUniform("projectionMatrix")->set(mProjectionMatrix);
|
2022-06-06 22:40:38 +02:00
|
|
|
if (mSkyRTT && nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
|
|
|
{
|
|
|
|
osg::Texture* skyTexture = mSkyRTT->getColorTexture(static_cast<osgUtil::CullVisitor*>(nv));
|
|
|
|
stateset->setTextureAttribute(
|
|
|
|
mSkyTextureUnit, skyTexture, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
|
|
|
}
|
2022-06-29 18:15:12 -07:00
|
|
|
|
|
|
|
stateset->setTextureAttribute(mOpaqueTextureUnit,
|
|
|
|
mSceneManager->getOpaqueDepthTex(nv->getTraversalNumber()), osg::StateAttribute::ON);
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void applyLeft(osg::StateSet* stateset, osgUtil::CullVisitor* nv) override
|
|
|
|
{
|
2023-01-28 10:40:24 -08:00
|
|
|
stateset->getUniform("projectionMatrix")->set(getEyeProjectionMatrix(0));
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void applyRight(osg::StateSet* stateset, osgUtil::CullVisitor* nv) override
|
|
|
|
{
|
2023-01-28 10:40:24 -08:00
|
|
|
stateset->getUniform("projectionMatrix")->set(getEyeProjectionMatrix(1));
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void setProjectionMatrix(const osg::Matrixf& projectionMatrix) { mProjectionMatrix = projectionMatrix; }
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
const osg::Matrixf& getProjectionMatrix() const { return mProjectionMatrix; }
|
2022-04-04 22:51:23 +02:00
|
|
|
|
2022-06-06 22:40:38 +02:00
|
|
|
void enableSkyRTT(int skyTextureUnit, SceneUtil::RTTNode* skyRTT)
|
|
|
|
{
|
|
|
|
mSkyTextureUnit = skyTextureUnit;
|
|
|
|
mSkyRTT = skyRTT;
|
|
|
|
}
|
|
|
|
|
2022-04-04 22:51:23 +02:00
|
|
|
private:
|
2023-01-28 10:40:24 -08:00
|
|
|
osg::Matrixf getEyeProjectionMatrix(int view)
|
|
|
|
{
|
2023-03-12 10:53:15 +00:00
|
|
|
return Stereo::Manager::instance().computeEyeProjection(view, SceneUtil::AutoDepth::isReversed());
|
2023-01-28 10:40:24 -08:00
|
|
|
}
|
|
|
|
|
2022-04-04 22:51:23 +02:00
|
|
|
osg::Matrixf mProjectionMatrix;
|
2022-06-06 22:40:38 +02:00
|
|
|
int mSkyTextureUnit = -1;
|
|
|
|
SceneUtil::RTTNode* mSkyRTT = nullptr;
|
2022-06-29 18:15:12 -07:00
|
|
|
|
|
|
|
Resource::SceneManager* mSceneManager;
|
|
|
|
int mOpaqueTextureUnit = -1;
|
2022-04-04 22:51:23 +02:00
|
|
|
};
|
|
|
|
|
2021-07-09 10:05:27 -07:00
|
|
|
class SharedUniformStateUpdater : public SceneUtil::StateSetUpdater
|
|
|
|
{
|
|
|
|
public:
|
2023-04-01 09:09:45 +04:00
|
|
|
SharedUniformStateUpdater()
|
2023-02-25 11:03:39 -08:00
|
|
|
: mNear(0.f)
|
2021-08-04 17:49:57 -07:00
|
|
|
, mFar(0.f)
|
2021-09-20 18:17:55 +00:00
|
|
|
, mWindSpeed(0.f)
|
2023-01-28 10:40:24 -08:00
|
|
|
, mSkyBlendingStartCoef(Settings::Manager::getFloat("sky blending start", "Fog"))
|
2021-07-09 10:05:27 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-04-04 22:51:23 +02:00
|
|
|
void setDefaults(osg::StateSet* stateset) override
|
2021-07-09 10:05:27 -07:00
|
|
|
{
|
2021-08-04 17:49:57 -07:00
|
|
|
stateset->addUniform(new osg::Uniform("near", 0.f));
|
|
|
|
stateset->addUniform(new osg::Uniform("far", 0.f));
|
2022-06-06 22:40:38 +02:00
|
|
|
stateset->addUniform(new osg::Uniform("skyBlendingStart", 0.f));
|
2021-10-20 09:42:18 -07:00
|
|
|
stateset->addUniform(new osg::Uniform("screenRes", osg::Vec2f{}));
|
2022-08-25 22:34:50 +01:00
|
|
|
stateset->addUniform(new osg::Uniform("isReflection", false));
|
2023-04-01 09:09:45 +04:00
|
|
|
stateset->addUniform(new osg::Uniform("windSpeed", 0.0f));
|
|
|
|
stateset->addUniform(new osg::Uniform("playerPos", osg::Vec3f(0.f, 0.f, 0.f)));
|
2021-07-09 10:05:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) override
|
|
|
|
{
|
2023-01-28 10:40:24 -08:00
|
|
|
stateset->getUniform("near")->set(mNear);
|
|
|
|
stateset->getUniform("far")->set(mFar);
|
|
|
|
stateset->getUniform("skyBlendingStart")->set(mFar * mSkyBlendingStartCoef);
|
|
|
|
stateset->getUniform("screenRes")->set(mScreenRes);
|
2023-04-01 09:09:45 +04:00
|
|
|
stateset->getUniform("windSpeed")->set(mWindSpeed);
|
|
|
|
stateset->getUniform("playerPos")->set(mPlayerPos);
|
2021-07-09 10:05:27 -07:00
|
|
|
}
|
|
|
|
|
2021-08-04 17:49:57 -07:00
|
|
|
void setNear(float near) { mNear = near; }
|
|
|
|
|
|
|
|
void setFar(float far) { mFar = far; }
|
|
|
|
|
2021-10-20 09:42:18 -07:00
|
|
|
void setScreenRes(float width, float height) { mScreenRes = osg::Vec2f(width, height); }
|
|
|
|
|
2021-09-20 18:17:55 +00:00
|
|
|
void setWindSpeed(float windSpeed) { mWindSpeed = windSpeed; }
|
|
|
|
|
|
|
|
void setPlayerPos(osg::Vec3f playerPos) { mPlayerPos = playerPos; }
|
|
|
|
|
2021-07-09 10:05:27 -07:00
|
|
|
private:
|
2021-08-04 17:49:57 -07:00
|
|
|
float mNear;
|
|
|
|
float mFar;
|
2021-09-20 18:17:55 +00:00
|
|
|
float mWindSpeed;
|
2023-01-28 10:40:24 -08:00
|
|
|
float mSkyBlendingStartCoef;
|
2021-09-20 18:17:55 +00:00
|
|
|
osg::Vec3f mPlayerPos;
|
2021-10-20 09:42:18 -07:00
|
|
|
osg::Vec2f mScreenRes;
|
2021-07-09 10:05:27 -07:00
|
|
|
};
|
2021-01-12 12:39:19 +04:00
|
|
|
|
2015-04-14 17:29:12 +02:00
|
|
|
class StateUpdater : public SceneUtil::StateSetUpdater
|
2015-04-14 15:55:56 +02:00
|
|
|
{
|
|
|
|
public:
|
2015-04-21 23:27:26 +02:00
|
|
|
StateUpdater()
|
2015-07-01 03:21:39 +02:00
|
|
|
: mFogStart(0.f)
|
|
|
|
, mFogEnd(0.f)
|
2015-06-01 17:02:44 +02:00
|
|
|
, mWireframe(false)
|
2015-04-21 23:27:26 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-10-16 22:18:54 +04:00
|
|
|
void setDefaults(osg::StateSet* stateset) override
|
2015-04-14 15:55:56 +02:00
|
|
|
{
|
|
|
|
osg::LightModel* lightModel = new osg::LightModel;
|
|
|
|
stateset->setAttribute(lightModel, osg::StateAttribute::ON);
|
2015-04-21 23:27:26 +02:00
|
|
|
osg::Fog* fog = new osg::Fog;
|
2015-05-26 18:22:21 +02:00
|
|
|
fog->setMode(osg::Fog::LINEAR);
|
2015-04-21 23:27:26 +02:00
|
|
|
stateset->setAttributeAndModes(fog, osg::StateAttribute::ON);
|
2015-06-01 17:02:44 +02:00
|
|
|
if (mWireframe)
|
|
|
|
{
|
|
|
|
osg::PolygonMode* polygonmode = new osg::PolygonMode;
|
|
|
|
polygonmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
|
|
|
stateset->setAttributeAndModes(polygonmode, osg::StateAttribute::ON);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
stateset->removeAttribute(osg::StateAttribute::POLYGONMODE);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
2020-10-16 22:18:54 +04:00
|
|
|
void apply(osg::StateSet* stateset, osg::NodeVisitor*) override
|
2015-04-14 15:55:56 +02:00
|
|
|
{
|
|
|
|
osg::LightModel* lightModel
|
|
|
|
= static_cast<osg::LightModel*>(stateset->getAttribute(osg::StateAttribute::LIGHTMODEL));
|
|
|
|
lightModel->setAmbientIntensity(mAmbientColor);
|
2015-04-21 23:27:26 +02:00
|
|
|
osg::Fog* fog = static_cast<osg::Fog*>(stateset->getAttribute(osg::StateAttribute::FOG));
|
|
|
|
fog->setColor(mFogColor);
|
2015-07-01 03:21:39 +02:00
|
|
|
fog->setStart(mFogStart);
|
2015-04-21 23:27:26 +02:00
|
|
|
fog->setEnd(mFogEnd);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
2015-04-21 23:27:26 +02:00
|
|
|
void setAmbientColor(const osg::Vec4f& col) { mAmbientColor = col; }
|
2015-04-14 15:55:56 +02:00
|
|
|
|
2015-04-21 23:27:26 +02:00
|
|
|
void setFogColor(const osg::Vec4f& col) { mFogColor = col; }
|
|
|
|
|
2015-07-01 03:21:39 +02:00
|
|
|
void setFogStart(float start) { mFogStart = start; }
|
|
|
|
|
2015-04-21 23:27:26 +02:00
|
|
|
void setFogEnd(float end) { mFogEnd = end; }
|
|
|
|
|
2015-06-01 17:02:44 +02:00
|
|
|
void setWireframe(bool wireframe)
|
|
|
|
{
|
|
|
|
if (mWireframe != wireframe)
|
|
|
|
{
|
|
|
|
mWireframe = wireframe;
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool getWireframe() const { return mWireframe; }
|
|
|
|
|
2015-04-14 15:55:56 +02:00
|
|
|
private:
|
|
|
|
osg::Vec4f mAmbientColor;
|
2015-04-21 23:27:26 +02:00
|
|
|
osg::Vec4f mFogColor;
|
2015-07-01 03:21:39 +02:00
|
|
|
float mFogStart;
|
2015-04-21 23:27:26 +02:00
|
|
|
float mFogEnd;
|
2015-06-01 17:02:44 +02:00
|
|
|
bool mWireframe;
|
2015-04-14 15:55:56 +02:00
|
|
|
};
|
|
|
|
|
2016-02-09 01:17:02 +01:00
|
|
|
class PreloadCommonAssetsWorkItem : public SceneUtil::WorkItem
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
PreloadCommonAssetsWorkItem(Resource::ResourceSystem* resourceSystem)
|
|
|
|
: mResourceSystem(resourceSystem)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-10-16 22:18:54 +04:00
|
|
|
void doWork() override
|
2016-02-09 01:17:02 +01:00
|
|
|
{
|
2017-02-09 03:32:40 +01:00
|
|
|
try
|
|
|
|
{
|
|
|
|
for (std::vector<std::string>::const_iterator it = mModels.begin(); it != mModels.end(); ++it)
|
2021-09-28 07:07:49 +00:00
|
|
|
mResourceSystem->getSceneManager()->getTemplate(*it);
|
2017-02-09 03:32:40 +01:00
|
|
|
for (std::vector<std::string>::const_iterator it = mTextures.begin(); it != mTextures.end(); ++it)
|
|
|
|
mResourceSystem->getImageManager()->getImage(*it);
|
|
|
|
for (std::vector<std::string>::const_iterator it = mKeyframes.begin(); it != mKeyframes.end(); ++it)
|
|
|
|
mResourceSystem->getKeyframeManager()->get(*it);
|
|
|
|
}
|
|
|
|
catch (std::exception&)
|
|
|
|
{
|
|
|
|
// ignore error (will be shown when these are needed proper)
|
|
|
|
}
|
2016-02-09 01:17:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> mModels;
|
|
|
|
std::vector<std::string> mTextures;
|
2017-02-09 03:32:40 +01:00
|
|
|
std::vector<std::string> mKeyframes;
|
2016-02-09 01:17:02 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
Resource::ResourceSystem* mResourceSystem;
|
|
|
|
};
|
|
|
|
|
2018-04-07 16:11:23 +03:00
|
|
|
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode,
|
2022-06-19 13:28:33 +02:00
|
|
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
|
2023-01-29 11:14:08 -08:00
|
|
|
DetourNavigator::Navigator& navigator, const MWWorld::GroundcoverStore& groundcoverStore,
|
|
|
|
SceneUtil::UnrefQueue& unrefQueue)
|
2022-06-06 22:40:38 +02:00
|
|
|
: mSkyBlending(Settings::Manager::getBool("sky blending", "Fog"))
|
|
|
|
, mViewer(viewer)
|
2015-04-12 15:34:50 +02:00
|
|
|
, mRootNode(rootNode)
|
|
|
|
, mResourceSystem(resourceSystem)
|
2017-02-14 03:37:45 +01:00
|
|
|
, mWorkQueue(workQueue)
|
2018-04-07 16:11:23 +03:00
|
|
|
, mNavigator(navigator)
|
2021-03-30 18:12:57 -07:00
|
|
|
, mMinimumAmbientLuminance(0.f)
|
2015-06-11 23:16:05 +02:00
|
|
|
, mNightEyeFactor(0.f)
|
Initialize RenderingManager fields before use
PostProcessor is constructed before mNearClip, mViewDistance, mFieldOfView are
initialized and the constructor calls updateProjectionMatrix that uses these
fields.
==16218== Conditional jump or move depends on uninitialised value(s)
==16218== at 0x722EBE: min<float> (stl_algobase.h:235)
==16218== by 0x722EBE: MWRender::RenderingManager::updateProjectionMatrix() (renderingmanager.cpp:1183)
==16218== by 0x7D022F: MWRender::PostProcessor::PostProcessor(MWRender::RenderingManager&, osgViewer::Viewer*, osg::Group*) (postprocessor.cpp:144)
==16218== by 0x728B41: MWRender::RenderingManager::RenderingManager(osgViewer::Viewer*, osg::ref_ptr<osg::Group>, Resource::ResourceSystem*, SceneUtil::WorkQueue*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DetourNavigator::Navigator&) (renderingmanager.cpp:452)
==16218== by 0xBB5E65: MWWorld::World::World(osgViewer::Viewer*, osg::ref_ptr<osg::Group>, Resource::ResourceSystem*, SceneUtil::WorkQueue*, Files::Collections const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ToUTF8::Utf8Encoder*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (worldimp.cpp:190)
==16218== by 0xDEEA6F: OMW::Engine::prepareEngine(Settings::Manager&) (engine.cpp:789)
==16218== by 0xDF2068: OMW::Engine::go() (engine.cpp:959)
==16218== by 0xDE7B8F: runApplication(int, char**) (main.cpp:220)
==16218== by 0x1006593: wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (debugging.cpp:205)
==16218== by 0x7152C3: main (main.cpp:232)
==16218==
==17455== Conditional jump or move depends on uninitialised value(s)
==17455== at 0x4F8613F: osg::Matrixd::makeFrustum(double, double, double, double, double, double) (Matrix_implementation.cpp:916)
==17455== by 0x4EC0E11: osg::Camera::setProjectionMatrixAsPerspective(double, double, double, double) (Matrixd:580)
==17455== by 0x722DDA: MWRender::RenderingManager::updateProjectionMatrix() (renderingmanager.cpp:1167)
==17455== by 0x7D01EF: MWRender::PostProcessor::PostProcessor(MWRender::RenderingManager&, osgViewer::Viewer*, osg::Group*) (postprocessor.cpp:144)
==17455== by 0x728BA1: MWRender::RenderingManager::RenderingManager(osgViewer::Viewer*, osg::ref_ptr<osg::Group>, Resource::ResourceSystem*, SceneUtil::WorkQueue*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DetourNavigator::Navigator&) (renderingmanager.cpp:453)
==17455== by 0xBB5E25: MWWorld::World::World(osgViewer::Viewer*, osg::ref_ptr<osg::Group>, Resource::ResourceSystem*, SceneUtil::WorkQueue*, Files::Collections const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, ToUTF8::Utf8Encoder*, int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (worldimp.cpp:190)
==17455== by 0xDEEA3F: OMW::Engine::prepareEngine(Settings::Manager&) (engine.cpp:789)
==17455== by 0xDF2038: OMW::Engine::go() (engine.cpp:959)
==17455== by 0xDE7B5F: runApplication(int, char**) (main.cpp:220)
==17455== by 0x1006563: wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (debugging.cpp:205)
==17455== by 0x7152C3: main (main.cpp:232)
==17455==
2021-10-16 00:22:40 +02:00
|
|
|
// TODO: Near clip should not need to be bounded like this, but too small values break OSG shadow calculations
|
|
|
|
// CPU-side. See issue: #6072
|
2023-05-20 22:23:09 +02:00
|
|
|
, mNearClip(Settings::camera().mNearClip)
|
|
|
|
, mViewDistance(Settings::camera().mViewingDistance)
|
2018-08-01 20:18:37 +04:00
|
|
|
, mFieldOfViewOverridden(false)
|
2017-09-20 11:42:15 -07:00
|
|
|
, mFieldOfViewOverride(0.f)
|
2023-05-20 22:23:09 +02:00
|
|
|
, mFieldOfView(Settings::camera().mFieldOfView)
|
|
|
|
, mFirstPersonFieldOfView(Settings::camera().mFirstPersonFieldOfView)
|
2023-05-23 00:23:47 +02:00
|
|
|
, mGroundCoverStore(groundcoverStore)
|
2014-06-22 16:10:52 +02:00
|
|
|
{
|
2021-11-21 02:25:05 +00:00
|
|
|
bool reverseZ = SceneUtil::AutoDepth::isReversed();
|
2021-04-16 11:55:40 -07:00
|
|
|
auto lightingMethod = SceneUtil::LightManager::getLightingMethodFromString(
|
|
|
|
Settings::Manager::getString("lighting method", "Shaders"));
|
|
|
|
|
2020-04-20 18:47:14 +02:00
|
|
|
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
2022-04-04 22:51:23 +02:00
|
|
|
// Shadows and radial fog have problems with fixed-function mode.
|
2022-06-06 22:40:38 +02:00
|
|
|
bool forceShaders = Settings::Manager::getBool("radial fog", "Fog")
|
|
|
|
|| Settings::Manager::getBool("exponential fog", "Fog")
|
2021-11-20 18:39:20 -08:00
|
|
|
|| Settings::Manager::getBool("soft particles", "Shaders")
|
2021-04-16 11:55:40 -07:00
|
|
|
|| Settings::Manager::getBool("force shaders", "Shaders")
|
|
|
|
|| Settings::Manager::getBool("enable shadows", "Shadows")
|
2021-07-09 10:05:27 -07:00
|
|
|
|| lightingMethod != SceneUtil::LightingMethod::FFP || reverseZ || mSkyBlending || Stereo::getMultiview();
|
2020-03-14 16:39:32 +04:00
|
|
|
resourceSystem->getSceneManager()->setForceShaders(forceShaders);
|
2022-05-09 19:40:48 +00:00
|
|
|
|
2019-02-20 13:37:00 +00:00
|
|
|
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped
|
2021-04-09 17:41:33 -07:00
|
|
|
resourceSystem->getSceneManager()->setClampLighting(Settings::Manager::getBool("clamp lighting", "Shaders"));
|
2016-02-20 17:57:19 +01:00
|
|
|
resourceSystem->getSceneManager()->setAutoUseNormalMaps(
|
|
|
|
Settings::Manager::getBool("auto use object normal maps", "Shaders"));
|
|
|
|
resourceSystem->getSceneManager()->setNormalMapPattern(
|
|
|
|
Settings::Manager::getString("normal map pattern", "Shaders"));
|
2016-03-22 21:00:31 +01:00
|
|
|
resourceSystem->getSceneManager()->setNormalHeightMapPattern(
|
|
|
|
Settings::Manager::getString("normal height map pattern", "Shaders"));
|
2016-02-20 19:02:11 +01:00
|
|
|
resourceSystem->getSceneManager()->setAutoUseSpecularMaps(
|
|
|
|
Settings::Manager::getBool("auto use object specular maps", "Shaders"));
|
|
|
|
resourceSystem->getSceneManager()->setSpecularMapPattern(
|
|
|
|
Settings::Manager::getString("specular map pattern", "Shaders"));
|
2020-11-09 13:53:58 +03:00
|
|
|
resourceSystem->getSceneManager()->setApplyLightingToEnvMaps(
|
|
|
|
Settings::Manager::getBool("apply lighting to environment maps", "Shaders"));
|
2021-02-24 18:01:06 +00:00
|
|
|
resourceSystem->getSceneManager()->setConvertAlphaTestToAlphaToCoverage(
|
|
|
|
Settings::Manager::getBool("antialias alpha test", "Shaders")
|
|
|
|
&& Settings::Manager::getInt("antialiasing", "Video") > 1);
|
2022-12-09 00:22:08 +00:00
|
|
|
resourceSystem->getSceneManager()->setAdjustCoverageForAlphaTest(
|
|
|
|
Settings::Manager::getBool("adjust coverage for alpha test", "Shaders"));
|
2022-09-22 21:26:05 +03:00
|
|
|
|
2021-04-09 17:41:33 -07:00
|
|
|
// Let LightManager choose which backend to use based on our hint. For methods besides legacy lighting, this
|
|
|
|
// depends on support for various OpenGL extensions.
|
2021-04-16 11:55:40 -07:00
|
|
|
osg::ref_ptr<SceneUtil::LightManager> sceneRoot
|
|
|
|
= new SceneUtil::LightManager(lightingMethod == SceneUtil::LightingMethod::FFP);
|
2021-03-14 21:42:34 -07:00
|
|
|
resourceSystem->getSceneManager()->setLightingMethod(sceneRoot->getLightingMethod());
|
2021-04-16 11:55:40 -07:00
|
|
|
resourceSystem->getSceneManager()->setSupportedLightingMethods(sceneRoot->getSupportedLightingMethods());
|
2021-04-03 22:25:13 -07:00
|
|
|
mMinimumAmbientLuminance
|
|
|
|
= std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);
|
2021-03-30 18:12:57 -07:00
|
|
|
|
2020-04-20 18:47:14 +02:00
|
|
|
sceneRoot->setLightingMask(Mask_Lighting);
|
2016-02-08 16:45:56 +01:00
|
|
|
mSceneRoot = sceneRoot;
|
|
|
|
sceneRoot->setStartLight(1);
|
2019-06-21 13:37:00 +00:00
|
|
|
sceneRoot->setNodeMask(Mask_Scene);
|
|
|
|
sceneRoot->setName("Scene Root");
|
2012-07-20 16:44:03 +02:00
|
|
|
|
2020-04-20 18:47:14 +02:00
|
|
|
int shadowCastingTraversalMask = Mask_Scene;
|
2017-12-27 02:32:17 +00:00
|
|
|
if (Settings::Manager::getBool("actor shadows", "Shadows"))
|
2020-04-20 18:47:14 +02:00
|
|
|
shadowCastingTraversalMask |= Mask_Actor;
|
2017-12-27 02:32:17 +00:00
|
|
|
if (Settings::Manager::getBool("player shadows", "Shadows"))
|
2020-04-20 18:47:14 +02:00
|
|
|
shadowCastingTraversalMask |= Mask_Player;
|
2018-03-03 15:13:36 +00:00
|
|
|
|
|
|
|
int indoorShadowCastingTraversalMask = shadowCastingTraversalMask;
|
|
|
|
if (Settings::Manager::getBool("object shadows", "Shadows"))
|
2020-04-20 18:47:14 +02:00
|
|
|
shadowCastingTraversalMask |= (Mask_Object | Mask_Static);
|
2021-10-11 09:27:50 +00:00
|
|
|
if (Settings::Manager::getBool("terrain shadows", "Shadows"))
|
|
|
|
shadowCastingTraversalMask |= Mask_Terrain;
|
2019-02-27 19:41:07 +04:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mShadowManager = std::make_unique<SceneUtil::ShadowManager>(sceneRoot, mRootNode, shadowCastingTraversalMask,
|
|
|
|
indoorShadowCastingTraversalMask, Mask_Terrain | Mask_Object | Mask_Static,
|
|
|
|
mResourceSystem->getSceneManager()->getShaderManager());
|
2017-04-14 15:32:18 +02:00
|
|
|
|
2018-02-26 22:27:09 +00:00
|
|
|
Shader::ShaderManager::DefineMap shadowDefines = mShadowManager->getShadowDefines();
|
2021-02-21 10:38:15 -08:00
|
|
|
Shader::ShaderManager::DefineMap lightDefines = sceneRoot->getLightDefines();
|
2017-11-22 20:07:07 +00:00
|
|
|
Shader::ShaderManager::DefineMap globalDefines
|
|
|
|
= mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
2017-11-22 20:54:39 +00:00
|
|
|
|
|
|
|
for (auto itr = shadowDefines.begin(); itr != shadowDefines.end(); itr++)
|
|
|
|
globalDefines[itr->first] = itr->second;
|
|
|
|
|
2019-02-20 13:37:00 +00:00
|
|
|
globalDefines["forcePPL"] = Settings::Manager::getBool("force per pixel lighting", "Shaders") ? "1" : "0";
|
|
|
|
globalDefines["clamp"] = Settings::Manager::getBool("clamp lighting", "Shaders") ? "1" : "0";
|
2020-03-03 20:08:59 +03:00
|
|
|
globalDefines["preLightEnv"]
|
|
|
|
= Settings::Manager::getBool("apply lighting to environment maps", "Shaders") ? "1" : "0";
|
2022-06-06 22:40:38 +02:00
|
|
|
bool exponentialFog = Settings::Manager::getBool("exponential fog", "Fog");
|
|
|
|
globalDefines["radialFog"] = (exponentialFog || Settings::Manager::getBool("radial fog", "Fog")) ? "1" : "0";
|
|
|
|
globalDefines["exponentialFog"] = exponentialFog ? "1" : "0";
|
|
|
|
globalDefines["skyBlending"] = mSkyBlending ? "1" : "0";
|
2022-05-13 18:58:00 -07:00
|
|
|
globalDefines["refraction_enabled"] = "0";
|
2021-01-07 18:13:51 +00:00
|
|
|
globalDefines["useGPUShader4"] = "0";
|
2022-04-04 22:51:23 +02:00
|
|
|
globalDefines["useOVR_multiview"] = "0";
|
|
|
|
globalDefines["numViews"] = "1";
|
2022-05-13 18:58:00 -07:00
|
|
|
globalDefines["disableNormals"] = "1";
|
2019-02-20 13:37:00 +00:00
|
|
|
|
2021-03-14 21:42:34 -07:00
|
|
|
for (auto itr = lightDefines.begin(); itr != lightDefines.end(); itr++)
|
|
|
|
globalDefines[itr->first] = itr->second;
|
2019-02-20 13:37:00 +00:00
|
|
|
|
2021-04-18 21:44:23 +01:00
|
|
|
// Refactor this at some point - most shaders don't care about these defines
|
2021-05-12 09:18:54 +04:00
|
|
|
float groundcoverDistance = std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover"));
|
2021-01-11 09:59:57 +04:00
|
|
|
globalDefines["groundcoverFadeStart"] = std::to_string(groundcoverDistance * 0.9f);
|
2020-01-12 11:42:47 +04:00
|
|
|
globalDefines["groundcoverFadeEnd"] = std::to_string(groundcoverDistance);
|
2021-04-18 21:44:23 +01:00
|
|
|
globalDefines["groundcoverStompMode"]
|
|
|
|
= std::to_string(std::clamp(Settings::Manager::getInt("stomp mode", "Groundcover"), 0, 2));
|
|
|
|
globalDefines["groundcoverStompIntensity"]
|
|
|
|
= std::to_string(std::clamp(Settings::Manager::getInt("stomp intensity", "Groundcover"), 0, 2));
|
2021-03-29 00:13:35 -07:00
|
|
|
|
2021-06-01 12:15:25 -07:00
|
|
|
globalDefines["reverseZ"] = reverseZ ? "1" : "0";
|
|
|
|
|
2017-12-17 23:55:19 +00:00
|
|
|
// It is unnecessary to stop/start the viewer as no frames are being rendered yet.
|
|
|
|
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(globalDefines);
|
2011-11-03 23:47:15 -04:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mNavMesh = std::make_unique<NavMesh>(mRootNode, mWorkQueue,
|
|
|
|
Settings::Manager::getBool("enable nav mesh render", "Navigator"),
|
|
|
|
parseNavMeshMode(Settings::Manager::getString("nav mesh render mode", "Navigator")));
|
|
|
|
mActorsPaths = std::make_unique<ActorsPaths>(
|
|
|
|
mRootNode, Settings::Manager::getBool("enable agents paths render", "Navigator"));
|
|
|
|
mRecastMesh = std::make_unique<RecastMesh>(
|
|
|
|
mRootNode, Settings::Manager::getBool("enable recast mesh render", "Navigator"));
|
|
|
|
mPathgrid = std::make_unique<Pathgrid>(mRootNode);
|
2015-05-02 22:45:27 +02:00
|
|
|
|
2022-07-24 20:55:03 +02:00
|
|
|
mObjects = std::make_unique<Objects>(mResourceSystem, sceneRoot, unrefQueue);
|
2012-02-26 13:13:29 +01:00
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
if (getenv("OPENMW_DONT_PRECOMPILE") == nullptr)
|
2018-02-13 00:40:41 +00:00
|
|
|
{
|
2017-02-15 20:57:12 +01:00
|
|
|
mViewer->setIncrementalCompileOperation(new osgUtil::IncrementalCompileOperation);
|
2023-05-22 14:23:06 +02:00
|
|
|
mViewer->getIncrementalCompileOperation()->setTargetFrameRate(Settings::cells().mTargetFramerate);
|
2018-02-13 00:40:41 +00:00
|
|
|
}
|
2015-05-03 18:16:54 +02:00
|
|
|
|
2022-09-02 13:40:41 +02:00
|
|
|
mDebugDraw
|
|
|
|
= std::make_unique<Debug::DebugDrawer>(mResourceSystem->getSceneManager()->getShaderManager(), mRootNode);
|
2015-05-26 20:20:18 +02:00
|
|
|
mResourceSystem->getSceneManager()->setIncrementalCompileOperation(mViewer->getIncrementalCompileOperation());
|
2015-05-03 18:16:54 +02:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mEffectManager = std::make_unique<EffectManager>(sceneRoot, mResourceSystem);
|
2015-06-02 16:35:35 +02:00
|
|
|
|
2022-08-28 16:38:11 +02:00
|
|
|
const std::string& normalMapPattern = Settings::Manager::getString("normal map pattern", "Shaders");
|
|
|
|
const std::string& heightMapPattern = Settings::Manager::getString("normal height map pattern", "Shaders");
|
|
|
|
const std::string& specularMapPattern = Settings::Manager::getString("terrain specular map pattern", "Shaders");
|
2019-02-27 19:41:07 +04:00
|
|
|
const bool useTerrainNormalMaps = Settings::Manager::getBool("auto use terrain normal maps", "Shaders");
|
|
|
|
const bool useTerrainSpecularMaps = Settings::Manager::getBool("auto use terrain specular maps", "Shaders");
|
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mTerrainStorage = std::make_unique<TerrainStorage>(mResourceSystem, normalMapPattern, heightMapPattern,
|
|
|
|
useTerrainNormalMaps, specularMapPattern, useTerrainSpecularMaps);
|
2017-03-09 03:49:40 +01:00
|
|
|
|
2023-05-23 00:23:47 +02:00
|
|
|
WorldspaceChunkMgr& chunkMgr = getWorldspaceChunkMgr(ESM::Cell::sDefaultWorldspaceId);
|
|
|
|
mTerrain = chunkMgr.mTerrain.get();
|
|
|
|
mGroundcover = chunkMgr.mGroundcover.get();
|
|
|
|
mObjectPaging = chunkMgr.mObjectPaging.get();
|
2021-07-09 10:05:27 -07:00
|
|
|
|
2021-08-17 17:45:50 -07:00
|
|
|
mStateUpdater = new StateUpdater;
|
2021-09-20 18:17:55 +00:00
|
|
|
sceneRoot->addUpdateCallback(mStateUpdater);
|
2021-08-17 17:45:50 -07:00
|
|
|
|
2023-04-01 09:09:45 +04:00
|
|
|
mSharedUniformStateUpdater = new SharedUniformStateUpdater();
|
2021-08-17 17:45:50 -07:00
|
|
|
rootNode->addUpdateCallback(mSharedUniformStateUpdater);
|
|
|
|
|
2022-06-29 18:15:12 -07:00
|
|
|
mPerViewUniformStateUpdater = new PerViewUniformStateUpdater(mResourceSystem->getSceneManager());
|
2022-04-04 22:51:23 +02:00
|
|
|
rootNode->addCullCallback(mPerViewUniformStateUpdater);
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
mPostProcessor = new PostProcessor(*this, viewer, mRootNode, resourceSystem->getVFS());
|
|
|
|
resourceSystem->getSceneManager()->setOpaqueDepthTex(
|
|
|
|
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 0),
|
|
|
|
mPostProcessor->getTexture(PostProcessor::Tex_OpaqueDepth, 1));
|
2022-07-02 09:42:15 -07:00
|
|
|
resourceSystem->getSceneManager()->setSoftParticles(mPostProcessor->softParticlesEnabled());
|
2022-05-13 18:58:00 -07:00
|
|
|
resourceSystem->getSceneManager()->setSupportsNormalsRT(mPostProcessor->getSupportsNormalsRT());
|
2021-08-04 17:49:57 -07:00
|
|
|
|
2019-06-13 13:37:00 +00:00
|
|
|
// water goes after terrain for correct waterculling order
|
2023-01-29 11:14:08 -08:00
|
|
|
mWater = std::make_unique<Water>(
|
|
|
|
sceneRoot->getParent(0), sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation());
|
2022-05-09 19:40:48 +00:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mCamera = std::make_unique<Camera>(mViewer->getCamera());
|
2015-05-21 23:54:39 +02:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mScreenshotManager
|
|
|
|
= std::make_unique<ScreenshotManager>(viewer, mRootNode, sceneRoot, mResourceSystem, mWater.get());
|
2021-01-08 19:33:51 +04:00
|
|
|
|
2015-05-14 21:42:04 +02:00
|
|
|
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
2011-11-03 23:47:15 -04:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
2020-04-20 18:47:14 +02:00
|
|
|
source->setNodeMask(Mask_Lighting);
|
2015-04-12 15:34:50 +02:00
|
|
|
mSunLight = new osg::Light;
|
|
|
|
source->setLight(mSunLight);
|
|
|
|
mSunLight->setDiffuse(osg::Vec4f(0, 0, 0, 1));
|
|
|
|
mSunLight->setAmbient(osg::Vec4f(0, 0, 0, 1));
|
2015-05-26 18:22:21 +02:00
|
|
|
mSunLight->setSpecular(osg::Vec4f(0, 0, 0, 0));
|
2015-04-12 15:34:50 +02:00
|
|
|
mSunLight->setConstantAttenuation(1.f);
|
2021-02-21 10:38:15 -08:00
|
|
|
sceneRoot->setSunlight(mSunLight);
|
2016-02-08 16:45:56 +01:00
|
|
|
sceneRoot->addChild(source);
|
2011-11-03 23:47:15 -04:00
|
|
|
|
2016-02-08 16:45:56 +01:00
|
|
|
sceneRoot->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
|
|
|
sceneRoot->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
|
|
|
|
sceneRoot->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
|
2017-02-01 03:18:17 +01:00
|
|
|
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));
|
|
|
|
sceneRoot->getOrCreateStateSet()->setAttribute(defaultMat);
|
2021-10-01 08:11:00 +00:00
|
|
|
sceneRoot->getOrCreateStateSet()->addUniform(new osg::Uniform("emissiveMult", 1.f));
|
2021-11-10 19:58:06 +03:00
|
|
|
sceneRoot->getOrCreateStateSet()->addUniform(new osg::Uniform("specStrength", 1.f));
|
2015-04-14 15:55:56 +02:00
|
|
|
|
2022-05-29 13:24:48 +02:00
|
|
|
mFog = std::make_unique<FogManager>();
|
2017-10-24 14:12:41 +02:00
|
|
|
|
2023-01-06 22:23:03 -08:00
|
|
|
mSky = std::make_unique<SkyManager>(
|
|
|
|
sceneRoot, mRootNode, mViewer->getCamera(), resourceSystem->getSceneManager(), mSkyBlending);
|
2022-06-06 22:40:38 +02:00
|
|
|
if (mSkyBlending)
|
|
|
|
{
|
2022-06-29 18:15:12 -07:00
|
|
|
int skyTextureUnit = mResourceSystem->getSceneManager()->getShaderManager().reserveGlobalTextureUnits(
|
|
|
|
Shader::ShaderManager::Slot::SkyTexture);
|
2022-06-06 22:40:38 +02:00
|
|
|
mPerViewUniformStateUpdater->enableSkyRTT(skyTextureUnit, mSky->getSkyRTT());
|
|
|
|
}
|
2015-04-30 23:21:25 +02:00
|
|
|
|
2015-04-14 15:55:56 +02:00
|
|
|
source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON);
|
|
|
|
|
2015-04-21 23:27:26 +02:00
|
|
|
osg::Camera::CullingMode cullingMode = osg::Camera::DEFAULT_CULLING | osg::Camera::FAR_PLANE_CULLING;
|
2011-11-03 23:47:15 -04:00
|
|
|
|
2023-05-20 22:23:09 +02:00
|
|
|
if (!Settings::camera().mSmallFeatureCulling)
|
2015-05-14 18:46:04 +02:00
|
|
|
cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING);
|
|
|
|
else
|
2017-02-01 05:38:59 +01:00
|
|
|
{
|
2023-05-20 22:23:09 +02:00
|
|
|
mViewer->getCamera()->setSmallFeatureCullingPixelSize(Settings::camera().mSmallFeatureCullingPixelSize);
|
2015-05-14 18:46:04 +02:00
|
|
|
cullingMode |= osg::CullStack::SMALL_FEATURE_CULLING;
|
2017-02-01 05:38:59 +01:00
|
|
|
}
|
2015-04-21 23:27:26 +02:00
|
|
|
|
2015-05-14 21:42:04 +02:00
|
|
|
mViewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
|
|
|
mViewer->getCamera()->setCullingMode(cullingMode);
|
2022-05-14 22:53:53 -07:00
|
|
|
mViewer->getCamera()->setName(Constants::SceneCamera);
|
2015-04-21 23:27:26 +02:00
|
|
|
|
2022-04-04 22:51:23 +02:00
|
|
|
auto mask = ~(Mask_UpdateVisitor | Mask_SimpleWater);
|
|
|
|
MWBase::Environment::get().getWindowManager()->setCullMask(mask);
|
2020-04-22 13:34:19 +02:00
|
|
|
NifOsg::Loader::setHiddenNodeMask(Mask_UpdateVisitor);
|
2020-04-29 16:20:03 +03:00
|
|
|
NifOsg::Loader::setIntersectionDisabledNodeMask(Mask_Effect);
|
2022-09-17 19:24:42 +02:00
|
|
|
Nif::Reader::setLoadUnsupportedFiles(Settings::Manager::getBool("load unsupported nif files", "Models"));
|
2023-02-08 21:36:05 +01:00
|
|
|
Nif::Reader::setWriteNifDebugLog(Settings::Manager::getBool("write nif debug log", "Models"));
|
2015-05-20 03:35:52 +02:00
|
|
|
|
2015-06-02 16:35:35 +02:00
|
|
|
mStateUpdater->setFogEnd(mViewDistance);
|
2015-10-28 18:59:35 +01:00
|
|
|
|
2020-12-18 00:02:51 +00:00
|
|
|
// Hopefully, anything genuinely requiring the default alpha func of GL_ALWAYS explicitly sets it
|
2020-12-18 16:31:21 +00:00
|
|
|
mRootNode->getOrCreateStateSet()->setAttribute(Shader::RemovedAlphaFunc::getInstance(GL_ALWAYS));
|
2021-01-02 02:50:19 +00:00
|
|
|
// The transparent renderbin sets alpha testing on because that was faster on old GPUs. It's now slower and
|
|
|
|
// breaks things.
|
|
|
|
mRootNode->getOrCreateStateSet()->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
|
2020-12-18 00:02:51 +00:00
|
|
|
|
2021-06-01 12:15:25 -07:00
|
|
|
if (reverseZ)
|
|
|
|
{
|
|
|
|
osg::ref_ptr<osg::ClipControl> clipcontrol
|
|
|
|
= new osg::ClipControl(osg::ClipControl::LOWER_LEFT, osg::ClipControl::ZERO_TO_ONE);
|
2021-11-21 02:25:05 +00:00
|
|
|
mRootNode->getOrCreateStateSet()->setAttributeAndModes(new SceneUtil::AutoDepth, osg::StateAttribute::ON);
|
2021-06-01 12:15:25 -07:00
|
|
|
mRootNode->getOrCreateStateSet()->setAttributeAndModes(clipcontrol, osg::StateAttribute::ON);
|
|
|
|
}
|
|
|
|
|
2021-08-04 17:49:57 -07:00
|
|
|
SceneUtil::setCameraClearDepth(mViewer->getCamera());
|
|
|
|
|
2017-09-26 14:14:28 +02:00
|
|
|
updateProjectionMatrix();
|
2022-02-07 11:51:59 -08:00
|
|
|
|
|
|
|
mViewer->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
RenderingManager::~RenderingManager()
|
|
|
|
{
|
2016-08-14 18:10:29 +02:00
|
|
|
// let background loading thread finish before we delete anything else
|
2018-10-09 10:21:12 +04:00
|
|
|
mWorkQueue = nullptr;
|
2013-02-03 15:46:23 +01:00
|
|
|
}
|
2012-02-24 16:12:43 +01:00
|
|
|
|
2019-11-24 17:40:19 +04:00
|
|
|
osgUtil::IncrementalCompileOperation* RenderingManager::getIncrementalCompileOperation()
|
|
|
|
{
|
|
|
|
return mViewer->getIncrementalCompileOperation();
|
|
|
|
}
|
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
MWRender::Objects& RenderingManager::getObjects()
|
2014-03-05 21:45:43 +01:00
|
|
|
{
|
2015-04-12 15:34:50 +02:00
|
|
|
return *mObjects.get();
|
2014-03-05 21:45:43 +01:00
|
|
|
}
|
2014-02-18 16:44:37 +01:00
|
|
|
|
2015-04-12 15:34:50 +02:00
|
|
|
Resource::ResourceSystem* RenderingManager::getResourceSystem()
|
2012-05-14 21:37:43 +02:00
|
|
|
{
|
2015-04-12 15:34:50 +02:00
|
|
|
return mResourceSystem;
|
2012-05-14 21:37:43 +02:00
|
|
|
}
|
|
|
|
|
2016-02-09 20:57:30 +01:00
|
|
|
SceneUtil::WorkQueue* RenderingManager::getWorkQueue()
|
2016-02-09 01:02:40 +01:00
|
|
|
{
|
|
|
|
return mWorkQueue.get();
|
|
|
|
}
|
|
|
|
|
2016-02-09 20:57:30 +01:00
|
|
|
Terrain::World* RenderingManager::getTerrain()
|
|
|
|
{
|
2023-05-14 20:00:02 +02:00
|
|
|
return mTerrain;
|
2016-02-09 20:57:30 +01:00
|
|
|
}
|
|
|
|
|
2016-02-09 01:17:02 +01:00
|
|
|
void RenderingManager::preloadCommonAssets()
|
|
|
|
{
|
|
|
|
osg::ref_ptr<PreloadCommonAssetsWorkItem> workItem(new PreloadCommonAssetsWorkItem(mResourceSystem));
|
|
|
|
mSky->listAssetsToPreload(workItem->mModels, workItem->mTextures);
|
|
|
|
mWater->listAssetsToPreload(workItem->mTextures);
|
|
|
|
|
2020-12-30 22:11:32 +02:00
|
|
|
workItem->mModels.push_back(Settings::Manager::getString("xbaseanim", "Models"));
|
|
|
|
workItem->mModels.push_back(Settings::Manager::getString("xbaseanim1st", "Models"));
|
|
|
|
workItem->mModels.push_back(Settings::Manager::getString("xbaseanimfemale", "Models"));
|
|
|
|
workItem->mModels.push_back(Settings::Manager::getString("xargonianswimkna", "Models"));
|
|
|
|
|
|
|
|
workItem->mKeyframes.push_back(Settings::Manager::getString("xbaseanimkf", "Models"));
|
|
|
|
workItem->mKeyframes.push_back(Settings::Manager::getString("xbaseanim1stkf", "Models"));
|
|
|
|
workItem->mKeyframes.push_back(Settings::Manager::getString("xbaseanimfemalekf", "Models"));
|
|
|
|
workItem->mKeyframes.push_back(Settings::Manager::getString("xargonianswimknakf", "Models"));
|
2017-02-09 03:32:40 +01:00
|
|
|
|
2020-10-17 12:26:35 +04:00
|
|
|
workItem->mTextures.emplace_back("textures/_land_default.dds");
|
2016-02-09 01:17:02 +01:00
|
|
|
|
2021-07-10 12:11:48 +02:00
|
|
|
mWorkQueue->addWorkItem(std::move(workItem));
|
2016-02-09 01:17:02 +01:00
|
|
|
}
|
|
|
|
|
2016-02-07 00:36:31 +01:00
|
|
|
double RenderingManager::getReferenceTime() const
|
|
|
|
{
|
|
|
|
return mViewer->getFrameStamp()->getReferenceTime();
|
|
|
|
}
|
|
|
|
|
2022-05-14 22:53:53 -07:00
|
|
|
SceneUtil::LightManager* RenderingManager::getLightRoot()
|
2015-12-05 00:44:04 +01:00
|
|
|
{
|
2016-02-08 16:45:56 +01:00
|
|
|
return mSceneRoot.get();
|
2015-12-05 00:44:04 +01:00
|
|
|
}
|
|
|
|
|
2015-06-11 23:16:05 +02:00
|
|
|
void RenderingManager::setNightEyeFactor(float factor)
|
|
|
|
{
|
|
|
|
if (factor != mNightEyeFactor)
|
|
|
|
{
|
|
|
|
mNightEyeFactor = factor;
|
|
|
|
updateAmbient();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-14 15:55:56 +02:00
|
|
|
void RenderingManager::setAmbientColour(const osg::Vec4f& colour)
|
|
|
|
{
|
2015-06-11 23:16:05 +02:00
|
|
|
mAmbientColor = colour;
|
|
|
|
updateAmbient();
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
2015-06-16 20:56:48 +02:00
|
|
|
void RenderingManager::skySetDate(int day, int month)
|
|
|
|
{
|
|
|
|
mSky->setDate(day, month);
|
|
|
|
}
|
|
|
|
|
|
|
|
int RenderingManager::skyGetMasserPhase() const
|
|
|
|
{
|
|
|
|
return mSky->getMasserPhase();
|
|
|
|
}
|
|
|
|
|
|
|
|
int RenderingManager::skyGetSecundaPhase() const
|
|
|
|
{
|
|
|
|
return mSky->getSecundaPhase();
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::skySetMoonColour(bool red)
|
|
|
|
{
|
|
|
|
mSky->setMoonColour(red);
|
|
|
|
}
|
|
|
|
|
2023-01-27 01:13:17 +01:00
|
|
|
void RenderingManager::configureAmbient(const MWWorld::Cell& cell)
|
2012-05-23 01:32:36 +02:00
|
|
|
{
|
2023-01-27 01:13:17 +01:00
|
|
|
bool isInterior = !cell.isExterior() && !cell.isQuasiExterior();
|
2021-03-31 22:35:02 -07:00
|
|
|
bool needsAdjusting = false;
|
|
|
|
if (mResourceSystem->getSceneManager()->getLightingMethod() != SceneUtil::LightingMethod::FFP)
|
2022-05-13 18:58:00 -07:00
|
|
|
needsAdjusting = isInterior;
|
2021-03-31 22:35:02 -07:00
|
|
|
|
2023-01-27 01:13:17 +01:00
|
|
|
osg::Vec4f ambient = SceneUtil::colourFromRGB(cell.getMood().mAmbiantColor);
|
2021-03-31 22:35:02 -07:00
|
|
|
|
|
|
|
if (needsAdjusting)
|
|
|
|
{
|
2021-04-09 17:41:33 -07:00
|
|
|
constexpr float pR = 0.2126;
|
|
|
|
constexpr float pG = 0.7152;
|
|
|
|
constexpr float pB = 0.0722;
|
2021-03-31 22:35:02 -07:00
|
|
|
|
|
|
|
// we already work in linear RGB so no conversions are needed for the luminosity function
|
|
|
|
float relativeLuminance = pR * ambient.r() + pG * ambient.g() + pB * ambient.b();
|
|
|
|
if (relativeLuminance < mMinimumAmbientLuminance)
|
|
|
|
{
|
|
|
|
// brighten ambient so it reaches the minimum threshold but no more, we want to mess with content data
|
|
|
|
// as least we can
|
|
|
|
if (ambient.r() == 0.f && ambient.g() == 0.f && ambient.b() == 0.f)
|
2021-04-16 11:55:40 -07:00
|
|
|
ambient = osg::Vec4(
|
|
|
|
mMinimumAmbientLuminance, mMinimumAmbientLuminance, mMinimumAmbientLuminance, ambient.a());
|
2021-03-31 22:35:02 -07:00
|
|
|
else
|
Avoid unnecessary computation
And fix UBSAN error:
/home/elsid/dev/openmw/apps/openmw/mwrender/renderingmanager.cpp:659:81: runtime error: division by zero
#0 0x556eac16f4dc in MWRender::RenderingManager::configureAmbient(ESM::Cell const*) /home/elsid/dev/openmw/apps/openmw/mwrender/renderingmanager.cpp:659
#1 0x556eadfd3d60 in MWWorld::Scene::loadCell(MWWorld::CellStore*, Loading::Listener*, bool, osg::Vec3f const&) /home/elsid/dev/openmw/apps/openmw/mwworld/scene.cpp:467
#2 0x556eadfe3047 in MWWorld::Scene::changeToInteriorCell(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ESM::Position const&, bool, bool) /home/elsid/dev/openmw/apps/openmw/mwworld/scene.cpp:830
#3 0x556eadeb8fb3 in MWWorld::World::changeToInteriorCell(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ESM::Position const&, bool, bool) /home/elsid/dev/openmw/apps/openmw/mwworld/worldimp.cpp:978
#4 0x556eadeba5f1 in MWWorld::World::changeToCell(ESM::CellId const&, ESM::Position const&, bool, bool) /home/elsid/dev/openmw/apps/openmw/mwworld/worldimp.cpp:1008
#5 0x556eaeb852dd in MWState::StateManager::loadGame(MWState::Character const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:533
#6 0x556eaeb81674 in MWState::StateManager::loadGame(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/elsid/dev/openmw/apps/openmw/mwstate/statemanagerimp.cpp:366
#7 0x556eaebd2aae in OMW::Engine::go() /home/elsid/dev/openmw/apps/openmw/engine.cpp:1025
#8 0x556eaeba810a in runApplication(int, char**) /home/elsid/dev/openmw/apps/openmw/main.cpp:221
#9 0x556eaf865e9a in wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/elsid/dev/openmw/components/debug/debugging.cpp:205
#10 0x556eaeba8368 in main /home/elsid/dev/openmw/apps/openmw/main.cpp:233
#11 0x7f89773b3b24 in __libc_start_main (/usr/lib/libc.so.6+0x27b24)
#12 0x556eac13c09d in _start (/home/elsid/dev/openmw/build/gcc/ubsan/openmw+0x669c09d)
2022-02-03 00:04:28 +01:00
|
|
|
ambient *= mMinimumAmbientLuminance / relativeLuminance;
|
2021-03-31 22:35:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setAmbientColour(ambient);
|
2012-05-29 04:54:54 +02:00
|
|
|
|
2023-01-27 01:13:17 +01:00
|
|
|
osg::Vec4f diffuse = SceneUtil::colourFromRGB(cell.getMood().mDirectionalColor);
|
2023-01-22 23:40:55 +01:00
|
|
|
|
2023-01-03 10:16:30 -08:00
|
|
|
setSunColour(diffuse, diffuse, 1.f);
|
|
|
|
|
|
|
|
const osg::Vec4f interiorSunPos = osg::Vec4f(-0.15f, 0.15f, 1.f, 0.f);
|
|
|
|
mPostProcessor->getStateUpdater()->setSunPos(interiorSunPos, false);
|
|
|
|
mSunLight->setPosition(interiorSunPos);
|
2012-05-27 21:39:18 +02:00
|
|
|
}
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
void RenderingManager::setSunColour(const osg::Vec4f& diffuse, const osg::Vec4f& specular, float sunVis)
|
2015-04-14 15:55:56 +02:00
|
|
|
{
|
2015-05-26 18:22:21 +02:00
|
|
|
// need to wrap this in a StateUpdater?
|
2016-05-10 17:39:57 +02:00
|
|
|
mSunLight->setDiffuse(diffuse);
|
|
|
|
mSunLight->setSpecular(specular);
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
mPostProcessor->getStateUpdater()->setSunColor(diffuse);
|
|
|
|
mPostProcessor->getStateUpdater()->setSunVis(sunVis);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::setSunDirection(const osg::Vec3f& direction)
|
|
|
|
{
|
2015-05-20 02:07:18 +02:00
|
|
|
osg::Vec3 position = direction * -1;
|
2015-05-26 18:22:21 +02:00
|
|
|
// need to wrap this in a StateUpdater?
|
2015-05-20 02:07:18 +02:00
|
|
|
mSunLight->setPosition(osg::Vec4(position.x(), position.y(), position.z(), 0));
|
2015-04-14 15:55:56 +02:00
|
|
|
|
2015-05-20 02:07:18 +02:00
|
|
|
mSky->setSunDirection(position);
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
mPostProcessor->getStateUpdater()->setSunPos(mSunLight->getPosition(), mNight);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
2015-05-02 22:45:27 +02:00
|
|
|
void RenderingManager::addCell(const MWWorld::CellStore* store)
|
|
|
|
{
|
2015-05-04 17:41:30 +02:00
|
|
|
mPathgrid->addCell(store);
|
2015-06-02 16:35:35 +02:00
|
|
|
|
|
|
|
mWater->changeCell(store);
|
2015-06-03 01:18:36 +02:00
|
|
|
|
|
|
|
if (store->getCell()->isExterior())
|
2020-01-12 11:42:47 +04:00
|
|
|
{
|
2023-05-19 00:16:58 +02:00
|
|
|
enableTerrain(true, store->getCell()->getWorldSpace());
|
2015-06-03 01:18:36 +02:00
|
|
|
mTerrain->loadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
2020-01-12 11:42:47 +04:00
|
|
|
}
|
2015-05-02 22:45:27 +02:00
|
|
|
}
|
2015-04-12 15:34:50 +02:00
|
|
|
void RenderingManager::removeCell(const MWWorld::CellStore* store)
|
2013-08-20 09:52:27 +02:00
|
|
|
{
|
2015-05-04 17:41:30 +02:00
|
|
|
mPathgrid->removeCell(store);
|
2018-07-21 13:37:02 +03:00
|
|
|
mActorsPaths->removeCell(store);
|
2015-04-12 15:34:50 +02:00
|
|
|
mObjects->removeCell(store);
|
2015-06-03 01:18:36 +02:00
|
|
|
|
|
|
|
if (store->getCell()->isExterior())
|
2020-01-12 11:42:47 +04:00
|
|
|
{
|
2023-05-23 00:23:47 +02:00
|
|
|
getWorldspaceChunkMgr(store->getCell()->getWorldSpace())
|
|
|
|
.mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
2020-01-12 11:42:47 +04:00
|
|
|
}
|
2015-06-16 20:36:48 +02:00
|
|
|
|
|
|
|
mWater->removeCell(store);
|
2013-08-20 09:52:27 +02:00
|
|
|
}
|
2012-05-23 01:32:36 +02:00
|
|
|
|
2023-05-14 22:00:13 +02:00
|
|
|
void RenderingManager::enableTerrain(bool enable, ESM::RefId worldspace)
|
2017-03-09 02:17:25 +01:00
|
|
|
{
|
2019-06-13 13:37:00 +00:00
|
|
|
if (!enable)
|
|
|
|
mWater->setCullCallback(nullptr);
|
2023-05-14 22:00:13 +02:00
|
|
|
else
|
2023-05-18 11:56:45 +02:00
|
|
|
{
|
2023-05-23 00:23:47 +02:00
|
|
|
WorldspaceChunkMgr& newChunks = getWorldspaceChunkMgr(worldspace);
|
|
|
|
if (newChunks.mTerrain.get() != mTerrain)
|
2023-05-18 11:56:45 +02:00
|
|
|
{
|
|
|
|
mTerrain->enable(false);
|
2023-05-23 00:23:47 +02:00
|
|
|
mTerrain = newChunks.mTerrain.get();
|
|
|
|
mGroundcover = newChunks.mGroundcover.get();
|
|
|
|
mObjectPaging = newChunks.mObjectPaging.get();
|
2023-05-18 11:56:45 +02:00
|
|
|
}
|
|
|
|
}
|
2017-03-09 02:17:25 +01:00
|
|
|
mTerrain->enable(enable);
|
|
|
|
}
|
|
|
|
|
2015-04-14 15:55:56 +02:00
|
|
|
void RenderingManager::setSkyEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
mSky->setEnabled(enabled);
|
2018-02-27 00:13:51 +00:00
|
|
|
if (enabled)
|
|
|
|
mShadowManager->enableOutdoorMode();
|
|
|
|
else
|
|
|
|
mShadowManager->enableIndoorMode();
|
2022-05-13 18:58:00 -07:00
|
|
|
mPostProcessor->getStateUpdater()->setIsInterior(!enabled);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
2018-04-07 16:11:23 +03:00
|
|
|
|
2018-06-13 01:48:31 +02:00
|
|
|
bool RenderingManager::toggleBorders()
|
|
|
|
{
|
2020-06-06 14:10:24 +04:00
|
|
|
bool borders = !mTerrain->getBordersVisible();
|
|
|
|
mTerrain->setBordersVisible(borders);
|
|
|
|
return borders;
|
2018-06-13 01:48:31 +02:00
|
|
|
}
|
2015-04-14 15:55:56 +02:00
|
|
|
|
2015-05-02 22:45:27 +02:00
|
|
|
bool RenderingManager::toggleRenderMode(RenderMode mode)
|
|
|
|
{
|
|
|
|
if (mode == Render_CollisionDebug || mode == Render_Pathgrid)
|
2015-05-04 17:41:30 +02:00
|
|
|
return mPathgrid->toggleRenderMode(mode);
|
2015-05-02 22:45:27 +02:00
|
|
|
else if (mode == Render_Wireframe)
|
|
|
|
{
|
2015-06-01 17:02:44 +02:00
|
|
|
bool wireframe = !mStateUpdater->getWireframe();
|
|
|
|
mStateUpdater->setWireframe(wireframe);
|
|
|
|
return wireframe;
|
2015-05-02 22:45:27 +02:00
|
|
|
}
|
2015-06-02 16:35:35 +02:00
|
|
|
else if (mode == Render_Water)
|
|
|
|
{
|
|
|
|
return mWater->toggle();
|
|
|
|
}
|
|
|
|
else if (mode == Render_Scene)
|
|
|
|
{
|
2022-05-06 17:46:50 +02:00
|
|
|
const auto wm = MWBase::Environment::get().getWindowManager();
|
2022-04-04 22:51:23 +02:00
|
|
|
unsigned int mask = wm->getCullMask();
|
2021-10-27 09:16:01 -07:00
|
|
|
bool enabled = !(mask & sToggleWorldMask);
|
2015-06-02 16:35:35 +02:00
|
|
|
if (enabled)
|
2021-10-27 09:16:01 -07:00
|
|
|
mask |= sToggleWorldMask;
|
2015-06-02 16:35:35 +02:00
|
|
|
else
|
2021-10-27 09:16:01 -07:00
|
|
|
mask &= ~sToggleWorldMask;
|
|
|
|
mWater->showWorld(enabled);
|
2022-04-04 22:51:23 +02:00
|
|
|
wm->setCullMask(mask);
|
2015-06-02 16:35:35 +02:00
|
|
|
return enabled;
|
|
|
|
}
|
2018-04-07 16:11:23 +03:00
|
|
|
else if (mode == Render_NavMesh)
|
|
|
|
{
|
|
|
|
return mNavMesh->toggle();
|
|
|
|
}
|
2018-07-21 13:37:02 +03:00
|
|
|
else if (mode == Render_ActorsPaths)
|
|
|
|
{
|
|
|
|
return mActorsPaths->toggle();
|
|
|
|
}
|
2019-11-27 23:45:01 +01:00
|
|
|
else if (mode == Render_RecastMesh)
|
|
|
|
{
|
|
|
|
return mRecastMesh->toggle();
|
|
|
|
}
|
2015-05-02 22:45:27 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-01-27 01:13:17 +01:00
|
|
|
void RenderingManager::configureFog(const MWWorld::Cell& cell)
|
2015-04-21 23:27:26 +02:00
|
|
|
{
|
2020-06-07 10:35:33 +04:00
|
|
|
mFog->configure(mViewDistance, cell);
|
2015-04-21 23:27:26 +02:00
|
|
|
}
|
|
|
|
|
2017-09-21 03:08:45 -07:00
|
|
|
void RenderingManager::configureFog(
|
|
|
|
float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& color)
|
2015-04-14 15:55:56 +02:00
|
|
|
{
|
2020-06-07 10:35:33 +04:00
|
|
|
mFog->configure(mViewDistance, fogDepth, underwaterFog, dlFactor, dlOffset, color);
|
2015-04-14 15:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
SkyManager* RenderingManager::getSkyManager()
|
|
|
|
{
|
|
|
|
return mSky.get();
|
|
|
|
}
|
|
|
|
|
2015-04-19 01:57:52 +02:00
|
|
|
void RenderingManager::update(float dt, bool paused)
|
|
|
|
{
|
2017-02-22 02:18:18 +01:00
|
|
|
reportStats();
|
|
|
|
|
2022-08-12 18:26:04 +02:00
|
|
|
mResourceSystem->getSceneManager()->getShaderManager().update(*mViewer);
|
|
|
|
|
2021-03-10 19:10:17 +04:00
|
|
|
float rainIntensity = mSky->getPrecipitationAlpha();
|
2021-03-08 10:58:51 +04:00
|
|
|
mWater->setRainIntensity(rainIntensity);
|
|
|
|
|
2023-04-01 09:09:45 +04:00
|
|
|
mWater->update(dt, paused);
|
2015-06-19 03:32:48 +02:00
|
|
|
if (!paused)
|
2015-06-20 17:08:46 +02:00
|
|
|
{
|
2015-06-19 03:32:48 +02:00
|
|
|
mEffectManager->update(dt);
|
2015-06-20 17:08:46 +02:00
|
|
|
mSky->update(dt);
|
2020-01-12 11:42:47 +04:00
|
|
|
|
2021-09-20 18:17:55 +00:00
|
|
|
const MWWorld::Ptr& player = mPlayerAnimation->getPtr();
|
|
|
|
osg::Vec3f playerPos(player.getRefData().getPosition().asVec3());
|
2020-01-12 11:42:47 +04:00
|
|
|
|
2021-09-20 18:17:55 +00:00
|
|
|
float windSpeed = mSky->getBaseWindSpeed();
|
|
|
|
mSharedUniformStateUpdater->setWindSpeed(windSpeed);
|
|
|
|
mSharedUniformStateUpdater->setPlayerPos(playerPos);
|
2015-06-20 17:08:46 +02:00
|
|
|
}
|
2015-06-19 03:32:48 +02:00
|
|
|
|
2019-01-20 19:27:52 +03:00
|
|
|
updateNavMesh();
|
2019-11-27 23:45:01 +01:00
|
|
|
updateRecastMesh();
|
2018-08-31 01:39:44 +03:00
|
|
|
|
2022-04-03 20:42:19 +02:00
|
|
|
if (mUpdateProjectionMatrix)
|
|
|
|
{
|
|
|
|
mUpdateProjectionMatrix = false;
|
|
|
|
updateProjectionMatrix();
|
|
|
|
}
|
2015-05-22 01:43:16 +02:00
|
|
|
mCamera->update(dt, paused);
|
2015-06-02 16:35:35 +02:00
|
|
|
|
2021-06-20 00:57:41 +02:00
|
|
|
bool isUnderwater = mWater->isUnderwater(mCamera->getPosition());
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
float fogStart = mFog->getFogStart(isUnderwater);
|
|
|
|
float fogEnd = mFog->getFogEnd(isUnderwater);
|
|
|
|
osg::Vec4f fogColor = mFog->getFogColor(isUnderwater);
|
|
|
|
|
|
|
|
mStateUpdater->setFogStart(fogStart);
|
|
|
|
mStateUpdater->setFogEnd(fogEnd);
|
|
|
|
setFogColor(fogColor);
|
|
|
|
|
|
|
|
auto world = MWBase::Environment::get().getWorld();
|
|
|
|
const auto& stateUpdater = mPostProcessor->getStateUpdater();
|
|
|
|
|
|
|
|
stateUpdater->setFogRange(fogStart, fogEnd);
|
|
|
|
stateUpdater->setNearFar(mNearClip, mViewDistance);
|
|
|
|
stateUpdater->setIsUnderwater(isUnderwater);
|
|
|
|
stateUpdater->setFogColor(fogColor);
|
|
|
|
stateUpdater->setGameHour(world->getTimeStamp().getHour());
|
|
|
|
stateUpdater->setWeatherId(world->getCurrentWeather());
|
|
|
|
stateUpdater->setNextWeatherId(world->getNextWeather());
|
|
|
|
stateUpdater->setWeatherTransition(world->getWeatherTransition());
|
|
|
|
stateUpdater->setWindSpeed(world->getWindSpeed());
|
2023-01-20 14:39:28 -08:00
|
|
|
stateUpdater->setSkyColor(mSky->getSkyColor());
|
2022-05-13 18:58:00 -07:00
|
|
|
mPostProcessor->setUnderwaterFlag(isUnderwater);
|
2015-04-19 17:55:56 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 23:54:39 +02:00
|
|
|
void RenderingManager::updatePlayerPtr(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
|
|
|
if (mPlayerAnimation.get())
|
2017-09-17 23:07:17 +00:00
|
|
|
{
|
|
|
|
setupPlayer(ptr);
|
2015-05-21 23:54:39 +02:00
|
|
|
mPlayerAnimation->updatePtr(ptr);
|
2017-09-17 23:07:17 +00:00
|
|
|
}
|
2015-05-21 23:54:39 +02:00
|
|
|
mCamera->attachTo(ptr);
|
|
|
|
}
|
|
|
|
|
2015-06-16 20:36:48 +02:00
|
|
|
void RenderingManager::removePlayer(const MWWorld::Ptr& player)
|
|
|
|
{
|
|
|
|
mWater->removeEmitter(player);
|
|
|
|
}
|
|
|
|
|
2015-04-23 23:50:46 +02:00
|
|
|
void RenderingManager::rotateObject(const MWWorld::Ptr& ptr, const osg::Quat& rot)
|
|
|
|
{
|
2015-05-21 23:54:39 +02:00
|
|
|
if (ptr == mCamera->getTrackingPtr() && !mCamera->isVanityOrPreviewModeEnabled())
|
|
|
|
{
|
2020-07-18 11:48:46 +02:00
|
|
|
mCamera->rotateCameraToTrackingPtr();
|
2015-05-21 23:54:39 +02:00
|
|
|
}
|
2015-04-23 23:50:46 +02:00
|
|
|
|
|
|
|
ptr.getRefData().getBaseNode()->setAttitude(rot);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::moveObject(const MWWorld::Ptr& ptr, const osg::Vec3f& pos)
|
|
|
|
{
|
|
|
|
ptr.getRefData().getBaseNode()->setPosition(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::scaleObject(const MWWorld::Ptr& ptr, const osg::Vec3f& scale)
|
|
|
|
{
|
|
|
|
ptr.getRefData().getBaseNode()->setScale(scale);
|
2015-11-09 17:30:11 +01:00
|
|
|
|
|
|
|
if (ptr == mCamera->getTrackingPtr()) // update height of camera
|
|
|
|
mCamera->processViewChange();
|
2015-04-23 23:50:46 +02:00
|
|
|
}
|
|
|
|
|
2015-05-22 00:55:43 +02:00
|
|
|
void RenderingManager::removeObject(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
2018-07-21 13:37:02 +03:00
|
|
|
mActorsPaths->remove(ptr);
|
2015-05-22 00:55:43 +02:00
|
|
|
mObjects->removeObject(ptr);
|
2015-06-16 20:36:48 +02:00
|
|
|
mWater->removeEmitter(ptr);
|
2015-05-22 00:55:43 +02:00
|
|
|
}
|
|
|
|
|
2015-06-02 16:35:35 +02:00
|
|
|
void RenderingManager::setWaterEnabled(bool enabled)
|
|
|
|
{
|
|
|
|
mWater->setEnabled(enabled);
|
2015-11-03 23:15:43 +01:00
|
|
|
mSky->setWaterEnabled(enabled);
|
2022-07-31 10:33:18 +04:00
|
|
|
|
|
|
|
mPostProcessor->getStateUpdater()->setIsWaterEnabled(enabled);
|
2015-06-02 16:35:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::setWaterHeight(float height)
|
|
|
|
{
|
2019-06-13 13:37:00 +00:00
|
|
|
mWater->setCullCallback(mTerrain->getHeightCullCallback(height, Mask_Water));
|
2015-06-02 16:35:35 +02:00
|
|
|
mWater->setHeight(height);
|
2015-11-03 23:15:43 +01:00
|
|
|
mSky->setWaterHeight(height);
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
mPostProcessor->getStateUpdater()->setWaterHeight(height);
|
2015-06-02 16:35:35 +02:00
|
|
|
}
|
|
|
|
|
2021-01-08 19:33:51 +04:00
|
|
|
void RenderingManager::screenshot(osg::Image* image, int w, int h)
|
2015-06-03 16:40:16 +02:00
|
|
|
{
|
2021-01-08 19:33:51 +04:00
|
|
|
mScreenshotManager->screenshot(image, w, h);
|
|
|
|
}
|
2015-06-03 16:40:16 +02:00
|
|
|
|
2021-01-08 19:33:51 +04:00
|
|
|
bool RenderingManager::screenshot360(osg::Image* image)
|
2017-11-07 13:07:11 +01:00
|
|
|
{
|
2017-11-11 13:51:42 +01:00
|
|
|
if (mCamera->isVanityOrPreviewModeEnabled())
|
|
|
|
{
|
2018-08-14 23:05:43 +04:00
|
|
|
Log(Debug::Warning) << "Spherical screenshots are not allowed in preview mode.";
|
2017-11-11 13:51:42 +01:00
|
|
|
return false;
|
|
|
|
}
|
2017-11-09 20:25:29 +01:00
|
|
|
|
2021-01-08 19:33:51 +04:00
|
|
|
mScreenshotManager->screenshot360(image);
|
2017-11-07 22:13:05 +01:00
|
|
|
|
2017-11-10 15:23:44 +01:00
|
|
|
return true;
|
2017-11-07 13:07:11 +01:00
|
|
|
}
|
|
|
|
|
2020-05-11 13:37:00 +00:00
|
|
|
osg::Vec4f RenderingManager::getScreenBounds(const osg::BoundingBox& worldbb)
|
2015-05-24 03:36:34 +02:00
|
|
|
{
|
2020-05-11 13:37:00 +00:00
|
|
|
if (!worldbb.valid())
|
|
|
|
return osg::Vec4f();
|
2015-05-24 03:36:34 +02:00
|
|
|
osg::Matrix viewProj = mViewer->getCamera()->getViewMatrix() * mViewer->getCamera()->getProjectionMatrix();
|
|
|
|
float min_x = 1.0f, max_x = 0.0f, min_y = 1.0f, max_y = 0.0f;
|
|
|
|
for (int i = 0; i < 8; ++i)
|
|
|
|
{
|
2020-05-11 13:37:00 +00:00
|
|
|
osg::Vec3f corner = worldbb.corner(i);
|
2015-05-24 03:36:34 +02:00
|
|
|
corner = corner * viewProj;
|
|
|
|
|
|
|
|
float x = (corner.x() + 1.f) * 0.5f;
|
|
|
|
float y = (corner.y() - 1.f) * (-0.5f);
|
|
|
|
|
|
|
|
if (x < min_x)
|
|
|
|
min_x = x;
|
|
|
|
|
|
|
|
if (x > max_x)
|
|
|
|
max_x = x;
|
|
|
|
|
|
|
|
if (y < min_y)
|
|
|
|
min_y = y;
|
|
|
|
|
|
|
|
if (y > max_y)
|
|
|
|
max_y = y;
|
|
|
|
}
|
|
|
|
|
|
|
|
return osg::Vec4f(min_x, min_y, max_x, max_y);
|
|
|
|
}
|
|
|
|
|
2015-06-05 02:26:16 +02:00
|
|
|
RenderingManager::RayResult getIntersectionResult(osgUtil::LineSegmentIntersector* intersector)
|
|
|
|
{
|
|
|
|
RenderingManager::RayResult result;
|
|
|
|
result.mHit = false;
|
2016-07-06 22:03:37 +09:00
|
|
|
result.mRatio = 0;
|
2015-06-05 02:26:16 +02:00
|
|
|
if (intersector->containsIntersections())
|
|
|
|
{
|
|
|
|
result.mHit = true;
|
|
|
|
osgUtil::LineSegmentIntersector::Intersection intersection = intersector->getFirstIntersection();
|
|
|
|
|
|
|
|
result.mHitPointWorld = intersection.getWorldIntersectPoint();
|
|
|
|
result.mHitNormalWorld = intersection.getWorldIntersectNormal();
|
2016-07-06 22:03:37 +09:00
|
|
|
result.mRatio = intersection.ratio;
|
2015-06-05 02:26:16 +02:00
|
|
|
|
2018-10-09 10:21:12 +04:00
|
|
|
PtrHolder* ptrHolder = nullptr;
|
2020-05-11 13:37:00 +00:00
|
|
|
std::vector<RefnumMarker*> refnumMarkers;
|
2015-06-05 02:26:16 +02:00
|
|
|
for (osg::NodePath::const_iterator it = intersection.nodePath.begin(); it != intersection.nodePath.end();
|
|
|
|
++it)
|
|
|
|
{
|
|
|
|
osg::UserDataContainer* userDataContainer = (*it)->getUserDataContainer();
|
|
|
|
if (!userDataContainer)
|
|
|
|
continue;
|
|
|
|
for (unsigned int i = 0; i < userDataContainer->getNumUserObjects(); ++i)
|
|
|
|
{
|
|
|
|
if (PtrHolder* p = dynamic_cast<PtrHolder*>(userDataContainer->getUserObject(i)))
|
|
|
|
ptrHolder = p;
|
2020-05-11 13:37:00 +00:00
|
|
|
if (RefnumMarker* r = dynamic_cast<RefnumMarker*>(userDataContainer->getUserObject(i)))
|
|
|
|
refnumMarkers.push_back(r);
|
2015-06-05 02:26:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ptrHolder)
|
|
|
|
result.mHitObject = ptrHolder->mPtr;
|
2020-05-11 13:37:00 +00:00
|
|
|
|
|
|
|
unsigned int vertexCounter = 0;
|
|
|
|
for (unsigned int i = 0; i < refnumMarkers.size(); ++i)
|
|
|
|
{
|
|
|
|
unsigned int intersectionIndex = intersection.indexList.empty() ? 0 : intersection.indexList[0];
|
|
|
|
if (!refnumMarkers[i]->mNumVertices
|
|
|
|
|| (intersectionIndex >= vertexCounter
|
|
|
|
&& intersectionIndex < vertexCounter + refnumMarkers[i]->mNumVertices))
|
|
|
|
{
|
|
|
|
result.mHitRefnum = refnumMarkers[i]->mRefnum;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
vertexCounter += refnumMarkers[i]->mNumVertices;
|
|
|
|
}
|
2015-06-05 02:26:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-03-12 19:48:41 +01:00
|
|
|
osg::ref_ptr<osgUtil::IntersectionVisitor> RenderingManager::getIntersectionVisitor(
|
|
|
|
osgUtil::Intersector* intersector, bool ignorePlayer, bool ignoreActors)
|
2015-06-05 02:26:16 +02:00
|
|
|
{
|
2017-03-12 19:48:41 +01:00
|
|
|
if (!mIntersectionVisitor)
|
|
|
|
mIntersectionVisitor = new osgUtil::IntersectionVisitor;
|
|
|
|
|
|
|
|
mIntersectionVisitor->setTraversalNumber(mViewer->getFrameStamp()->getFrameNumber());
|
2020-05-12 13:37:00 +00:00
|
|
|
mIntersectionVisitor->setFrameStamp(mViewer->getFrameStamp());
|
2017-03-12 19:48:41 +01:00
|
|
|
mIntersectionVisitor->setIntersector(intersector);
|
|
|
|
|
2021-04-20 10:42:06 +04:00
|
|
|
unsigned int mask = ~0u;
|
2020-01-12 11:42:47 +04:00
|
|
|
mask &= ~(Mask_RenderToTexture | Mask_Sky | Mask_Debug | Mask_Effect | Mask_Water | Mask_SimpleWater
|
|
|
|
| Mask_Groundcover);
|
2015-06-05 02:26:16 +02:00
|
|
|
if (ignorePlayer)
|
2020-04-20 18:47:14 +02:00
|
|
|
mask &= ~(Mask_Player);
|
2015-06-05 02:26:16 +02:00
|
|
|
if (ignoreActors)
|
2020-04-20 18:47:14 +02:00
|
|
|
mask &= ~(Mask_Actor | Mask_Player);
|
2015-06-05 02:26:16 +02:00
|
|
|
|
2017-03-12 19:48:41 +01:00
|
|
|
mIntersectionVisitor->setTraversalMask(mask);
|
|
|
|
return mIntersectionVisitor;
|
2015-10-31 01:30:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RenderingManager::RayResult RenderingManager::castRay(
|
|
|
|
const osg::Vec3f& origin, const osg::Vec3f& dest, bool ignorePlayer, bool ignoreActors)
|
|
|
|
{
|
|
|
|
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector(
|
|
|
|
new osgUtil::LineSegmentIntersector(osgUtil::LineSegmentIntersector::MODEL, origin, dest));
|
|
|
|
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST);
|
2015-06-05 02:26:16 +02:00
|
|
|
|
2017-03-12 19:48:41 +01:00
|
|
|
mRootNode->accept(*getIntersectionVisitor(intersector, ignorePlayer, ignoreActors));
|
2015-06-05 02:26:16 +02:00
|
|
|
|
|
|
|
return getIntersectionResult(intersector);
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderingManager::RayResult RenderingManager::castCameraToViewportRay(
|
|
|
|
const float nX, const float nY, float maxDistance, bool ignorePlayer, bool ignoreActors)
|
2015-05-24 03:36:34 +02:00
|
|
|
{
|
|
|
|
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector(new osgUtil::LineSegmentIntersector(
|
|
|
|
osgUtil::LineSegmentIntersector::PROJECTION, nX * 2.f - 1.f, nY * (-2.f) + 1.f));
|
|
|
|
|
|
|
|
osg::Vec3d dist(0.f, 0.f, -maxDistance);
|
|
|
|
|
|
|
|
dist = dist * mViewer->getCamera()->getProjectionMatrix();
|
|
|
|
|
|
|
|
osg::Vec3d end = intersector->getEnd();
|
|
|
|
end.z() = dist.z();
|
|
|
|
intersector->setEnd(end);
|
|
|
|
intersector->setIntersectionLimit(osgUtil::LineSegmentIntersector::LIMIT_NEAREST);
|
|
|
|
|
2017-03-12 19:48:41 +01:00
|
|
|
mViewer->getCamera()->accept(*getIntersectionVisitor(intersector, ignorePlayer, ignoreActors));
|
2015-05-24 03:36:34 +02:00
|
|
|
|
2015-06-05 02:26:16 +02:00
|
|
|
return getIntersectionResult(intersector);
|
2015-05-24 03:36:34 +02:00
|
|
|
}
|
|
|
|
|
2015-05-14 17:34:55 +02:00
|
|
|
void RenderingManager::updatePtr(const MWWorld::Ptr& old, const MWWorld::Ptr& updated)
|
|
|
|
{
|
|
|
|
mObjects->updatePtr(old, updated);
|
2018-07-21 13:37:02 +03:00
|
|
|
mActorsPaths->updatePtr(old, updated);
|
2015-05-14 17:34:55 +02:00
|
|
|
}
|
|
|
|
|
2022-08-28 17:20:49 +02:00
|
|
|
void RenderingManager::spawnEffect(const std::string& model, std::string_view texture,
|
|
|
|
const osg::Vec3f& worldPosition, float scale, bool isMagicVFX)
|
2015-04-19 17:55:56 +02:00
|
|
|
{
|
2016-09-14 23:18:29 +09:00
|
|
|
mEffectManager->addEffect(model, texture, worldPosition, scale, isMagicVFX);
|
2015-04-19 17:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::notifyWorldSpaceChanged()
|
|
|
|
{
|
|
|
|
mEffectManager->clear();
|
2020-02-19 23:26:42 +03:00
|
|
|
mWater->clearRipples();
|
2015-04-19 17:55:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::clear()
|
|
|
|
{
|
2015-06-16 20:56:48 +02:00
|
|
|
mSky->setMoonColour(false);
|
|
|
|
|
2015-04-19 17:55:56 +02:00
|
|
|
notifyWorldSpaceChanged();
|
2019-08-03 13:37:00 +00:00
|
|
|
if (mObjectPaging)
|
|
|
|
mObjectPaging->clear();
|
2015-04-19 01:57:52 +02:00
|
|
|
}
|
|
|
|
|
2015-04-25 15:19:17 +02:00
|
|
|
MWRender::Animation* RenderingManager::getAnimation(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
2015-05-22 04:36:17 +02:00
|
|
|
if (mPlayerAnimation.get() && ptr == mPlayerAnimation->getPtr())
|
|
|
|
return mPlayerAnimation.get();
|
|
|
|
|
2015-04-25 15:19:17 +02:00
|
|
|
return mObjects->getAnimation(ptr);
|
|
|
|
}
|
|
|
|
|
2015-12-18 17:21:51 +01:00
|
|
|
const MWRender::Animation* RenderingManager::getAnimation(const MWWorld::ConstPtr& ptr) const
|
|
|
|
{
|
|
|
|
if (mPlayerAnimation.get() && ptr == mPlayerAnimation->getPtr())
|
|
|
|
return mPlayerAnimation.get();
|
|
|
|
|
|
|
|
return mObjects->getAnimation(ptr);
|
|
|
|
}
|
|
|
|
|
2022-05-13 18:58:00 -07:00
|
|
|
PostProcessor* RenderingManager::getPostProcessor()
|
|
|
|
{
|
|
|
|
return mPostProcessor;
|
|
|
|
}
|
|
|
|
|
2015-05-01 18:21:50 +02:00
|
|
|
void RenderingManager::setupPlayer(const MWWorld::Ptr& player)
|
|
|
|
{
|
|
|
|
if (!mPlayerNode)
|
|
|
|
{
|
2015-11-20 21:57:04 +01:00
|
|
|
mPlayerNode = new SceneUtil::PositionAttitudeTransform;
|
2020-04-20 18:47:14 +02:00
|
|
|
mPlayerNode->setNodeMask(Mask_Player);
|
2017-02-02 21:46:25 +01:00
|
|
|
mPlayerNode->setName("Player Root");
|
2016-02-08 16:45:56 +01:00
|
|
|
mSceneRoot->addChild(mPlayerNode);
|
2015-05-01 18:21:50 +02:00
|
|
|
}
|
|
|
|
|
2015-05-24 04:00:35 +02:00
|
|
|
mPlayerNode->setUserDataContainer(new osg::DefaultUserDataContainer);
|
|
|
|
mPlayerNode->getUserDataContainer()->addUserObject(new PtrHolder(player));
|
2015-05-01 18:21:50 +02:00
|
|
|
|
2015-05-24 04:00:35 +02:00
|
|
|
player.getRefData().setBaseNode(mPlayerNode);
|
2015-06-16 20:36:48 +02:00
|
|
|
|
2017-09-17 23:07:17 +00:00
|
|
|
mWater->removeEmitter(player);
|
2015-06-16 20:36:48 +02:00
|
|
|
mWater->addEmitter(player);
|
2015-05-01 18:21:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::renderPlayer(const MWWorld::Ptr& player)
|
|
|
|
{
|
2017-02-22 15:22:40 +01:00
|
|
|
mPlayerAnimation = new NpcAnimation(player, player.getRefData().getBaseNode(), mResourceSystem, 0,
|
|
|
|
NpcAnimation::VM_Normal, mFirstPersonFieldOfView);
|
2015-05-01 18:21:50 +02:00
|
|
|
|
2015-05-21 23:54:39 +02:00
|
|
|
mCamera->setAnimation(mPlayerAnimation.get());
|
|
|
|
mCamera->attachTo(player);
|
2015-05-01 18:21:50 +02:00
|
|
|
}
|
|
|
|
|
2015-05-21 23:54:39 +02:00
|
|
|
void RenderingManager::rebuildPtr(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
2018-10-09 10:21:12 +04:00
|
|
|
NpcAnimation* anim = nullptr;
|
2015-05-21 23:54:39 +02:00
|
|
|
if (ptr == mPlayerAnimation->getPtr())
|
|
|
|
anim = mPlayerAnimation.get();
|
|
|
|
else
|
|
|
|
anim = dynamic_cast<NpcAnimation*>(mObjects->getAnimation(ptr));
|
|
|
|
if (anim)
|
|
|
|
{
|
|
|
|
anim->rebuild();
|
|
|
|
if (mCamera->getTrackingPtr() == ptr)
|
|
|
|
{
|
|
|
|
mCamera->attachTo(ptr);
|
|
|
|
mCamera->setAnimation(anim);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-16 20:36:48 +02:00
|
|
|
void RenderingManager::addWaterRippleEmitter(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
|
|
|
mWater->addEmitter(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::removeWaterRippleEmitter(const MWWorld::Ptr& ptr)
|
|
|
|
{
|
|
|
|
mWater->removeEmitter(ptr);
|
|
|
|
}
|
|
|
|
|
2015-12-04 23:28:11 +01:00
|
|
|
void RenderingManager::emitWaterRipple(const osg::Vec3f& pos)
|
|
|
|
{
|
|
|
|
mWater->emitRipple(pos);
|
|
|
|
}
|
|
|
|
|
2015-05-14 18:46:04 +02:00
|
|
|
void RenderingManager::updateProjectionMatrix()
|
|
|
|
{
|
2022-08-20 16:14:22 +01:00
|
|
|
if (mNearClip < 0.0f)
|
|
|
|
throw std::runtime_error("Near clip is less than zero");
|
|
|
|
if (mViewDistance < mNearClip)
|
|
|
|
throw std::runtime_error("Viewing distance is less than near clip");
|
|
|
|
|
2022-01-05 10:43:30 +00:00
|
|
|
double width = Settings::Manager::getInt("resolution x", "Video");
|
|
|
|
double height = Settings::Manager::getInt("resolution y", "Video");
|
|
|
|
|
|
|
|
double aspect = (height == 0.0) ? 1.0 : width / height;
|
2015-12-07 16:11:47 +01:00
|
|
|
float fov = mFieldOfView;
|
|
|
|
if (mFieldOfViewOverridden)
|
|
|
|
fov = mFieldOfViewOverride;
|
2021-06-01 12:15:25 -07:00
|
|
|
|
2021-07-09 10:05:27 -07:00
|
|
|
mViewer->getCamera()->setProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance);
|
|
|
|
|
2021-11-21 02:25:05 +00:00
|
|
|
if (SceneUtil::AutoDepth::isReversed())
|
2021-06-01 12:15:25 -07:00
|
|
|
{
|
2022-04-04 22:51:23 +02:00
|
|
|
mPerViewUniformStateUpdater->setProjectionMatrix(
|
|
|
|
SceneUtil::getReversedZProjectionMatrixAsPerspective(fov, aspect, mNearClip, mViewDistance));
|
2021-06-01 12:15:25 -07:00
|
|
|
}
|
|
|
|
else
|
2022-04-04 22:51:23 +02:00
|
|
|
mPerViewUniformStateUpdater->setProjectionMatrix(mViewer->getCamera()->getProjectionMatrix());
|
2017-09-26 14:14:28 +02:00
|
|
|
|
2021-08-04 17:49:57 -07:00
|
|
|
mSharedUniformStateUpdater->setNear(mNearClip);
|
|
|
|
mSharedUniformStateUpdater->setFar(mViewDistance);
|
2022-04-04 22:51:23 +02:00
|
|
|
if (Stereo::getStereo())
|
|
|
|
{
|
|
|
|
auto res = Stereo::Manager::instance().eyeResolution();
|
|
|
|
mSharedUniformStateUpdater->setScreenRes(res.x(), res.y());
|
2022-05-13 18:58:00 -07:00
|
|
|
Stereo::Manager::instance().setMasterProjectionMatrix(mPerViewUniformStateUpdater->getProjectionMatrix());
|
2022-04-04 22:51:23 +02:00
|
|
|
}
|
2022-05-13 18:58:00 -07:00
|
|
|
else if (!mPostProcessor->isEnabled())
|
2022-04-04 22:51:23 +02:00
|
|
|
{
|
|
|
|
mSharedUniformStateUpdater->setScreenRes(width, height);
|
|
|
|
}
|
2019-02-20 13:37:00 +00:00
|
|
|
|
|
|
|
// Since our fog is not radial yet, we should take FOV in account, otherwise terrain near viewing distance may
|
2019-03-03 21:29:51 +04:00
|
|
|
// disappear. Limit FOV here just for sure, otherwise viewing distance can be too high.
|
2022-04-03 20:42:19 +02:00
|
|
|
float distanceMult = std::cos(osg::DegreesToRadians(std::min(fov, 140.f)) / 2.f);
|
2019-02-20 13:37:00 +00:00
|
|
|
mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f / distanceMult : 1.f));
|
2022-05-13 18:58:00 -07:00
|
|
|
|
|
|
|
if (mPostProcessor)
|
|
|
|
{
|
|
|
|
mPostProcessor->getStateUpdater()->setProjectionMatrix(mPerViewUniformStateUpdater->getProjectionMatrix());
|
|
|
|
mPostProcessor->getStateUpdater()->setFov(fov);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::setScreenRes(int width, int height)
|
|
|
|
{
|
|
|
|
mSharedUniformStateUpdater->setScreenRes(width, height);
|
2015-05-14 21:42:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RenderingManager::updateTextureFiltering()
|
|
|
|
{
|
2016-02-14 23:14:52 +01:00
|
|
|
mViewer->stopThreading();
|
2016-02-05 23:20:13 +01:00
|
|
|
|
2016-02-05 18:51:51 +01:00
|
|
|
mResourceSystem->getSceneManager()->setFilterSettings(
|
2015-12-13 17:05:19 -08:00
|
|
|
Settings::Manager::getString("texture mag filter", "General"),
|
|
|
|
Settings::Manager::getString("texture min filter", "General"),
|
2015-12-13 16:51:27 -08:00
|
|
|
Settings::Manager::getString("texture mipmap", "General"),
|
2016-02-14 23:14:52 +01:00
|
|
|
Settings::Manager::getInt("anisotropy", "General"));
|
|
|
|
|
|
|
|
mTerrain->updateTextureFiltering();
|
2022-04-29 17:26:09 -07:00
|
|
|
mWater->processChangedSettings({});
|
2016-02-14 23:14:52 +01:00
|
|
|
|
|
|
|
mViewer->startThreading();
|
2015-05-14 18:46:04 +02:00
|
|
|
}
|
|
|
|
|
2015-06-11 23:16:05 +02:00
|
|
|
void RenderingManager::updateAmbient()
|
|
|
|
{
|
|
|
|
osg::Vec4f color = mAmbientColor;
|
|
|
|
|
|
|
|
if (mNightEyeFactor > 0.f)
|
|
|
|
color += osg::Vec4f(0.7, 0.7, 0.7, 0.0) * mNightEyeFactor;
|
|
|
|
|
2023-01-20 14:39:28 -08:00
|
|
|
mPostProcessor->getStateUpdater()->setAmbientColor(color);
|
2015-06-11 23:16:05 +02:00
|
|
|
mStateUpdater->setAmbientColor(color);
|
|
|
|
}
|
|
|
|
|
2015-06-02 16:35:35 +02:00
|
|
|
void RenderingManager::setFogColor(const osg::Vec4f& color)
|
|
|
|
{
|
|
|
|
mViewer->getCamera()->setClearColor(color);
|
|
|
|
|
|
|
|
mStateUpdater->setFogColor(color);
|
|
|
|
}
|
|
|
|
|
2023-05-23 00:23:47 +02:00
|
|
|
RenderingManager::WorldspaceChunkMgr& RenderingManager::getWorldspaceChunkMgr(ESM::RefId worldspace)
|
2023-05-14 20:00:02 +02:00
|
|
|
{
|
2023-05-23 00:23:47 +02:00
|
|
|
auto existingChunkMgr = mWorldspaceChunks.find(worldspace);
|
|
|
|
if (existingChunkMgr != mWorldspaceChunks.end())
|
|
|
|
return existingChunkMgr->second;
|
|
|
|
RenderingManager::WorldspaceChunkMgr newChunkMgr;
|
2023-05-14 20:00:02 +02:00
|
|
|
|
|
|
|
const float lodFactor = Settings::Manager::getFloat("lod factor", "Terrain");
|
|
|
|
bool groundcover = Settings::Manager::getBool("enabled", "Groundcover");
|
|
|
|
bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
|
|
|
if (distantTerrain || groundcover)
|
|
|
|
{
|
|
|
|
const int compMapResolution = Settings::Manager::getInt("composite map resolution", "Terrain");
|
|
|
|
int compMapPower = Settings::Manager::getInt("composite map level", "Terrain");
|
|
|
|
compMapPower = std::max(-3, compMapPower);
|
|
|
|
float compMapLevel = pow(2, compMapPower);
|
|
|
|
const int vertexLodMod = Settings::Manager::getInt("vertex lod mod", "Terrain");
|
|
|
|
float maxCompGeometrySize = Settings::Manager::getFloat("max composite geometry size", "Terrain");
|
|
|
|
maxCompGeometrySize = std::max(maxCompGeometrySize, 1.f);
|
|
|
|
bool debugChunks = Settings::Manager::getBool("debug chunks", "Terrain");
|
2023-05-23 00:23:47 +02:00
|
|
|
auto quadTreeWorld = std::make_unique<Terrain::QuadTreeWorld>(mSceneRoot, mRootNode, mResourceSystem,
|
2023-05-14 20:00:02 +02:00
|
|
|
mTerrainStorage.get(), Mask_Terrain, Mask_PreCompile, Mask_Debug, compMapResolution, compMapLevel,
|
|
|
|
lodFactor, vertexLodMod, maxCompGeometrySize, debugChunks, worldspace);
|
|
|
|
if (Settings::Manager::getBool("object paging", "Terrain"))
|
|
|
|
{
|
2023-05-23 00:23:47 +02:00
|
|
|
newChunkMgr.mObjectPaging = std::make_unique<ObjectPaging>(mResourceSystem->getSceneManager());
|
|
|
|
quadTreeWorld->addChunkManager(newChunkMgr.mObjectPaging.get());
|
|
|
|
mResourceSystem->addResourceManager(newChunkMgr.mObjectPaging.get());
|
|
|
|
}
|
|
|
|
if (groundcover)
|
|
|
|
{
|
|
|
|
float groundcoverDistance
|
|
|
|
= std::max(0.f, Settings::Manager::getFloat("rendering distance", "Groundcover"));
|
|
|
|
float density = Settings::Manager::getFloat("density", "Groundcover");
|
|
|
|
density = std::clamp(density, 0.f, 1.f);
|
|
|
|
|
|
|
|
newChunkMgr.mGroundcover = std::make_unique<Groundcover>(
|
|
|
|
mResourceSystem->getSceneManager(), density, groundcoverDistance, mGroundCoverStore);
|
|
|
|
quadTreeWorld->addChunkManager(newChunkMgr.mGroundcover.get());
|
|
|
|
mResourceSystem->addResourceManager(newChunkMgr.mGroundcover.get());
|
2023-05-14 20:00:02 +02:00
|
|
|
}
|
2023-05-23 00:23:47 +02:00
|
|
|
newChunkMgr.mTerrain = std::move(quadTreeWorld);
|
2023-05-14 20:00:02 +02:00
|
|
|
}
|
|
|
|
else
|
2023-05-23 00:23:47 +02:00
|
|
|
newChunkMgr.mTerrain = std::make_unique<Terrain::TerrainGrid>(mSceneRoot, mRootNode, mResourceSystem,
|
2023-05-14 20:00:02 +02:00
|
|
|
mTerrainStorage.get(), Mask_Terrain, worldspace, Mask_PreCompile, Mask_Debug);
|
|
|
|
|
2023-05-26 13:07:23 +02:00
|
|
|
newChunkMgr.mTerrain->setTargetFrameRate(Settings::cells().mTargetFramerate);
|
2023-05-19 10:19:16 +02:00
|
|
|
float distanceMult = std::cos(osg::DegreesToRadians(std::min(mFieldOfView, 140.f)) / 2.f);
|
2023-05-23 00:23:47 +02:00
|
|
|
newChunkMgr.mTerrain->setViewDistance(mViewDistance * (distanceMult ? 1.f / distanceMult : 1.f));
|
2023-05-19 10:19:16 +02:00
|
|
|
|
2023-05-23 00:23:47 +02:00
|
|
|
return mWorldspaceChunks.emplace(worldspace, std::move(newChunkMgr)).first->second;
|
2023-05-14 20:00:02 +02:00
|
|
|
}
|
|
|
|
|
2017-03-07 04:02:06 +01:00
|
|
|
void RenderingManager::reportStats() const
|
2017-02-22 02:18:18 +01:00
|
|
|
{
|
|
|
|
osg::Stats* stats = mViewer->getViewerStats();
|
|
|
|
unsigned int frameNumber = mViewer->getFrameStamp()->getFrameNumber();
|
|
|
|
if (stats->collectStats("resource"))
|
|
|
|
{
|
2017-03-09 19:52:30 +01:00
|
|
|
mTerrain->reportStats(frameNumber, stats);
|
2017-02-22 02:18:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-14 18:46:04 +02:00
|
|
|
void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
|
|
|
{
|
2021-11-30 16:00:30 +00:00
|
|
|
// Only perform a projection matrix update once if a relevant setting is changed.
|
|
|
|
bool updateProjection = false;
|
|
|
|
|
2015-05-14 18:46:04 +02:00
|
|
|
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
|
|
|
{
|
2015-12-07 16:23:06 +01:00
|
|
|
if (it->first == "Camera" && it->second == "field of view")
|
2015-05-14 18:46:04 +02:00
|
|
|
{
|
2023-05-20 22:23:09 +02:00
|
|
|
mFieldOfView = Settings::camera().mFieldOfView;
|
2021-11-30 16:00:30 +00:00
|
|
|
updateProjection = true;
|
|
|
|
}
|
|
|
|
else if (it->first == "Video" && (it->second == "resolution x" || it->second == "resolution y"))
|
|
|
|
{
|
|
|
|
updateProjection = true;
|
2015-05-14 18:46:04 +02:00
|
|
|
}
|
2015-05-24 02:34:20 +02:00
|
|
|
else if (it->first == "Camera" && it->second == "viewing distance")
|
2015-05-14 18:46:04 +02:00
|
|
|
{
|
2023-05-20 22:23:09 +02:00
|
|
|
setViewDistance(Settings::camera().mViewingDistance);
|
2015-05-14 18:46:04 +02:00
|
|
|
}
|
2015-12-13 16:02:09 -08:00
|
|
|
else if (it->first == "General"
|
|
|
|
&& (it->second == "texture filter" || it->second == "texture mipmap" || it->second == "anisotropy"))
|
2021-04-03 22:25:13 -07:00
|
|
|
{
|
2015-05-14 21:42:04 +02:00
|
|
|
updateTextureFiltering();
|
2021-04-03 22:25:13 -07:00
|
|
|
}
|
2015-10-28 21:22:14 +01:00
|
|
|
else if (it->first == "Water")
|
2021-04-03 22:25:13 -07:00
|
|
|
{
|
2015-10-28 21:22:14 +01:00
|
|
|
mWater->processChangedSettings(changed);
|
2021-04-03 22:25:13 -07:00
|
|
|
}
|
|
|
|
else if (it->first == "Shaders" && it->second == "minimum interior brightness")
|
|
|
|
{
|
|
|
|
mMinimumAmbientLuminance
|
|
|
|
= std::clamp(Settings::Manager::getFloat("minimum interior brightness", "Shaders"), 0.f, 1.f);
|
2021-04-05 10:43:17 -07:00
|
|
|
if (MWMechanics::getPlayer().isInCell())
|
2023-01-27 01:13:17 +01:00
|
|
|
configureAmbient(*MWMechanics::getPlayer().getCell()->getCell());
|
2021-04-03 22:25:13 -07:00
|
|
|
}
|
|
|
|
else if (it->first == "Shaders"
|
|
|
|
&& (it->second == "light bounds multiplier" || it->second == "maximum light distance"
|
2021-04-05 10:43:17 -07:00
|
|
|
|| it->second == "light fade start" || it->second == "max lights"))
|
2021-04-03 22:25:13 -07:00
|
|
|
{
|
2022-05-14 22:53:53 -07:00
|
|
|
auto* lightManager = getLightRoot();
|
2021-04-05 10:43:17 -07:00
|
|
|
lightManager->processChangedSettings(changed);
|
|
|
|
|
|
|
|
if (it->second == "max lights" && !lightManager->usingFFP())
|
|
|
|
{
|
|
|
|
mViewer->stopThreading();
|
|
|
|
|
|
|
|
lightManager->updateMaxLights();
|
|
|
|
|
|
|
|
auto defines = mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
2021-04-13 11:00:48 -07:00
|
|
|
for (const auto& [name, key] : lightManager->getLightDefines())
|
|
|
|
defines[name] = key;
|
2021-04-05 10:43:17 -07:00
|
|
|
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
|
|
|
|
2021-10-06 09:15:47 +00:00
|
|
|
mStateUpdater->reset();
|
2021-04-05 10:43:17 -07:00
|
|
|
|
|
|
|
mViewer->startThreading();
|
|
|
|
}
|
2021-04-03 22:25:13 -07:00
|
|
|
}
|
2022-05-13 18:58:00 -07:00
|
|
|
else if (it->first == "Post Processing" && it->second == "enabled")
|
|
|
|
{
|
|
|
|
if (Settings::Manager::getBool("enabled", "Post Processing"))
|
|
|
|
mPostProcessor->enable();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mPostProcessor->disable();
|
|
|
|
if (auto* hud = MWBase::Environment::get().getWindowManager()->getPostProcessorHud())
|
|
|
|
hud->setVisible(false);
|
|
|
|
}
|
|
|
|
}
|
2015-05-14 18:46:04 +02:00
|
|
|
}
|
2021-11-30 16:00:30 +00:00
|
|
|
|
|
|
|
if (updateProjection)
|
|
|
|
{
|
|
|
|
updateProjectionMatrix();
|
|
|
|
}
|
2015-05-14 18:46:04 +02:00
|
|
|
}
|
|
|
|
|
2022-05-09 19:40:48 +00:00
|
|
|
void RenderingManager::setViewDistance(float distance, bool delay)
|
2015-06-01 15:34:46 +02:00
|
|
|
{
|
2022-05-09 19:40:48 +00:00
|
|
|
mViewDistance = distance;
|
|
|
|
|
|
|
|
if (delay)
|
|
|
|
{
|
|
|
|
mUpdateProjectionMatrix = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
updateProjectionMatrix();
|
2015-06-01 15:34:46 +02:00
|
|
|
}
|
|
|
|
|
2023-05-14 18:47:09 +02:00
|
|
|
float RenderingManager::getTerrainHeightAt(const osg::Vec3f& pos, ESM::RefId worldspace)
|
2015-06-03 01:18:36 +02:00
|
|
|
{
|
2023-05-23 00:23:47 +02:00
|
|
|
return getWorldspaceChunkMgr(worldspace).mTerrain->getHeightAt(pos);
|
2015-06-03 01:18:36 +02:00
|
|
|
}
|
|
|
|
|
2015-12-07 16:11:47 +01:00
|
|
|
void RenderingManager::overrideFieldOfView(float val)
|
|
|
|
{
|
|
|
|
if (mFieldOfViewOverridden != true || mFieldOfViewOverride != val)
|
|
|
|
{
|
|
|
|
mFieldOfViewOverridden = true;
|
|
|
|
mFieldOfViewOverride = val;
|
|
|
|
updateProjectionMatrix();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 20:42:19 +02:00
|
|
|
void RenderingManager::setFieldOfView(float val)
|
|
|
|
{
|
|
|
|
mFieldOfView = val;
|
|
|
|
mUpdateProjectionMatrix = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
float RenderingManager::getFieldOfView() const
|
|
|
|
{
|
|
|
|
return mFieldOfViewOverridden ? mFieldOfViewOverridden : mFieldOfView;
|
|
|
|
}
|
|
|
|
|
2018-06-16 10:18:04 +04:00
|
|
|
osg::Vec3f RenderingManager::getHalfExtents(const MWWorld::ConstPtr& object) const
|
|
|
|
{
|
|
|
|
osg::Vec3f halfExtents(0, 0, 0);
|
|
|
|
std::string modelName = object.getClass().getModel(object);
|
|
|
|
if (modelName.empty())
|
|
|
|
return halfExtents;
|
|
|
|
|
|
|
|
osg::ref_ptr<const osg::Node> node = mResourceSystem->getSceneManager()->getTemplate(modelName);
|
|
|
|
osg::ComputeBoundsVisitor computeBoundsVisitor;
|
2020-04-20 18:47:14 +02:00
|
|
|
computeBoundsVisitor.setTraversalMask(~(MWRender::Mask_ParticleSystem | MWRender::Mask_Effect));
|
2018-06-16 10:18:04 +04:00
|
|
|
const_cast<osg::Node*>(node.get())->accept(computeBoundsVisitor);
|
|
|
|
osg::BoundingBox bounds = computeBoundsVisitor.getBoundingBox();
|
|
|
|
|
|
|
|
if (bounds.valid())
|
|
|
|
{
|
|
|
|
halfExtents[0] = std::abs(bounds.xMax() - bounds.xMin()) / 2.f;
|
|
|
|
halfExtents[1] = std::abs(bounds.yMax() - bounds.yMin()) / 2.f;
|
|
|
|
halfExtents[2] = std::abs(bounds.zMax() - bounds.zMin()) / 2.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
return halfExtents;
|
|
|
|
}
|
|
|
|
|
2023-05-19 14:29:01 -07:00
|
|
|
osg::BoundingBox RenderingManager::getCullSafeBoundingBox(const MWWorld::Ptr& ptr) const
|
|
|
|
{
|
|
|
|
const std::string model = ptr.getClass().getModel(ptr);
|
|
|
|
if (model.empty())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> rootNode = new SceneUtil::PositionAttitudeTransform;
|
|
|
|
// Hack even used by osg internally, osg's NodeVisitor won't accept const qualified nodes
|
|
|
|
rootNode->addChild(const_cast<osg::Node*>(mResourceSystem->getSceneManager()->getTemplate(model).get()));
|
|
|
|
|
|
|
|
const SceneUtil::PositionAttitudeTransform* baseNode = ptr.getRefData().getBaseNode();
|
|
|
|
if (baseNode)
|
|
|
|
{
|
|
|
|
rootNode->setPosition(baseNode->getPosition());
|
|
|
|
rootNode->setAttitude(baseNode->getAttitude());
|
|
|
|
rootNode->setScale(baseNode->getScale());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rootNode->setPosition(ptr.getRefData().getPosition().asVec3());
|
|
|
|
osg::Vec3f rot = ptr.getRefData().getPosition().asRotationVec3();
|
|
|
|
rootNode->setAttitude(osg::Quat(rot[2], osg::Vec3f(0, 0, -1)) * osg::Quat(rot[1], osg::Vec3f(0, -1, 0))
|
|
|
|
* osg::Quat(rot[0], osg::Vec3f(-1, 0, 0)));
|
|
|
|
const float refScale = ptr.getCellRef().getScale();
|
|
|
|
rootNode->setScale({ refScale, refScale, refScale });
|
|
|
|
}
|
|
|
|
|
|
|
|
SceneUtil::CullSafeBoundsVisitor computeBounds;
|
|
|
|
computeBounds.setTraversalMask(~(MWRender::Mask_ParticleSystem | MWRender::Mask_Effect));
|
|
|
|
rootNode->accept(computeBounds);
|
|
|
|
|
|
|
|
const osg::Vec3f& scale = rootNode->getScale();
|
|
|
|
|
|
|
|
computeBounds.mBoundingBox.xMin() *= scale.x();
|
|
|
|
computeBounds.mBoundingBox.xMax() *= scale.x();
|
|
|
|
computeBounds.mBoundingBox.yMin() *= scale.y();
|
|
|
|
computeBounds.mBoundingBox.yMax() *= scale.y();
|
|
|
|
computeBounds.mBoundingBox.zMin() *= scale.z();
|
|
|
|
computeBounds.mBoundingBox.zMax() *= scale.z();
|
|
|
|
|
|
|
|
return computeBounds.mBoundingBox;
|
|
|
|
}
|
|
|
|
|
2015-12-07 16:11:47 +01:00
|
|
|
void RenderingManager::resetFieldOfView()
|
|
|
|
{
|
|
|
|
if (mFieldOfViewOverridden == true)
|
|
|
|
{
|
|
|
|
mFieldOfViewOverridden = false;
|
2017-02-01 03:00:33 +01:00
|
|
|
|
2015-12-07 16:11:47 +01:00
|
|
|
updateProjectionMatrix();
|
|
|
|
}
|
|
|
|
}
|
2022-06-19 13:28:33 +02:00
|
|
|
void RenderingManager::exportSceneGraph(
|
|
|
|
const MWWorld::Ptr& ptr, const std::filesystem::path& filename, const std::string& format)
|
2017-02-01 03:00:33 +01:00
|
|
|
{
|
|
|
|
osg::Node* node = mViewer->getSceneData();
|
|
|
|
if (!ptr.isEmpty())
|
|
|
|
node = ptr.getRefData().getBaseNode();
|
|
|
|
|
|
|
|
SceneUtil::writeScene(node, filename, format);
|
|
|
|
}
|
2015-12-07 16:11:47 +01:00
|
|
|
|
2017-03-06 19:04:17 +01:00
|
|
|
LandManager* RenderingManager::getLandManager() const
|
|
|
|
{
|
|
|
|
return mTerrainStorage->getLandManager();
|
|
|
|
}
|
|
|
|
|
2018-07-21 13:37:02 +03:00
|
|
|
void RenderingManager::updateActorPath(const MWWorld::ConstPtr& actor, const std::deque<osg::Vec3f>& path,
|
2022-06-17 00:28:44 +02:00
|
|
|
const DetourNavigator::AgentBounds& agentBounds, const osg::Vec3f& start, const osg::Vec3f& end) const
|
2018-07-21 13:37:02 +03:00
|
|
|
{
|
2022-06-17 00:28:44 +02:00
|
|
|
mActorsPaths->update(actor, path, agentBounds, start, end, mNavigator.getSettings());
|
2018-07-21 13:37:02 +03:00
|
|
|
}
|
2017-03-06 19:04:17 +01:00
|
|
|
|
2018-07-21 13:37:02 +03:00
|
|
|
void RenderingManager::removeActorPath(const MWWorld::ConstPtr& actor) const
|
|
|
|
{
|
|
|
|
mActorsPaths->remove(actor);
|
|
|
|
}
|
2017-03-06 19:04:17 +01:00
|
|
|
|
2018-08-31 01:39:44 +03:00
|
|
|
void RenderingManager::setNavMeshNumber(const std::size_t value)
|
|
|
|
{
|
|
|
|
mNavMeshNumber = value;
|
|
|
|
}
|
2019-01-20 19:27:52 +03:00
|
|
|
|
|
|
|
void RenderingManager::updateNavMesh()
|
|
|
|
{
|
2019-01-20 19:30:26 +03:00
|
|
|
if (!mNavMesh->isEnabled())
|
|
|
|
return;
|
|
|
|
|
2019-01-20 19:27:52 +03:00
|
|
|
const auto navMeshes = mNavigator.getNavMeshes();
|
|
|
|
|
|
|
|
auto it = navMeshes.begin();
|
|
|
|
for (std::size_t i = 0; it != navMeshes.end() && i < mNavMeshNumber; ++i)
|
|
|
|
++it;
|
|
|
|
if (it == navMeshes.end())
|
|
|
|
{
|
|
|
|
mNavMesh->reset();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2022-02-20 19:34:04 +01:00
|
|
|
mNavMesh->update(it->second, mNavMeshNumber, mNavigator.getSettings());
|
2019-01-20 19:27:52 +03:00
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
|
|
|
Log(Debug::Error) << "NavMesh render update exception: " << e.what();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-27 23:45:01 +01:00
|
|
|
|
|
|
|
void RenderingManager::updateRecastMesh()
|
|
|
|
{
|
|
|
|
if (!mRecastMesh->isEnabled())
|
|
|
|
return;
|
|
|
|
|
|
|
|
mRecastMesh->update(mNavigator.getRecastMeshTiles(), mNavigator.getSettings());
|
|
|
|
}
|
2019-06-13 13:37:00 +00:00
|
|
|
|
|
|
|
void RenderingManager::setActiveGrid(const osg::Vec4i& grid)
|
|
|
|
{
|
|
|
|
mTerrain->setActiveGrid(grid);
|
|
|
|
}
|
2020-05-08 13:37:00 +00:00
|
|
|
bool RenderingManager::pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled)
|
2019-08-03 13:37:00 +00:00
|
|
|
{
|
2020-05-11 13:37:00 +00:00
|
|
|
if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging)
|
2020-05-08 13:37:00 +00:00
|
|
|
return false;
|
2020-07-10 00:44:54 +02:00
|
|
|
if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(),
|
|
|
|
osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY()), enabled))
|
2020-05-08 13:37:00 +00:00
|
|
|
{
|
|
|
|
mTerrain->rebuildViews();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2019-08-03 13:37:00 +00:00
|
|
|
}
|
2020-05-11 13:37:00 +00:00
|
|
|
void RenderingManager::pagingBlacklistObject(int type, const MWWorld::ConstPtr& ptr)
|
|
|
|
{
|
|
|
|
if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging)
|
|
|
|
return;
|
|
|
|
const ESM::RefNum& refnum = ptr.getCellRef().getRefNum();
|
|
|
|
if (!refnum.hasContentFile())
|
|
|
|
return;
|
2020-07-09 23:17:01 +02:00
|
|
|
if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3(),
|
|
|
|
osg::Vec2i(ptr.getCell()->getCell()->getGridX(), ptr.getCell()->getCell()->getGridY())))
|
2020-05-11 13:37:00 +00:00
|
|
|
mTerrain->rebuildViews();
|
|
|
|
}
|
2020-05-12 13:37:00 +00:00
|
|
|
bool RenderingManager::pagingUnlockCache()
|
|
|
|
{
|
|
|
|
if (mObjectPaging && mObjectPaging->unlockCache())
|
|
|
|
{
|
|
|
|
mTerrain->rebuildViews();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-26 21:53:06 +02:00
|
|
|
void RenderingManager::getPagedRefnums(const osg::Vec4i& activeGrid, std::vector<ESM::RefNum>& out)
|
2020-05-10 13:37:00 +00:00
|
|
|
{
|
|
|
|
if (mObjectPaging)
|
|
|
|
mObjectPaging->getPagedRefnums(activeGrid, out);
|
|
|
|
}
|
2022-02-03 02:05:43 +01:00
|
|
|
|
|
|
|
void RenderingManager::setNavMeshMode(NavMeshMode value)
|
|
|
|
{
|
|
|
|
mNavMesh->setMode(value);
|
|
|
|
}
|
2012-05-27 21:39:18 +02:00
|
|
|
}
|