forked from mirror/openmw-tes3mp
Merge pull request #244 from OpenMW/master
Add OpenMW commits up to 19 Jul 2017
This commit is contained in:
commit
b8b3856c73
16 changed files with 103 additions and 17 deletions
|
@ -852,6 +852,9 @@ void OMW::Engine::go()
|
||||||
{
|
{
|
||||||
mViewer->eventTraversal();
|
mViewer->eventTraversal();
|
||||||
mViewer->updateTraversal();
|
mViewer->updateTraversal();
|
||||||
|
|
||||||
|
mEnvironment.getWorld()->updateWindowManager();
|
||||||
|
|
||||||
mViewer->renderingTraversals();
|
mViewer->renderingTraversals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -363,6 +363,8 @@ namespace MWBase
|
||||||
|
|
||||||
virtual void update (float duration, bool paused) = 0;
|
virtual void update (float duration, bool paused) = 0;
|
||||||
|
|
||||||
|
virtual void updateWindowManager () = 0;
|
||||||
|
|
||||||
virtual MWWorld::Ptr placeObject (const MWWorld::ConstPtr& object, float cursorX, float cursorY, int amount) = 0;
|
virtual MWWorld::Ptr placeObject (const MWWorld::ConstPtr& object, float cursorX, float cursorY, int amount) = 0;
|
||||||
///< copy and place an object into the gameworld at the specified cursor position
|
///< copy and place an object into the gameworld at the specified cursor position
|
||||||
/// @param object
|
/// @param object
|
||||||
|
|
|
@ -254,7 +254,10 @@ namespace MWRender
|
||||||
sizeX = std::max(sizeX, 0);
|
sizeX = std::max(sizeX, 0);
|
||||||
sizeY = std::max(sizeY, 0);
|
sizeY = std::max(sizeY, 0);
|
||||||
|
|
||||||
mCamera->setViewport(0, mSizeY-sizeY, std::min(mSizeX, sizeX), std::min(mSizeY, sizeY));
|
// NB Camera::setViewport has threading issues
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
|
||||||
|
stateset->setAttributeAndModes(new osg::Viewport(0, mSizeY-sizeY, std::min(mSizeX, sizeX), std::min(mSizeY, sizeY)));
|
||||||
|
mCamera->setStateSet(stateset);
|
||||||
|
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,6 +222,7 @@ namespace MWRender
|
||||||
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||||
else
|
else
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||||
|
mTerrain->setDefaultViewer(mViewer->getCamera());
|
||||||
|
|
||||||
mCamera.reset(new Camera(mViewer->getCamera()));
|
mCamera.reset(new Camera(mViewer->getCamera()));
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,7 @@ namespace MWWorld
|
||||||
, mPreloadExteriorGrid(Settings::Manager::getBool("preload exterior grid", "Cells"))
|
, mPreloadExteriorGrid(Settings::Manager::getBool("preload exterior grid", "Cells"))
|
||||||
, mPreloadDoors(Settings::Manager::getBool("preload doors", "Cells"))
|
, mPreloadDoors(Settings::Manager::getBool("preload doors", "Cells"))
|
||||||
, mPreloadFastTravel(Settings::Manager::getBool("preload fast travel", "Cells"))
|
, mPreloadFastTravel(Settings::Manager::getBool("preload fast travel", "Cells"))
|
||||||
|
, mPredictionTime(Settings::Manager::getFloat("prediction time", "Cells"))
|
||||||
{
|
{
|
||||||
mPreloader.reset(new CellPreloader(rendering.getResourceSystem(), physics->getShapeManager(), rendering.getTerrain(), rendering.getLandManager()));
|
mPreloader.reset(new CellPreloader(rendering.getResourceSystem(), physics->getShapeManager(), rendering.getTerrain(), rendering.getLandManager()));
|
||||||
mPreloader->setWorkQueue(mRendering.getWorkQueue());
|
mPreloader->setWorkQueue(mRendering.getWorkQueue());
|
||||||
|
@ -750,7 +751,7 @@ namespace MWWorld
|
||||||
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
const MWWorld::ConstPtr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
osg::Vec3f playerPos = player.getRefData().getPosition().asVec3();
|
||||||
osg::Vec3f moved = playerPos - mLastPlayerPos;
|
osg::Vec3f moved = playerPos - mLastPlayerPos;
|
||||||
osg::Vec3f predictedPos = playerPos + moved / dt;
|
osg::Vec3f predictedPos = playerPos + moved / dt * mPredictionTime;
|
||||||
|
|
||||||
if (mCurrentCell->isExterior())
|
if (mCurrentCell->isExterior())
|
||||||
exteriorPositions.push_back(predictedPos);
|
exteriorPositions.push_back(predictedPos);
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace MWWorld
|
||||||
bool mPreloadExteriorGrid;
|
bool mPreloadExteriorGrid;
|
||||||
bool mPreloadDoors;
|
bool mPreloadDoors;
|
||||||
bool mPreloadFastTravel;
|
bool mPreloadFastTravel;
|
||||||
|
float mPredictionTime;
|
||||||
|
|
||||||
osg::Vec3f mLastPlayerPos;
|
osg::Vec3f mLastPlayerPos;
|
||||||
|
|
||||||
|
|
|
@ -1711,16 +1711,14 @@ namespace MWWorld
|
||||||
if (!paused)
|
if (!paused)
|
||||||
doPhysics (duration);
|
doPhysics (duration);
|
||||||
|
|
||||||
|
updatePlayer(paused);
|
||||||
|
|
||||||
mPhysics->debugDraw();
|
mPhysics->debugDraw();
|
||||||
|
|
||||||
mWorldScene->update (duration, paused);
|
mWorldScene->update (duration, paused);
|
||||||
|
|
||||||
updateWindowManager ();
|
|
||||||
|
|
||||||
updateSoundListener();
|
updateSoundListener();
|
||||||
|
|
||||||
updatePlayer(paused);
|
|
||||||
|
|
||||||
mSpellPreloadTimer -= duration;
|
mSpellPreloadTimer -= duration;
|
||||||
if (mSpellPreloadTimer <= 0.f)
|
if (mSpellPreloadTimer <= 0.f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -130,7 +130,6 @@ namespace MWWorld
|
||||||
Ptr copyObjectToCell(const ConstPtr &ptr, CellStore* cell, ESM::Position pos, int count, bool adjustPos);
|
Ptr copyObjectToCell(const ConstPtr &ptr, CellStore* cell, ESM::Position pos, int count, bool adjustPos);
|
||||||
|
|
||||||
void updateSoundListener();
|
void updateSoundListener();
|
||||||
void updateWindowManager ();
|
|
||||||
void updatePlayer(bool paused);
|
void updatePlayer(bool paused);
|
||||||
|
|
||||||
void preloadSpells();
|
void preloadSpells();
|
||||||
|
@ -465,6 +464,8 @@ namespace MWWorld
|
||||||
|
|
||||||
virtual void update (float duration, bool paused);
|
virtual void update (float duration, bool paused);
|
||||||
|
|
||||||
|
virtual void updateWindowManager ();
|
||||||
|
|
||||||
virtual MWWorld::Ptr placeObject (const MWWorld::ConstPtr& object, float cursorX, float cursorY, int amount);
|
virtual MWWorld::Ptr placeObject (const MWWorld::ConstPtr& object, float cursorX, float cursorY, int amount);
|
||||||
///< copy and place an object into the gameworld at the specified cursor position
|
///< copy and place an object into the gameworld at the specified cursor position
|
||||||
/// @param object
|
/// @param object
|
||||||
|
|
|
@ -99,8 +99,10 @@ void QuadTreeNode::traverse(osg::NodeVisitor &nv)
|
||||||
if (!hasValidBounds())
|
if (!hasValidBounds())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((mLodCallback && mLodCallback->isSufficientDetail(this, nv.getEyePoint())) || !getNumChildren())
|
ViewData* vd = getView(nv);
|
||||||
getView(nv)->add(this, true);
|
|
||||||
|
if ((mLodCallback && mLodCallback->isSufficientDetail(this, vd->getEyePoint())) || !getNumChildren())
|
||||||
|
vd->add(this, true);
|
||||||
else
|
else
|
||||||
osg::Group::traverse(nv);
|
osg::Group::traverse(nv);
|
||||||
}
|
}
|
||||||
|
@ -130,11 +132,20 @@ ViewData* QuadTreeNode::getView(osg::NodeVisitor &nv)
|
||||||
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
|
||||||
{
|
{
|
||||||
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
|
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(&nv);
|
||||||
return mViewDataMap->getViewData(cv->getCurrentCamera(), true);
|
ViewData* vd = mViewDataMap->getViewData(cv->getCurrentCamera());
|
||||||
|
vd->setEyePoint(nv.getEyePoint());
|
||||||
|
return vd;
|
||||||
}
|
}
|
||||||
else // INTERSECTION_VISITOR
|
else // INTERSECTION_VISITOR
|
||||||
{
|
{
|
||||||
return mViewDataMap->getViewData(&nv, (nv.referenceCount() > 0)); // if no referenceCount, the visitor was allocated on the stack
|
static osg::ref_ptr<osg::Object> dummyObj = new osg::DummyObject;
|
||||||
|
ViewData* vd = mViewDataMap->getViewData(dummyObj.get());
|
||||||
|
ViewData* defaultView = mViewDataMap->getDefaultView();
|
||||||
|
if (defaultView->hasEyePoint())
|
||||||
|
vd->setEyePoint(defaultView->getEyePoint());
|
||||||
|
else
|
||||||
|
vd->setEyePoint(nv.getEyePoint());
|
||||||
|
return vd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -456,5 +456,10 @@ void QuadTreeWorld::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||||
stats->setAttribute(frameNumber, "Composite", mCompositeMapRenderer->getCompileSetSize());
|
stats->setAttribute(frameNumber, "Composite", mCompositeMapRenderer->getCompileSetSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QuadTreeWorld::setDefaultViewer(osg::Object *obj)
|
||||||
|
{
|
||||||
|
mViewDataMap->setDefaultViewer(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace Terrain
|
||||||
|
|
||||||
void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||||
|
|
||||||
|
virtual void setDefaultViewer(osg::Object* obj);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ensureQuadTreeBuilt();
|
void ensureQuadTreeBuilt();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ ViewData::ViewData()
|
||||||
: mNumEntries(0)
|
: mNumEntries(0)
|
||||||
, mFrameLastUsed(0)
|
, mFrameLastUsed(0)
|
||||||
, mChanged(false)
|
, mChanged(false)
|
||||||
|
, mHasEyePoint(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -43,6 +44,22 @@ bool ViewData::hasChanged() const
|
||||||
return mChanged;
|
return mChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ViewData::hasEyePoint() const
|
||||||
|
{
|
||||||
|
return mHasEyePoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ViewData::setEyePoint(const osg::Vec3f &eye)
|
||||||
|
{
|
||||||
|
mEyePoint = eye;
|
||||||
|
mHasEyePoint = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const osg::Vec3f& ViewData::getEyePoint() const
|
||||||
|
{
|
||||||
|
return mEyePoint;
|
||||||
|
}
|
||||||
|
|
||||||
void ViewData::reset(unsigned int frame)
|
void ViewData::reset(unsigned int frame)
|
||||||
{
|
{
|
||||||
// clear any unused entries
|
// clear any unused entries
|
||||||
|
@ -95,14 +112,13 @@ bool ViewData::Entry::set(QuadTreeNode *node, bool visible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewData *ViewDataMap::getViewData(osg::Object *viewer, bool ref)
|
ViewData *ViewDataMap::getViewData(osg::Object *viewer)
|
||||||
{
|
{
|
||||||
Map::const_iterator found = mViews.find(viewer);
|
Map::const_iterator found = mViews.find(viewer);
|
||||||
if (found == mViews.end())
|
if (found == mViews.end())
|
||||||
{
|
{
|
||||||
ViewData* vd = createOrReuseView();
|
ViewData* vd = createOrReuseView();
|
||||||
if (ref)
|
vd->setViewer(viewer);
|
||||||
vd->setViewer(viewer);
|
|
||||||
mViews[viewer] = vd;
|
mViews[viewer] = vd;
|
||||||
return vd;
|
return vd;
|
||||||
}
|
}
|
||||||
|
@ -130,8 +146,7 @@ void ViewDataMap::clearUnusedViews(unsigned int frame)
|
||||||
for (Map::iterator it = mViews.begin(); it != mViews.end(); )
|
for (Map::iterator it = mViews.begin(); it != mViews.end(); )
|
||||||
{
|
{
|
||||||
ViewData* vd = it->second;
|
ViewData* vd = it->second;
|
||||||
if ((!vd->getViewer() // if no ref was held, always need to clear to avoid holding a dangling ref.
|
if (vd->getFrameLastUsed() + 2 < frame)
|
||||||
|| vd->getFrameLastUsed() + 2 < frame))
|
|
||||||
{
|
{
|
||||||
vd->setViewer(NULL);
|
vd->setViewer(NULL);
|
||||||
vd->clear();
|
vd->clear();
|
||||||
|
@ -150,5 +165,15 @@ void ViewDataMap::clear()
|
||||||
mViewVector.clear();
|
mViewVector.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ViewDataMap::setDefaultViewer(osg::Object *viewer)
|
||||||
|
{
|
||||||
|
mDefaultViewer = viewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewData* ViewDataMap::getDefaultView()
|
||||||
|
{
|
||||||
|
return getViewData(mDefaultViewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,18 +52,25 @@ namespace Terrain
|
||||||
/// @return Have any nodes changed since the last frame
|
/// @return Have any nodes changed since the last frame
|
||||||
bool hasChanged() const;
|
bool hasChanged() const;
|
||||||
|
|
||||||
|
bool hasEyePoint() const;
|
||||||
|
|
||||||
|
void setEyePoint(const osg::Vec3f& eye);
|
||||||
|
const osg::Vec3f& getEyePoint() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Entry> mEntries;
|
std::vector<Entry> mEntries;
|
||||||
unsigned int mNumEntries;
|
unsigned int mNumEntries;
|
||||||
unsigned int mFrameLastUsed;
|
unsigned int mFrameLastUsed;
|
||||||
bool mChanged;
|
bool mChanged;
|
||||||
osg::ref_ptr<osg::Object> mViewer;
|
osg::ref_ptr<osg::Object> mViewer;
|
||||||
|
osg::Vec3f mEyePoint;
|
||||||
|
bool mHasEyePoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ViewDataMap : public osg::Referenced
|
class ViewDataMap : public osg::Referenced
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ViewData* getViewData(osg::Object* viewer, bool ref);
|
ViewData* getViewData(osg::Object* viewer);
|
||||||
|
|
||||||
ViewData* createOrReuseView();
|
ViewData* createOrReuseView();
|
||||||
|
|
||||||
|
@ -71,6 +78,10 @@ namespace Terrain
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void setDefaultViewer(osg::Object* viewer);
|
||||||
|
|
||||||
|
ViewData* getDefaultView();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<ViewData> mViewVector;
|
std::list<ViewData> mViewVector;
|
||||||
|
|
||||||
|
@ -78,6 +89,8 @@ namespace Terrain
|
||||||
Map mViews;
|
Map mViews;
|
||||||
|
|
||||||
std::deque<ViewData*> mUnusedViews;
|
std::deque<ViewData*> mUnusedViews;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Object> mDefaultViewer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace osg
|
||||||
class Group;
|
class Group;
|
||||||
class Stats;
|
class Stats;
|
||||||
class Node;
|
class Node;
|
||||||
|
class Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Resource
|
namespace Resource
|
||||||
|
@ -87,6 +88,9 @@ namespace Terrain
|
||||||
|
|
||||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
||||||
|
|
||||||
|
/// Set the default viewer (usually a Camera), used as viewpoint for any viewers that don't use their own viewpoint.
|
||||||
|
virtual void setDefaultViewer(osg::Object* obj) {}
|
||||||
|
|
||||||
Storage* getStorage() { return mStorage; }
|
Storage* getStorage() { return mStorage; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -155,6 +155,19 @@ preload cell expiry delay
|
||||||
The amount of time (in seconds) that a preloaded cell will stay in cache after it is no longer referenced or required,
|
The amount of time (in seconds) that a preloaded cell will stay in cache after it is no longer referenced or required,
|
||||||
for example, after the player has moved away from a door without entering it.
|
for example, after the player has moved away from a door without entering it.
|
||||||
|
|
||||||
|
prediction time
|
||||||
|
---------------
|
||||||
|
|
||||||
|
:Type: floating point
|
||||||
|
:Range: >=0
|
||||||
|
:Default: 1
|
||||||
|
|
||||||
|
The amount of time (in seconds) in the future to predict the player position for. This predicted position is used to preload any cells and/or distant terrain required at that position.
|
||||||
|
|
||||||
|
This setting will only have an effect if 'preload enabled' is set or the 'distant terrain' in the Terrain section is set.
|
||||||
|
|
||||||
|
Increasing this setting from its default may help if your computer/hard disk is too slow to preload in time and you see loading screens and/or lag spikes.
|
||||||
|
|
||||||
cache expiry delay
|
cache expiry delay
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,9 @@ preload cell cache max = 20
|
||||||
# How long to keep preloaded cells in cache after they're no longer referenced/required (in seconds)
|
# How long to keep preloaded cells in cache after they're no longer referenced/required (in seconds)
|
||||||
preload cell expiry delay = 5
|
preload cell expiry delay = 5
|
||||||
|
|
||||||
|
# The predicted position of the player N seconds in the future will be used for preloading cells and distant terrain
|
||||||
|
prediction time = 1
|
||||||
|
|
||||||
# How long to keep models/textures/collision shapes in cache after they're no longer referenced/required (in seconds)
|
# How long to keep models/textures/collision shapes in cache after they're no longer referenced/required (in seconds)
|
||||||
cache expiry delay = 5
|
cache expiry delay = 5
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue