mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 06:53:52 +00:00
Merge pull request #2579 from OpenMW/revert-2453-fog_compression
Revert "Store raw data about fog of war instead of RGBA images"
This commit is contained in:
commit
1aa4cc3388
7 changed files with 80 additions and 113 deletions
|
@ -144,7 +144,6 @@
|
|||
Bug #5104: Black Dart's enchantment doesn't trigger at low Enchant levels
|
||||
Bug #5105: NPCs start combat with werewolves from any distance
|
||||
Bug #5106: Still can jump even when encumbered
|
||||
Bug #5108: Savegame bloating due to inefficient fog textures format
|
||||
Bug #5110: ModRegion with a redundant numerical argument breaks script execution
|
||||
Bug #5112: Insufficient magicka for current spell not reflected on HUD icon
|
||||
Bug #5113: Unknown alchemy question mark not centered
|
||||
|
|
|
@ -209,7 +209,6 @@ namespace MWGui
|
|||
MyGUI::IntCoord(mx*mMapWidgetSize, my*mMapWidgetSize, mMapWidgetSize, mMapWidgetSize),
|
||||
MyGUI::Align::Top | MyGUI::Align::Left);
|
||||
fog->setDepth(Local_FogLayer);
|
||||
fog->setColour(MyGUI::Colour(0, 0, 0));
|
||||
|
||||
map->setNeedMouseFocus(false);
|
||||
fog->setNeedMouseFocus(false);
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <osg/LightSource>
|
||||
#include <osg/PolygonMode>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm/fogstate.hpp>
|
||||
#include <components/esm/loadcell.hpp>
|
||||
|
@ -16,6 +18,7 @@
|
|||
#include <components/settings/settings.hpp>
|
||||
#include <components/sceneutil/visitor.hpp>
|
||||
#include <components/sceneutil/shadow.hpp>
|
||||
#include <components/files/memorystream.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -538,10 +541,11 @@ bool LocalMap::isPositionExplored (float nX, float nY, int x, int y)
|
|||
nX = std::max(0.f, std::min(1.f, nX));
|
||||
nY = std::max(0.f, std::min(1.f, nY));
|
||||
|
||||
int texU = static_cast<int>((ESM::FogTexture::sFogOfWarResolution - 1) * nX);
|
||||
int texV = static_cast<int>((ESM::FogTexture::sFogOfWarResolution - 1) * nY);
|
||||
int texU = static_cast<int>((sFogOfWarResolution - 1) * nX);
|
||||
int texV = static_cast<int>((sFogOfWarResolution - 1) * nY);
|
||||
|
||||
uint8_t alpha = ((const uint8_t*)segment.mFogOfWarImage->data())[texV * ESM::FogTexture::sFogOfWarResolution + texU];
|
||||
uint32_t clr = ((const uint32_t*)segment.mFogOfWarImage->data())[texV * sFogOfWarResolution + texU];
|
||||
uint8_t alpha = (clr >> 24);
|
||||
return alpha < 200;
|
||||
}
|
||||
|
||||
|
@ -576,9 +580,9 @@ void LocalMap::updatePlayer (const osg::Vec3f& position, const osg::Quat& orient
|
|||
}
|
||||
|
||||
// explore radius (squared)
|
||||
const float exploreRadius = 0.17f * (ESM::FogTexture::sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
|
||||
const float exploreRadius = 0.17f * (sFogOfWarResolution-1); // explore radius from 0 to sFogOfWarResolution-1
|
||||
const float sqrExploreRadius = square(exploreRadius);
|
||||
const float exploreRadiusUV = exploreRadius / ESM::FogTexture::sFogOfWarResolution; // explore radius from 0 to 1 (UV space)
|
||||
const float exploreRadiusUV = exploreRadius / sFogOfWarResolution; // explore radius from 0 to 1 (UV space)
|
||||
|
||||
// change the affected fog of war textures (in a 3x3 grid around the player)
|
||||
for (int mx = -mCellDistance; mx<=mCellDistance; ++mx)
|
||||
|
@ -607,21 +611,23 @@ void LocalMap::updatePlayer (const osg::Vec3f& position, const osg::Quat& orient
|
|||
if (!segment.mFogOfWarImage || !segment.mMapTexture)
|
||||
continue;
|
||||
|
||||
uint8_t* data = (uint8_t*)segment.mFogOfWarImage->data();
|
||||
uint32_t* data = (uint32_t*)segment.mFogOfWarImage->data();
|
||||
bool changed = false;
|
||||
for (int texV = 0; texV<ESM::FogTexture::sFogOfWarResolution; ++texV)
|
||||
for (int texV = 0; texV<sFogOfWarResolution; ++texV)
|
||||
{
|
||||
for (int texU = 0; texU<ESM::FogTexture::sFogOfWarResolution; ++texU)
|
||||
for (int texU = 0; texU<sFogOfWarResolution; ++texU)
|
||||
{
|
||||
float sqrDist = square((texU + mx*(ESM::FogTexture::sFogOfWarResolution-1)) - u*(ESM::FogTexture::sFogOfWarResolution-1))
|
||||
+ square((texV + my*(ESM::FogTexture::sFogOfWarResolution-1)) - v*(ESM::FogTexture::sFogOfWarResolution-1));
|
||||
float sqrDist = square((texU + mx*(sFogOfWarResolution-1)) - u*(sFogOfWarResolution-1))
|
||||
+ square((texV + my*(sFogOfWarResolution-1)) - v*(sFogOfWarResolution-1));
|
||||
|
||||
uint8_t alpha = *data;
|
||||
uint32_t clr = *(uint32_t*)data;
|
||||
uint8_t alpha = (clr >> 24);
|
||||
|
||||
alpha = std::min( alpha, (uint8_t) (std::max(0.f, std::min(1.f, (sqrDist/sqrExploreRadius)))*255) );
|
||||
if ( *data != alpha)
|
||||
uint32_t val = (uint32_t) (alpha << 24);
|
||||
if ( *data != val)
|
||||
{
|
||||
*data = alpha;
|
||||
*data = val;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
|
@ -664,7 +670,15 @@ void LocalMap::MapSegment::createFogOfWarTexture()
|
|||
|
||||
void LocalMap::MapSegment::initFogOfWar()
|
||||
{
|
||||
mFogOfWarImage = ESM::FogState::initFogOfWar();
|
||||
mFogOfWarImage = new osg::Image;
|
||||
// Assign a PixelBufferObject for asynchronous transfer of data to the GPU
|
||||
mFogOfWarImage->setPixelBufferObject(new osg::PixelBufferObject);
|
||||
mFogOfWarImage->allocateImage(sFogOfWarResolution, sFogOfWarResolution, 1, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
assert(mFogOfWarImage->isDataContiguous());
|
||||
std::vector<uint32_t> data;
|
||||
data.resize(sFogOfWarResolution*sFogOfWarResolution, 0xff000000);
|
||||
|
||||
memcpy(mFogOfWarImage->data(), &data[0], data.size()*4);
|
||||
|
||||
createFogOfWarTexture();
|
||||
mFogOfWarTexture->setImage(mFogOfWarImage);
|
||||
|
@ -672,9 +686,34 @@ void LocalMap::MapSegment::initFogOfWar()
|
|||
|
||||
void LocalMap::MapSegment::loadFogOfWar(const ESM::FogTexture &esm)
|
||||
{
|
||||
mFogOfWarImage = ESM::FogState::loadFogOfWar(esm);
|
||||
if (!mFogOfWarImage)
|
||||
const std::vector<char>& data = esm.mImageData;
|
||||
if (data.empty())
|
||||
{
|
||||
initFogOfWar();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: deprecate tga and use raw data instead
|
||||
|
||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
||||
if (!readerwriter)
|
||||
{
|
||||
Log(Debug::Error) << "Error: Unable to load fog, can't find a tga ReaderWriter" ;
|
||||
return;
|
||||
}
|
||||
|
||||
Files::IMemStream in(&data[0], data.size());
|
||||
|
||||
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(in);
|
||||
if (!result.success())
|
||||
{
|
||||
Log(Debug::Error) << "Error: Failed to read fog: " << result.message() << " code " << result.status();
|
||||
return;
|
||||
}
|
||||
|
||||
mFogOfWarImage = result.getImage();
|
||||
mFogOfWarImage->flipVertical();
|
||||
mFogOfWarImage->dirty();
|
||||
|
||||
createFogOfWarTexture();
|
||||
mFogOfWarTexture->setImage(mFogOfWarImage);
|
||||
|
@ -686,7 +725,27 @@ void LocalMap::MapSegment::saveFogOfWar(ESM::FogTexture &fog) const
|
|||
if (!mFogOfWarImage)
|
||||
return;
|
||||
|
||||
ESM::FogState::saveFogOfWar(mFogOfWarImage, fog);
|
||||
std::ostringstream ostream;
|
||||
|
||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
||||
if (!readerwriter)
|
||||
{
|
||||
Log(Debug::Error) << "Error: Unable to write fog, can't find a tga ReaderWriter";
|
||||
return;
|
||||
}
|
||||
|
||||
// extra flips are unfortunate, but required for compatibility with older versions
|
||||
mFogOfWarImage->flipVertical();
|
||||
osgDB::ReaderWriter::WriteResult result = readerwriter->writeImage(*mFogOfWarImage, ostream);
|
||||
if (!result.success())
|
||||
{
|
||||
Log(Debug::Error) << "Error: Unable to write fog: " << result.message() << " code " << result.status();
|
||||
return;
|
||||
}
|
||||
mFogOfWarImage->flipVertical();
|
||||
|
||||
std::string data = ostream.str();
|
||||
fog.mImageData = std::vector<char>(data.begin(), data.end());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -136,6 +136,9 @@ namespace MWRender
|
|||
|
||||
int mMapResolution;
|
||||
|
||||
// the dynamic texture is a bottleneck, so don't set this too high
|
||||
static const int sFogOfWarResolution = 32;
|
||||
|
||||
// size of a map segment (for exteriors, 1 cell)
|
||||
float mMapWorldSize;
|
||||
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
#include "fogstate.hpp"
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/files/memorystream.hpp>
|
||||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
#include "savedgame.hpp"
|
||||
|
||||
void ESM::FogState::load (ESMReader &esm)
|
||||
{
|
||||
|
@ -24,10 +18,6 @@ void ESM::FogState::load (ESMReader &esm)
|
|||
size_t imageSize = esm.getSubSize()-sizeof(int)*2;
|
||||
tex.mImageData.resize(imageSize);
|
||||
esm.getExact(&tex.mImageData[0], imageSize);
|
||||
|
||||
if (esm.getFormat() < 6)
|
||||
convertFogOfWar(tex.mImageData);
|
||||
|
||||
mFogTextures.push_back(tex);
|
||||
}
|
||||
}
|
||||
|
@ -48,74 +38,3 @@ void ESM::FogState::save (ESMWriter &esm, bool interiorCell) const
|
|||
esm.endRecord("FTEX");
|
||||
}
|
||||
}
|
||||
|
||||
osg::Image* ESM::FogState::initFogOfWar()
|
||||
{
|
||||
osg::Image* fogOfWarImage = new osg::Image;
|
||||
// Assign a PixelBufferObject for asynchronous transfer of data to the GPU
|
||||
fogOfWarImage->setPixelBufferObject(new osg::PixelBufferObject);
|
||||
fogOfWarImage->allocateImage(FogTexture::sFogOfWarResolution, FogTexture::sFogOfWarResolution, 1, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
assert(fogOfWarImage->isDataContiguous());
|
||||
std::fill(fogOfWarImage->data(), fogOfWarImage->data() + FogTexture::sFogOfWarResolution*FogTexture::sFogOfWarResolution, 0xff);
|
||||
|
||||
return fogOfWarImage;
|
||||
}
|
||||
|
||||
void ESM::FogState::saveFogOfWar(osg::Image* fogImage, ESM::FogTexture &fog)
|
||||
{
|
||||
if (!fogImage)
|
||||
return;
|
||||
|
||||
assert (fogImage->isDataContiguous());
|
||||
fog.mImageData.assign(fogImage->data(), fogImage->data() + FogTexture::sFogOfWarResolution*FogTexture::sFogOfWarResolution);
|
||||
}
|
||||
|
||||
osg::Image* ESM::FogState::loadFogOfWar(const ESM::FogTexture &esm)
|
||||
{
|
||||
osg::Image* fogImage = initFogOfWar();
|
||||
const std::vector<char>& data = esm.mImageData;
|
||||
if (data.empty())
|
||||
{
|
||||
return fogImage;
|
||||
}
|
||||
|
||||
std::copy(data.begin(), data.end(), fogImage->data());
|
||||
fogImage->dirty();
|
||||
|
||||
return fogImage;
|
||||
}
|
||||
|
||||
void ESM::FogState::convertFogOfWar(std::vector<char>& imageData)
|
||||
{
|
||||
if (imageData.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
osgDB::ReaderWriter* readerwriter = osgDB::Registry::instance()->getReaderWriterForExtension("tga");
|
||||
if (!readerwriter)
|
||||
{
|
||||
Log(Debug::Error) << "Error: Unable to load fog, can't find a TGA ReaderWriter";
|
||||
return;
|
||||
}
|
||||
|
||||
Files::IMemStream in(&imageData[0], imageData.size());
|
||||
|
||||
osgDB::ReaderWriter::ReadResult result = readerwriter->readImage(in);
|
||||
if (!result.success())
|
||||
{
|
||||
Log(Debug::Error) << "Error: Failed to read fog: " << result.message() << " code " << result.status();
|
||||
return;
|
||||
}
|
||||
std::ostringstream ostream;
|
||||
|
||||
osg::Image* resultImage = result.getImage();
|
||||
resultImage->flipVertical();
|
||||
|
||||
unsigned char* oldFogData = resultImage->data();
|
||||
for (int i=0;i<FogTexture::sFogOfWarResolution*FogTexture::sFogOfWarResolution;++i)
|
||||
ostream << oldFogData[4*i+3];
|
||||
|
||||
std::string str = ostream.str();
|
||||
imageData = std::vector<char>(str.begin(), str.end());
|
||||
}
|
||||
|
|
|
@ -3,11 +3,6 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
|
@ -17,8 +12,6 @@ namespace ESM
|
|||
{
|
||||
int mX, mY; // Only used for interior cells
|
||||
std::vector<char> mImageData;
|
||||
// the dynamic texture is a bottleneck, so don't set this too high
|
||||
static const int sFogOfWarResolution = 32;
|
||||
};
|
||||
|
||||
// format 0, saved games only
|
||||
|
@ -39,11 +32,6 @@ namespace ESM
|
|||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm, bool interiorCell) const;
|
||||
|
||||
static void saveFogOfWar(osg::Image* fogImage, ESM::FogTexture &fog);
|
||||
static osg::Image* loadFogOfWar(const ESM::FogTexture &esm);
|
||||
static void convertFogOfWar(std::vector<char>& imageData);
|
||||
static osg::Image* initFogOfWar();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "defs.hpp"
|
||||
|
||||
unsigned int ESM::SavedGame::sRecordId = ESM::REC_SAVE;
|
||||
int ESM::SavedGame::sCurrentFormat = 6;
|
||||
int ESM::SavedGame::sCurrentFormat = 5;
|
||||
|
||||
void ESM::SavedGame::load (ESMReader &esm)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue