2013-08-16 13:01:52 +02:00
|
|
|
#include "terrainstorage.hpp"
|
|
|
|
|
2023-08-12 15:45:44 +02:00
|
|
|
#include <components/esm3/loadland.hpp>
|
2023-09-25 20:24:48 +03:00
|
|
|
#include <components/esm4/loadwrld.hpp>
|
2023-08-12 15:45:44 +02:00
|
|
|
|
2013-08-16 13:01:52 +02:00
|
|
|
#include "../mwbase/environment.hpp"
|
|
|
|
#include "../mwworld/esmstore.hpp"
|
|
|
|
|
2017-03-06 19:04:17 +01:00
|
|
|
#include "landmanager.hpp"
|
|
|
|
|
2013-08-16 13:01:52 +02:00
|
|
|
namespace MWRender
|
|
|
|
{
|
|
|
|
|
2017-03-06 19:04:17 +01:00
|
|
|
TerrainStorage::TerrainStorage(Resource::ResourceSystem* resourceSystem, const std::string& normalMapPattern,
|
|
|
|
const std::string& normalHeightMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern,
|
|
|
|
bool autoUseSpecularMaps)
|
|
|
|
: ESMTerrain::Storage(resourceSystem->getVFS(), normalMapPattern, normalHeightMapPattern, autoUseNormalMaps,
|
|
|
|
specularMapPattern, autoUseSpecularMaps)
|
|
|
|
, mLandManager(new LandManager(
|
|
|
|
ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VTEX))
|
|
|
|
, mResourceSystem(resourceSystem)
|
|
|
|
{
|
|
|
|
mResourceSystem->addResourceManager(mLandManager.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
TerrainStorage::~TerrainStorage()
|
2015-01-29 03:30:07 +01:00
|
|
|
{
|
2017-03-06 19:04:17 +01:00
|
|
|
mResourceSystem->removeResourceManager(mLandManager.get());
|
2015-01-29 03:30:07 +01:00
|
|
|
}
|
|
|
|
|
2023-05-14 20:00:02 +02:00
|
|
|
bool TerrainStorage::hasData(ESM::ExteriorCellLocation cellLocation)
|
2019-02-20 13:37:00 +00:00
|
|
|
{
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
2019-02-20 13:37:00 +00:00
|
|
|
|
2023-05-24 00:00:40 +02:00
|
|
|
if (ESM::isEsm4Ext(cellLocation.mWorldspace))
|
|
|
|
{
|
2023-09-25 20:24:48 +03:00
|
|
|
const ESM4::World* worldspace = esmStore.get<ESM4::World>().find(cellLocation.mWorldspace);
|
|
|
|
if (!worldspace->mParent.isZeroOrUnset() && worldspace->mParentUseFlags & ESM4::World::UseFlag_Land)
|
|
|
|
cellLocation.mWorldspace = worldspace->mParent;
|
|
|
|
|
2023-05-24 00:00:40 +02:00
|
|
|
return esmStore.get<ESM4::Land>().search(cellLocation) != nullptr;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return esmStore.get<ESM::Land>().search(cellLocation.mX, cellLocation.mY) != nullptr;
|
|
|
|
}
|
2019-02-20 13:37:00 +00:00
|
|
|
}
|
|
|
|
|
2023-05-20 00:31:38 +02:00
|
|
|
static void BoundUnion(float& minX, float& maxX, float& minY, float& maxY, float x, float y)
|
|
|
|
{
|
|
|
|
if (x < minX)
|
|
|
|
minX = x;
|
|
|
|
if (x > maxX)
|
|
|
|
maxX = x;
|
|
|
|
if (y < minY)
|
|
|
|
minY = y;
|
|
|
|
if (y > maxY)
|
|
|
|
maxY = y;
|
|
|
|
}
|
|
|
|
|
2023-05-19 01:07:34 +02:00
|
|
|
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace)
|
2013-08-16 13:01:52 +02:00
|
|
|
{
|
2021-08-29 14:12:14 +02:00
|
|
|
minX = 0;
|
|
|
|
minY = 0;
|
|
|
|
maxX = 0;
|
|
|
|
maxY = 0;
|
2013-08-16 13:01:52 +02:00
|
|
|
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
2013-08-16 13:01:52 +02:00
|
|
|
|
2023-05-19 01:07:34 +02:00
|
|
|
if (ESM::isEsm4Ext(worldspace))
|
2013-08-16 13:01:52 +02:00
|
|
|
{
|
2023-09-25 20:24:48 +03:00
|
|
|
const ESM4::World* worldRec = esmStore.get<ESM4::World>().find(worldspace);
|
|
|
|
if (!worldRec->mParent.isZeroOrUnset() && worldRec->mParentUseFlags & ESM4::World::UseFlag_Land)
|
|
|
|
worldspace = worldRec->mParent;
|
|
|
|
|
2023-05-19 01:07:34 +02:00
|
|
|
const auto& lands = esmStore.get<ESM4::Land>().getLands();
|
2023-05-20 00:31:38 +02:00
|
|
|
for (const auto& [landPos, _] : lands)
|
2023-05-19 01:07:34 +02:00
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
if (landPos.mWorldspace == worldspace)
|
2023-05-19 01:07:34 +02:00
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
BoundUnion(minX, maxX, minY, maxY, static_cast<float>(landPos.mX), static_cast<float>(landPos.mY));
|
2023-05-19 01:07:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MWWorld::Store<ESM::Land>::iterator it = esmStore.get<ESM::Land>().begin();
|
|
|
|
for (; it != esmStore.get<ESM::Land>().end(); ++it)
|
|
|
|
{
|
2023-05-20 00:31:38 +02:00
|
|
|
BoundUnion(minX, maxX, minY, maxY, static_cast<float>(it->mX), static_cast<float>(it->mY));
|
2023-05-19 01:07:34 +02:00
|
|
|
}
|
2013-08-16 13:01:52 +02:00
|
|
|
}
|
|
|
|
// since grid coords are at cell origin, we need to add 1 cell
|
|
|
|
maxX += 1;
|
|
|
|
maxY += 1;
|
|
|
|
}
|
|
|
|
|
2017-03-06 19:04:17 +01:00
|
|
|
LandManager* TerrainStorage::getLandManager() const
|
2013-08-16 13:01:52 +02:00
|
|
|
{
|
2017-03-06 19:04:17 +01:00
|
|
|
return mLandManager.get();
|
|
|
|
}
|
2016-02-09 20:14:16 +01:00
|
|
|
|
2023-05-14 20:00:02 +02:00
|
|
|
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(ESM::ExteriorCellLocation cellLocation)
|
2017-03-06 19:04:17 +01:00
|
|
|
{
|
2023-05-14 20:00:02 +02:00
|
|
|
return mLandManager->getLand(cellLocation);
|
2013-08-16 13:01:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
|
|
|
{
|
2023-04-20 21:07:53 +02:00
|
|
|
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
2015-11-27 21:45:37 +01:00
|
|
|
return esmStore.get<ESM::LandTexture>().search(index, plugin);
|
2013-08-16 13:01:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|