2011-10-20 19:02:19 +00:00
# include "renderingmanager.hpp"
2015-08-21 10:00:08 +00:00
# include <limits>
2017-02-15 19:57:12 +00:00
# include <cstdlib>
2020-06-25 19:46:07 +00:00
# include <condition_variable>
# include <mutex>
2011-10-20 22:15:30 +00:00
2015-04-12 13:34:50 +00:00
# include <osg/Light>
# include <osg/LightModel>
2015-04-21 21:27:26 +00:00
# include <osg/Fog>
2017-02-01 02:18:17 +00:00
# include <osg/Material>
2015-06-01 15:02:44 +00:00
# include <osg/PolygonMode>
2015-04-12 13:34:50 +00:00
# include <osg/Group>
2015-05-24 01:36:34 +00:00
# include <osg/UserDataContainer>
# include <osg/ComputeBoundsVisitor>
2017-11-15 14:20:59 +00:00
# include <osg/ShapeDrawable>
# include <osg/TextureCubeMap>
2011-10-20 22:15:30 +00:00
2015-05-24 01:36:34 +00:00
# include <osgUtil/LineSegmentIntersector>
2015-05-03 16:16:54 +00:00
2017-11-07 14:02:01 +00:00
# include <osg/ImageUtils>
2015-04-12 13:34:50 +00:00
# include <osgViewer/Viewer>
2013-07-29 00:32:08 +00:00
2020-04-22 13:57:24 +00:00
# include <components/nifosg/nifloader.hpp>
2020-04-22 11:34:19 +00:00
2018-08-14 19:05:43 +00:00
# include <components/debug/debuglog.hpp>
2020-01-09 11:57:05 +00:00
# include <components/misc/stringops.hpp>
2015-04-22 17:08:56 +00:00
# include <components/resource/resourcesystem.hpp>
2016-02-05 22:03:53 +00:00
# include <components/resource/imagemanager.hpp>
2015-05-26 18:20:18 +00:00
# include <components/resource/scenemanager.hpp>
2017-02-09 02:32:40 +00:00
# include <components/resource/keyframemanager.hpp>
2017-11-15 14:20:59 +00:00
# include <components/shader/shadermanager.hpp>
2015-04-22 17:08:56 +00:00
2015-04-21 21:27:26 +00:00
# include <components/settings/settings.hpp>
2015-04-12 13:34:50 +00:00
# include <components/sceneutil/util.hpp>
# include <components/sceneutil/lightmanager.hpp>
2015-04-14 15:29:12 +00:00
# include <components/sceneutil/statesetupdater.hpp>
2015-11-20 20:57:04 +00:00
# include <components/sceneutil/positionattitudetransform.hpp>
2016-02-09 00:02:40 +00:00
# include <components/sceneutil/workqueue.hpp>
2016-02-09 14:30:53 +00:00
# include <components/sceneutil/unrefqueue.hpp>
2017-02-01 02:00:33 +00:00
# include <components/sceneutil/writescene.hpp>
2017-11-08 01:44:49 +00:00
# include <components/sceneutil/shadow.hpp>
2015-04-14 13:55:56 +00:00
2015-06-02 23:18:36 +00:00
# include <components/terrain/terraingrid.hpp>
2017-03-09 02:49:40 +00:00
# include <components/terrain/quadtreeworld.hpp>
2015-06-02 23:18:36 +00:00
2015-04-12 13:34:50 +00:00
# include <components/esm/loadcell.hpp>
2016-01-06 11:46:06 +00:00
# include <components/fallback/fallback.hpp>
2013-08-16 11:01:52 +00:00
2018-04-07 13:11:23 +00:00
# include <components/detournavigator/navigator.hpp>
2015-11-03 01:17:42 +00:00
# include "../mwworld/cellstore.hpp"
2018-06-16 06:18:04 +00:00
# include "../mwworld/class.hpp"
2017-11-16 21:08:33 +00:00
# include "../mwgui/loadingscreen.hpp"
# include "../mwbase/environment.hpp"
# include "../mwbase/windowmanager.hpp"
2015-11-01 21:09:02 +00:00
2015-04-14 13:55:56 +00:00
# include "sky.hpp"
2015-04-19 15:55:56 +00:00
# include "effectmanager.hpp"
2015-05-01 16:21:50 +00:00
# include "npcanimation.hpp"
2020-04-20 16:47:14 +00:00
# include "vismask.hpp"
2015-05-04 15:41:30 +00:00
# include "pathgrid.hpp"
2015-05-21 21:54:39 +00:00
# include "camera.hpp"
2020-07-11 12:21:18 +00:00
# include "viewovershoulder.hpp"
2015-06-02 14:35:35 +00:00
# include "water.hpp"
2015-06-02 23:18:36 +00:00
# include "terrainstorage.hpp"
2016-01-29 16:00:18 +00:00
# include "util.hpp"
2018-04-07 13:11:23 +00:00
# include "navmesh.hpp"
2018-07-21 10:37:02 +00:00
# include "actorspaths.hpp"
2019-11-27 22:45:01 +00:00
# include "recastmesh.hpp"
2020-06-07 06:35:33 +00:00
# include "fogmanager.hpp"
2019-06-13 13:37:00 +00:00
# include "objectpaging.hpp"
2017-09-21 10:08:45 +00:00
2015-04-12 13:34:50 +00:00
namespace MWRender
2012-03-08 06:46:34 +00:00
{
2012-03-13 21:14:35 +00:00
2015-04-14 15:29:12 +00:00
class StateUpdater : public SceneUtil : : StateSetUpdater
2015-04-14 13:55:56 +00:00
{
public :
2015-04-21 21:27:26 +00:00
StateUpdater ( )
2015-07-01 01:21:39 +00:00
: mFogStart ( 0.f )
, mFogEnd ( 0.f )
2015-06-01 15:02:44 +00:00
, mWireframe ( false )
2015-04-21 21:27:26 +00:00
{
}
2015-04-14 13:55:56 +00:00
virtual void setDefaults ( osg : : StateSet * stateset )
{
osg : : LightModel * lightModel = new osg : : LightModel ;
stateset - > setAttribute ( lightModel , osg : : StateAttribute : : ON ) ;
2015-04-21 21:27:26 +00:00
osg : : Fog * fog = new osg : : Fog ;
2015-05-26 16:22:21 +00:00
fog - > setMode ( osg : : Fog : : LINEAR ) ;
2015-04-21 21:27:26 +00:00
stateset - > setAttributeAndModes ( fog , osg : : StateAttribute : : ON ) ;
2015-06-01 15:02:44 +00: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 13:55:56 +00:00
}
virtual void apply ( osg : : StateSet * stateset , osg : : NodeVisitor * )
{
osg : : LightModel * lightModel = static_cast < osg : : LightModel * > ( stateset - > getAttribute ( osg : : StateAttribute : : LIGHTMODEL ) ) ;
lightModel - > setAmbientIntensity ( mAmbientColor ) ;
2015-04-21 21:27:26 +00:00
osg : : Fog * fog = static_cast < osg : : Fog * > ( stateset - > getAttribute ( osg : : StateAttribute : : FOG ) ) ;
fog - > setColor ( mFogColor ) ;
2015-07-01 01:21:39 +00:00
fog - > setStart ( mFogStart ) ;
2015-04-21 21:27:26 +00:00
fog - > setEnd ( mFogEnd ) ;
2015-04-14 13:55:56 +00:00
}
2015-04-21 21:27:26 +00:00
void setAmbientColor ( const osg : : Vec4f & col )
2015-04-14 13:55:56 +00:00
{
mAmbientColor = col ;
}
2015-04-21 21:27:26 +00:00
void setFogColor ( const osg : : Vec4f & col )
{
mFogColor = col ;
}
2015-07-01 01:21:39 +00:00
void setFogStart ( float start )
{
mFogStart = start ;
}
2015-04-21 21:27:26 +00:00
void setFogEnd ( float end )
{
mFogEnd = end ;
}
2015-06-01 15:02:44 +00:00
void setWireframe ( bool wireframe )
{
if ( mWireframe ! = wireframe )
{
mWireframe = wireframe ;
reset ( ) ;
}
}
bool getWireframe ( ) const
{
return mWireframe ;
}
2015-04-14 13:55:56 +00:00
private :
osg : : Vec4f mAmbientColor ;
2015-04-21 21:27:26 +00:00
osg : : Vec4f mFogColor ;
2015-07-01 01:21:39 +00:00
float mFogStart ;
2015-04-21 21:27:26 +00:00
float mFogEnd ;
2015-06-01 15:02:44 +00:00
bool mWireframe ;
2015-04-14 13:55:56 +00:00
} ;
2016-02-09 00:17:02 +00:00
class PreloadCommonAssetsWorkItem : public SceneUtil : : WorkItem
{
public :
PreloadCommonAssetsWorkItem ( Resource : : ResourceSystem * resourceSystem )
: mResourceSystem ( resourceSystem )
{
}
virtual void doWork ( )
{
2017-02-09 02:32:40 +00:00
try
{
for ( std : : vector < std : : string > : : const_iterator it = mModels . begin ( ) ; it ! = mModels . end ( ) ; + + it )
mResourceSystem - > getSceneManager ( ) - > cacheInstance ( * it ) ;
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 00:17:02 +00:00
}
std : : vector < std : : string > mModels ;
std : : vector < std : : string > mTextures ;
2017-02-09 02:32:40 +00:00
std : : vector < std : : string > mKeyframes ;
2016-02-09 00:17:02 +00:00
private :
Resource : : ResourceSystem * mResourceSystem ;
} ;
2018-04-07 13:11:23 +00:00
RenderingManager : : RenderingManager ( osgViewer : : Viewer * viewer , osg : : ref_ptr < osg : : Group > rootNode ,
Resource : : ResourceSystem * resourceSystem , SceneUtil : : WorkQueue * workQueue ,
2019-01-22 06:08:48 +00:00
const std : : string & resourcePath , DetourNavigator : : Navigator & navigator )
2015-04-12 13:34:50 +00:00
: mViewer ( viewer )
, mRootNode ( rootNode )
, mResourceSystem ( resourceSystem )
2017-02-14 02:37:45 +00:00
, mWorkQueue ( workQueue )
2016-02-09 14:30:53 +00:00
, mUnrefQueue ( new SceneUtil : : UnrefQueue )
2018-04-07 13:11:23 +00:00
, mNavigator ( navigator )
2015-06-11 21:16:05 +00:00
, mNightEyeFactor ( 0.f )
2018-08-01 16:18:37 +00:00
, mFieldOfViewOverridden ( false )
2017-09-20 18:42:15 +00:00
, mFieldOfViewOverride ( 0.f )
2014-06-22 14:10:52 +00:00
{
2020-04-20 16:47:14 +00:00
resourceSystem - > getSceneManager ( ) - > setParticleSystemMask ( MWRender : : Mask_ParticleSystem ) ;
2016-02-16 17:18:48 +00:00
resourceSystem - > getSceneManager ( ) - > setShaderPath ( resourcePath + " /shaders " ) ;
2020-03-14 12:39:32 +00:00
// Shadows and radial fog have problems with fixed-function mode
bool forceShaders = Settings : : Manager : : getBool ( " radial fog " , " Shaders " ) | | Settings : : Manager : : getBool ( " force shaders " , " Shaders " ) | | Settings : : Manager : : getBool ( " enable shadows " , " Shadows " ) ;
resourceSystem - > getSceneManager ( ) - > setForceShaders ( forceShaders ) ;
2019-02-20 13:37:00 +00:00
// FIXME: calling dummy method because terrain needs to know whether lighting is clamped
2016-02-18 16:08:18 +00:00
resourceSystem - > getSceneManager ( ) - > setClampLighting ( Settings : : Manager : : getBool ( " clamp lighting " , " Shaders " ) ) ;
2016-02-20 16:57:19 +00: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 20:00:31 +00:00
resourceSystem - > getSceneManager ( ) - > setNormalHeightMapPattern ( Settings : : Manager : : getString ( " normal height map pattern " , " Shaders " ) ) ;
2016-02-20 18:02:11 +00:00
resourceSystem - > getSceneManager ( ) - > setAutoUseSpecularMaps ( Settings : : Manager : : getBool ( " auto use object specular maps " , " Shaders " ) ) ;
resourceSystem - > getSceneManager ( ) - > setSpecularMapPattern ( Settings : : Manager : : getString ( " specular map pattern " , " Shaders " ) ) ;
2015-11-10 16:00:33 +00:00
2016-02-08 15:45:56 +00:00
osg : : ref_ptr < SceneUtil : : LightManager > sceneRoot = new SceneUtil : : LightManager ;
2020-04-20 16:47:14 +00:00
sceneRoot - > setLightingMask ( Mask_Lighting ) ;
2016-02-08 15:45:56 +00: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 14:44:03 +00:00
2020-04-20 16:47:14 +00:00
int shadowCastingTraversalMask = Mask_Scene ;
2017-12-27 02:32:17 +00:00
if ( Settings : : Manager : : getBool ( " actor shadows " , " Shadows " ) )
2020-04-20 16:47:14 +00:00
shadowCastingTraversalMask | = Mask_Actor ;
2017-12-27 02:32:17 +00:00
if ( Settings : : Manager : : getBool ( " player shadows " , " Shadows " ) )
2020-04-20 16:47:14 +00:00
shadowCastingTraversalMask | = Mask_Player ;
2017-12-27 02:32:17 +00:00
if ( Settings : : Manager : : getBool ( " terrain shadows " , " Shadows " ) )
2020-04-20 16:47:14 +00:00
shadowCastingTraversalMask | = Mask_Terrain ;
2018-03-03 15:13:36 +00:00
int indoorShadowCastingTraversalMask = shadowCastingTraversalMask ;
if ( Settings : : Manager : : getBool ( " object shadows " , " Shadows " ) )
2020-04-20 16:47:14 +00:00
shadowCastingTraversalMask | = ( Mask_Object | Mask_Static ) ;
2019-02-27 15:41:07 +00:00
2018-10-16 20:23:31 +00:00
mShadowManager . reset ( new SceneUtil : : ShadowManager ( sceneRoot , mRootNode , shadowCastingTraversalMask , indoorShadowCastingTraversalMask , mResourceSystem - > getSceneManager ( ) - > getShaderManager ( ) ) ) ;
2017-04-14 13:32:18 +00:00
2018-02-26 22:27:09 +00:00
Shader : : ShaderManager : : DefineMap shadowDefines = mShadowManager - > getShadowDefines ( ) ;
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 17:08:59 +00:00
globalDefines [ " preLightEnv " ] = Settings : : Manager : : getBool ( " apply lighting to environment maps " , " Shaders " ) ? " 1 " : " 0 " ;
2020-03-14 12:39:32 +00:00
globalDefines [ " radialFog " ] = Settings : : Manager : : getBool ( " radial fog " , " Shaders " ) ? " 1 " : " 0 " ;
2019-02-20 13:37:00 +00:00
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-04 03:47:15 +00:00
2018-07-21 10:37:02 +00:00
mNavMesh . reset ( new NavMesh ( mRootNode , Settings : : Manager : : getBool ( " enable nav mesh render " , " Navigator " ) ) ) ;
mActorsPaths . reset ( new ActorsPaths ( mRootNode , Settings : : Manager : : getBool ( " enable agents paths render " , " Navigator " ) ) ) ;
2019-11-27 22:45:01 +00:00
mRecastMesh . reset ( new RecastMesh ( mRootNode , Settings : : Manager : : getBool ( " enable recast mesh render " , " Navigator " ) ) ) ;
2015-05-04 15:41:30 +00:00
mPathgrid . reset ( new Pathgrid ( mRootNode ) ) ;
2015-05-02 20:45:27 +00:00
2016-02-08 15:45:56 +00:00
mObjects . reset ( new Objects ( mResourceSystem , sceneRoot , mUnrefQueue . get ( ) ) ) ;
2012-02-26 12:13:29 +00:00
2018-10-09 06:21:12 +00:00
if ( getenv ( " OPENMW_DONT_PRECOMPILE " ) = = nullptr )
2018-02-13 00:40:41 +00:00
{
2017-02-15 19:57:12 +00:00
mViewer - > setIncrementalCompileOperation ( new osgUtil : : IncrementalCompileOperation ) ;
2018-02-13 00:40:41 +00:00
mViewer - > getIncrementalCompileOperation ( ) - > setTargetFrameRate ( Settings : : Manager : : getFloat ( " target framerate " , " Cells " ) ) ;
}
2015-05-03 16:16:54 +00:00
2015-05-26 18:20:18 +00:00
mResourceSystem - > getSceneManager ( ) - > setIncrementalCompileOperation ( mViewer - > getIncrementalCompileOperation ( ) ) ;
2015-05-03 16:16:54 +00:00
2016-02-08 15:45:56 +00:00
mEffectManager . reset ( new EffectManager ( sceneRoot , mResourceSystem ) ) ;
2015-06-02 14:35:35 +00:00
2019-02-27 15:41:07 +00: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 " ) ;
const bool useTerrainNormalMaps = Settings : : Manager : : getBool ( " auto use terrain normal maps " , " Shaders " ) ;
const bool useTerrainSpecularMaps = Settings : : Manager : : getBool ( " auto use terrain specular maps " , " Shaders " ) ;
mTerrainStorage = new TerrainStorage ( mResourceSystem , normalMapPattern , heightMapPattern , useTerrainNormalMaps , specularMapPattern , useTerrainSpecularMaps ) ;
2017-03-09 02:49:40 +00:00
2020-06-06 10:10:24 +00:00
if ( Settings : : Manager : : getBool ( " distant terrain " , " Terrain " ) )
2019-02-27 15:41:07 +00:00
{
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 float lodFactor = Settings : : Manager : : getFloat ( " lod factor " , " Terrain " ) ;
2019-02-20 13:37:00 +00:00
const int vertexLodMod = Settings : : Manager : : getInt ( " vertex lod mod " , " Terrain " ) ;
2019-02-28 08:48:04 +00:00
float maxCompGeometrySize = Settings : : Manager : : getFloat ( " max composite geometry size " , " Terrain " ) ;
maxCompGeometrySize = std : : max ( maxCompGeometrySize , 1.f ) ;
mTerrain . reset ( new Terrain : : QuadTreeWorld (
2020-04-20 16:47:14 +00:00
sceneRoot , mRootNode , mResourceSystem , mTerrainStorage , Mask_Terrain , Mask_PreCompile , Mask_Debug ,
compMapResolution , compMapLevel , lodFactor , vertexLodMod , maxCompGeometrySize ) ) ;
2019-06-13 13:37:00 +00:00
if ( Settings : : Manager : : getBool ( " object paging " , " Terrain " ) )
{
mObjectPaging . reset ( new ObjectPaging ( mResourceSystem - > getSceneManager ( ) ) ) ;
static_cast < Terrain : : QuadTreeWorld * > ( mTerrain . get ( ) ) - > addChunkManager ( mObjectPaging . get ( ) ) ;
mResourceSystem - > addResourceManager ( mObjectPaging . get ( ) ) ;
}
2019-02-27 15:41:07 +00:00
}
2017-03-09 02:49:40 +00:00
else
2020-04-20 16:47:14 +00:00
mTerrain . reset ( new Terrain : : TerrainGrid ( sceneRoot , mRootNode , mResourceSystem , mTerrainStorage , Mask_Terrain , Mask_PreCompile , Mask_Debug ) ) ;
2018-06-12 23:48:31 +00:00
2018-02-13 00:40:41 +00:00
mTerrain - > setTargetFrameRate ( Settings : : Manager : : getFloat ( " target framerate " , " Cells " ) ) ;
2019-02-20 13:37:00 +00:00
mTerrain - > setWorkQueue ( mWorkQueue . get ( ) ) ;
2015-04-19 15:55:56 +00:00
2019-06-13 13:37:00 +00:00
// water goes after terrain for correct waterculling order
mWater . reset ( new Water ( mRootNode , sceneRoot , mResourceSystem , mViewer - > getIncrementalCompileOperation ( ) , resourcePath ) ) ;
2015-05-21 21:54:39 +00:00
mCamera . reset ( new Camera ( mViewer - > getCamera ( ) ) ) ;
2020-07-11 12:21:18 +00:00
if ( Settings : : Manager : : getBool ( " view over shoulder " , " Camera " ) )
mViewOverShoulderController . reset ( new ViewOverShoulderController ( mCamera . get ( ) ) ) ;
2015-05-21 21:54:39 +00:00
2015-05-14 19:42:04 +00:00
mViewer - > setLightingMode ( osgViewer : : View : : NO_LIGHT ) ;
2011-11-04 03:47:15 +00:00
2015-04-12 13:34:50 +00:00
osg : : ref_ptr < osg : : LightSource > source = new osg : : LightSource ;
2020-04-20 16:47:14 +00:00
source - > setNodeMask ( Mask_Lighting ) ;
2015-04-12 13:34:50 +00: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 16:22:21 +00:00
mSunLight - > setSpecular ( osg : : Vec4f ( 0 , 0 , 0 , 0 ) ) ;
2015-04-12 13:34:50 +00:00
mSunLight - > setConstantAttenuation ( 1.f ) ;
2016-02-08 15:45:56 +00:00
sceneRoot - > addChild ( source ) ;
2011-11-04 03:47:15 +00:00
2016-02-08 15:45:56 +00: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 02:18:17 +00: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 ) ;
2015-04-14 13:55:56 +00:00
2020-06-07 06:35:33 +00:00
mFog . reset ( new FogManager ( ) ) ;
2017-10-24 12:12:41 +00:00
2020-06-07 06:35:33 +00:00
mSky . reset ( new SkyManager ( sceneRoot , resourceSystem - > getSceneManager ( ) ) ) ;
2017-10-14 16:45:29 +00:00
mSky - > setCamera ( mViewer - > getCamera ( ) ) ;
2017-10-16 17:47:08 +00:00
mSky - > setRainIntensityUniform ( mWater - > getRainIntensityUniform ( ) ) ;
2015-04-30 21:21:25 +00:00
2015-04-14 13:55:56 +00:00
source - > setStateSetModes ( * mRootNode - > getOrCreateStateSet ( ) , osg : : StateAttribute : : ON ) ;
mStateUpdater = new StateUpdater ;
2016-02-08 15:45:56 +00:00
sceneRoot - > addUpdateCallback ( mStateUpdater ) ;
2015-04-21 21:27:26 +00:00
osg : : Camera : : CullingMode cullingMode = osg : : Camera : : DEFAULT_CULLING | osg : : Camera : : FAR_PLANE_CULLING ;
2011-11-04 03:47:15 +00:00
2015-05-24 00:34:20 +00:00
if ( ! Settings : : Manager : : getBool ( " small feature culling " , " Camera " ) )
2015-05-14 16:46:04 +00:00
cullingMode & = ~ ( osg : : CullStack : : SMALL_FEATURE_CULLING ) ;
else
2017-02-01 04:38:59 +00:00
{
mViewer - > getCamera ( ) - > setSmallFeatureCullingPixelSize ( Settings : : Manager : : getFloat ( " small feature culling pixel size " , " Camera " ) ) ;
2015-05-14 16:46:04 +00:00
cullingMode | = osg : : CullStack : : SMALL_FEATURE_CULLING ;
2017-02-01 04:38:59 +00:00
}
2015-04-21 21:27:26 +00:00
2015-05-14 19:42:04 +00:00
mViewer - > getCamera ( ) - > setCullingMode ( cullingMode ) ;
2015-04-14 13:55:56 +00:00
2015-05-14 19:42:04 +00:00
mViewer - > getCamera ( ) - > setComputeNearFarMode ( osg : : Camera : : DO_NOT_COMPUTE_NEAR_FAR ) ;
mViewer - > getCamera ( ) - > setCullingMode ( cullingMode ) ;
2015-04-21 21:27:26 +00:00
2020-04-20 16:47:14 +00:00
mViewer - > getCamera ( ) - > setCullMask ( ~ ( Mask_UpdateVisitor | Mask_SimpleWater ) ) ;
2020-04-22 11:34:19 +00:00
NifOsg : : Loader : : setHiddenNodeMask ( Mask_UpdateVisitor ) ;
2020-04-29 13:20:03 +00:00
NifOsg : : Loader : : setIntersectionDisabledNodeMask ( Mask_Effect ) ;
2015-05-20 01:35:52 +00:00
2015-05-24 00:34:20 +00:00
mNearClip = Settings : : Manager : : getFloat ( " near clip " , " Camera " ) ;
mViewDistance = Settings : : Manager : : getFloat ( " viewing distance " , " Camera " ) ;
2019-03-03 17:29:51 +00:00
float fov = Settings : : Manager : : getFloat ( " field of view " , " Camera " ) ;
mFieldOfView = std : : min ( std : : max ( 1.f , fov ) , 179.f ) ;
float firstPersonFov = Settings : : Manager : : getFloat ( " first person field of view " , " Camera " ) ;
mFirstPersonFieldOfView = std : : min ( std : : max ( 1.f , firstPersonFov ) , 179.f ) ;
2015-06-02 14:35:35 +00:00
mStateUpdater - > setFogEnd ( mViewDistance ) ;
2015-10-28 17:59:35 +00:00
mRootNode - > getOrCreateStateSet ( ) - > addUniform ( new osg : : Uniform ( " near " , mNearClip ) ) ;
mRootNode - > getOrCreateStateSet ( ) - > addUniform ( new osg : : Uniform ( " far " , mViewDistance ) ) ;
2017-09-26 12:14:28 +00:00
mUniformNear = mRootNode - > getOrCreateStateSet ( ) - > getUniform ( " near " ) ;
mUniformFar = mRootNode - > getOrCreateStateSet ( ) - > getUniform ( " far " ) ;
updateProjectionMatrix ( ) ;
2015-04-14 13:55:56 +00:00
}
RenderingManager : : ~ RenderingManager ( )
{
2016-08-14 16:10:29 +00:00
// let background loading thread finish before we delete anything else
2018-10-09 06:21:12 +00:00
mWorkQueue = nullptr ;
2013-02-03 14:46:23 +00:00
}
2012-02-24 15:12:43 +00:00
2019-11-24 13:40:19 +00:00
osgUtil : : IncrementalCompileOperation * RenderingManager : : getIncrementalCompileOperation ( )
{
return mViewer - > getIncrementalCompileOperation ( ) ;
}
2015-04-12 13:34:50 +00:00
MWRender : : Objects & RenderingManager : : getObjects ( )
2014-03-05 20:45:43 +00:00
{
2015-04-12 13:34:50 +00:00
return * mObjects . get ( ) ;
2014-03-05 20:45:43 +00:00
}
2014-02-18 15:44:37 +00:00
2015-04-12 13:34:50 +00:00
Resource : : ResourceSystem * RenderingManager : : getResourceSystem ( )
2012-05-14 19:37:43 +00:00
{
2015-04-12 13:34:50 +00:00
return mResourceSystem ;
2012-05-14 19:37:43 +00:00
}
2016-02-09 19:57:30 +00:00
SceneUtil : : WorkQueue * RenderingManager : : getWorkQueue ( )
2016-02-09 00:02:40 +00:00
{
return mWorkQueue . get ( ) ;
}
2016-02-09 19:57:30 +00:00
SceneUtil : : UnrefQueue * RenderingManager : : getUnrefQueue ( )
2016-02-09 18:04:59 +00:00
{
return mUnrefQueue . get ( ) ;
}
2016-02-09 19:57:30 +00:00
Terrain : : World * RenderingManager : : getTerrain ( )
{
return mTerrain . get ( ) ;
}
2016-02-09 00:17:02 +00:00
void RenderingManager : : preloadCommonAssets ( )
{
osg : : ref_ptr < PreloadCommonAssetsWorkItem > workItem ( new PreloadCommonAssetsWorkItem ( mResourceSystem ) ) ;
mSky - > listAssetsToPreload ( workItem - > mModels , workItem - > mTextures ) ;
mWater - > listAssetsToPreload ( workItem - > mTextures ) ;
2017-02-09 02:32:40 +00:00
const char * basemodels [ ] = { " xbase_anim " , " xbase_anim.1st " , " xbase_anim_female " , " xbase_animkna " } ;
for ( size_t i = 0 ; i < sizeof ( basemodels ) / sizeof ( basemodels [ 0 ] ) ; + + i )
{
workItem - > mModels . push_back ( std : : string ( " meshes/ " ) + basemodels [ i ] + " .nif " ) ;
workItem - > mKeyframes . push_back ( std : : string ( " meshes/ " ) + basemodels [ i ] + " .kf " ) ;
}
2016-02-09 00:17:02 +00:00
workItem - > mTextures . push_back ( " textures/_land_default.dds " ) ;
mWorkQueue - > addWorkItem ( workItem ) ;
}
2016-02-06 23:36:31 +00:00
double RenderingManager : : getReferenceTime ( ) const
{
return mViewer - > getFrameStamp ( ) - > getReferenceTime ( ) ;
}
2015-12-04 23:44:04 +00:00
osg : : Group * RenderingManager : : getLightRoot ( )
{
2016-02-08 15:45:56 +00:00
return mSceneRoot . get ( ) ;
2015-12-04 23:44:04 +00:00
}
2015-06-11 21:16:05 +00:00
void RenderingManager : : setNightEyeFactor ( float factor )
{
if ( factor ! = mNightEyeFactor )
{
mNightEyeFactor = factor ;
updateAmbient ( ) ;
}
}
2015-04-14 13:55:56 +00:00
void RenderingManager : : setAmbientColour ( const osg : : Vec4f & colour )
{
2015-06-11 21:16:05 +00:00
mAmbientColor = colour ;
updateAmbient ( ) ;
2015-04-14 13:55:56 +00:00
}
2015-06-16 18:56:48 +00: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 ) ;
}
2015-04-12 13:34:50 +00:00
void RenderingManager : : configureAmbient ( const ESM : : Cell * cell )
2012-05-22 23:32:36 +00:00
{
2015-04-14 13:55:56 +00:00
setAmbientColour ( SceneUtil : : colourFromRGB ( cell - > mAmbi . mAmbient ) ) ;
2012-05-29 02:54:54 +00:00
2016-02-20 18:02:11 +00:00
osg : : Vec4f diffuse = SceneUtil : : colourFromRGB ( cell - > mAmbi . mSunlight ) ;
mSunLight - > setDiffuse ( diffuse ) ;
mSunLight - > setSpecular ( diffuse ) ;
2018-08-08 22:30:33 +00:00
mSunLight - > setPosition ( osg : : Vec4f ( - 0.15f , 0.15f , 1.f , 0.f ) ) ;
2012-05-27 19:39:18 +00:00
}
2016-05-10 15:39:57 +00:00
void RenderingManager : : setSunColour ( const osg : : Vec4f & diffuse , const osg : : Vec4f & specular )
2015-04-14 13:55:56 +00:00
{
2015-05-26 16:22:21 +00:00
// need to wrap this in a StateUpdater?
2016-05-10 15:39:57 +00:00
mSunLight - > setDiffuse ( diffuse ) ;
mSunLight - > setSpecular ( specular ) ;
2015-04-14 13:55:56 +00:00
}
void RenderingManager : : setSunDirection ( const osg : : Vec3f & direction )
{
2015-05-20 00:07:18 +00:00
osg : : Vec3 position = direction * - 1 ;
2015-05-26 16:22:21 +00:00
// need to wrap this in a StateUpdater?
2015-05-20 00:07:18 +00:00
mSunLight - > setPosition ( osg : : Vec4 ( position . x ( ) , position . y ( ) , position . z ( ) , 0 ) ) ;
2015-04-14 13:55:56 +00:00
2015-05-20 00:07:18 +00:00
mSky - > setSunDirection ( position ) ;
2015-04-14 13:55:56 +00:00
}
2015-05-02 20:45:27 +00:00
void RenderingManager : : addCell ( const MWWorld : : CellStore * store )
{
2015-05-04 15:41:30 +00:00
mPathgrid - > addCell ( store ) ;
2015-06-02 14:35:35 +00:00
mWater - > changeCell ( store ) ;
2015-06-02 23:18:36 +00:00
if ( store - > getCell ( ) - > isExterior ( ) )
mTerrain - > loadCell ( store - > getCell ( ) - > getGridX ( ) , store - > getCell ( ) - > getGridY ( ) ) ;
2015-05-02 20:45:27 +00:00
}
2015-04-12 13:34:50 +00:00
void RenderingManager : : removeCell ( const MWWorld : : CellStore * store )
2013-08-20 07:52:27 +00:00
{
2015-05-04 15:41:30 +00:00
mPathgrid - > removeCell ( store ) ;
2018-07-21 10:37:02 +00:00
mActorsPaths - > removeCell ( store ) ;
2015-04-12 13:34:50 +00:00
mObjects - > removeCell ( store ) ;
2015-06-02 23:18:36 +00:00
if ( store - > getCell ( ) - > isExterior ( ) )
mTerrain - > unloadCell ( store - > getCell ( ) - > getGridX ( ) , store - > getCell ( ) - > getGridY ( ) ) ;
2015-06-16 18:36:48 +00:00
mWater - > removeCell ( store ) ;
2013-08-20 07:52:27 +00:00
}
2012-05-22 23:32:36 +00:00
2017-03-09 01:17:25 +00:00
void RenderingManager : : enableTerrain ( bool enable )
{
2019-06-13 13:37:00 +00:00
if ( ! enable )
mWater - > setCullCallback ( nullptr ) ;
2017-03-09 01:17:25 +00:00
mTerrain - > enable ( enable ) ;
}
2015-04-14 13:55:56 +00:00
void RenderingManager : : setSkyEnabled ( bool enabled )
{
mSky - > setEnabled ( enabled ) ;
2018-02-27 00:13:51 +00:00
if ( enabled )
mShadowManager - > enableOutdoorMode ( ) ;
else
mShadowManager - > enableIndoorMode ( ) ;
2015-04-14 13:55:56 +00:00
}
2018-04-07 13:11:23 +00:00
2018-06-12 23:48:31 +00:00
bool RenderingManager : : toggleBorders ( )
{
2020-06-06 10:10:24 +00:00
bool borders = ! mTerrain - > getBordersVisible ( ) ;
mTerrain - > setBordersVisible ( borders ) ;
return borders ;
2018-06-12 23:48:31 +00:00
}
2015-04-14 13:55:56 +00:00
2015-05-02 20:45:27 +00:00
bool RenderingManager : : toggleRenderMode ( RenderMode mode )
{
if ( mode = = Render_CollisionDebug | | mode = = Render_Pathgrid )
2015-05-04 15:41:30 +00:00
return mPathgrid - > toggleRenderMode ( mode ) ;
2015-05-02 20:45:27 +00:00
else if ( mode = = Render_Wireframe )
{
2015-06-01 15:02:44 +00:00
bool wireframe = ! mStateUpdater - > getWireframe ( ) ;
mStateUpdater - > setWireframe ( wireframe ) ;
return wireframe ;
2015-05-02 20:45:27 +00:00
}
2015-06-02 14:35:35 +00:00
else if ( mode = = Render_Water )
{
return mWater - > toggle ( ) ;
}
else if ( mode = = Render_Scene )
{
int mask = mViewer - > getCamera ( ) - > getCullMask ( ) ;
2020-04-20 16:47:14 +00:00
bool enabled = mask & Mask_Scene ;
2015-06-02 14:35:35 +00:00
enabled = ! enabled ;
if ( enabled )
2020-04-20 16:47:14 +00:00
mask | = Mask_Scene ;
2015-06-02 14:35:35 +00:00
else
2020-04-20 16:47:14 +00:00
mask & = ~ Mask_Scene ;
2015-06-02 14:35:35 +00:00
mViewer - > getCamera ( ) - > setCullMask ( mask ) ;
return enabled ;
}
2018-04-07 13:11:23 +00:00
else if ( mode = = Render_NavMesh )
{
return mNavMesh - > toggle ( ) ;
}
2018-07-21 10:37:02 +00:00
else if ( mode = = Render_ActorsPaths )
{
return mActorsPaths - > toggle ( ) ;
}
2019-11-27 22:45:01 +00:00
else if ( mode = = Render_RecastMesh )
{
return mRecastMesh - > toggle ( ) ;
}
2015-05-02 20:45:27 +00:00
return false ;
}
2015-04-21 21:27:26 +00:00
void RenderingManager : : configureFog ( const ESM : : Cell * cell )
{
2020-06-07 06:35:33 +00:00
mFog - > configure ( mViewDistance , cell ) ;
2015-04-21 21:27:26 +00:00
}
2017-09-21 10:08:45 +00:00
void RenderingManager : : configureFog ( float fogDepth , float underwaterFog , float dlFactor , float dlOffset , const osg : : Vec4f & color )
2015-04-14 13:55:56 +00:00
{
2020-06-07 06:35:33 +00:00
mFog - > configure ( mViewDistance , fogDepth , underwaterFog , dlFactor , dlOffset , color ) ;
2015-04-14 13:55:56 +00:00
}
SkyManager * RenderingManager : : getSkyManager ( )
{
return mSky . get ( ) ;
}
2015-04-18 23:57:52 +00:00
void RenderingManager : : update ( float dt , bool paused )
{
2017-02-22 01:18:18 +00:00
reportStats ( ) ;
2016-02-09 14:30:53 +00:00
mUnrefQueue - > flush ( mWorkQueue . get ( ) ) ;
2015-06-19 01:32:48 +00:00
if ( ! paused )
2015-06-20 15:08:46 +00:00
{
2015-06-19 01:32:48 +00:00
mEffectManager - > update ( dt ) ;
2015-06-20 15:08:46 +00:00
mSky - > update ( dt ) ;
2016-10-30 16:19:38 +00:00
mWater - > update ( dt ) ;
2015-06-20 15:08:46 +00:00
}
2015-06-19 01:32:48 +00:00
2019-01-20 16:27:52 +00:00
updateNavMesh ( ) ;
2019-11-27 22:45:01 +00:00
updateRecastMesh ( ) ;
2018-08-30 22:39:44 +00:00
2020-07-11 12:21:18 +00:00
if ( mViewOverShoulderController )
mViewOverShoulderController - > update ( ) ;
2015-05-21 23:43:16 +00:00
mCamera - > update ( dt , paused ) ;
2015-06-02 14:35:35 +00:00
2020-06-21 23:54:08 +00:00
osg : : Vec3d focal , cameraPos ;
2015-06-02 14:35:35 +00:00
mCamera - > getPosition ( focal , cameraPos ) ;
2015-12-03 14:16:20 +00:00
mCurrentCameraPos = cameraPos ;
2015-08-18 23:13:14 +00:00
2020-06-07 06:35:33 +00:00
bool isUnderwater = mWater - > isUnderwater ( cameraPos ) ;
mStateUpdater - > setFogStart ( mFog - > getFogStart ( isUnderwater ) ) ;
mStateUpdater - > setFogEnd ( mFog - > getFogEnd ( isUnderwater ) ) ;
setFogColor ( mFog - > getFogColor ( isUnderwater ) ) ;
2015-04-19 15:55:56 +00:00
}
2015-05-21 21:54:39 +00:00
void RenderingManager : : updatePlayerPtr ( const MWWorld : : Ptr & ptr )
{
if ( mPlayerAnimation . get ( ) )
2017-09-17 23:07:17 +00:00
{
setupPlayer ( ptr ) ;
2015-05-21 21:54:39 +00:00
mPlayerAnimation - > updatePtr ( ptr ) ;
2017-09-17 23:07:17 +00:00
}
2015-05-21 21:54:39 +00:00
mCamera - > attachTo ( ptr ) ;
}
2015-06-16 18:36:48 +00:00
void RenderingManager : : removePlayer ( const MWWorld : : Ptr & player )
{
mWater - > removeEmitter ( player ) ;
}
2015-04-23 21:50:46 +00:00
void RenderingManager : : rotateObject ( const MWWorld : : Ptr & ptr , const osg : : Quat & rot )
{
2015-05-21 21:54:39 +00:00
if ( ptr = = mCamera - > getTrackingPtr ( ) & &
! mCamera - > isVanityOrPreviewModeEnabled ( ) )
{
2020-07-18 09:48:46 +00:00
mCamera - > rotateCameraToTrackingPtr ( ) ;
2015-05-21 21:54:39 +00:00
}
2015-04-23 21:50:46 +00: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 16:30:11 +00:00
if ( ptr = = mCamera - > getTrackingPtr ( ) ) // update height of camera
mCamera - > processViewChange ( ) ;
2015-04-23 21:50:46 +00:00
}
2015-05-21 22:55:43 +00:00
void RenderingManager : : removeObject ( const MWWorld : : Ptr & ptr )
{
2018-07-21 10:37:02 +00:00
mActorsPaths - > remove ( ptr ) ;
2015-05-21 22:55:43 +00:00
mObjects - > removeObject ( ptr ) ;
2015-06-16 18:36:48 +00:00
mWater - > removeEmitter ( ptr ) ;
2015-05-21 22:55:43 +00:00
}
2015-06-02 14:35:35 +00:00
void RenderingManager : : setWaterEnabled ( bool enabled )
{
mWater - > setEnabled ( enabled ) ;
2015-11-03 22:15:43 +00:00
mSky - > setWaterEnabled ( enabled ) ;
2015-06-02 14:35:35 +00:00
}
void RenderingManager : : setWaterHeight ( float height )
{
2019-06-13 13:37:00 +00:00
mWater - > setCullCallback ( mTerrain - > getHeightCullCallback ( height , Mask_Water ) ) ;
2015-06-02 14:35:35 +00:00
mWater - > setHeight ( height ) ;
2015-11-03 22:15:43 +00:00
mSky - > setWaterHeight ( height ) ;
2015-06-02 14:35:35 +00:00
}
2015-06-03 14:40:16 +00:00
class NotifyDrawCompletedCallback : public osg : : Camera : : DrawCallback
{
public :
2019-02-20 13:37:00 +00:00
NotifyDrawCompletedCallback ( unsigned int frame )
: mDone ( false ) , mFrame ( frame )
2015-08-02 15:57:50 +00:00
{
}
2015-06-03 14:40:16 +00:00
virtual void operator ( ) ( osg : : RenderInfo & renderInfo ) const
{
2020-06-25 19:46:07 +00:00
std : : lock_guard < std : : mutex > lock ( mMutex ) ;
2019-02-20 13:37:00 +00:00
if ( renderInfo . getState ( ) - > getFrameStamp ( ) - > getFrameNumber ( ) > = mFrame )
{
mDone = true ;
2020-06-25 19:46:07 +00:00
mCondition . notify_one ( ) ;
2019-02-20 13:37:00 +00:00
}
2015-06-03 14:40:16 +00:00
}
2015-08-02 15:57:50 +00:00
void waitTillDone ( )
{
2020-06-25 19:46:07 +00:00
std : : unique_lock < std : : mutex > lock ( mMutex ) ;
2015-08-02 15:57:50 +00:00
if ( mDone )
return ;
2020-06-25 19:46:07 +00:00
mCondition . wait ( lock ) ;
2015-08-02 15:57:50 +00:00
}
2020-06-25 19:46:07 +00:00
mutable std : : condition_variable mCondition ;
mutable std : : mutex mMutex ;
2015-08-02 15:57:50 +00:00
mutable bool mDone ;
2019-02-20 13:37:00 +00:00
unsigned int mFrame ;
2015-06-03 14:40:16 +00:00
} ;
2017-11-11 13:32:28 +00:00
bool RenderingManager : : screenshot360 ( osg : : Image * image , std : : string settingStr )
2017-11-07 12:07:11 +00:00
{
2017-11-11 12:51:42 +00:00
int screenshotW = mViewer - > getCamera ( ) - > getViewport ( ) - > width ( ) ;
int screenshotH = mViewer - > getCamera ( ) - > getViewport ( ) - > height ( ) ;
2017-11-15 16:01:16 +00:00
int screenshotMapping = 0 ;
2017-11-11 12:51:42 +00:00
2017-11-11 13:32:28 +00:00
std : : vector < std : : string > settingArgs ;
2020-01-09 11:57:05 +00:00
Misc : : StringUtils : : split ( settingStr , settingArgs ) ;
2017-11-11 12:51:42 +00:00
2017-11-11 13:32:28 +00:00
if ( settingArgs . size ( ) > 0 )
{
std : : string typeStrings [ 4 ] = { " spherical " , " cylindrical " , " planet " , " cubemap " } ;
bool found = false ;
2017-11-11 12:51:42 +00:00
2017-11-11 13:32:28 +00:00
for ( int i = 0 ; i < 4 ; + + i )
if ( settingArgs [ 0 ] . compare ( typeStrings [ i ] ) = = 0 )
2017-11-11 12:51:42 +00:00
{
2017-11-15 16:01:16 +00:00
screenshotMapping = i ;
2017-11-11 13:32:28 +00:00
found = true ;
break ;
2017-11-11 12:51:42 +00:00
}
2017-11-11 13:32:28 +00:00
if ( ! found )
{
2018-08-14 19:05:43 +00:00
Log ( Debug : : Warning ) < < " Wrong screenshot type: " < < settingArgs [ 0 ] < < " . " ;
2017-11-11 13:32:28 +00:00
return false ;
2017-11-11 12:51:42 +00:00
}
2017-11-11 13:32:28 +00:00
}
2018-08-01 15:36:55 +00:00
// planet mapping needs higher resolution
int cubeSize = screenshotMapping = = 2 ? screenshotW : screenshotW / 2 ;
2017-11-11 13:32:28 +00:00
if ( settingArgs . size ( ) > 1 )
screenshotW = std : : min ( 10000 , std : : atoi ( settingArgs [ 1 ] . c_str ( ) ) ) ;
2017-11-11 12:51:42 +00:00
2017-11-11 13:32:28 +00:00
if ( settingArgs . size ( ) > 2 )
screenshotH = std : : min ( 10000 , std : : atoi ( settingArgs [ 2 ] . c_str ( ) ) ) ;
2017-11-11 12:51:42 +00:00
2017-11-11 13:32:28 +00:00
if ( settingArgs . size ( ) > 3 )
cubeSize = std : : min ( 5000 , std : : atoi ( settingArgs [ 3 ] . c_str ( ) ) ) ;
2017-11-10 14:23:44 +00:00
2017-11-11 12:51:42 +00:00
if ( mCamera - > isVanityOrPreviewModeEnabled ( ) )
{
2018-08-14 19:05:43 +00:00
Log ( Debug : : Warning ) < < " Spherical screenshots are not allowed in preview mode. " ;
2017-11-11 12:51:42 +00:00
return false ;
}
2017-11-09 19:25:29 +00:00
2017-11-15 16:01:16 +00:00
bool rawCubemap = screenshotMapping = = 3 ;
if ( rawCubemap )
2017-11-11 12:51:42 +00:00
screenshotW = cubeSize * 6 ; // the image will consist of 6 cube sides in a row
2017-11-15 16:01:16 +00:00
else if ( screenshotMapping = = 2 )
screenshotH = screenshotW ; // use square resolution for planet mapping
2017-11-10 09:50:28 +00:00
2017-11-15 16:01:16 +00:00
std : : vector < osg : : ref_ptr < osg : : Image > > images ;
for ( int i = 0 ; i < 6 ; + + i )
images . push_back ( new osg : : Image ) ;
2017-11-07 18:47:36 +00:00
2017-11-07 14:02:01 +00:00
osg : : Vec3 directions [ 6 ] = {
2017-11-15 16:01:16 +00:00
rawCubemap ? osg : : Vec3 ( 1 , 0 , 0 ) : osg : : Vec3 ( 0 , 0 , 1 ) ,
2018-04-07 13:11:23 +00:00
osg : : Vec3 ( 0 , 0 , - 1 ) ,
osg : : Vec3 ( - 1 , 0 , 0 ) ,
2017-11-15 16:01:16 +00:00
rawCubemap ? osg : : Vec3 ( 0 , 0 , 1 ) : osg : : Vec3 ( 1 , 0 , 0 ) ,
2017-11-15 15:07:01 +00:00
osg : : Vec3 ( 0 , 1 , 0 ) ,
osg : : Vec3 ( 0 , - 1 , 0 ) } ;
double rotations [ ] = {
- osg : : PI / 2.0 ,
osg : : PI / 2.0 ,
osg : : PI ,
0 ,
osg : : PI / 2.0 ,
osg : : PI / 2.0 } ;
2017-11-07 14:02:01 +00:00
double fovBackup = mFieldOfView ;
2017-11-11 12:51:42 +00:00
mFieldOfView = 90.0 ; // each cubemap side sees 90 degrees
2017-11-07 14:02:01 +00:00
2017-11-09 22:09:13 +00:00
int maskBackup = mPlayerAnimation - > getObjectRoot ( ) - > getNodeMask ( ) ;
2017-11-07 15:12:31 +00:00
if ( mCamera - > isFirstPerson ( ) )
2020-04-20 16:47:14 +00:00
mPlayerAnimation - > getObjectRoot ( ) - > setNodeMask ( 0 ) ;
2017-11-07 15:12:31 +00:00
2017-11-16 22:20:24 +00:00
for ( int i = 0 ; i < 6 ; + + i ) // for each cubemap side
2017-11-07 14:02:01 +00:00
{
2017-11-15 16:01:16 +00:00
osg : : Matrixd transform = osg : : Matrixd : : rotate ( osg : : Vec3 ( 0 , 0 , - 1 ) , directions [ i ] ) ;
if ( ! rawCubemap )
transform * = osg : : Matrixd : : rotate ( rotations [ i ] , osg : : Vec3 ( 0 , 0 , - 1 ) ) ;
osg : : Image * sideImage = images [ i ] . get ( ) ;
2017-11-15 15:07:01 +00:00
screenshot ( sideImage , cubeSize , cubeSize , transform ) ;
2017-11-07 14:02:01 +00:00
2017-11-15 16:01:16 +00:00
if ( ! rawCubemap )
sideImage - > flipHorizontal ( ) ;
}
2017-11-07 21:13:05 +00:00
2017-11-09 22:09:13 +00:00
mPlayerAnimation - > getObjectRoot ( ) - > setNodeMask ( maskBackup ) ;
2017-11-07 14:02:01 +00:00
mFieldOfView = fovBackup ;
2017-11-10 14:23:44 +00:00
2017-11-15 16:01:16 +00:00
if ( rawCubemap ) // for raw cubemap don't run on GPU, just merge the images
2018-04-07 13:11:23 +00:00
{
2017-11-15 16:01:16 +00:00
image - > allocateImage ( cubeSize * 6 , cubeSize , images [ 0 ] - > r ( ) , images [ 0 ] - > getPixelFormat ( ) , images [ 0 ] - > getDataType ( ) ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 16:01:16 +00:00
for ( int i = 0 ; i < 6 ; + + i )
osg : : copyImage ( images [ i ] . get ( ) , 0 , 0 , 0 , images [ i ] - > s ( ) , images [ i ] - > t ( ) , images [ i ] - > r ( ) , image , i * cubeSize , 0 , 0 ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 16:01:16 +00:00
return true ;
}
2018-04-07 13:11:23 +00:00
2017-11-15 16:01:16 +00:00
// run on GPU now:
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
osg : : ref_ptr < osg : : TextureCubeMap > cubeTexture ( new osg : : TextureCubeMap ) ;
2017-11-16 19:06:34 +00:00
cubeTexture - > setResizeNonPowerOfTwoHint ( false ) ;
2017-11-16 21:43:41 +00:00
2017-12-01 20:47:26 +00:00
cubeTexture - > setFilter ( osg : : Texture : : MIN_FILTER , osg : : Texture : : NEAREST ) ;
cubeTexture - > setFilter ( osg : : Texture : : MAG_FILTER , osg : : Texture : : NEAREST ) ;
2018-10-10 19:44:26 +00:00
2017-11-15 16:01:16 +00:00
cubeTexture - > setWrap ( osg : : Texture : : WRAP_S , osg : : Texture : : CLAMP_TO_EDGE ) ;
cubeTexture - > setWrap ( osg : : Texture : : WRAP_T , osg : : Texture : : CLAMP_TO_EDGE ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
for ( int i = 0 ; i < 6 ; + + i )
2017-11-15 16:01:16 +00:00
cubeTexture - > setImage ( i , images [ i ] . get ( ) ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
osg : : ref_ptr < osg : : Camera > screenshotCamera ( new osg : : Camera ) ;
osg : : ref_ptr < osg : : ShapeDrawable > quad ( new osg : : ShapeDrawable ( new osg : : Box ( osg : : Vec3 ( 0 , 0 , 0 ) , 2.0 ) ) ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
std : : map < std : : string , std : : string > defineMap ;
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
Shader : : ShaderManager & shaderMgr = mResourceSystem - > getSceneManager ( ) - > getShaderManager ( ) ;
osg : : ref_ptr < osg : : Shader > fragmentShader ( shaderMgr . getShader ( " s360_fragment.glsl " , defineMap , osg : : Shader : : FRAGMENT ) ) ;
osg : : ref_ptr < osg : : Shader > vertexShader ( shaderMgr . getShader ( " s360_vertex.glsl " , defineMap , osg : : Shader : : VERTEX ) ) ;
osg : : ref_ptr < osg : : StateSet > stateset = new osg : : StateSet ;
osg : : ref_ptr < osg : : Program > program ( new osg : : Program ) ;
program - > addShader ( fragmentShader ) ;
program - > addShader ( vertexShader ) ;
stateset - > setAttributeAndModes ( program , osg : : StateAttribute : : ON ) ;
stateset - > addUniform ( new osg : : Uniform ( " cubeMap " , 0 ) ) ;
2017-11-15 16:01:16 +00:00
stateset - > addUniform ( new osg : : Uniform ( " mapping " , screenshotMapping ) ) ;
2017-11-15 15:07:01 +00:00
stateset - > setTextureAttributeAndModes ( 0 , cubeTexture , osg : : StateAttribute : : ON ) ;
2018-10-10 19:44:26 +00:00
2017-11-15 15:07:01 +00:00
quad - > setStateSet ( stateset ) ;
2018-10-09 06:21:12 +00:00
quad - > setUpdateCallback ( nullptr ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 15:07:01 +00:00
screenshotCamera - > addChild ( quad ) ;
2017-11-15 14:20:59 +00:00
2017-11-15 16:01:16 +00:00
renderCameraToImage ( screenshotCamera , image , screenshotW , screenshotH ) ;
2017-11-15 14:20:59 +00:00
2017-11-10 14:23:44 +00:00
return true ;
2017-11-07 12:07:11 +00:00
}
2017-11-15 14:20:59 +00:00
void RenderingManager : : renderCameraToImage ( osg : : Camera * camera , osg : : Image * image , int w , int h )
{
2020-04-20 16:47:14 +00:00
camera - > setNodeMask ( Mask_RenderToTexture ) ;
2017-11-15 14:20:59 +00:00
camera - > attach ( osg : : Camera : : COLOR_BUFFER , image ) ;
camera - > setRenderOrder ( osg : : Camera : : PRE_RENDER ) ;
camera - > setReferenceFrame ( osg : : Camera : : ABSOLUTE_RF ) ;
camera - > setRenderTargetImplementation ( osg : : Camera : : FRAME_BUFFER_OBJECT , osg : : Camera : : PIXEL_BUFFER_RTT ) ;
camera - > setViewport ( 0 , 0 , w , h ) ;
osg : : ref_ptr < osg : : Texture2D > texture ( new osg : : Texture2D ) ;
texture - > setInternalFormat ( GL_RGB ) ;
texture - > setTextureSize ( w , h ) ;
texture - > setResizeNonPowerOfTwoHint ( false ) ;
texture - > setFilter ( osg : : Texture : : MIN_FILTER , osg : : Texture : : LINEAR ) ;
texture - > setFilter ( osg : : Texture : : MAG_FILTER , osg : : Texture : : LINEAR ) ;
camera - > attach ( osg : : Camera : : COLOR_BUFFER , texture ) ;
image - > setDataType ( GL_UNSIGNED_BYTE ) ;
image - > setPixelFormat ( texture - > getInternalFormat ( ) ) ;
2018-10-10 19:44:26 +00:00
mRootNode - > addChild ( camera ) ;
2017-11-15 14:20:59 +00:00
// The draw needs to complete before we can copy back our image.
2019-02-20 13:37:00 +00:00
osg : : ref_ptr < NotifyDrawCompletedCallback > callback ( new NotifyDrawCompletedCallback ( 0 ) ) ;
2017-11-15 14:20:59 +00:00
camera - > setFinalDrawCallback ( callback ) ;
2017-11-16 21:08:33 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) - > loadingOn ( false ) ;
2017-11-16 11:46:46 +00:00
2017-11-15 14:20:59 +00:00
mViewer - > eventTraversal ( ) ;
mViewer - > updateTraversal ( ) ;
mViewer - > renderingTraversals ( ) ;
callback - > waitTillDone ( ) ;
2017-11-16 21:08:33 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) - > loadingOff ( ) ;
2017-11-16 11:17:52 +00:00
2017-11-15 14:20:59 +00:00
// now that we've "used up" the current frame, get a fresh framenumber for the next frame() following after the screenshot is completed
mViewer - > advance ( mViewer - > getFrameStamp ( ) - > getSimulationTime ( ) ) ;
2018-10-10 19:44:26 +00:00
camera - > removeChildren ( 0 , camera - > getNumChildren ( ) ) ;
mRootNode - > removeChild ( camera ) ;
2017-11-15 14:20:59 +00:00
}
2019-02-20 13:37:00 +00:00
class ReadImageFromFramebufferCallback : public osg : : Drawable : : DrawCallback
{
public :
ReadImageFromFramebufferCallback ( osg : : Image * image , int width , int height )
: mWidth ( width ) , mHeight ( height ) , mImage ( image )
{
}
virtual void drawImplementation ( osg : : RenderInfo & renderInfo , const osg : : Drawable * /*drawable*/ ) const
{
int screenW = renderInfo . getCurrentCamera ( ) - > getViewport ( ) - > width ( ) ;
int screenH = renderInfo . getCurrentCamera ( ) - > getViewport ( ) - > height ( ) ;
double imageaspect = ( double ) mWidth / ( double ) mHeight ;
int leftPadding = std : : max ( 0 , static_cast < int > ( screenW - screenH * imageaspect ) / 2 ) ;
int topPadding = std : : max ( 0 , static_cast < int > ( screenH - screenW / imageaspect ) / 2 ) ;
int width = screenW - leftPadding * 2 ;
int height = screenH - topPadding * 2 ;
mImage - > readPixels ( leftPadding , topPadding , width , height , GL_RGB , GL_UNSIGNED_BYTE ) ;
mImage - > scaleImage ( mWidth , mHeight , 1 ) ;
}
private :
int mWidth ;
int mHeight ;
osg : : ref_ptr < osg : : Image > mImage ;
} ;
2020-04-22 18:29:50 +00:00
void RenderingManager : : screenshotFramebuffer ( osg : : Image * image , int w , int h )
2019-02-20 13:37:00 +00:00
{
osg : : Camera * camera = mViewer - > getCamera ( ) ;
osg : : ref_ptr < osg : : Drawable > tempDrw = new osg : : Drawable ;
tempDrw - > setDrawCallback ( new ReadImageFromFramebufferCallback ( image , w , h ) ) ;
tempDrw - > setCullingActive ( false ) ;
tempDrw - > getOrCreateStateSet ( ) - > setRenderBinDetails ( 100 , " RenderBin " , osg : : StateSet : : USE_RENDERBIN_DETAILS ) ; // so its after all scene bins but before POST_RENDER gui camera
camera - > addChild ( tempDrw ) ;
osg : : ref_ptr < NotifyDrawCompletedCallback > callback ( new NotifyDrawCompletedCallback ( mViewer - > getFrameStamp ( ) - > getFrameNumber ( ) ) ) ;
camera - > setFinalDrawCallback ( callback ) ;
mViewer - > eventTraversal ( ) ;
mViewer - > updateTraversal ( ) ;
mViewer - > renderingTraversals ( ) ;
callback - > waitTillDone ( ) ;
2020-04-22 18:29:50 +00:00
// now that we've "used up" the current frame, get a fresh frame number for the next frame() following after the screenshot is completed
2019-02-20 13:37:00 +00:00
mViewer - > advance ( mViewer - > getFrameStamp ( ) - > getSimulationTime ( ) ) ;
camera - > removeChild ( tempDrw ) ;
camera - > setFinalDrawCallback ( nullptr ) ;
}
2017-11-15 15:07:01 +00:00
void RenderingManager : : screenshot ( osg : : Image * image , int w , int h , osg : : Matrixd cameraTransform )
2015-06-03 14:40:16 +00:00
{
osg : : ref_ptr < osg : : Camera > rttCamera ( new osg : : Camera ) ;
rttCamera - > setProjectionMatrixAsPerspective ( mFieldOfView , w / float ( h ) , mNearClip , mViewDistance ) ;
2017-11-15 15:07:01 +00:00
rttCamera - > setViewMatrix ( mViewer - > getCamera ( ) - > getViewMatrix ( ) * cameraTransform ) ;
2017-11-07 14:02:01 +00:00
2015-11-06 22:13:57 +00:00
rttCamera - > setUpdateCallback ( new NoTraverseCallback ) ;
2016-02-08 15:45:56 +00:00
rttCamera - > addChild ( mSceneRoot ) ;
2015-06-03 14:40:16 +00:00
2017-11-10 18:18:16 +00:00
rttCamera - > addChild ( mWater - > getReflectionCamera ( ) ) ;
rttCamera - > addChild ( mWater - > getRefractionCamera ( ) ) ;
2015-06-03 14:40:16 +00:00
2020-04-20 16:47:14 +00:00
rttCamera - > setCullMask ( mViewer - > getCamera ( ) - > getCullMask ( ) & ( ~ Mask_GUI ) ) ;
2015-08-02 15:57:50 +00:00
2017-11-14 17:23:12 +00:00
rttCamera - > setClearMask ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2015-06-03 14:40:16 +00:00
2017-11-15 14:20:59 +00:00
renderCameraToImage ( rttCamera . get ( ) , image , w , h ) ;
2015-06-03 14:40:16 +00:00
}
2020-05-11 13:37:00 +00:00
osg : : Vec4f RenderingManager : : getScreenBounds ( const osg : : BoundingBox & worldbb )
2015-05-24 01:36:34 +00:00
{
2020-05-11 13:37:00 +00:00
if ( ! worldbb . valid ( ) ) return osg : : Vec4f ( ) ;
2015-05-24 01:36:34 +00: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 01:36:34 +00: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 00:26:16 +00:00
RenderingManager : : RayResult getIntersectionResult ( osgUtil : : LineSegmentIntersector * intersector )
{
RenderingManager : : RayResult result ;
result . mHit = false ;
2020-05-11 13:37:00 +00:00
result . mHitRefnum . mContentFile = - 1 ;
2016-07-06 13:03:37 +00:00
result . mRatio = 0 ;
2015-06-05 00:26:16 +00:00
if ( intersector - > containsIntersections ( ) )
{
result . mHit = true ;
osgUtil : : LineSegmentIntersector : : Intersection intersection = intersector - > getFirstIntersection ( ) ;
result . mHitPointWorld = intersection . getWorldIntersectPoint ( ) ;
result . mHitNormalWorld = intersection . getWorldIntersectNormal ( ) ;
2016-07-06 13:03:37 +00:00
result . mRatio = intersection . ratio ;
2015-06-05 00:26:16 +00:00
2018-10-09 06:21:12 +00:00
PtrHolder * ptrHolder = nullptr ;
2020-05-11 13:37:00 +00:00
std : : vector < RefnumMarker * > refnumMarkers ;
2015-06-05 00:26:16 +00: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 00:26:16 +00: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 00:26:16 +00:00
}
return result ;
}
2017-03-12 18:48:41 +00:00
osg : : ref_ptr < osgUtil : : IntersectionVisitor > RenderingManager : : getIntersectionVisitor ( osgUtil : : Intersector * intersector , bool ignorePlayer , bool ignoreActors )
2015-06-05 00:26:16 +00:00
{
2017-03-12 18:48:41 +00: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 18:48:41 +00:00
mIntersectionVisitor - > setIntersector ( intersector ) ;
2020-04-20 16:47:14 +00:00
int mask = ~ 0 ;
mask & = ~ ( Mask_RenderToTexture | Mask_Sky | Mask_Debug | Mask_Effect | Mask_Water | Mask_SimpleWater ) ;
2015-06-05 00:26:16 +00:00
if ( ignorePlayer )
2020-04-20 16:47:14 +00:00
mask & = ~ ( Mask_Player ) ;
2015-06-05 00:26:16 +00:00
if ( ignoreActors )
2020-04-20 16:47:14 +00:00
mask & = ~ ( Mask_Actor | Mask_Player ) ;
2015-06-05 00:26:16 +00:00
2017-03-12 18:48:41 +00:00
mIntersectionVisitor - > setTraversalMask ( mask ) ;
return mIntersectionVisitor ;
2015-10-31 00:30:02 +00: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 00:26:16 +00:00
2017-03-12 18:48:41 +00:00
mRootNode - > accept ( * getIntersectionVisitor ( intersector , ignorePlayer , ignoreActors ) ) ;
2015-06-05 00:26:16 +00:00
return getIntersectionResult ( intersector ) ;
}
RenderingManager : : RayResult RenderingManager : : castCameraToViewportRay ( const float nX , const float nY , float maxDistance , bool ignorePlayer , bool ignoreActors )
2015-05-24 01:36:34 +00: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 18:48:41 +00:00
mViewer - > getCamera ( ) - > accept ( * getIntersectionVisitor ( intersector , ignorePlayer , ignoreActors ) ) ;
2015-05-24 01:36:34 +00:00
2015-06-05 00:26:16 +00:00
return getIntersectionResult ( intersector ) ;
2015-05-24 01:36:34 +00:00
}
2015-05-14 15:34:55 +00:00
void RenderingManager : : updatePtr ( const MWWorld : : Ptr & old , const MWWorld : : Ptr & updated )
{
mObjects - > updatePtr ( old , updated ) ;
2018-07-21 10:37:02 +00:00
mActorsPaths - > updatePtr ( old , updated ) ;
2015-05-14 15:34:55 +00:00
}
2016-09-14 14:18:29 +00:00
void RenderingManager : : spawnEffect ( const std : : string & model , const std : : string & texture , const osg : : Vec3f & worldPosition , float scale , bool isMagicVFX )
2015-04-19 15:55:56 +00:00
{
2016-09-14 14:18:29 +00:00
mEffectManager - > addEffect ( model , texture , worldPosition , scale , isMagicVFX ) ;
2015-04-19 15:55:56 +00:00
}
void RenderingManager : : notifyWorldSpaceChanged ( )
{
mEffectManager - > clear ( ) ;
2020-02-19 20:26:42 +00:00
mWater - > clearRipples ( ) ;
2015-04-19 15:55:56 +00:00
}
void RenderingManager : : clear ( )
{
2015-06-16 18:56:48 +00:00
mSky - > setMoonColour ( false ) ;
2015-04-19 15:55:56 +00:00
notifyWorldSpaceChanged ( ) ;
2019-08-03 13:37:00 +00:00
if ( mObjectPaging )
mObjectPaging - > clear ( ) ;
2015-04-18 23:57:52 +00:00
}
2015-04-25 13:19:17 +00:00
MWRender : : Animation * RenderingManager : : getAnimation ( const MWWorld : : Ptr & ptr )
{
2015-05-22 02:36:17 +00:00
if ( mPlayerAnimation . get ( ) & & ptr = = mPlayerAnimation - > getPtr ( ) )
return mPlayerAnimation . get ( ) ;
2015-04-25 13:19:17 +00:00
return mObjects - > getAnimation ( ptr ) ;
}
2015-12-18 16:21:51 +00:00
const MWRender : : Animation * RenderingManager : : getAnimation ( const MWWorld : : ConstPtr & ptr ) const
{
if ( mPlayerAnimation . get ( ) & & ptr = = mPlayerAnimation - > getPtr ( ) )
return mPlayerAnimation . get ( ) ;
return mObjects - > getAnimation ( ptr ) ;
}
2015-05-01 16:21:50 +00:00
void RenderingManager : : setupPlayer ( const MWWorld : : Ptr & player )
{
if ( ! mPlayerNode )
{
2015-11-20 20:57:04 +00:00
mPlayerNode = new SceneUtil : : PositionAttitudeTransform ;
2020-04-20 16:47:14 +00:00
mPlayerNode - > setNodeMask ( Mask_Player ) ;
2017-02-02 20:46:25 +00:00
mPlayerNode - > setName ( " Player Root " ) ;
2016-02-08 15:45:56 +00:00
mSceneRoot - > addChild ( mPlayerNode ) ;
2015-05-01 16:21:50 +00:00
}
2015-05-24 02:00:35 +00:00
mPlayerNode - > setUserDataContainer ( new osg : : DefaultUserDataContainer ) ;
mPlayerNode - > getUserDataContainer ( ) - > addUserObject ( new PtrHolder ( player ) ) ;
2015-05-01 16:21:50 +00:00
2015-05-24 02:00:35 +00:00
player . getRefData ( ) . setBaseNode ( mPlayerNode ) ;
2015-06-16 18:36:48 +00:00
2017-09-17 23:07:17 +00:00
mWater - > removeEmitter ( player ) ;
2015-06-16 18:36:48 +00:00
mWater - > addEmitter ( player ) ;
2015-05-01 16:21:50 +00:00
}
void RenderingManager : : renderPlayer ( const MWWorld : : Ptr & player )
{
2017-02-22 14:22:40 +00:00
mPlayerAnimation = new NpcAnimation ( player , player . getRefData ( ) . getBaseNode ( ) , mResourceSystem , 0 , NpcAnimation : : VM_Normal ,
mFirstPersonFieldOfView ) ;
2015-05-01 16:21:50 +00:00
2015-05-21 21:54:39 +00:00
mCamera - > setAnimation ( mPlayerAnimation . get ( ) ) ;
mCamera - > attachTo ( player ) ;
2015-05-01 16:21:50 +00:00
}
2015-05-21 21:54:39 +00:00
void RenderingManager : : rebuildPtr ( const MWWorld : : Ptr & ptr )
{
2018-10-09 06:21:12 +00:00
NpcAnimation * anim = nullptr ;
2015-05-21 21:54:39 +00: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 18:36:48 +00:00
void RenderingManager : : addWaterRippleEmitter ( const MWWorld : : Ptr & ptr )
{
mWater - > addEmitter ( ptr ) ;
}
void RenderingManager : : removeWaterRippleEmitter ( const MWWorld : : Ptr & ptr )
{
mWater - > removeEmitter ( ptr ) ;
}
2015-12-04 22:28:11 +00:00
void RenderingManager : : emitWaterRipple ( const osg : : Vec3f & pos )
{
mWater - > emitRipple ( pos ) ;
}
2015-05-14 16:46:04 +00:00
void RenderingManager : : updateProjectionMatrix ( )
{
2015-05-26 14:40:44 +00:00
double aspect = mViewer - > getCamera ( ) - > getViewport ( ) - > aspectRatio ( ) ;
2015-12-07 15:11:47 +00:00
float fov = mFieldOfView ;
if ( mFieldOfViewOverridden )
fov = mFieldOfViewOverride ;
mViewer - > getCamera ( ) - > setProjectionMatrixAsPerspective ( fov , aspect , mNearClip , mViewDistance ) ;
2017-09-26 12:14:28 +00:00
mUniformNear - > set ( mNearClip ) ;
mUniformFar - > set ( mViewDistance ) ;
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 disappear.
2019-03-03 17:29:51 +00:00
// Limit FOV here just for sure, otherwise viewing distance can be too high.
fov = std : : min ( mFieldOfView , 140.f ) ;
float distanceMult = std : : cos ( osg : : DegreesToRadians ( fov ) / 2.f ) ;
2019-02-20 13:37:00 +00:00
mTerrain - > setViewDistance ( mViewDistance * ( distanceMult ? 1.f / distanceMult : 1.f ) ) ;
2015-05-14 19:42:04 +00:00
}
void RenderingManager : : updateTextureFiltering ( )
{
2016-02-14 22:14:52 +00:00
mViewer - > stopThreading ( ) ;
2016-02-05 22:20:13 +00:00
2016-02-05 17:51:51 +00:00
mResourceSystem - > getSceneManager ( ) - > setFilterSettings (
2015-12-14 01:05:19 +00:00
Settings : : Manager : : getString ( " texture mag filter " , " General " ) ,
Settings : : Manager : : getString ( " texture min filter " , " General " ) ,
2015-12-14 00:51:27 +00:00
Settings : : Manager : : getString ( " texture mipmap " , " General " ) ,
2016-02-14 22:14:52 +00:00
Settings : : Manager : : getInt ( " anisotropy " , " General " )
2015-12-14 00:51:27 +00:00
) ;
2016-02-14 22:14:52 +00:00
mTerrain - > updateTextureFiltering ( ) ;
mViewer - > startThreading ( ) ;
2015-05-14 16:46:04 +00:00
}
2015-06-11 21:16:05 +00:00
void RenderingManager : : updateAmbient ( )
{
osg : : Vec4f color = mAmbientColor ;
if ( mNightEyeFactor > 0.f )
color + = osg : : Vec4f ( 0.7 , 0.7 , 0.7 , 0.0 ) * mNightEyeFactor ;
mStateUpdater - > setAmbientColor ( color ) ;
}
2015-06-02 14:35:35 +00:00
void RenderingManager : : setFogColor ( const osg : : Vec4f & color )
{
mViewer - > getCamera ( ) - > setClearColor ( color ) ;
mStateUpdater - > setFogColor ( color ) ;
}
2017-03-07 03:02:06 +00:00
void RenderingManager : : reportStats ( ) const
2017-02-22 01:18:18 +00:00
{
osg : : Stats * stats = mViewer - > getViewerStats ( ) ;
unsigned int frameNumber = mViewer - > getFrameStamp ( ) - > getFrameNumber ( ) ;
if ( stats - > collectStats ( " resource " ) )
{
stats - > setAttribute ( frameNumber , " UnrefQueue " , mUnrefQueue - > getNumItems ( ) ) ;
2017-03-09 18:52:30 +00:00
mTerrain - > reportStats ( frameNumber , stats ) ;
2017-02-22 01:18:18 +00:00
}
}
2015-05-14 16:46:04 +00:00
void RenderingManager : : processChangedSettings ( const Settings : : CategorySettingVector & changed )
{
for ( Settings : : CategorySettingVector : : const_iterator it = changed . begin ( ) ; it ! = changed . end ( ) ; + + it )
{
2015-12-07 15:23:06 +00:00
if ( it - > first = = " Camera " & & it - > second = = " field of view " )
2015-05-14 16:46:04 +00:00
{
2015-12-07 15:23:06 +00:00
mFieldOfView = Settings : : Manager : : getFloat ( " field of view " , " Camera " ) ;
2015-05-14 16:46:04 +00:00
updateProjectionMatrix ( ) ;
}
2015-05-24 00:34:20 +00:00
else if ( it - > first = = " Camera " & & it - > second = = " viewing distance " )
2015-05-14 16:46:04 +00:00
{
2015-05-24 00:34:20 +00:00
mViewDistance = Settings : : Manager : : getFloat ( " viewing distance " , " Camera " ) ;
2020-06-07 06:35:33 +00:00
if ( ! Settings : : Manager : : getBool ( " use distant fog " , " Fog " ) )
2017-09-21 10:08:45 +00:00
mStateUpdater - > setFogEnd ( mViewDistance ) ;
2015-05-14 16:46:04 +00:00
updateProjectionMatrix ( ) ;
}
2015-12-14 00:02:09 +00:00
else if ( it - > first = = " General " & & ( it - > second = = " texture filter " | |
it - > second = = " texture mipmap " | |
2015-12-13 19:24:23 +00:00
it - > second = = " anisotropy " ) )
2015-05-14 19:42:04 +00:00
updateTextureFiltering ( ) ;
2015-10-28 20:22:14 +00:00
else if ( it - > first = = " Water " )
mWater - > processChangedSettings ( changed ) ;
2015-05-14 16:46:04 +00:00
}
}
2015-06-01 13:34:46 +00:00
float RenderingManager : : getNearClipDistance ( ) const
{
return mNearClip ;
}
2015-06-02 23:18:36 +00:00
float RenderingManager : : getTerrainHeightAt ( const osg : : Vec3f & pos )
{
return mTerrain - > getHeightAt ( pos ) ;
}
2015-05-21 21:54:39 +00:00
bool RenderingManager : : vanityRotateCamera ( const float * rot )
{
if ( ! mCamera - > isVanityOrPreviewModeEnabled ( ) )
return false ;
mCamera - > rotateCamera ( rot [ 0 ] , rot [ 2 ] , true ) ;
return true ;
}
void RenderingManager : : setCameraDistance ( float dist , bool adjust , bool override )
{
if ( ! mCamera - > isVanityOrPreviewModeEnabled ( ) & & ! mCamera - > isFirstPerson ( ) )
{
if ( mCamera - > isNearest ( ) & & dist > 0.f )
mCamera - > toggleViewMode ( ) ;
2020-06-21 23:54:08 +00:00
else if ( override )
2020-06-23 18:05:22 +00:00
mCamera - > updateBaseCameraDistance ( - dist / 120.f * 10 , adjust ) ;
2015-05-21 21:54:39 +00:00
else
2020-06-21 23:54:08 +00:00
mCamera - > setCameraDistance ( - dist / 120.f * 10 , adjust ) ;
2015-05-21 21:54:39 +00:00
}
else if ( mCamera - > isFirstPerson ( ) & & dist < 0.f )
{
mCamera - > toggleViewMode ( ) ;
2020-06-21 23:54:08 +00:00
if ( override )
2020-06-23 18:05:22 +00:00
mCamera - > updateBaseCameraDistance ( 0.f , false ) ;
2020-06-21 23:54:08 +00:00
else
mCamera - > setCameraDistance ( 0.f , false ) ;
2015-05-21 21:54:39 +00:00
}
}
void RenderingManager : : resetCamera ( )
{
mCamera - > reset ( ) ;
}
float RenderingManager : : getCameraDistance ( ) const
{
return mCamera - > getCameraDistance ( ) ;
}
Camera * RenderingManager : : getCamera ( )
{
return mCamera . get ( ) ;
}
2015-12-03 14:16:20 +00:00
const osg : : Vec3f & RenderingManager : : getCameraPosition ( ) const
{
return mCurrentCameraPos ;
}
2019-09-19 17:48:43 +00:00
void RenderingManager : : togglePOV ( bool force )
2015-05-21 21:54:39 +00:00
{
2019-09-19 17:48:43 +00:00
mCamera - > toggleViewMode ( force ) ;
2015-05-21 21:54:39 +00:00
}
void RenderingManager : : togglePreviewMode ( bool enable )
{
mCamera - > togglePreviewMode ( enable ) ;
}
bool RenderingManager : : toggleVanityMode ( bool enable )
{
2020-07-18 09:48:46 +00:00
return mCamera - > toggleVanityMode ( enable ) ;
2015-05-21 21:54:39 +00:00
}
void RenderingManager : : allowVanityMode ( bool allow )
{
mCamera - > allowVanityMode ( allow ) ;
}
void RenderingManager : : changeVanityModeScale ( float factor )
{
if ( mCamera - > isVanityOrPreviewModeEnabled ( ) )
2020-06-23 18:05:22 +00:00
mCamera - > updateBaseCameraDistance ( - factor / 120.f * 10 , true ) ;
2015-05-21 21:54:39 +00:00
}
2015-12-07 15:11:47 +00:00
void RenderingManager : : overrideFieldOfView ( float val )
{
if ( mFieldOfViewOverridden ! = true | | mFieldOfViewOverride ! = val )
{
mFieldOfViewOverridden = true ;
mFieldOfViewOverride = val ;
updateProjectionMatrix ( ) ;
}
}
2018-06-16 06:18:04 +00: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 16:47:14 +00:00
computeBoundsVisitor . setTraversalMask ( ~ ( MWRender : : Mask_ParticleSystem | MWRender : : Mask_Effect ) ) ;
2018-06-16 06:18:04 +00: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 ;
}
2015-12-07 15:11:47 +00:00
void RenderingManager : : resetFieldOfView ( )
{
if ( mFieldOfViewOverridden = = true )
{
mFieldOfViewOverridden = false ;
2017-02-01 02:00:33 +00:00
2015-12-07 15:11:47 +00:00
updateProjectionMatrix ( ) ;
}
}
2017-02-01 02:00:33 +00:00
void RenderingManager : : exportSceneGraph ( const MWWorld : : Ptr & ptr , const std : : string & filename , const std : : string & format )
{
osg : : Node * node = mViewer - > getSceneData ( ) ;
if ( ! ptr . isEmpty ( ) )
node = ptr . getRefData ( ) . getBaseNode ( ) ;
SceneUtil : : writeScene ( node , filename , format ) ;
}
2015-12-07 15:11:47 +00:00
2017-03-06 18:04:17 +00:00
LandManager * RenderingManager : : getLandManager ( ) const
{
return mTerrainStorage - > getLandManager ( ) ;
}
2018-07-21 10:37:02 +00:00
void RenderingManager : : updateActorPath ( const MWWorld : : ConstPtr & actor , const std : : deque < osg : : Vec3f > & path ,
const osg : : Vec3f & halfExtents , const osg : : Vec3f & start , const osg : : Vec3f & end ) const
{
mActorsPaths - > update ( actor , path , halfExtents , start , end , mNavigator . getSettings ( ) ) ;
}
2017-03-06 18:04:17 +00:00
2018-07-21 10:37:02 +00:00
void RenderingManager : : removeActorPath ( const MWWorld : : ConstPtr & actor ) const
{
mActorsPaths - > remove ( actor ) ;
}
2017-03-06 18:04:17 +00:00
2018-08-30 22:39:44 +00:00
void RenderingManager : : setNavMeshNumber ( const std : : size_t value )
{
mNavMeshNumber = value ;
}
2019-01-20 16:27:52 +00:00
void RenderingManager : : updateNavMesh ( )
{
2019-01-20 16:30:26 +00:00
if ( ! mNavMesh - > isEnabled ( ) )
return ;
2019-01-20 16:27:52 +00: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
{
2019-03-10 13:49:56 +00:00
const auto locked = it - > second - > lockConst ( ) ;
2019-03-10 12:48:12 +00:00
mNavMesh - > update ( locked - > getImpl ( ) , mNavMeshNumber , locked - > getGeneration ( ) ,
2019-01-20 16:27:52 +00:00
locked - > getNavMeshRevision ( ) , mNavigator . getSettings ( ) ) ;
}
catch ( const std : : exception & e )
{
Log ( Debug : : Error ) < < " NavMesh render update exception: " < < e . what ( ) ;
}
}
}
2019-11-27 22:45:01 +00: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-09 22:44:54 +00: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 21:17:01 +00: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 ;
}
2020-05-10 13:37:00 +00:00
void RenderingManager : : getPagedRefnums ( const osg : : Vec4i & activeGrid , std : : set < ESM : : RefNum > & out )
{
if ( mObjectPaging )
mObjectPaging - > getPagedRefnums ( activeGrid , out ) ;
}
2012-05-27 19:39:18 +00:00
}