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) 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); osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(cellIndex);
if (obj) if (obj)
return static_cast<ESMTerrain::LandObject*>(obj.get()); return static_cast<ESMTerrain::LandObject*>(obj.get());
@ -30,12 +28,25 @@ namespace MWRender
const auto world = MWBase::Environment::get().getWorld(); const auto world = MWBase::Environment::get().getWorld();
if (!world) if (!world)
return nullptr; return nullptr;
const ESM::Land* land = world->getStore().get<ESM::Land>().search(cellIndex.mX, cellIndex.mY);
if (!land) if (ESM::isEsm4Ext(cellIndex.mWorldspace))
return nullptr; {
osg::ref_ptr<ESMTerrain::LandObject> landObj(new ESMTerrain::LandObject(land, mLoadFlags)); const ESM4::Land* land = world->getStore().get<ESM4::Land>().search(cellIndex);
mCache->addEntryToObjectCache(cellIndex, landObj.get()); if (!land)
return landObj; 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/misc/algorithm.hpp>
#include <components/esm4/common.hpp> #include <components/esm4/common.hpp>
#include <components/esm4/loadland.hpp>
#include <components/esm4/loadwrld.hpp> #include <components/esm4/loadwrld.hpp>
#include <components/esm4/reader.hpp> #include <components/esm4/reader.hpp>
#include <components/esm4/readerutils.hpp> #include <components/esm4/readerutils.hpp>
@ -385,6 +386,7 @@ namespace MWWorld
{ {
auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); }; auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); };
ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {}); ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {});
getWritable<ESM4::Land>().updateLandPositions(get<ESM4::Cell>());
} }
void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type) void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type)

@ -43,6 +43,7 @@ namespace ESM4
struct MiscItem; struct MiscItem;
struct Weapon; struct Weapon;
struct World; struct World;
struct Land;
} }
namespace ESM 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::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::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::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: private:
template <typename T> template <typename T>

@ -8,11 +8,14 @@
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include <components/esm3/esmreader.hpp> #include <components/esm3/esmreader.hpp>
#include <components/esm3/esmwriter.hpp> #include <components/esm3/esmwriter.hpp>
#include <components/esm4/loadland.hpp>
#include <components/esm4/loadwrld.hpp> #include <components/esm4/loadwrld.hpp>
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/rng.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 namespace
{ {
@ -1189,6 +1192,29 @@ namespace MWWorld
MWWorld::TypedDynamicStore<ESM4::Cell>::clearDynamic(); 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 // 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::Cell>;
template class MWWorld::TypedDynamicStore<ESM4::Weapon>; template class MWWorld::TypedDynamicStore<ESM4::Weapon>;
template class MWWorld::TypedDynamicStore<ESM4::World>; template class MWWorld::TypedDynamicStore<ESM4::World>;
template class MWWorld::TypedDynamicStore<ESM4::Land>;

@ -35,6 +35,11 @@ namespace ESM
class ESMWriter; class ESMWriter;
} }
namespace ESM4
{
struct Land;
}
namespace Loading namespace Loading
{ {
class Listener; class Listener;
@ -298,6 +303,17 @@ namespace MWWorld
void clearDynamic() override; 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 <> template <>
class Store<ESM::Land> : public DynamicStore class Store<ESM::Land> : public DynamicStore
{ {

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

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

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

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

@ -54,11 +54,12 @@
// //
void ESM4::Land::load(ESM4::Reader& reader) void ESM4::Land::load(ESM4::Reader& reader)
{ {
mFormId = reader.hdr().record.getFormId(); ESM::FormId formId = reader.hdr().record.getFormId();
reader.adjustFormId(mFormId); reader.adjustFormId(formId);
mId = ESM::RefId::formIdRefId(formId);
mFlags = reader.hdr().record.flags; mFlags = reader.hdr().record.flags;
mDataTypes = 0; mDataTypes = 0;
mCell = ESM::RefId::formIdRefId(reader.currCell());
TxtLayer layer; TxtLayer layer;
std::int8_t currentAddQuad = -1; // for VTXT following ATXT 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 // void ESM4::Land::save(ESM4::Writer& writer) const
//{ //{
// } // }

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

Loading…
Cancel
Save