Do not re-render maps for all active cells during cell transitions

pull/541/head
bzzt 6 years ago committed by Andrei Kortunov
parent 368d1f9d25
commit ed4ce4609b

@ -350,6 +350,7 @@ namespace MWBase
virtual std::string correctTexturePath(const std::string& path) = 0;
virtual bool textureExists(const std::string& path) = 0;
virtual void addCell(MWWorld::CellStore* cell) = 0;
virtual void removeCell(MWWorld::CellStore* cell) = 0;
virtual void writeFog(MWWorld::CellStore* cell) = 0;

@ -237,9 +237,6 @@ namespace MWGui
{
for (int my=0; my<mNumCells; ++my)
{
int x = mCurX + (mx - mCellDistance);
int y = mCurY + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx];
MyGUI::ImageBox* fog = entry.mFogWidget;
@ -249,19 +246,6 @@ namespace MWGui
entry.mFogTexture.reset();
continue;
}
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(x, y);
if (tex)
{
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
fog->setRenderItemTexture(entry.mFogTexture.get());
fog->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
}
else
{
fog->setImageTexture("black");
entry.mFogTexture.reset();
}
}
}
@ -366,31 +350,18 @@ namespace MWGui
mInterior = interior;
mChanged = false;
applyFogOfWar();
// Update the map textures
for (int mx=0; mx<mNumCells; ++mx)
{
for (int my=0; my<mNumCells; ++my)
{
int mapX = x + (mx - mCellDistance);
int mapY = y + (-1*(my - mCellDistance));
MapEntry& entry = mMaps[my + mNumCells*mx];
MyGUI::ImageBox* box = entry.mMapWidget;
entry.mMapWidget->setRenderItemTexture(nullptr);
entry.mFogWidget->setRenderItemTexture(nullptr);
entry.mMapTexture.reset();
entry.mFogTexture.reset();
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(mapX, mapY);
if (texture)
{
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
box->setRenderItemTexture(entry.mMapTexture.get());
box->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
}
else
{
box->setRenderItemTexture(nullptr);
entry.mMapTexture.reset();
}
entry.mCellX = x + (mx - mCellDistance);
entry.mCellY = y - (my - mCellDistance);
}
}
@ -404,22 +375,7 @@ namespace MWGui
void LocalMapBase::requestMapRender(const MWWorld::CellStore *cell)
{
std::set<const MWWorld::CellStore*> cells;
if (!cell->isExterior())
cells.insert(cell);
else
{
for (int dX=-mCellDistance; dX<=mCellDistance; ++dX)
{
for (int dY=-mCellDistance; dY<=mCellDistance; ++dY)
{
const MWWorld::CellStore* gridCell = MWBase::Environment::get().getWorld()->getExterior (cell->getCell()->getGridX()+dX, cell->getCell()->getGridY()+dY);
cells.insert(gridCell);
}
}
}
mLocalMapRender->requestMap(cells);
mLocalMapRender->requestMap(cell);
}
void LocalMapBase::redraw()
@ -522,6 +478,68 @@ namespace MWGui
mMarkerUpdateTimer = 0;
updateMagicMarkers();
}
updateRequiredMaps();
}
bool widgetCropped(MyGUI::Widget* widget, MyGUI::Widget* cropTo)
{
MyGUI::IntRect coord = widget->getAbsoluteRect();
MyGUI::IntRect croppedCoord = cropTo->getAbsoluteRect();
if (coord.left < croppedCoord.left && coord.right < croppedCoord.left)
return true;
if (coord.left > croppedCoord.right && coord.right > croppedCoord.right)
return true;
if (coord.top < croppedCoord.top && coord.bottom < croppedCoord.top)
return true;
if (coord.top > croppedCoord.bottom && coord.bottom > croppedCoord.bottom)
return true;
return false;
}
void LocalMapBase::updateRequiredMaps()
{
bool needRedraw = false;
for (MapEntry& entry : mMaps)
{
if (widgetCropped(entry.mMapWidget, mLocalMap))
continue;
if (!entry.mMapTexture)
{
if (!mInterior)
requestMapRender(MWBase::Environment::get().getWorld()->getExterior (entry.mCellX, entry.mCellY));
osg::ref_ptr<osg::Texture2D> texture = mLocalMapRender->getMapTexture(entry.mCellX, entry.mCellY);
if (texture)
{
entry.mMapTexture.reset(new osgMyGUI::OSGTexture(texture));
entry.mMapWidget->setRenderItemTexture(entry.mMapTexture.get());
entry.mMapWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 0.f, 1.f, 1.f));
needRedraw = true;
}
else
entry.mMapTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
}
if (!entry.mFogTexture && mFogOfWarToggled && mFogOfWarEnabled)
{
osg::ref_ptr<osg::Texture2D> tex = mLocalMapRender->getFogOfWarTexture(entry.mCellX, entry.mCellY);
if (tex)
{
entry.mFogTexture.reset(new osgMyGUI::OSGTexture(tex));
entry.mFogWidget->setRenderItemTexture(entry.mFogTexture.get());
entry.mFogWidget->getSubWidgetMain()->_setUVSet(MyGUI::FloatRect(0.f, 1.f, 1.f, 0.f));
}
else
{
entry.mFogWidget->setImageTexture("black");
entry.mFogTexture.reset(new osgMyGUI::OSGTexture("", nullptr));
}
needRedraw = true;
}
}
if (needRedraw)
redraw();
}
void LocalMapBase::updateDoorMarkers()

