ESM4::Land loaded, added to store and to land objects

it does not work yet. Some things are displayed, but it looks all wrong.
macos_ci
florent.teppe 2 years ago
parent fffcf52316
commit c35c7b3640

@ -20,8 +20,6 @@ namespace MWRender
osg::ref_ptr<ESMTerrain::LandObject> LandManager::getLand(ESM::ExteriorCellLocation cellIndex)
{
if (ESM::isEsm4Ext(cellIndex.mWorldspace))
return osg::ref_ptr<ESMTerrain::LandObject>(nullptr);
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(cellIndex);
if (obj)
return static_cast<ESMTerrain::LandObject*>(obj.get());
@ -30,12 +28,25 @@ namespace MWRender
const auto world = MWBase::Environment::get().getWorld();
if (!world)
return nullptr;
const ESM::Land* land = world->getStore().get<ESM::Land>().search(cellIndex.mX, cellIndex.mY);
if (!land)
return nullptr;
osg::ref_ptr<ESMTerrain::LandObject> landObj(new ESMTerrain::LandObject(land, mLoadFlags));
mCache->addEntryToObjectCache(cellIndex, landObj.get());
return landObj;
if (ESM::isEsm4Ext(cellIndex.mWorldspace))
{
const ESM4::Land* land = world->getStore().get<ESM4::Land>().search(cellIndex);
if (!land)
return nullptr;
osg::ref_ptr<ESMTerrain::LandObject> landObj(new ESMTerrain::LandObject(land, mLoadFlags));
mCache->addEntryToObjectCache(cellIndex, landObj.get());
return landObj;
}
else
{
const ESM::Land* land = world->getStore().get<ESM::Land>().search(cellIndex.mX, cellIndex.mY);
if (!land)
return nullptr;
osg::ref_ptr<ESMTerrain::LandObject> landObj(new ESMTerrain::LandObject(land, mLoadFlags));
mCache->addEntryToObjectCache(cellIndex, landObj.get());
return landObj;
}
}
}

@ -14,6 +14,7 @@
#include <components/misc/algorithm.hpp>
#include <components/esm4/common.hpp>
#include <components/esm4/loadland.hpp>
#include <components/esm4/loadwrld.hpp>
#include <components/esm4/reader.hpp>
#include <components/esm4/readerutils.hpp>
@ -385,6 +386,7 @@ namespace MWWorld
{
auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); };
ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {});
getWritable<ESM4::Land>().updateLandPositions(get<ESM4::Cell>());
}
void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type)

@ -43,6 +43,7 @@ namespace ESM4
struct MiscItem;
struct Weapon;
struct World;
struct Land;
}
namespace ESM
@ -121,7 +122,7 @@ namespace MWWorld
Store<ESM4::Static>, Store<ESM4::Cell>, Store<ESM4::Light>, Store<ESM4::Reference>, Store<ESM4::Activator>,
Store<ESM4::Potion>, Store<ESM4::Ammunition>, Store<ESM4::Armor>, Store<ESM4::Book>, Store<ESM4::Clothing>,
Store<ESM4::Container>, Store<ESM4::Door>, Store<ESM4::Ingredient>, Store<ESM4::MiscItem>,
Store<ESM4::Weapon>, Store<ESM4::World>>;
Store<ESM4::Weapon>, Store<ESM4::World>, Store<ESM4::Land>>;
private:
template <typename T>

