2011-07-31 15:07:11 +00:00
# include "scene.hpp"
2015-06-03 21:04:35 +00:00
# include <limits>
2020-06-25 19:46:07 +00:00
# include <chrono>
# include <thread>
2013-08-19 18:30:22 +00:00
2018-03-13 22:49:08 +00:00
# include <BulletCollision/CollisionDispatch/btCollisionObject.h>
2018-07-12 08:44:11 +00:00
# include <BulletCollision/CollisionShapes/btCompoundShape.h>
2018-03-13 22:49:08 +00:00
2018-08-14 19:05:43 +00:00
# include <components/debug/debuglog.hpp>
2015-07-09 17:22:04 +00:00
# include <components/loadinglistener/loadinglistener.hpp>
2015-01-12 10:29:56 +00:00
# include <components/misc/resourcehelpers.hpp>
2015-04-01 15:02:15 +00:00
# include <components/settings/settings.hpp>
2015-04-22 17:08:56 +00:00
# include <components/resource/resourcesystem.hpp>
2017-02-14 23:55:35 +00:00
# include <components/resource/scenemanager.hpp>
2018-03-13 22:49:08 +00:00
# include <components/resource/bulletshape.hpp>
2019-11-24 13:40:19 +00:00
# include <components/sceneutil/unrefqueue.hpp>
2020-05-10 13:37:00 +00:00
# include <components/sceneutil/positionattitudetransform.hpp>
2018-03-13 22:49:08 +00:00
# include <components/detournavigator/navigator.hpp>
2018-04-21 11:56:04 +00:00
# include <components/detournavigator/debug.hpp>
2019-02-28 20:03:42 +00:00
# include <components/misc/convert.hpp>
2015-04-12 13:34:50 +00:00
2012-04-23 13:27:03 +00:00
# include "../mwbase/environment.hpp"
2014-10-02 14:30:23 +00:00
# include "../mwbase/world.hpp"
2012-08-09 12:33:21 +00:00
# include "../mwbase/soundmanager.hpp"
2012-08-11 15:30:55 +00:00
# include "../mwbase/mechanicsmanager.hpp"
2012-08-12 16:11:09 +00:00
# include "../mwbase/windowmanager.hpp"
2012-03-10 15:05:12 +00:00
2019-11-24 13:40:19 +00:00
# include "../mwmechanics/actorutil.hpp"
2015-04-12 13:34:50 +00:00
# include "../mwrender/renderingmanager.hpp"
2017-03-06 18:04:17 +00:00
# include "../mwrender/landmanager.hpp"
2015-04-12 13:34:50 +00:00
2015-05-09 23:09:00 +00:00
# include "../mwphysics/physicssystem.hpp"
2018-03-13 22:49:08 +00:00
# include "../mwphysics/actor.hpp"
# include "../mwphysics/object.hpp"
# include "../mwphysics/heightfield.hpp"
2015-05-09 23:09:00 +00:00
2011-07-31 15:07:11 +00:00
# include "player.hpp"
2012-07-03 10:30:50 +00:00
# include "localscripts.hpp"
2012-10-01 15:17:04 +00:00
# include "esmstore.hpp"
2013-01-06 05:12:08 +00:00
# include "class.hpp"
2015-12-06 17:13:04 +00:00
# include "cellvisitors.hpp"
2014-02-23 19:11:05 +00:00
# include "cellstore.hpp"
2016-02-06 23:36:31 +00:00
# include "cellpreloader.hpp"
2011-07-31 15:07:11 +00:00
2012-05-14 15:41:17 +00:00
namespace
2011-08-08 22:05:16 +00:00
{
2019-11-30 11:29:31 +00:00
using MWWorld : : RotationOrder ;
2018-08-26 20:27:38 +00:00
osg : : Quat makeActorOsgQuat ( const ESM : : Position & position )
{
return osg : : Quat ( position . rot [ 2 ] , osg : : Vec3 ( 0 , 0 , - 1 ) ) ;
}
osg : : Quat makeInversedOrderObjectOsgQuat ( const ESM : : Position & position )
{
const float xr = position . rot [ 0 ] ;
const float yr = position . rot [ 1 ] ;
const float zr = position . rot [ 2 ] ;
return osg : : Quat ( xr , osg : : Vec3 ( - 1 , 0 , 0 ) )
* osg : : Quat ( yr , osg : : Vec3 ( 0 , - 1 , 0 ) )
* osg : : Quat ( zr , osg : : Vec3 ( 0 , 0 , - 1 ) ) ;
}
2015-01-13 16:14:54 +00:00
2018-08-26 20:27:38 +00:00
osg : : Quat makeObjectOsgQuat ( const ESM : : Position & position )
{
const float xr = position . rot [ 0 ] ;
const float yr = position . rot [ 1 ] ;
const float zr = position . rot [ 2 ] ;
return osg : : Quat ( zr , osg : : Vec3 ( 0 , 0 , - 1 ) )
* osg : : Quat ( yr , osg : : Vec3 ( 0 , - 1 , 0 ) )
* osg : : Quat ( xr , osg : : Vec3 ( - 1 , 0 , 0 ) ) ;
}
2021-01-29 12:51:13 +00:00
void setNodeRotation ( const MWWorld : : Ptr & ptr , MWRender : : RenderingManager & rendering , RotationOrder order )
2017-02-04 14:12:01 +00:00
{
2021-01-29 12:51:13 +00:00
if ( ! ptr . getRefData ( ) . getBaseNode ( ) )
return ;
2021-01-23 09:43:32 +00:00
2021-01-29 12:51:13 +00:00
rendering . rotateObject ( ptr ,
ptr . getClass ( ) . isActor ( )
? makeActorOsgQuat ( ptr . getRefData ( ) . getPosition ( ) )
: ( order = = RotationOrder : : inverse
? makeInversedOrderObjectOsgQuat ( ptr . getRefData ( ) . getPosition ( ) )
: makeObjectOsgQuat ( ptr . getRefData ( ) . getPosition ( ) ) )
) ;
2017-02-04 14:12:01 +00:00
}
2020-05-11 13:37:00 +00:00
std : : string getModel ( const MWWorld : : Ptr & ptr , const VFS : : Manager * vfs )
{
bool useAnim = ptr . getClass ( ) . useAnim ( ) ;
std : : string model = ptr . getClass ( ) . getModel ( ptr ) ;
if ( useAnim )
model = Misc : : ResourceHelpers : : correctActorModelPath ( model , vfs ) ;
const std : : string & id = ptr . getCellRef ( ) . getRefId ( ) ;
if ( id = = " prisonmarker " | | id = = " divinemarker " | | id = = " templemarker " | | id = = " northmarker " )
model = " " ; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
return model ;
}
2015-05-09 23:09:00 +00:00
void addObject ( const MWWorld : : Ptr & ptr , MWPhysics : : PhysicsSystem & physics ,
2021-01-29 12:51:05 +00:00
MWRender : : RenderingManager & rendering , std : : set < ESM : : RefNum > & pagedRefs )
2015-01-13 16:14:54 +00:00
{
2017-06-28 20:40:13 +00:00
if ( ptr . getRefData ( ) . getBaseNode ( ) | | physics . getActor ( ptr ) )
{
2018-08-14 19:05:43 +00:00
Log ( Debug : : Warning ) < < " Warning: Tried to add " < < ptr . getCellRef ( ) . getRefId ( ) < < " to the scene twice " ;
2017-06-28 20:40:13 +00:00
return ;
}
2021-01-29 12:51:05 +00:00
bool useAnim = ptr . getClass ( ) . useAnim ( ) ;
2020-05-11 13:37:00 +00:00
std : : string model = getModel ( ptr , rendering . getResourceSystem ( ) - > getVFS ( ) ) ;
2017-02-20 18:04:02 +00:00
2021-01-29 12:51:05 +00:00
const ESM : : RefNum & refnum = ptr . getCellRef ( ) . getRefNum ( ) ;
if ( ! refnum . hasContentFile ( ) | | pagedRefs . find ( refnum ) = = pagedRefs . end ( ) )
ptr . getClass ( ) . insertObjectRendering ( ptr , model , rendering ) ;
2021-01-29 12:51:13 +00:00
else
ptr . getRefData ( ) . setBaseNode ( new SceneUtil : : PositionAttitudeTransform ) ; // FIXME remove this when physics code is fixed not to depend on basenode
setNodeRotation ( ptr , rendering , RotationOrder : : direct ) ;
2017-02-04 14:12:01 +00:00
2021-01-29 12:51:13 +00:00
ptr . getClass ( ) . insertObject ( ptr , model , physics ) ;
2015-06-16 18:36:48 +00:00
2021-01-29 12:51:05 +00:00
if ( useAnim )
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > add ( ptr ) ;
2017-02-20 18:04:02 +00:00
2021-01-29 12:51:05 +00:00
if ( ptr . getClass ( ) . isActor ( ) )
rendering . addWaterRippleEmitter ( ptr ) ;
2018-03-17 09:41:13 +00:00
2021-01-29 12:51:05 +00:00
// Restore effect particles
MWBase : : Environment : : get ( ) . getWorld ( ) - > applyLoopingParticles ( ptr ) ;
2015-01-13 16:14:54 +00:00
}
2018-08-26 20:27:38 +00:00
void addObject ( const MWWorld : : Ptr & ptr , const MWPhysics : : PhysicsSystem & physics , DetourNavigator : : Navigator & navigator )
{
if ( const auto object = physics . getObject ( ptr ) )
{
if ( ptr . getClass ( ) . isDoor ( ) & & ! ptr . getCellRef ( ) . getTeleport ( ) )
{
const auto shape = object - > getShapeInstance ( ) - > getCollisionShape ( ) ;
btVector3 aabbMin ;
btVector3 aabbMax ;
shape - > getAabb ( btTransform : : getIdentity ( ) , aabbMin , aabbMax ) ;
const auto center = ( aabbMax + aabbMin ) * 0.5f ;
const auto distanceFromDoor = MWBase : : Environment : : get ( ) . getWorld ( ) - > getMaxActivationDistance ( ) * 0.5f ;
const auto toPoint = aabbMax . x ( ) - aabbMin . x ( ) < aabbMax . y ( ) - aabbMin . y ( )
? btVector3 ( distanceFromDoor , 0 , 0 )
: btVector3 ( 0 , distanceFromDoor , 0 ) ;
2020-10-14 13:55:15 +00:00
const auto transform = object - > getTransform ( ) ;
2018-08-26 20:27:38 +00:00
const btTransform closedDoorTransform (
2019-02-28 20:03:42 +00:00
Misc : : Convert : : toBullet ( makeObjectOsgQuat ( ptr . getCellRef ( ) . getPosition ( ) ) ) ,
2018-08-26 20:27:38 +00:00
transform . getOrigin ( )
) ;
2019-02-28 20:03:42 +00:00
const auto start = Misc : : Convert : : makeOsgVec3f ( closedDoorTransform ( center + toPoint ) ) ;
2018-08-26 20:27:38 +00:00
const auto startPoint = physics . castRay ( start , start - osg : : Vec3f ( 0 , 0 , 1000 ) , ptr , { } ,
MWPhysics : : CollisionType_World | MWPhysics : : CollisionType_HeightMap | MWPhysics : : CollisionType_Water ) ;
const auto connectionStart = startPoint . mHit ? startPoint . mHitPos : start ;
2019-02-28 20:03:42 +00:00
const auto end = Misc : : Convert : : makeOsgVec3f ( closedDoorTransform ( center - toPoint ) ) ;
2018-08-26 20:27:38 +00:00
const auto endPoint = physics . castRay ( end , end - osg : : Vec3f ( 0 , 0 , 1000 ) , ptr , { } ,
MWPhysics : : CollisionType_World | MWPhysics : : CollisionType_HeightMap | MWPhysics : : CollisionType_Water ) ;
const auto connectionEnd = endPoint . mHit ? endPoint . mHitPos : end ;
navigator . addObject (
2018-09-22 15:36:57 +00:00
DetourNavigator : : ObjectId ( object ) ,
2018-08-26 20:27:38 +00:00
DetourNavigator : : DoorShapes (
* shape ,
object - > getShapeInstance ( ) - > getAvoidCollisionShape ( ) ,
connectionStart ,
connectionEnd
) ,
transform
) ;
}
else
{
navigator . addObject (
2018-09-22 15:36:57 +00:00
DetourNavigator : : ObjectId ( object ) ,
2018-08-26 20:27:38 +00:00
DetourNavigator : : ObjectShapes {
* object - > getShapeInstance ( ) - > getCollisionShape ( ) ,
object - > getShapeInstance ( ) - > getAvoidCollisionShape ( )
} ,
2020-10-14 13:55:15 +00:00
object - > getTransform ( )
2018-08-26 20:27:38 +00:00
) ;
}
}
2019-03-03 11:58:03 +00:00
else if ( physics . getActor ( ptr ) )
2018-08-26 20:27:38 +00:00
{
2019-03-03 11:58:03 +00:00
navigator . addAgent ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getPathfindingHalfExtents ( ptr ) ) ;
2018-08-26 20:27:38 +00:00
}
}
2015-12-06 17:13:04 +00:00
struct InsertVisitor
2014-02-23 20:21:27 +00:00
{
MWWorld : : CellStore & mCell ;
Loading : : Listener & mLoadingListener ;
2019-11-24 13:40:19 +00:00
bool mTest ;
2014-02-23 20:21:27 +00:00
2016-02-05 17:29:33 +00:00
std : : vector < MWWorld : : Ptr > mToInsert ;
2021-01-29 12:51:05 +00:00
InsertVisitor ( MWWorld : : CellStore & cell , Loading : : Listener & loadingListener , bool test ) ;
2014-02-23 20:21:27 +00:00
bool operator ( ) ( const MWWorld : : Ptr & ptr ) ;
2018-08-26 20:27:38 +00:00
template < class AddObject >
void insert ( AddObject & & addObject ) ;
2014-02-23 20:21:27 +00:00
} ;
2021-01-29 12:51:05 +00:00
InsertVisitor : : InsertVisitor ( MWWorld : : CellStore & cell , Loading : : Listener & loadingListener , bool test )
: mCell ( cell ) , mLoadingListener ( loadingListener ) , mTest ( test )
2014-02-23 20:21:27 +00:00
{ }
2015-12-06 17:13:04 +00:00
bool InsertVisitor : : operator ( ) ( const MWWorld : : Ptr & ptr )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
// do not insert directly as we can't modify the cell from within the visitation
// CreatureLevList::insertObjectRendering may spawn a new creature
mToInsert . push_back ( ptr ) ;
return true ;
}
2014-02-23 20:21:27 +00:00
2018-08-26 20:27:38 +00:00
template < class AddObject >
void InsertVisitor : : insert ( AddObject & & addObject )
2016-02-05 17:29:33 +00:00
{
2019-03-07 08:38:55 +00:00
for ( MWWorld : : Ptr & ptr : mToInsert )
2014-02-23 20:21:27 +00:00
{
2021-01-29 12:51:05 +00:00
if ( ! ptr . getRefData ( ) . isDeleted ( ) & & ptr . getRefData ( ) . isEnabled ( ) )
2014-02-23 20:21:27 +00:00
{
2016-02-05 17:29:33 +00:00
try
{
2018-08-26 20:27:38 +00:00
addObject ( ptr ) ;
2016-02-05 17:29:33 +00:00
}
catch ( const std : : exception & e )
{
2017-03-02 21:07:43 +00:00
std : : string error ( " failed to render ' " + ptr . getCellRef ( ) . getRefId ( ) + " ': " ) ;
2018-08-14 19:05:43 +00:00
Log ( Debug : : Error ) < < error + e . what ( ) ;
2016-02-05 17:29:33 +00:00
}
2014-02-23 20:21:27 +00:00
}
2019-11-24 13:40:19 +00:00
if ( ! mTest )
mLoadingListener . increaseProgress ( 1 ) ;
2016-02-05 17:29:33 +00:00
}
2014-02-23 20:21:27 +00:00
}
2015-12-04 18:46:02 +00:00
2020-01-13 17:12:44 +00:00
struct PositionVisitor
2015-12-04 18:46:02 +00:00
{
bool operator ( ) ( const MWWorld : : Ptr & ptr )
{
if ( ! ptr . getRefData ( ) . isDeleted ( ) & & ptr . getRefData ( ) . isEnabled ( ) )
2020-12-12 17:02:46 +00:00
ptr . getClass ( ) . adjustPosition ( ptr , false ) ;
2015-12-04 18:46:02 +00:00
return true ;
}
} ;
2018-04-01 13:54:10 +00:00
int getCellPositionDistanceToOrigin ( const std : : pair < int , int > & cellPosition )
{
return std : : abs ( cellPosition . first ) + std : : abs ( cellPosition . second ) ;
}
2011-08-08 22:05:16 +00:00
}
2011-07-31 15:07:11 +00:00
namespace MWWorld
{
2012-03-19 01:31:31 +00:00
2020-05-11 13:37:00 +00:00
void Scene : : removeFromPagedRefs ( const Ptr & ptr )
{
const ESM : : RefNum & refnum = ptr . getCellRef ( ) . getRefNum ( ) ;
if ( refnum . hasContentFile ( ) & & mPagedRefs . erase ( refnum ) )
{
if ( ! ptr . getRefData ( ) . getBaseNode ( ) ) return ;
ptr . getClass ( ) . insertObjectRendering ( ptr , getModel ( ptr , mRendering . getResourceSystem ( ) - > getVFS ( ) ) , mRendering ) ;
2021-01-29 12:51:13 +00:00
setNodeRotation ( ptr , mRendering , RotationOrder : : direct ) ;
2020-05-11 13:37:00 +00:00
reloadTerrain ( ) ;
}
}
void Scene : : updateObjectPosition ( const Ptr & ptr , const osg : : Vec3f & pos , bool movePhysics )
{
mRendering . moveObject ( ptr , pos ) ;
if ( movePhysics )
{
mPhysics - > updatePosition ( ptr ) ;
}
}
void Scene : : updateObjectRotation ( const Ptr & ptr , RotationOrder order )
2014-06-14 15:56:41 +00:00
{
2021-01-29 12:51:13 +00:00
setNodeRotation ( ptr , mRendering , order ) ;
mPhysics - > updateRotation ( ptr ) ;
2014-06-14 15:56:41 +00:00
}
2015-04-24 12:49:20 +00:00
void Scene : : updateObjectScale ( const Ptr & ptr )
{
2020-05-11 13:37:00 +00:00
float scale = ptr . getCellRef ( ) . getScale ( ) ;
osg : : Vec3f scaleVec ( scale , scale , scale ) ;
ptr . getClass ( ) . adjustScale ( ptr , scaleVec , true ) ;
mRendering . scaleObject ( ptr , scaleVec ) ;
mPhysics - > updateScale ( ptr ) ;
2015-04-24 12:49:20 +00:00
}
2014-05-11 13:17:25 +00:00
void Scene : : update ( float duration , bool paused )
{
2020-05-12 13:37:00 +00:00
mPreloader - > updateCache ( mRendering . getReferenceTime ( ) ) ;
2020-05-12 13:37:00 +00:00
preloadCells ( duration ) ;
2016-02-07 13:13:46 +00:00
2015-04-18 23:57:52 +00:00
mRendering . update ( duration , paused ) ;
2011-12-27 00:23:46 +00:00
}
2012-03-19 01:31:31 +00:00
2021-01-29 12:51:05 +00:00
void Scene : : unloadCell ( CellStoreCollection : : iterator iter , bool test )
2011-07-31 15:07:11 +00:00
{
2019-11-24 13:40:19 +00:00
if ( ! test )
2021-01-29 12:51:05 +00:00
Log ( Debug : : Info ) < < " Unloading cell " < < ( * iter ) - > getCell ( ) - > getDescription ( ) ;
2018-03-13 22:49:08 +00:00
const auto navigator = MWBase : : Environment : : get ( ) . getWorld ( ) - > getNavigator ( ) ;
2015-12-06 17:13:04 +00:00
ListAndResetObjectsVisitor visitor ;
2013-03-10 09:00:20 +00:00
2021-01-29 12:51:05 +00:00
( * iter ) - > forEach ( visitor ) ;
2019-03-03 11:58:03 +00:00
const auto world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
2018-03-13 22:49:08 +00:00
for ( const auto & ptr : visitor . mObjects )
2011-11-21 11:52:28 +00:00
{
2018-03-13 22:49:08 +00:00
if ( const auto object = mPhysics - > getObject ( ptr ) )
2018-09-22 15:36:57 +00:00
navigator - > removeObject ( DetourNavigator : : ObjectId ( object ) ) ;
2019-03-10 11:24:03 +00:00
else if ( mPhysics - > getActor ( ptr ) )
2018-07-21 10:37:02 +00:00
{
2019-03-03 11:58:03 +00:00
navigator - > removeAgent ( world - > getPathfindingHalfExtents ( ptr ) ) ;
2018-07-21 10:37:02 +00:00
mRendering . removeActorPath ( ptr ) ;
}
2021-01-29 12:51:05 +00:00
mPhysics - > remove ( ptr ) ;
2013-04-17 15:05:54 +00:00
}
2012-03-13 16:09:50 +00:00
2021-01-29 12:51:05 +00:00
const auto cellX = ( * iter ) - > getCell ( ) - > getGridX ( ) ;
const auto cellY = ( * iter ) - > getCell ( ) - > getGridY ( ) ;
2018-07-20 19:11:34 +00:00
2021-01-29 12:51:05 +00:00
if ( ( * iter ) - > getCell ( ) - > isExterior ( ) )
2013-04-17 15:05:54 +00:00
{
2021-01-22 23:56:46 +00:00
if ( const auto heightField = mPhysics - > getHeightField ( cellX , cellY ) )
navigator - > removeObject ( DetourNavigator : : ObjectId ( heightField ) ) ;
2021-01-29 12:51:05 +00:00
mPhysics - > removeHeightField ( cellX , cellY ) ;
2011-11-19 06:01:19 +00:00
}
2012-03-19 01:31:31 +00:00
2021-01-29 12:51:05 +00:00
if ( ( * iter ) - > getCell ( ) - > hasWater ( ) )
2018-07-20 19:11:34 +00:00
navigator - > removeWater ( osg : : Vec2i ( cellX , cellY ) ) ;
2021-01-29 12:51:05 +00:00
if ( const auto pathgrid = world - > getStore ( ) . get < ESM : : Pathgrid > ( ) . search ( * ( * iter ) - > getCell ( ) ) )
2020-06-11 21:23:30 +00:00
navigator - > removePathgrid ( * pathgrid ) ;
2019-03-03 11:58:03 +00:00
const auto player = world - > getPlayerPtr ( ) ;
2018-04-21 12:27:25 +00:00
navigator - > update ( player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
2021-01-29 12:51:05 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > drop ( * iter ) ;
2015-05-21 22:55:43 +00:00
2021-01-29 12:51:05 +00:00
mRendering . removeCell ( * iter ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > removeCell ( * iter ) ;
2012-01-23 13:33:06 +00:00
2021-01-29 12:51:05 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > getLocalScripts ( ) . clearCell ( * iter ) ;
2013-11-30 09:50:02 +00:00
2021-01-29 12:51:05 +00:00
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > stopSound ( * iter ) ;
mActiveCells . erase ( * iter ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2021-01-29 12:51:05 +00:00
void Scene : : loadCell ( CellStore * cell , Loading : : Listener * loadingListener , bool respawn , bool test )
2011-07-31 15:07:11 +00:00
{
2021-01-29 12:51:05 +00:00
std : : pair < CellStoreCollection : : iterator , bool > result = mActiveCells . insert ( cell ) ;
2011-11-21 11:52:28 +00:00
2021-01-29 12:51:05 +00:00
if ( result . second )
2012-03-13 16:09:50 +00:00
{
2021-01-29 12:51:05 +00:00
if ( test )
Log ( Debug : : Info ) < < " Testing cell " < < cell - > getCell ( ) - > getDescription ( ) ;
else
Log ( Debug : : Info ) < < " Loading cell " < < cell - > getCell ( ) - > getDescription ( ) ;
2012-03-13 16:09:50 +00:00
2021-01-29 12:51:05 +00:00
float verts = ESM : : Land : : LAND_SIZE ;
float worldsize = ESM : : Land : : REAL_SIZE ;
2018-03-13 22:49:08 +00:00
2021-01-29 12:51:05 +00:00
const auto world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
const auto navigator = world - > getNavigator ( ) ;
2018-07-20 19:11:34 +00:00
2021-01-29 12:51:05 +00:00
const int cellX = cell - > getCell ( ) - > getGridX ( ) ;
const int cellY = cell - > getCell ( ) - > getGridY ( ) ;
2021-01-23 19:59:24 +00:00
2021-01-29 12:51:05 +00:00
// Load terrain physics first...
if ( ! test & & cell - > getCell ( ) - > isExterior ( ) )
2012-03-28 20:46:29 +00:00
{
2021-01-29 12:51:05 +00:00
osg : : ref_ptr < const ESMTerrain : : LandObject > land = mRendering . getLandManager ( ) - > getLand ( cellX , cellY ) ;
const ESM : : Land : : LandData * data = land ? land - > getData ( ESM : : Land : : DATA_VHGT ) : nullptr ;
if ( data )
2017-03-06 18:04:17 +00:00
{
2021-01-29 12:51:05 +00:00
mPhysics - > addHeightField ( data - > mHeights , cellX , cellY , worldsize / ( verts - 1 ) , verts , data - > mMinHeight , data - > mMaxHeight , land . get ( ) ) ;
2012-11-05 12:07:59 +00:00
}
2016-02-28 15:47:41 +00:00
else
{
2021-01-29 12:51:05 +00:00
static std : : vector < float > defaultHeight ;
defaultHeight . resize ( verts * verts , ESM : : Land : : DEFAULT_HEIGHT ) ;
mPhysics - > addHeightField ( & defaultHeight [ 0 ] , cell - > getCell ( ) - > getGridX ( ) , cell - > getCell ( ) - > getGridY ( ) , worldsize / ( verts - 1 ) , verts , ESM : : Land : : DEFAULT_HEIGHT , ESM : : Land : : DEFAULT_HEIGHT , land . get ( ) ) ;
2016-02-28 15:47:41 +00:00
}
2021-01-29 12:51:05 +00:00
if ( const auto heightField = mPhysics - > getHeightField ( cellX , cellY ) )
navigator - > addObject ( DetourNavigator : : ObjectId ( heightField ) , * heightField - > getShape ( ) ,
heightField - > getCollisionObject ( ) - > getWorldTransform ( ) ) ;
2012-03-28 20:46:29 +00:00
}
2012-03-28 19:46:52 +00:00
2021-01-29 12:51:05 +00:00
if ( const auto pathgrid = world - > getStore ( ) . get < ESM : : Pathgrid > ( ) . search ( * cell - > getCell ( ) ) )
navigator - > addPathgrid ( * cell - > getCell ( ) , * pathgrid ) ;
2016-02-05 17:29:33 +00:00
2021-01-29 12:51:05 +00:00
// register local scripts
// do this before insertCell, to make sure we don't add scripts from levelled creature spawning twice
MWBase : : Environment : : get ( ) . getWorld ( ) - > getLocalScripts ( ) . addCell ( cell ) ;
2016-02-27 11:53:07 +00:00
2021-01-29 12:51:05 +00:00
if ( respawn )
cell - > respawn ( ) ;
2013-04-04 14:51:22 +00:00
2021-01-29 12:51:05 +00:00
// ... then references. This is important for adjustPosition to work correctly.
insertCell ( * cell , loadingListener , test ) ;
2019-11-24 13:40:19 +00:00
2021-01-29 12:51:05 +00:00
mRendering . addCell ( cell ) ;
if ( ! test )
{
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > addCell ( cell ) ;
bool waterEnabled = cell - > getCell ( ) - > hasWater ( ) | | cell - > isExterior ( ) ;
float waterLevel = cell - > getWaterLevel ( ) ;
mRendering . setWaterEnabled ( waterEnabled ) ;
if ( waterEnabled )
{
mPhysics - > enableWater ( waterLevel ) ;
mRendering . setWaterHeight ( waterLevel ) ;
2019-11-24 13:40:19 +00:00
2021-01-29 12:51:05 +00:00
if ( cell - > getCell ( ) - > isExterior ( ) )
{
if ( const auto heightField = mPhysics - > getHeightField ( cellX , cellY ) )
navigator - > addWater ( osg : : Vec2i ( cellX , cellY ) , ESM : : Land : : REAL_SIZE ,
cell - > getWaterLevel ( ) , heightField - > getCollisionObject ( ) - > getWorldTransform ( ) ) ;
}
else
{
navigator - > addWater ( osg : : Vec2i ( cellX , cellY ) , std : : numeric_limits < int > : : max ( ) ,
cell - > getWaterLevel ( ) , btTransform : : getIdentity ( ) ) ;
}
}
else
mPhysics - > disableWater ( ) ;
2019-11-24 13:40:19 +00:00
2021-01-29 12:51:05 +00:00
const auto player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
2021-03-14 12:40:48 +00:00
// By default the player is grounded, with the scene fully loaded, we validate and correct this.
2021-03-14 21:11:18 +00:00
if ( player . mCell = = cell ) // Only run once, during initial cell load.
{
2021-03-14 01:39:18 +00:00
mPhysics - > traceDown ( player , player . getRefData ( ) . getPosition ( ) . asVec3 ( ) , 10.f ) ;
}
2021-01-29 12:51:05 +00:00
navigator - > update ( player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
2019-11-24 13:40:19 +00:00
2021-01-29 12:51:05 +00:00
if ( ! cell - > isExterior ( ) & & ! ( cell - > getCell ( ) - > mData . mFlags & ESM : : Cell : : QuasiEx ) )
{
mRendering . configureAmbient ( cell - > getCell ( ) ) ;
}
2014-10-05 20:24:11 +00:00
}
2011-07-31 15:07:11 +00:00
}
2016-02-09 17:33:02 +00:00
2021-01-29 12:51:05 +00:00
mPreloader - > notifyLoaded ( cell ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2017-02-09 03:03:38 +00:00
void Scene : : clear ( )
2013-05-15 15:54:18 +00:00
{
2021-01-29 12:51:05 +00:00
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) )
unloadCell ( active + + ) ;
2013-05-15 15:54:18 +00:00
assert ( mActiveCells . empty ( ) ) ;
2018-10-09 06:21:12 +00:00
mCurrentCell = nullptr ;
2017-02-09 03:03:38 +00:00
mPreloader - > clear ( ) ;
2013-05-15 15:54:18 +00:00
}
2019-06-13 13:37:00 +00:00
osg : : Vec4i Scene : : gridCenterToBounds ( const osg : : Vec2i & centerCell ) const
{
return osg : : Vec4i ( centerCell . x ( ) - mHalfGridSize , centerCell . y ( ) - mHalfGridSize , centerCell . x ( ) + mHalfGridSize + 1 , centerCell . y ( ) + mHalfGridSize + 1 ) ;
}
osg : : Vec2i Scene : : getNewGridCenter ( const osg : : Vec3f & pos , const osg : : Vec2i * currentGridCenter ) const
{
if ( currentGridCenter )
{
float centerX , centerY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( currentGridCenter - > x ( ) , currentGridCenter - > y ( ) , centerX , centerY , true ) ;
2020-04-30 13:37:00 +00:00
float distance = std : : max ( std : : abs ( centerX - pos . x ( ) ) , std : : abs ( centerY - pos . y ( ) ) ) ;
2019-06-13 13:37:00 +00:00
const float maxDistance = Constants : : CellSizeInUnits / 2 + mCellLoadingThreshold ; // 1/2 cell size + threshold
if ( distance < = maxDistance )
return * currentGridCenter ;
}
osg : : Vec2i newCenter ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , newCenter . x ( ) , newCenter . y ( ) ) ;
return newCenter ;
}
2015-04-12 13:34:50 +00:00
void Scene : : playerMoved ( const osg : : Vec3f & pos )
2014-10-02 14:30:23 +00:00
{
2018-04-20 23:57:01 +00:00
const auto navigator = MWBase : : Environment : : get ( ) . getWorld ( ) - > getNavigator ( ) ;
const auto player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
navigator - > update ( player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
2014-10-02 14:30:23 +00:00
if ( ! mCurrentCell | | ! mCurrentCell - > isExterior ( ) )
return ;
2019-06-13 13:37:00 +00:00
osg : : Vec2i newCell = getNewGridCenter ( pos , & mCurrentGridCenter ) ;
if ( newCell ! = mCurrentGridCenter )
2020-05-12 13:37:00 +00:00
changeCellGrid ( pos , newCell . x ( ) , newCell . y ( ) ) ;
2014-10-02 14:30:23 +00:00
}
2020-05-12 13:37:00 +00:00
void Scene : : changeCellGrid ( const osg : : Vec3f & pos , int playerCellX , int playerCellY , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
2021-01-29 12:51:05 +00:00
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) )
2011-07-31 15:07:11 +00:00
{
2021-01-29 12:51:05 +00:00
if ( ( * active ) - > getCell ( ) - > isExterior ( ) )
2021-01-23 19:59:24 +00:00
{
2021-01-29 12:51:05 +00:00
if ( std : : abs ( playerCellX - ( * active ) - > getCell ( ) - > getGridX ( ) ) < = mHalfGridSize & &
std : : abs ( playerCellY - ( * active ) - > getCell ( ) - > getGridY ( ) ) < = mHalfGridSize )
{
// keep cells within the new grid
+ + active ;
continue ;
}
2011-07-31 15:07:11 +00:00
}
2021-01-29 12:51:05 +00:00
unloadCell ( active + + ) ;
2011-07-31 15:07:11 +00:00
}
2020-05-10 13:37:00 +00:00
mCurrentGridCenter = osg : : Vec2i ( playerCellX , playerCellY ) ;
osg : : Vec4i newGrid = gridCenterToBounds ( mCurrentGridCenter ) ;
mRendering . setActiveGrid ( newGrid ) ;
2020-05-12 13:37:00 +00:00
preloadTerrain ( pos , true ) ;
2020-05-10 13:37:00 +00:00
mPagedRefs . clear ( ) ;
mRendering . getPagedRefnums ( newGrid , mPagedRefs ) ;
2018-04-01 13:48:25 +00:00
std : : size_t refsToLoad = 0 ;
2021-01-29 12:51:05 +00:00
std : : vector < std : : pair < int , int > > cellsPositionsToLoad ;
// get the number of refs to load
for ( int x = playerCellX - mHalfGridSize ; x < = playerCellX + mHalfGridSize ; + + x )
2014-10-02 14:30:23 +00:00
{
2021-01-29 12:51:05 +00:00
for ( int y = playerCellY - mHalfGridSize ; y < = playerCellY + mHalfGridSize ; + + y )
2012-09-11 14:37:54 +00:00
{
2021-01-29 12:51:05 +00:00
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
2018-04-01 13:54:10 +00:00
{
2021-01-29 12:51:05 +00:00
assert ( ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
if ( x = = ( * iter ) - > getCell ( ) - > getGridX ( ) & &
y = = ( * iter ) - > getCell ( ) - > getGridY ( ) )
break ;
+ + iter ;
}
if ( iter = = mActiveCells . end ( ) )
{
refsToLoad + = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) - > count ( ) ;
cellsPositionsToLoad . emplace_back ( x , y ) ;
2018-04-01 13:54:10 +00:00
}
2012-09-11 14:37:54 +00:00
}
2021-01-29 12:51:05 +00:00
}
2012-09-11 14:37:54 +00:00
2020-05-10 13:37:00 +00:00
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
Loading : : ScopedLoad load ( loadingListener ) ;
int messagesCount = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMessagesCount ( ) ;
std : : string loadingExteriorText = " #{sLoadingMessage3} " ;
loadingListener - > setLabel ( loadingExteriorText , false , messagesCount > 0 ) ;
2013-08-27 13:48:13 +00:00
loadingListener - > setProgressRange ( refsToLoad ) ;
2018-04-01 13:54:10 +00:00
const auto getDistanceToPlayerCell = [ & ] ( const std : : pair < int , int > & cellPosition )
{
return std : : abs ( cellPosition . first - playerCellX ) + std : : abs ( cellPosition . second - playerCellY ) ;
} ;
const auto getCellPositionPriority = [ & ] ( const std : : pair < int , int > & cellPosition )
{
return std : : make_pair ( getDistanceToPlayerCell ( cellPosition ) , getCellPositionDistanceToOrigin ( cellPosition ) ) ;
} ;
std : : sort ( cellsPositionsToLoad . begin ( ) , cellsPositionsToLoad . end ( ) ,
[ & ] ( const std : : pair < int , int > & lhs , const std : : pair < int , int > & rhs ) {
return getCellPositionPriority ( lhs ) < getCellPositionPriority ( rhs ) ;
} ) ;
2011-07-31 15:07:11 +00:00
// Load cells
2021-01-29 12:51:05 +00:00
for ( const auto & cellPosition : cellsPositionsToLoad )
2014-10-02 14:30:23 +00:00
{
2021-01-29 12:51:05 +00:00
const auto x = cellPosition . first ;
const auto y = cellPosition . second ;
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
2018-04-01 13:54:10 +00:00
{
2021-01-29 12:51:05 +00:00
assert ( ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
if ( x = = ( * iter ) - > getCell ( ) - > getGridX ( ) & &
y = = ( * iter ) - > getCell ( ) - > getGridY ( ) )
break ;
+ + iter ;
2018-04-01 13:54:10 +00:00
}
2021-01-29 12:51:05 +00:00
if ( iter = = mActiveCells . end ( ) )
2018-04-01 13:54:10 +00:00
{
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) ;
2021-01-29 12:51:05 +00:00
loadCell ( cell , loadingListener , changeEvent ) ;
2011-07-31 15:07:11 +00:00
}
2014-10-02 14:30:23 +00:00
}
2011-07-31 15:07:11 +00:00
2018-04-01 13:54:10 +00:00
CellStore * current = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( playerCellX , playerCellY ) ;
2014-10-02 14:30:23 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > changeCell ( current ) ;
2011-07-31 15:07:11 +00:00
2016-02-27 11:53:07 +00:00
if ( changeEvent )
mCellChanged = true ;
2014-10-02 14:30:23 +00:00
}
2011-07-31 15:07:11 +00:00
2019-11-24 13:40:19 +00:00
void Scene : : testExteriorCells ( )
{
// Note: temporary disable ICO to decrease memory usage
mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > setIncrementalCompileOperation ( nullptr ) ;
mRendering . getResourceSystem ( ) - > setExpiryDelay ( 1.f ) ;
const MWWorld : : Store < ESM : : Cell > & cells = MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . get < ESM : : Cell > ( ) ;
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
Loading : : ScopedLoad load ( loadingListener ) ;
loadingListener - > setProgressRange ( cells . getExtSize ( ) ) ;
MWWorld : : Store < ESM : : Cell > : : iterator it = cells . extBegin ( ) ;
int i = 1 ;
for ( ; it ! = cells . extEnd ( ) ; + + it )
{
loadingListener - > setLabel ( " Testing exterior cells ( " + std : : to_string ( i ) + " / " + std : : to_string ( cells . getExtSize ( ) ) + " )... " ) ;
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( it - > mData . mX , it - > mData . mY ) ;
2021-01-29 12:51:05 +00:00
loadCell ( cell , loadingListener , false , true ) ;
2019-11-24 13:40:19 +00:00
iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
{
if ( it - > isExterior ( ) & & it - > mData . mX = = ( * iter ) - > getCell ( ) - > getGridX ( ) & &
it - > mData . mY = = ( * iter ) - > getCell ( ) - > getGridY ( ) )
{
2021-01-29 12:51:05 +00:00
unloadCell ( iter , true ) ;
2019-11-24 13:40:19 +00:00
break ;
}
+ + iter ;
}
mRendering . getResourceSystem ( ) - > updateCache ( mRendering . getReferenceTime ( ) ) ;
mRendering . getUnrefQueue ( ) - > flush ( mRendering . getWorkQueue ( ) ) ;
loadingListener - > increaseProgress ( 1 ) ;
i + + ;
}
mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > setIncrementalCompileOperation ( mRendering . getIncrementalCompileOperation ( ) ) ;
mRendering . getResourceSystem ( ) - > setExpiryDelay ( Settings : : Manager : : getFloat ( " cache expiry delay " , " Cells " ) ) ;
}
void Scene : : testInteriorCells ( )
{
// Note: temporary disable ICO to decrease memory usage
mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > setIncrementalCompileOperation ( nullptr ) ;
mRendering . getResourceSystem ( ) - > setExpiryDelay ( 1.f ) ;
const MWWorld : : Store < ESM : : Cell > & cells = MWBase : : Environment : : get ( ) . getWorld ( ) - > getStore ( ) . get < ESM : : Cell > ( ) ;
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
Loading : : ScopedLoad load ( loadingListener ) ;
loadingListener - > setProgressRange ( cells . getIntSize ( ) ) ;
int i = 1 ;
MWWorld : : Store < ESM : : Cell > : : iterator it = cells . intBegin ( ) ;
for ( ; it ! = cells . intEnd ( ) ; + + it )
{
loadingListener - > setLabel ( " Testing interior cells ( " + std : : to_string ( i ) + " / " + std : : to_string ( cells . getIntSize ( ) ) + " )... " ) ;
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( it - > mName ) ;
2021-01-29 12:51:05 +00:00
loadCell ( cell , loadingListener , false , true ) ;
2019-11-24 13:40:19 +00:00
CellStoreCollection : : iterator iter = mActiveCells . begin ( ) ;
while ( iter ! = mActiveCells . end ( ) )
{
assert ( ! ( * iter ) - > getCell ( ) - > isExterior ( ) ) ;
if ( it - > mName = = ( * iter ) - > getCell ( ) - > mName )
{
2021-01-29 12:51:05 +00:00
unloadCell ( iter , true ) ;
2019-11-24 13:40:19 +00:00
break ;
}
+ + iter ;
}
mRendering . getResourceSystem ( ) - > updateCache ( mRendering . getReferenceTime ( ) ) ;
mRendering . getUnrefQueue ( ) - > flush ( mRendering . getWorkQueue ( ) ) ;
loadingListener - > increaseProgress ( 1 ) ;
i + + ;
}
mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > setIncrementalCompileOperation ( mRendering . getIncrementalCompileOperation ( ) ) ;
mRendering . getResourceSystem ( ) - > setExpiryDelay ( Settings : : Manager : : getFloat ( " cache expiry delay " , " Cells " ) ) ;
}
2014-10-02 14:30:23 +00:00
void Scene : : changePlayerCell ( CellStore * cell , const ESM : : Position & pos , bool adjustPlayerPos )
{
mCurrentCell = cell ;
2011-07-31 15:07:11 +00:00
2017-03-09 01:17:25 +00:00
mRendering . enableTerrain ( cell - > isExterior ( ) ) ;
2014-10-02 14:30:23 +00:00
MWBase : : World * world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
MWWorld : : Ptr old = world - > getPlayerPtr ( ) ;
world - > getPlayer ( ) . setCell ( cell ) ;
2011-07-31 15:07:11 +00:00
2014-10-02 14:30:23 +00:00
MWWorld : : Ptr player = world - > getPlayerPtr ( ) ;
2015-05-21 21:54:39 +00:00
mRendering . updatePlayerPtr ( player ) ;
2011-07-31 15:07:11 +00:00
2014-10-02 14:30:23 +00:00
if ( adjustPlayerPos ) {
world - > moveObject ( player , pos . pos [ 0 ] , pos . pos [ 1 ] , pos . pos [ 2 ] ) ;
2011-07-31 15:07:11 +00:00
2015-11-12 00:08:31 +00:00
float x = pos . rot [ 0 ] ;
float y = pos . rot [ 1 ] ;
float z = pos . rot [ 2 ] ;
2014-10-02 14:30:23 +00:00
world - > rotateObject ( player , x , y , z ) ;
2011-07-31 15:07:11 +00:00
Some PVS-Studio and cppcheck fixes
cppcheck:
[apps/esmtool/record.cpp:697]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/esmtool/record.cpp:1126]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/esmtool/record.cpp:1138]: (performance) Prefer prefix ++/-- operators for non-primitive types.
[apps/niftest/niftest.cpp:36]: (performance) Function parameter 'filename' should be passed by reference.
[apps/niftest/niftest.cpp:41]: (performance) Function parameter 'filename' should be passed by reference.
[apps/opencs/model/prefs/boolsetting.cpp:25]: (warning) Possible leak in public function. The pointer 'mWidget' is not deallocated before it is allocated.
[apps/opencs/model/prefs/shortcuteventhandler.cpp:52]: (warning) Return value of std::remove() ignored. Elements remain in container.
[apps/openmw/mwstate/quicksavemanager.cpp:5]: (performance) Variable 'mSaveName' is assigned in constructor body. Consider performing initialization in initialization list.
PVS-Studio:
apps/opencs/model/filter/parser.cpp 582 warn V560 A part of conditional expression is always true: allowPredefined.
apps/opencs/view/world/referencecreator.cpp 67 warn V547 Expression '!errors.empty()' is always false.
apps/opencs/view/world/referencecreator.cpp 74 warn V547 Expression '!errors.empty()' is always false.
apps/opencs/view/doc/loader.cpp 170 warn V560 A part of conditional expression is always true: !completed.
apps/opencs/view/doc/loader.cpp 170 warn V560 A part of conditional expression is always true: !error.empty().
apps/opencs/model/tools/pathgridcheck.cpp 32 err V517 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a probability of logical error presence. Check lines: 32, 34.
apps/opencs/model/world/refidadapterimp.cpp 1376 err V547 Expression 'subColIndex < 3' is always true.
apps/openmw/mwgui/widgets.hpp 318 warn V703 It is odd that the 'mEnableRepeat' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:318, MyGUI_ScrollBar.h:179.
apps/openmw/mwgui/widgets.hpp 319 warn V703 It is odd that the 'mRepeatTriggerTime' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:319, MyGUI_ScrollBar.h:180.
apps/openmw/mwgui/widgets.hpp 320 warn V703 It is odd that the 'mRepeatStepTime' field in derived class 'MWScrollBar' overwrites field in base class 'ScrollBar'. Check lines: widgets.hpp:320, MyGUI_ScrollBar.h:181
apps/openmw/mwmechanics/actors.cpp 1425 warn V547 Expression '!detected' is always true.
apps/openmw/mwmechanics/character.cpp 2155 err V547 Expression 'mode == 0' is always true.
apps/openmw/mwmechanics/character.cpp 1192 warn V592 The expression was enclosed by parentheses twice: ((expression)). One pair of parentheses is unnecessary or misprint is present.
apps/openmw/mwmechanics/character.cpp 521 warn V560 A part of conditional expression is always true: (idle == mIdleState).
apps/openmw/mwmechanics/pathfinding.cpp 317 err V547 Expression 'mPath.size() >= 2' is always true.
apps/openmw/mwscript/interpretercontext.cpp 409 warn V560 A part of conditional expression is always false: rank > 9.
apps/openmw/mwgui/windowbase.cpp 28 warn V560 A part of conditional expression is always true: !visible.
apps/openmw/mwgui/journalwindow.cpp 561 warn V547 Expression '!mAllQuests' is always false.
apps/openmw/mwgui/referenceinterface.cpp 18 warn V571 Recurring check. The '!mPtr.isEmpty()' condition was already verified in line 16.
apps/openmw/mwworld/scene.cpp 463 warn V547 Expression 'adjustPlayerPos' is always true.
apps/openmw/mwworld/worldimp.cpp 409 err V766 An item with the same key '"sCompanionShare"' has already been added.
apps/openmw/mwworld/cellstore.cpp 691 warn V519 The 'state.mWaterLevel' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 689, 691.
apps/openmw/mwworld/weather.cpp 1125 warn V519 The 'mResult.mParticleEffect' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1123, 1125.
apps/openmw/mwworld/weather.cpp 1137 warn V519 The 'mResult.mParticleEffect' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 1135, 1137.
apps/wizard/unshield/unshieldworker.cpp 475 warn V728 An excessive check can be simplified. The '(A && B) || (!A && !B)' expression is equivalent to the 'bool(A) == bool(B)' expression.
apps/wizard/installationpage.cpp 163 warn V735 Possibly an incorrect HTML. The "</p" closing tag was encountered, while the "</span" tag was expected.
components/fontloader/fontloader.cpp 427 err V547 Expression 'i == 1' is always true.
components/nifosg/nifloader.cpp 282 warn V519 The 'created' variable is assigned values twice successively. Perhaps this is a mistake. Check lines: 278, 282.
components/esm/loadregn.cpp 119 err V586 The 'clear' function is called twice for deallocation of the same resource. Check lines: 112, 119.
components/esm/cellref.cpp 178 warn V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 175, 178.
components/esmterrain/storage.cpp 235 warn V560 A part of conditional expression is always true: colStart == 0.
components/esmterrain/storage.cpp 237 warn V560 A part of conditional expression is always true: rowStart == 0.
2018-04-09 15:55:16 +00:00
player . getClass ( ) . adjustPosition ( player , true ) ;
2014-10-02 14:30:23 +00:00
}
2020-06-05 14:22:53 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > updateCell ( old , player ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > watchActor ( player ) ;
2014-10-02 14:30:23 +00:00
2017-06-25 10:47:57 +00:00
mPhysics - > updatePtr ( old , player ) ;
2020-06-05 14:22:53 +00:00
world - > adjustSky ( ) ;
2017-02-09 00:24:13 +00:00
2020-05-12 13:37:00 +00:00
mLastPlayerPos = player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2018-08-26 20:27:38 +00:00
Scene : : Scene ( MWRender : : RenderingManager & rendering , MWPhysics : : PhysicsSystem * physics ,
DetourNavigator : : Navigator & navigator )
2020-11-13 07:39:47 +00:00
: mCurrentCell ( nullptr ) , mCellChanged ( false ) , mPhysics ( physics ) , mRendering ( rendering ) , mNavigator ( navigator )
2016-02-07 15:37:56 +00:00
, mCellLoadingThreshold ( 1024.f )
2016-02-07 17:01:14 +00:00
, mPreloadDistance ( Settings : : Manager : : getInt ( " preload distance " , " Cells " ) )
, mPreloadEnabled ( Settings : : Manager : : getBool ( " preload enabled " , " Cells " ) )
2016-02-09 00:58:07 +00:00
, mPreloadExteriorGrid ( Settings : : Manager : : getBool ( " preload exterior grid " , " Cells " ) )
, mPreloadDoors ( Settings : : Manager : : getBool ( " preload doors " , " Cells " ) )
, mPreloadFastTravel ( Settings : : Manager : : getBool ( " preload fast travel " , " Cells " ) )
2017-07-19 14:43:29 +00:00
, mPredictionTime ( Settings : : Manager : : getFloat ( " prediction time " , " Cells " ) )
2011-08-01 01:33:02 +00:00
{
2017-03-06 18:04:17 +00:00
mPreloader . reset ( new CellPreloader ( rendering . getResourceSystem ( ) , physics - > getShapeManager ( ) , rendering . getTerrain ( ) , rendering . getLandManager ( ) ) ) ;
2016-02-09 00:02:40 +00:00
mPreloader - > setWorkQueue ( mRendering . getWorkQueue ( ) ) ;
2016-02-07 18:05:55 +00:00
2017-02-04 01:36:44 +00:00
mPreloader - > setUnrefQueue ( rendering . getUnrefQueue ( ) ) ;
2016-02-09 18:04:59 +00:00
mPhysics - > setUnrefQueue ( rendering . getUnrefQueue ( ) ) ;
2016-02-18 16:47:10 +00:00
rendering . getResourceSystem ( ) - > setExpiryDelay ( Settings : : Manager : : getFloat ( " cache expiry delay " , " Cells " ) ) ;
mPreloader - > setExpiryDelay ( Settings : : Manager : : getFloat ( " preload cell expiry delay " , " Cells " ) ) ;
mPreloader - > setMinCacheSize ( Settings : : Manager : : getInt ( " preload cell cache min " , " Cells " ) ) ;
mPreloader - > setMaxCacheSize ( Settings : : Manager : : getInt ( " preload cell cache max " , " Cells " ) ) ;
2016-03-29 21:28:53 +00:00
mPreloader - > setPreloadInstances ( Settings : : Manager : : getBool ( " preload instances " , " Cells " ) ) ;
2011-08-01 01:33:02 +00:00
}
Scene : : ~ Scene ( )
{
}
bool Scene : : hasCellChanged ( ) const
{
return mCellChanged ;
}
2011-08-09 07:56:09 +00:00
2011-11-16 04:31:18 +00:00
const Scene : : CellStoreCollection & Scene : : getActiveCells ( ) const
2011-08-01 02:06:38 +00:00
{
return mActiveCells ;
}
2011-08-09 07:56:09 +00:00
2016-03-24 16:18:08 +00:00
void Scene : : changeToInteriorCell ( const std : : string & cellName , const ESM : : Position & position , bool adjustPlayerPos , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
2014-08-07 14:37:03 +00:00
CellStore * cell = MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( cellName ) ;
2019-11-18 18:10:31 +00:00
bool useFading = ( mCurrentCell ! = nullptr ) ;
if ( useFading )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenOut ( 0.5 ) ;
2013-02-28 16:54:42 +00:00
2013-08-27 13:48:13 +00:00
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
2018-10-28 07:44:14 +00:00
int messagesCount = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMessagesCount ( ) ;
2013-08-27 13:48:13 +00:00
std : : string loadingInteriorText = " #{sLoadingMessage2} " ;
2018-10-28 07:44:14 +00:00
loadingListener - > setLabel ( loadingInteriorText , false , messagesCount > 0 ) ;
2014-08-07 14:37:03 +00:00
Loading : : ScopedLoad load ( loadingListener ) ;
2013-02-28 16:54:42 +00:00
2019-11-18 18:10:31 +00:00
if ( mCurrentCell ! = nullptr & & * mCurrentCell = = * cell )
2012-09-11 14:37:54 +00:00
{
2012-11-04 23:22:30 +00:00
MWBase : : World * world = MWBase : : Environment : : get ( ) . getWorld ( ) ;
2014-01-08 17:39:44 +00:00
world - > moveObject ( world - > getPlayerPtr ( ) , position . pos [ 0 ] , position . pos [ 1 ] , position . pos [ 2 ] ) ;
2012-11-04 23:22:30 +00:00
2015-11-12 00:08:31 +00:00
float x = position . rot [ 0 ] ;
float y = position . rot [ 1 ] ;
float z = position . rot [ 2 ] ;
2014-01-08 17:39:44 +00:00
world - > rotateObject ( world - > getPlayerPtr ( ) , x , y , z ) ;
2013-04-03 21:55:57 +00:00
2016-03-24 16:18:08 +00:00
if ( adjustPlayerPos )
world - > getPlayerPtr ( ) . getClass ( ) . adjustPosition ( world - > getPlayerPtr ( ) , true ) ;
2014-08-01 14:25:41 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2012-11-04 23:22:30 +00:00
return ;
2012-09-11 14:37:54 +00:00
}
2013-03-10 09:00:20 +00:00
2018-08-14 19:05:43 +00:00
Log ( Debug : : Info ) < < " Changing to interior " ;
2011-07-31 15:07:11 +00:00
2012-11-04 23:22:30 +00:00
// unload
2021-01-29 12:51:05 +00:00
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) )
unloadCell ( active + + ) ;
2012-04-23 13:27:03 +00:00
2018-04-01 13:48:25 +00:00
loadingListener - > setProgressRange ( cell - > count ( ) ) ;
2013-08-27 13:48:13 +00:00
2012-11-04 23:22:30 +00:00
// Load cell.
2020-05-10 13:37:00 +00:00
mPagedRefs . clear ( ) ;
2021-01-29 12:51:05 +00:00
loadCell ( cell , loadingListener , changeEvent ) ;
2011-07-31 15:07:11 +00:00
2016-03-29 23:54:03 +00:00
changePlayerCell ( cell , position , adjustPlayerPos ) ;
2012-11-03 19:29:55 +00:00
2012-11-04 23:22:30 +00:00
// adjust fog
2015-04-21 21:27:26 +00:00
mRendering . configureFog ( mCurrentCell - > getCell ( ) ) ;
2013-03-10 09:00:20 +00:00
2011-07-31 15:07:11 +00:00
// Sky system
2012-07-03 10:30:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > adjustSky ( ) ;
2011-07-31 15:07:11 +00:00
2016-02-27 11:53:07 +00:00
if ( changeEvent )
mCellChanged = true ;
2019-11-18 18:10:31 +00:00
if ( useFading )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2014-10-02 14:30:23 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > changeCell ( mCurrentCell ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-01 01:33:02 +00:00
2016-02-27 11:53:07 +00:00
void Scene : : changeToExteriorCell ( const ESM : : Position & position , bool adjustPlayerPos , bool changeEvent )
2011-07-31 15:07:11 +00:00
{
int x = 0 ;
int y = 0 ;
2012-07-03 10:30:50 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( position . pos [ 0 ] , position . pos [ 1 ] , x , y ) ;
2011-07-31 15:07:11 +00:00
2017-10-05 16:39:28 +00:00
if ( changeEvent )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenOut ( 0.5 ) ;
2020-05-12 13:37:00 +00:00
changeCellGrid ( position . asVec3 ( ) , x , y , changeEvent ) ;
2014-10-02 14:30:23 +00:00
CellStore * current = MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) ;
changePlayerCell ( current , position , adjustPlayerPos ) ;
2017-10-05 16:39:28 +00:00
if ( changeEvent )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > fadeScreenIn ( 0.5 ) ;
2011-07-31 15:07:11 +00:00
}
2011-08-09 07:56:09 +00:00
2013-12-05 12:21:26 +00:00
CellStore * Scene : : getCurrentCell ( )
2011-08-01 02:06:38 +00:00
{
return mCurrentCell ;
}
2011-08-01 01:33:02 +00:00
void Scene : : markCellAsUnchanged ( )
{
mCellChanged = false ;
}
2011-08-27 08:30:38 +00:00
2021-01-29 12:51:05 +00:00
void Scene : : insertCell ( CellStore & cell , Loading : : Listener * loadingListener , bool test )
2012-05-14 15:41:17 +00:00
{
2021-01-29 12:51:05 +00:00
InsertVisitor insertVisitor ( cell , * loadingListener , test ) ;
2015-12-06 17:13:04 +00:00
cell . forEach ( insertVisitor ) ;
2021-01-29 12:51:05 +00:00
insertVisitor . insert ( [ & ] ( const MWWorld : : Ptr & ptr ) { addObject ( ptr , * mPhysics , mRendering , mPagedRefs ) ; } ) ;
insertVisitor . insert ( [ & ] ( const MWWorld : : Ptr & ptr ) { addObject ( ptr , * mPhysics , mNavigator ) ; } ) ;
2015-12-04 18:46:02 +00:00
2021-01-29 12:51:05 +00:00
// do adjustPosition (snapping actors to ground) after objects are loaded, so we don't depend on the loading order
PositionVisitor posVisitor ;
cell . forEach ( posVisitor ) ;
2012-05-14 15:41:17 +00:00
}
2011-08-08 22:05:16 +00:00
2012-05-25 15:28:27 +00:00
void Scene : : addObjectToScene ( const Ptr & ptr )
{
2015-01-31 18:21:16 +00:00
try
{
2021-01-29 12:51:05 +00:00
addObject ( ptr , * mPhysics , mRendering , mPagedRefs ) ;
2018-08-26 20:27:38 +00:00
addObject ( ptr , * mPhysics , mNavigator ) ;
2015-04-23 21:50:46 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > scaleObject ( ptr , ptr . getCellRef ( ) . getScale ( ) ) ;
2018-04-21 12:27:25 +00:00
const auto navigator = MWBase : : Environment : : get ( ) . getWorld ( ) - > getNavigator ( ) ;
const auto player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
navigator - > update ( player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
2015-01-31 18:21:16 +00:00
}
catch ( std : : exception & e )
{
2018-08-14 19:05:43 +00:00
Log ( Debug : : Error ) < < " failed to render ' " < < ptr . getCellRef ( ) . getRefId ( ) < < " ': " < < e . what ( ) ;
2015-01-31 18:21:16 +00:00
}
2012-05-25 15:28:27 +00:00
}
2012-08-09 12:33:21 +00:00
2012-05-25 15:28:27 +00:00
void Scene : : removeObjectFromScene ( const Ptr & ptr )
{
2013-01-29 07:39:11 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > remove ( ptr ) ;
2012-05-25 15:28:27 +00:00
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > stopSound3D ( ptr ) ;
2018-03-13 22:49:08 +00:00
const auto navigator = MWBase : : Environment : : get ( ) . getWorld ( ) - > getNavigator ( ) ;
if ( const auto object = mPhysics - > getObject ( ptr ) )
2018-04-21 12:27:25 +00:00
{
2018-09-22 15:36:57 +00:00
navigator - > removeObject ( DetourNavigator : : ObjectId ( object ) ) ;
2018-04-21 12:27:25 +00:00
const auto player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
navigator - > update ( player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
}
2019-03-10 11:24:03 +00:00
else if ( mPhysics - > getActor ( ptr ) )
2018-04-22 16:22:00 +00:00
{
2019-03-03 11:58:03 +00:00
navigator - > removeAgent ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getPathfindingHalfExtents ( ptr ) ) ;
2018-04-22 16:22:00 +00:00
}
2015-05-12 01:02:15 +00:00
mPhysics - > remove ( ptr ) ;
2015-05-21 22:55:43 +00:00
mRendering . removeObject ( ptr ) ;
2015-06-16 18:36:48 +00:00
if ( ptr . getClass ( ) . isActor ( ) )
mRendering . removeWaterRippleEmitter ( ptr ) ;
2020-05-10 13:37:00 +00:00
ptr . getRefData ( ) . setBaseNode ( nullptr ) ;
2012-05-25 15:28:27 +00:00
}
2012-07-26 12:14:11 +00:00
bool Scene : : isCellActive ( const CellStore & cell )
{
CellStoreCollection : : iterator active = mActiveCells . begin ( ) ;
while ( active ! = mActiveCells . end ( ) ) {
2012-08-08 10:51:33 +00:00
if ( * * active = = cell ) {
2012-07-26 12:14:11 +00:00
return true ;
}
+ + active ;
}
return false ;
}
2014-04-29 13:27:49 +00:00
Ptr Scene : : searchPtrViaActorId ( int actorId )
{
for ( CellStoreCollection : : const_iterator iter ( mActiveCells . begin ( ) ) ;
iter ! = mActiveCells . end ( ) ; + + iter )
if ( Ptr ptr = ( * iter ) - > searchViaActorId ( actorId ) )
return ptr ;
return Ptr ( ) ;
}
2016-02-07 13:13:46 +00:00
2017-02-14 23:55:35 +00:00
class PreloadMeshItem : public SceneUtil : : WorkItem
{
public :
PreloadMeshItem ( const std : : string & mesh , Resource : : SceneManager * sceneManager )
: mMesh ( mesh ) , mSceneManager ( sceneManager )
{
}
2020-10-16 18:18:54 +00:00
void doWork ( ) override
2017-02-14 23:55:35 +00:00
{
try
{
mSceneManager - > getTemplate ( mMesh ) ;
}
catch ( std : : exception & e )
{
}
}
private :
std : : string mMesh ;
Resource : : SceneManager * mSceneManager ;
} ;
2017-02-20 18:58:00 +00:00
void Scene : : preload ( const std : : string & mesh , bool useAnim )
2017-02-14 23:55:35 +00:00
{
2017-02-20 18:58:00 +00:00
std : : string mesh_ = mesh ;
if ( useAnim )
mesh_ = Misc : : ResourceHelpers : : correctActorModelPath ( mesh_ , mRendering . getResourceSystem ( ) - > getVFS ( ) ) ;
if ( ! mRendering . getResourceSystem ( ) - > getSceneManager ( ) - > checkLoaded ( mesh_ , mRendering . getReferenceTime ( ) ) )
mRendering . getWorkQueue ( ) - > addWorkItem ( new PreloadMeshItem ( mesh_ , mRendering . getResourceSystem ( ) - > getSceneManager ( ) ) ) ;
2017-02-14 23:55:35 +00:00
}
2017-02-09 00:24:13 +00:00
void Scene : : preloadCells ( float dt )
2016-02-07 15:37:56 +00:00
{
2020-05-12 13:37:00 +00:00
if ( dt < = 1e-06 ) return ;
2019-06-13 13:37:00 +00:00
std : : vector < PositionCellGrid > exteriorPositions ;
2017-03-09 03:18:35 +00:00
2017-02-09 00:24:13 +00:00
const MWWorld : : ConstPtr player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
osg : : Vec3f playerPos = player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ;
osg : : Vec3f moved = playerPos - mLastPlayerPos ;
2017-07-19 14:43:29 +00:00
osg : : Vec3f predictedPos = playerPos + moved / dt * mPredictionTime ;
2017-02-09 00:24:13 +00:00
2017-03-09 03:18:35 +00:00
if ( mCurrentCell - > isExterior ( ) )
2019-06-13 13:37:00 +00:00
exteriorPositions . emplace_back ( predictedPos , gridCenterToBounds ( getNewGridCenter ( predictedPos , & mCurrentGridCenter ) ) ) ;
2017-03-09 03:18:35 +00:00
2017-02-09 00:24:13 +00:00
mLastPlayerPos = playerPos ;
2017-03-09 20:45:38 +00:00
if ( mPreloadEnabled )
{
if ( mPreloadDoors )
preloadTeleportDoorDestinations ( playerPos , predictedPos , exteriorPositions ) ;
if ( mPreloadExteriorGrid )
preloadExteriorGrid ( playerPos , predictedPos ) ;
if ( mPreloadFastTravel )
2017-03-11 23:47:06 +00:00
preloadFastTravelDestinations ( playerPos , predictedPos , exteriorPositions ) ;
2017-03-09 20:45:38 +00:00
}
2017-03-09 03:18:35 +00:00
mPreloader - > setTerrainPreloadPositions ( exteriorPositions ) ;
2016-02-07 15:37:56 +00:00
}
2019-06-13 13:37:00 +00:00
void Scene : : preloadTeleportDoorDestinations ( const osg : : Vec3f & playerPos , const osg : : Vec3f & predictedPos , std : : vector < PositionCellGrid > & exteriorPositions )
2016-02-07 13:13:46 +00:00
{
std : : vector < MWWorld : : ConstPtr > teleportDoors ;
2019-03-07 08:38:55 +00:00
for ( const MWWorld : : CellStore * cellStore : mActiveCells )
2016-02-07 13:13:46 +00:00
{
typedef MWWorld : : CellRefList < ESM : : Door > : : List DoorList ;
const DoorList & doors = cellStore - > getReadOnlyDoors ( ) . mList ;
2019-03-07 08:38:55 +00:00
for ( auto & door : doors )
2016-02-07 13:13:46 +00:00
{
2019-03-07 08:38:55 +00:00
if ( ! door . mRef . getTeleport ( ) )
{
2016-02-07 13:13:46 +00:00
continue ;
}
2020-10-17 08:26:35 +00:00
teleportDoors . emplace_back ( & door , cellStore ) ;
2016-02-07 13:13:46 +00:00
}
}
2019-03-07 08:38:55 +00:00
for ( const MWWorld : : ConstPtr & door : teleportDoors )
2016-02-07 13:13:46 +00:00
{
2017-02-09 00:24:13 +00:00
float sqrDistToPlayer = ( playerPos - door . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) . length2 ( ) ;
sqrDistToPlayer = std : : min ( sqrDistToPlayer , ( predictedPos - door . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) . length2 ( ) ) ;
2016-02-07 13:13:46 +00:00
2016-02-07 15:37:56 +00:00
if ( sqrDistToPlayer < mPreloadDistance * mPreloadDistance )
2016-02-07 13:13:46 +00:00
{
try
{
if ( ! door . getCellRef ( ) . getDestCell ( ) . empty ( ) )
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( door . getCellRef ( ) . getDestCell ( ) ) ) ;
2016-02-07 13:13:46 +00:00
else
{
2017-03-09 03:18:35 +00:00
osg : : Vec3f pos = door . getCellRef ( ) . getDoorDest ( ) . asVec3 ( ) ;
2016-02-07 13:13:46 +00:00
int x , y ;
2017-03-09 03:18:35 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , x , y ) ;
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) , true ) ;
2019-06-13 13:37:00 +00:00
exteriorPositions . emplace_back ( pos , gridCenterToBounds ( getNewGridCenter ( pos ) ) ) ;
2016-02-07 13:13:46 +00:00
}
}
catch ( std : : exception & e )
{
// ignore error for now, would spam the log too much
}
}
}
}
2016-02-07 15:37:56 +00:00
2017-02-09 00:24:13 +00:00
void Scene : : preloadExteriorGrid ( const osg : : Vec3f & playerPos , const osg : : Vec3f & predictedPos )
2016-02-07 15:37:56 +00:00
{
if ( ! MWBase : : Environment : : get ( ) . getWorld ( ) - > isCellExterior ( ) )
return ;
int halfGridSizePlusOne = mHalfGridSize + 1 ;
int cellX , cellY ;
2019-06-13 13:37:00 +00:00
cellX = mCurrentGridCenter . x ( ) ; cellY = mCurrentGridCenter . y ( ) ;
2016-02-07 15:37:56 +00:00
float centerX , centerY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( cellX , cellY , centerX , centerY , true ) ;
for ( int dx = - halfGridSizePlusOne ; dx < = halfGridSizePlusOne ; + + dx )
{
for ( int dy = - halfGridSizePlusOne ; dy < = halfGridSizePlusOne ; + + dy )
{
if ( dy ! = halfGridSizePlusOne & & dy ! = - halfGridSizePlusOne & & dx ! = halfGridSizePlusOne & & dx ! = - halfGridSizePlusOne )
continue ; // only care about the outer (not yet loaded) part of the grid
float thisCellCenterX , thisCellCenterY ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > indexToPosition ( cellX + dx , cellY + dy , thisCellCenterX , thisCellCenterY , true ) ;
float dist = std : : max ( std : : abs ( thisCellCenterX - playerPos . x ( ) ) , std : : abs ( thisCellCenterY - playerPos . y ( ) ) ) ;
2017-02-09 00:24:13 +00:00
dist = std : : min ( dist , std : : max ( std : : abs ( thisCellCenterX - predictedPos . x ( ) ) , std : : abs ( thisCellCenterY - predictedPos . y ( ) ) ) ) ;
2018-09-17 10:52:43 +00:00
float loadDist = Constants : : CellSizeInUnits / 2 + Constants : : CellSizeInUnits - mCellLoadingThreshold + mPreloadDistance ;
2016-02-07 15:37:56 +00:00
if ( dist < loadDist )
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( cellX + dx , cellY + dy ) ) ;
}
}
}
void Scene : : preloadCell ( CellStore * cell , bool preloadSurrounding )
{
if ( preloadSurrounding & & cell - > isExterior ( ) )
{
int x = cell - > getCell ( ) - > getGridX ( ) ;
int y = cell - > getCell ( ) - > getGridY ( ) ;
2016-03-28 22:48:47 +00:00
unsigned int numpreloaded = 0 ;
2016-02-09 00:51:23 +00:00
for ( int dx = - mHalfGridSize ; dx < = mHalfGridSize ; + + dx )
{
for ( int dy = - mHalfGridSize ; dy < = mHalfGridSize ; + + dy )
{
mPreloader - > preload ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x + dx , y + dy ) , mRendering . getReferenceTime ( ) ) ;
2016-03-28 22:48:47 +00:00
if ( + + numpreloaded > = mPreloader - > getMaxCacheSize ( ) )
break ;
2016-02-09 00:51:23 +00:00
}
}
}
else
mPreloader - > preload ( cell , mRendering . getReferenceTime ( ) ) ;
}
2020-05-12 13:37:00 +00:00
void Scene : : preloadTerrain ( const osg : : Vec3f & pos , bool sync )
2017-03-12 21:38:50 +00:00
{
2019-06-13 13:37:00 +00:00
std : : vector < PositionCellGrid > vec ;
vec . emplace_back ( pos , gridCenterToBounds ( getNewGridCenter ( pos ) ) ) ;
2020-05-12 13:37:00 +00:00
if ( sync & & mRendering . pagingUnlockCache ( ) )
mPreloader - > abortTerrainPreloadExcept ( nullptr ) ;
else
mPreloader - > abortTerrainPreloadExcept ( & vec [ 0 ] ) ;
2017-03-12 21:38:50 +00:00
mPreloader - > setTerrainPreloadPositions ( vec ) ;
2020-05-12 13:37:00 +00:00
if ( ! sync ) return ;
Loading : : Listener * loadingListener = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
Loading : : ScopedLoad load ( loadingListener ) ;
int progress = 0 , initialProgress = - 1 , progressRange = 0 ;
while ( ! mPreloader - > syncTerrainLoad ( vec , progress , progressRange , mRendering . getReferenceTime ( ) ) )
{
if ( initialProgress = = - 1 )
{
loadingListener - > setLabel ( " #{sLoadingMessage4} " ) ;
initialProgress = progress ;
}
if ( progress )
{
loadingListener - > setProgressRange ( std : : max ( 0 , progressRange - initialProgress ) ) ;
loadingListener - > setProgress ( progress - initialProgress ) ;
}
else
loadingListener - > setProgress ( 0 ) ;
2020-06-25 19:46:07 +00:00
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
2020-05-12 13:37:00 +00:00
}
2017-03-12 21:38:50 +00:00
}
2020-05-08 13:37:00 +00:00
void Scene : : reloadTerrain ( )
{
mPreloader - > setTerrainPreloadPositions ( std : : vector < PositionCellGrid > ( ) ) ;
}
2016-02-09 00:51:23 +00:00
struct ListFastTravelDestinationsVisitor
{
ListFastTravelDestinationsVisitor ( float preloadDist , const osg : : Vec3f & playerPos )
: mPreloadDist ( preloadDist )
, mPlayerPos ( playerPos )
{
}
bool operator ( ) ( const MWWorld : : Ptr & ptr )
{
if ( ( ptr . getRefData ( ) . getPosition ( ) . asVec3 ( ) - mPlayerPos ) . length2 ( ) > mPreloadDist * mPreloadDist )
return true ;
if ( ptr . getClass ( ) . isNpc ( ) )
{
const std : : vector < ESM : : Transport : : Dest > & transport = ptr . get < ESM : : NPC > ( ) - > mBase - > mTransport . mList ;
mList . insert ( mList . begin ( ) , transport . begin ( ) , transport . end ( ) ) ;
}
else
{
const std : : vector < ESM : : Transport : : Dest > & transport = ptr . get < ESM : : Creature > ( ) - > mBase - > mTransport . mList ;
mList . insert ( mList . begin ( ) , transport . begin ( ) , transport . end ( ) ) ;
}
return true ;
}
float mPreloadDist ;
osg : : Vec3f mPlayerPos ;
std : : vector < ESM : : Transport : : Dest > mList ;
} ;
2019-06-13 13:37:00 +00:00
void Scene : : preloadFastTravelDestinations ( const osg : : Vec3f & playerPos , const osg : : Vec3f & /*predictedPos*/ , std : : vector < PositionCellGrid > & exteriorPositions ) // ignore predictedPos here since opening dialogue with travel service takes extra time
2016-02-09 00:51:23 +00:00
{
const MWWorld : : ConstPtr player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
ListFastTravelDestinationsVisitor listVisitor ( mPreloadDistance , player . getRefData ( ) . getPosition ( ) . asVec3 ( ) ) ;
2019-03-07 08:38:55 +00:00
for ( MWWorld : : CellStore * cellStore : mActiveCells )
2016-02-09 00:51:23 +00:00
{
cellStore - > forEachType < ESM : : NPC > ( listVisitor ) ;
cellStore - > forEachType < ESM : : Creature > ( listVisitor ) ;
}
2019-03-07 08:38:55 +00:00
for ( ESM : : Transport : : Dest & dest : listVisitor . mList )
2016-02-09 00:51:23 +00:00
{
2019-03-07 08:38:55 +00:00
if ( ! dest . mCellName . empty ( ) )
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getInterior ( dest . mCellName ) ) ;
2016-02-09 00:51:23 +00:00
else
{
2019-03-07 08:38:55 +00:00
osg : : Vec3f pos = dest . mPos . asVec3 ( ) ;
2016-02-09 00:51:23 +00:00
int x , y ;
2017-03-11 23:47:06 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > positionToIndex ( pos . x ( ) , pos . y ( ) , x , y ) ;
2016-02-09 00:51:23 +00:00
preloadCell ( MWBase : : Environment : : get ( ) . getWorld ( ) - > getExterior ( x , y ) , true ) ;
2019-06-13 13:37:00 +00:00
exteriorPositions . emplace_back ( pos , gridCenterToBounds ( getNewGridCenter ( pos ) ) ) ;
2016-02-07 15:37:56 +00:00
}
}
}
2011-07-31 15:07:11 +00:00
}