@ -129,12 +129,14 @@ namespace MWGui
struct MapEntry
{
MapEntry(MyGUI::ImageBox* mapWidget, MyGUI::ImageBox* fogWidget)
: mMapWidget(mapWidget), mFogWidget(fogWidget) {}
: mMapWidget(mapWidget), mFogWidget(fogWidget), mCellX(0), mCellY(0) {}
MyGUI::ImageBox* mMapWidget;
MyGUI::ImageBox* mFogWidget;
std::shared_ptr<MyGUI::ITexture> mMapTexture;
std::shared_ptr<MyGUI::ITexture> mFogTexture;
int mCellX;
int mCellY;
};
std::vector<MapEntry> mMaps;
@ -155,6 +157,8 @@ namespace MWGui
virtual void customMarkerCreated(MyGUI::Widget* marker) {}
virtual void doorMarkerCreated(MyGUI::Widget* marker) {}
void updateRequiredMaps();
void updateMagicMarkers();
void addDetectionMarkers(int type);

@ -976,6 +976,12 @@ namespace MWGui
void WindowManager::onFrame (float frameDuration)
{
bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!=
MWBase::StateManager::State_NoGame;
if (gameRunning)
updateMap();
if (!mGuiModes.empty())
{
GuiModeState& state = mGuiModeStates[mGuiModes.back()];
@ -1019,14 +1025,11 @@ namespace MWGui
if (mLocalMapRender)
mLocalMapRender->cleanupCameras();
if (MWBase::Environment::get().getStateManager()->getState()==
MWBase::StateManager::State_NoGame)
if (!gameRunning)
return;
mDragAndDrop->onFrame();
updateMap();
mHud->onFrame(frameDuration);
mDebugWindow->onFrame(frameDuration);
@ -2163,6 +2166,11 @@ namespace MWGui
tex->unlock();
}
void WindowManager::addCell(MWWorld::CellStore* cell)
{
mLocalMapRender->addCell(cell);
}
void WindowManager::removeCell(MWWorld::CellStore *cell)
{
mLocalMapRender->removeCell(cell);

@ -378,6 +378,7 @@ namespace MWGui
virtual std::string correctTexturePath(const std::string& path);
virtual bool textureExists(const std::string& path);
void addCell(MWWorld::CellStore* cell);
void removeCell(MWWorld::CellStore* cell);
void writeFog(MWWorld::CellStore* cell);

@ -256,36 +256,30 @@ bool needUpdate(std::set<std::pair<int, int> >& renderedGrid, std::set<std::pair
return false;
}
void LocalMap::requestMap(std::set<const MWWorld::CellStore*> cells)
void LocalMap::requestMap(const MWWorld::CellStore* cell)
{
std::set<std::pair<int, int> > grid;
for (const MWWorld::CellStore* cell : cells)
if (cell->isExterior())
{
if (cell->isExterior())
grid.insert(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
}
int cellX = cell->getCell()->getGridX();
int cellY = cell->getCell()->getGridY();
for (const MWWorld::CellStore* cell : cells)
{
if (cell->isExterior())
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
if (!needUpdate(segment.mGrid, mCurrentGrid, cellX, cellY))
return;
else
{
int cellX = cell->getCell()->getGridX();
int cellY = cell->getCell()->getGridY();
MapSegment& segment = mSegments[std::make_pair(cellX, cellY)];
if (!needUpdate(segment.mGrid, grid, cellX, cellY))
{
continue;
}
else
{
segment.mGrid = grid;
requestExteriorMap(cell);
}
segment.mGrid = mCurrentGrid;
requestExteriorMap(cell);
}
else
requestInteriorMap(cell);
}
else
requestInteriorMap(cell);
}
void LocalMap::addCell(MWWorld::CellStore *cell)
{
if (cell->isExterior())
mCurrentGrid.emplace(cell->getCell()->getGridX(), cell->getCell()->getGridY());
}
void LocalMap::removeCell(MWWorld::CellStore *cell)
@ -293,7 +287,11 @@ void LocalMap::removeCell(MWWorld::CellStore *cell)
saveFogOfWar(cell);
if (cell->isExterior())
mSegments.erase(std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY()));
{
std::pair<int, int> coords = std::make_pair(cell->getCell()->getGridX(), cell->getCell()->getGridY());
mSegments.erase(coords);
mCurrentGrid.erase(coords);
}
else
mSegments.clear();
}

@ -45,13 +45,12 @@ namespace MWRender
void clear();
/**
* Request a map render for the given cells. Render textures will be immediately created and can be retrieved with the getMapTexture function.
* Request a map render for the given cell. Render textures will be immediately created and can be retrieved with the getMapTexture function.
*/
void requestMap (std::set<const MWWorld::CellStore*> cells);
void requestMap (const MWWorld::CellStore* cell);
void addCell(MWWorld::CellStore* cell);
/**
* Remove map and fog textures for the given cell.
*/
void removeCell (MWWorld::CellStore* cell);
osg::ref_ptr<osg::Texture2D> getMapTexture (int x, int y);
@ -110,6 +109,9 @@ namespace MWRender
CameraVector mCamerasPendingRemoval;
typedef std::set<std::pair<int, int> > Grid;
Grid mCurrentGrid;
struct MapSegment
{
MapSegment();
@ -124,7 +126,7 @@ namespace MWRender
osg::ref_ptr<osg::Texture2D> mFogOfWarTexture;
osg::ref_ptr<osg::Image> mFogOfWarImage;
std::set<std::pair<int, int> > mGrid; // the grid that was active at the time of rendering this segment
Grid mGrid; // the grid that was active at the time of rendering this segment
bool mHasFogState;
};

@ -431,6 +431,7 @@ namespace MWWorld
insertCell (*cell, true, loadingListener);
mRendering.addCell(cell);
MWBase::Environment::get().getWindowManager()->addCell(cell);
bool waterEnabled = cell->getCell()->hasWater() || cell->isExterior();
float waterLevel = cell->getWaterLevel();
mRendering.setWaterEnabled(waterEnabled);

@ -112,5 +112,5 @@ local map cell distance
:Default: 1
Similar to "exterior cell load distance" in the Cells section, controls how many cells are rendered on the local map.
Values higher than the default may result in longer loading times. Please note that only loaded cells can be rendered,
Please note that only loaded cells can be rendered,
so this setting must be lower or equal to "exterior cell load distance" to work properly.

Loading…
Cancel
Save