@ -8,11 +8,14 @@
#include <components/esm/records.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp>
#include <components/esm4/loadland.hpp>
#include <components/esm4/loadwrld.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/rng.hpp>
#include <apps/openmw/mwworld/cell.hpp>
#include "../mwbase/environment.hpp"
#include "../mwworld/cell.hpp"
#include "../mwworld/worldimp.hpp"
namespace
{
@ -1189,6 +1192,29 @@ namespace MWWorld
MWWorld::TypedDynamicStore<ESM4::Cell>::clearDynamic();
}
void Store<ESM4::Land>::updateLandPositions(const Store<ESM4::Cell>& cells)
{
for (auto it : mStatic)
{
const ESM4::Cell* cell = cells.find(it.second.mCell);
mLands[cell->getExteriorCellLocation()] = &it.second;
}
for (auto it : mDynamic)
{
const ESM4::Cell* cell = cells.find(it.second.mCell);
mLands[cell->getExteriorCellLocation()] = &it.second;
}
}
const ESM4::Land* MWWorld::Store<ESM4::Land>::search(ESM::ExteriorCellLocation cellLocation) const
{
auto foundLand = mLands.find(cellLocation);
if (foundLand == mLands.end())
return nullptr;
else
return foundLand->second;
}
// ESM4 Reference
//=========================================================================
@ -1276,3 +1302,4 @@ template class MWWorld::TypedDynamicStore<ESM4::Reference, ESM::FormId>;
template class MWWorld::TypedDynamicStore<ESM4::Cell>;
template class MWWorld::TypedDynamicStore<ESM4::Weapon>;
template class MWWorld::TypedDynamicStore<ESM4::World>;
template class MWWorld::TypedDynamicStore<ESM4::Land>;

@ -35,6 +35,11 @@ namespace ESM
class ESMWriter;
}
namespace ESM4
{
struct Land;
}
namespace Loading
{
class Listener;
@ -298,6 +303,17 @@ namespace MWWorld
void clearDynamic() override;
};
template <>
class Store<ESM4::Land> : public TypedDynamicStore<ESM4::Land>
{
std::unordered_map<ESM::ExteriorCellLocation, const ESM4::Land*> mLands;
public:
void updateLandPositions(const Store<ESM4::Cell>& cells);
const ESM4::Land* search(ESM::ExteriorCellLocation cellLocation) const;
};
template <>
class Store<ESM::Land> : public DynamicStore
{

@ -17,6 +17,7 @@
#include <components/esm3/typetraits.hpp>
#include <components/esm4/common.hpp>
#include <components/esm4/loadcell.hpp>
#include <components/esm4/loadland.hpp>
#include <components/esm4/loadligh.hpp>
#include <components/esm4/loadrefr.hpp>
#include <components/esm4/loadstat.hpp>

@ -37,11 +37,11 @@ namespace ESMTerrain
LandObject::LandObject(const ESM::Land* land, int loadFlags)
: mLand(land)
, mLoadFlags(loadFlags)
, mData()
, mData(nullptr)
{
auto esm3LandData = new ESM::Land::LandData;
mData.reset(esm3LandData);
mLand->loadData(mLoadFlags, esm3LandData);
std::unique_ptr<ESM::Land::LandData> esm3LandData = std::make_unique<ESM::Land::LandData>();
mLand->loadData(mLoadFlags, esm3LandData.get());
mData = std::move(esm3LandData);
}
LandObject::LandObject(const LandObject& copy, const osg::CopyOp& copyop)
@ -478,15 +478,16 @@ namespace ESMTerrain
const ESM::LandData* data = land->getData(ESM::Land::DATA_VHGT);
if (!data)
return defaultHeight;
const int landSize = data->getLandSize();
// Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition
// Normalized position in the cell
float nX = (worldPos.x() - (cellX * Constants::CellSizeInUnits)) / cellSize;
float nY = (worldPos.y() - (cellY * Constants::CellSizeInUnits)) / cellSize;
float nX = (worldPos.x() - (cellX * cellSize)) / cellSize;
float nY = (worldPos.y() - (cellY * cellSize)) / cellSize;
// get left / bottom points (rounded down)
float factor = ESM::Land::LAND_SIZE - 1.0f;
float factor = landSize - 1.0f;
float invFactor = 1.0f / factor;
int startX = static_cast<int>(nX * factor);
@ -494,8 +495,8 @@ namespace ESMTerrain
int endX = startX + 1;
int endY = startY + 1;
endX = std::min(endX, ESM::Land::LAND_SIZE - 1);
endY = std::min(endY, ESM::Land::LAND_SIZE - 1);
endX = std::min(endX, landSize - 1);
endY = std::min(endY, landSize - 1);
// now get points in terrain space (effectively rounding them to boundaries)
float startXTS = startX * invFactor;

@ -41,6 +41,8 @@ namespace ESMTerrain
inline const ESM::LandData* getData(int flags) const
{
if (!mData)
return nullptr;
ESM::Land::LandData* esm3Land = dynamic_cast<ESM::Land::LandData*>(mData.get());
if (esm3Land && ((esm3Land->mDataLoaded & flags) != flags))
return nullptr;

@ -36,6 +36,7 @@
#include <components/esm/defs.hpp>
#include <components/esm/refid.hpp>
#include <components/esm/util.hpp>
#include <components/esm4/reader.hpp>
namespace ESM4
@ -107,7 +108,10 @@ namespace ESM4
int getGridX() const { return mX; }
int getGridY() const { return mY; }
bool isExterior() const { return !(mCellFlags & CELL_Interior); }
ESM::ExteriorCellLocation getExteriorCellLocation() const
{
return ESM::ExteriorCellLocation(mX, mY, isExterior() ? mParent : mId);
}
static float sInvalidWaterLevel;
};
}

@ -54,11 +54,12 @@
//
void ESM4::Land::load(ESM4::Reader& reader)
{
mFormId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId);
ESM::FormId formId = reader.hdr().record.getFormId();
reader.adjustFormId(formId);
mId = ESM::RefId::formIdRefId(formId);
mFlags = reader.hdr().record.flags;
mDataTypes = 0;
mCell = ESM::RefId::formIdRefId(reader.currCell());
TxtLayer layer;
std::int8_t currentAddQuad = -1; // for VTXT following ATXT
@ -252,6 +253,29 @@ void ESM4::Land::load(ESM4::Reader& reader)
}
}
ESM4::Land::Land(const Land& Other)
{
mId = Other.mId;
mCell = Other.mCell;
for (int i = 0; i < VERTS_PER_SIDE * VERTS_PER_SIDE; i++)
{
mHeights[i] = Other.mHeights[i];
}
for (int i = 0; i < VERTS_PER_SIDE * VERTS_PER_SIDE * 3; i++)
{
mVertNorm[i] = Other.mVertNorm[i];
mVertColr[i] = Other.mVertColr[i];
}
mMinHeight = Other.mMinHeight;
mMaxHeight = Other.mMaxHeight;
}
std::span<const uint16_t> ESM4::Land::getTextures() const
{
static uint16_t textureArray[16 * 16] = {};
return textureArray;
}
// void ESM4::Land::save(ESM4::Writer& writer) const
//{
// }

@ -33,7 +33,9 @@
#include "formid.hpp"
#include <components/esm/defs.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/refid.hpp>
namespace ESM4
{
@ -111,7 +113,7 @@ namespace ESM4
std::vector<TxtLayer> layers;
};
FormId mFormId; // from the header
ESM::RefId mId; // from the header
std::uint32_t mFlags; // from the header, see enum type RecordFlag for details
std::uint32_t mLandFlags; // from DATA subrecord
@ -126,16 +128,19 @@ namespace ESM4
VHGT mHeightMap;
Texture mTextures[4]; // 0 = bottom left, 1 = bottom right, 2 = top left, 3 = top right
std::vector<FormId> mIds; // land texture (LTEX) formids
ESM::RefId mCell;
void load(Reader& reader);
Land() = default;
Land(const Land& Other);
// void save(Writer& writer) const;
// void blank();
static constexpr ESM::RecNameInts sRecordId = ESM::REC_LAND4;
std::span<const float> getHeights() const override { return mHeights; }
std::span<const VNML> getNormals() const override { return mVertNorm; }
std::span<const unsigned char> getColors() const override { return mVertColr; }
std::span<const uint16_t> getTextures() const override { return {}; }
std::span<const uint16_t> getTextures() const override;
float getSize() const override { return REAL_SIZE; }
float getMinHeight() const override { return mMinHeight; }
float getMaxHeight() const { return mMaxHeight; }

@ -262,7 +262,7 @@ namespace Terrain
auto chunkBorder = CellBorder::createBorderGeometry(center.x() - size / 2.f, center.y() - size / 2.f, size,
mStorage, mSceneManager, mNodeMask, mWorldspace, 5.f, { 1, 0, 0, 0 });
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pat = new SceneUtil::PositionAttitudeTransform;
pat->setPosition(-center * Constants::CellSizeInUnits);
pat->setPosition(-center * ESM::getCellSize(mWorldspace));
pat->addChild(chunkBorder);
return pat;
}

Loading…
Cancel
Save