mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 17:45:34 +00:00
Use more decomposition, string_view, and implicit sizes in ESM code
This commit is contained in:
parent
e2787c0e7b
commit
2ab5678aab
12 changed files with 124 additions and 142 deletions
|
@ -897,9 +897,6 @@ namespace EsmTool
|
|||
if (const ESM::Land::LandData* data = mData.getLandData(mData.mDataTypes))
|
||||
{
|
||||
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
||||
// Lots of missing members.
|
||||
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << static_cast<unsigned>(data->mUnk2) << std::endl;
|
||||
}
|
||||
mData.unloadData();
|
||||
std::cout << " Deleted: " << mIsDeleted << std::endl;
|
||||
|
|
|
@ -232,7 +232,7 @@ namespace ESSImport
|
|||
esm.skip(4);
|
||||
}
|
||||
|
||||
esm.getExact(nam8, 32);
|
||||
esm.getT(nam8);
|
||||
|
||||
newcell.mFogOfWar.reserve(16 * 16);
|
||||
for (int x = 0; x < 16; ++x)
|
||||
|
|
|
@ -1,10 +1,30 @@
|
|||
#include "importcellref.hpp"
|
||||
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/misc/concepts.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
template <Misc::SameAsWithoutCvref<ACDT> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
f(v.mUnknown, v.mFlags, v.mBreathMeter, v.mUnknown2, v.mDynamic, v.mUnknown3, v.mAttributes, v.mMagicEffects,
|
||||
v.mUnknown4, v.mGoldPool, v.mCountDown, v.mUnknown5);
|
||||
}
|
||||
|
||||
template <Misc::SameAsWithoutCvref<ACSC> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
f(v.mUnknown1, v.mFlags, v.mUnknown2, v.mCorpseClearCountdown, v.mUnknown3);
|
||||
}
|
||||
|
||||
template <Misc::SameAsWithoutCvref<ANIS> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
f(v.mGroupIndex, v.mUnknown, v.mTime);
|
||||
}
|
||||
|
||||
void CellRef::load(ESM::ESMReader& esm)
|
||||
{
|
||||
|
@ -45,14 +65,9 @@ namespace ESSImport
|
|||
bool isDeleted = false;
|
||||
ESM::CellRef::loadData(esm, isDeleted);
|
||||
|
||||
mActorData.mHasACDT
|
||||
= esm.getHNOT("ACDT", mActorData.mACDT.mUnknown, mActorData.mACDT.mFlags, mActorData.mACDT.mBreathMeter,
|
||||
mActorData.mACDT.mUnknown2, mActorData.mACDT.mDynamic, mActorData.mACDT.mUnknown3,
|
||||
mActorData.mACDT.mAttributes, mActorData.mACDT.mMagicEffects, mActorData.mACDT.mUnknown4,
|
||||
mActorData.mACDT.mGoldPool, mActorData.mACDT.mCountDown, mActorData.mACDT.mUnknown5);
|
||||
mActorData.mHasACDT = esm.getOptionalComposite("ACDT", mActorData.mACDT);
|
||||
|
||||
mActorData.mHasACSC = esm.getHNOT("ACSC", mActorData.mACSC.mUnknown1, mActorData.mACSC.mFlags,
|
||||
mActorData.mACSC.mUnknown2, mActorData.mACSC.mCorpseClearCountdown, mActorData.mACSC.mUnknown3);
|
||||
mActorData.mHasACSC = esm.getOptionalComposite("ACSC", mActorData.mACSC);
|
||||
|
||||
if (esm.isNextSub("ACSL"))
|
||||
esm.skipHSubSize(112);
|
||||
|
@ -127,8 +142,7 @@ namespace ESSImport
|
|||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
|
||||
mActorData.mHasANIS
|
||||
= esm.getHNOT("ANIS", mActorData.mANIS.mGroupIndex, mActorData.mANIS.mUnknown, mActorData.mANIS.mTime);
|
||||
mActorData.mHasANIS = esm.getOptionalComposite("ANIS", mActorData.mANIS);
|
||||
|
||||
if (esm.isNextSub("LVCR"))
|
||||
{
|
||||
|
@ -146,7 +160,7 @@ namespace ESSImport
|
|||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||
// alarmvoi0000.ess
|
||||
for (int i = 0; i < 2; ++i)
|
||||
esm.getHNOT("DATA", mPos.pos, mPos.rot);
|
||||
esm.getOptionalComposite("DATA", mPos);
|
||||
|
||||
mDeleted = 0;
|
||||
if (esm.isNextSub("DELE"))
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace ESSImport
|
|||
sub.mFileOffset = esm.getFileOffset();
|
||||
sub.mName = esm.retSubName().toString();
|
||||
sub.mData.resize(esm.getSubSize());
|
||||
esm.getExact(&sub.mData[0], sub.mData.size());
|
||||
esm.getExact(sub.mData.data(), sub.mData.size());
|
||||
rec.mSubrecords.push_back(sub);
|
||||
}
|
||||
file.mRecords.push_back(rec);
|
||||
|
|
|
@ -38,7 +38,7 @@ std::string ESM::loadLuaBinaryData(ESMReader& esm)
|
|||
{
|
||||
esm.getSubHeader();
|
||||
data.resize(esm.getSubSize());
|
||||
esm.getExact(data.data(), static_cast<int>(data.size()));
|
||||
esm.getExact(data.data(), data.size());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ namespace ESM
|
|||
{
|
||||
if (isNextSub(name))
|
||||
return getHString();
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
ESM::RefId ESMReader::getHNORefId(NAME name)
|
||||
|
@ -244,21 +244,6 @@ namespace ESM
|
|||
skipHString();
|
||||
}
|
||||
|
||||
void ESMReader::getHExact(void* p, std::size_t size)
|
||||
{
|
||||
getSubHeader();
|
||||
if (size != mCtx.leftSub)
|
||||
reportSubSizeMismatch(size, mCtx.leftSub);
|
||||
getExact(p, size);
|
||||
}
|
||||
|
||||
// Read the given number of bytes from a named subrecord
|
||||
void ESMReader::getHNExact(void* p, std::size_t size, NAME name)
|
||||
{
|
||||
getSubNameIs(name);
|
||||
getHExact(p, size);
|
||||
}
|
||||
|
||||
FormId ESMReader::getFormId(bool wide, NAME tag)
|
||||
{
|
||||
FormId res;
|
||||
|
@ -316,7 +301,7 @@ namespace ESM
|
|||
|
||||
// reading the subrecord data anyway.
|
||||
const std::size_t subNameSize = decltype(mCtx.subName)::sCapacity;
|
||||
getExact(mCtx.subName.mData, static_cast<int>(subNameSize));
|
||||
getExact(mCtx.subName.mData, subNameSize);
|
||||
mCtx.leftRec -= static_cast<std::uint32_t>(subNameSize);
|
||||
}
|
||||
|
||||
|
@ -506,7 +491,7 @@ namespace ESM
|
|||
case RefIdType::Generated:
|
||||
{
|
||||
std::uint64_t generated{};
|
||||
getExact(&generated, sizeof(std::uint64_t));
|
||||
getT(generated);
|
||||
return RefId::generated(generated);
|
||||
}
|
||||
case RefIdType::Index:
|
||||
|
@ -514,14 +499,14 @@ namespace ESM
|
|||
RecNameInts recordType{};
|
||||
getExact(&recordType, sizeof(std::uint32_t));
|
||||
std::uint32_t index{};
|
||||
getExact(&index, sizeof(std::uint32_t));
|
||||
getT(index);
|
||||
return RefId::index(recordType, index);
|
||||
}
|
||||
case RefIdType::ESM3ExteriorCell:
|
||||
{
|
||||
int32_t x, y;
|
||||
getExact(&x, sizeof(std::int32_t));
|
||||
getExact(&y, sizeof(std::int32_t));
|
||||
getT(x);
|
||||
getT(y);
|
||||
return RefId::esm3ExteriorCell(x, y);
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +514,7 @@ namespace ESM
|
|||
fail("Unsupported RefIdType: " + std::to_string(static_cast<unsigned>(refIdType)));
|
||||
}
|
||||
|
||||
[[noreturn]] void ESMReader::fail(const std::string& msg)
|
||||
[[noreturn]] void ESMReader::fail(std::string_view msg)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
|
|
|
@ -237,12 +237,6 @@ namespace ESM
|
|||
|
||||
void skipHRefId();
|
||||
|
||||
// Read the given number of bytes from a subrecord
|
||||
void getHExact(void* p, std::size_t size);
|
||||
|
||||
// Read the given number of bytes from a named subrecord
|
||||
void getHNExact(void* p, std::size_t size, NAME name);
|
||||
|
||||
ESM::FormId getFormId(bool wide = false, NAME tag = "FRMR");
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -354,7 +348,7 @@ namespace ESM
|
|||
}
|
||||
|
||||
/// Used for error handling
|
||||
[[noreturn]] void fail(const std::string& msg);
|
||||
[[noreturn]] void fail(std::string_view msg);
|
||||
|
||||
/// Sets font encoder for ESM strings
|
||||
void setEncoder(ToUTF8::Utf8Encoder* encoder) { mEncoder = encoder; }
|
||||
|
|
|
@ -97,14 +97,14 @@ namespace ESM
|
|||
mHeader.mData.type = type;
|
||||
}
|
||||
|
||||
void ESMWriter::setAuthor(const std::string& auth)
|
||||
void ESMWriter::setAuthor(std::string_view auth)
|
||||
{
|
||||
mHeader.mData.author.assign(auth);
|
||||
mHeader.mData.author = auth;
|
||||
}
|
||||
|
||||
void ESMWriter::setDescription(const std::string& desc)
|
||||
void ESMWriter::setDescription(std::string_view desc)
|
||||
{
|
||||
mHeader.mData.desc.assign(desc);
|
||||
mHeader.mData.desc = desc;
|
||||
}
|
||||
|
||||
void ESMWriter::setRecordCount(int count)
|
||||
|
@ -122,7 +122,7 @@ namespace ESM
|
|||
mHeader.mMaster.clear();
|
||||
}
|
||||
|
||||
void ESMWriter::addMaster(const std::string& name, uint64_t size)
|
||||
void ESMWriter::addMaster(std::string_view name, uint64_t size)
|
||||
{
|
||||
Header::MasterData d;
|
||||
d.name = name;
|
||||
|
@ -208,14 +208,14 @@ namespace ESM
|
|||
endRecord(NAME(name));
|
||||
}
|
||||
|
||||
void ESMWriter::writeHNString(NAME name, const std::string& data)
|
||||
void ESMWriter::writeHNString(NAME name, std::string_view data)
|
||||
{
|
||||
startSubRecord(name);
|
||||
writeHString(data);
|
||||
endRecord(name);
|
||||
}
|
||||
|
||||
void ESMWriter::writeHNString(NAME name, const std::string& data, size_t size)
|
||||
void ESMWriter::writeHNString(NAME name, std::string_view data, size_t size)
|
||||
{
|
||||
assert(data.size() <= size);
|
||||
startSubRecord(name);
|
||||
|
@ -278,9 +278,9 @@ namespace ESM
|
|||
write(string.c_str(), string.size());
|
||||
}
|
||||
|
||||
void ESMWriter::writeHString(const std::string& data)
|
||||
void ESMWriter::writeHString(std::string_view data)
|
||||
{
|
||||
if (data.size() == 0)
|
||||
if (data.empty())
|
||||
write("\0", 1);
|
||||
else
|
||||
{
|
||||
|
@ -291,7 +291,7 @@ namespace ESM
|
|||
}
|
||||
}
|
||||
|
||||
void ESMWriter::writeHCString(const std::string& data)
|
||||
void ESMWriter::writeHCString(std::string_view data)
|
||||
{
|
||||
writeHString(data);
|
||||
if (data.size() > 0 && data[data.size() - 1] != '\0')
|
||||
|
|
|
@ -38,8 +38,8 @@ namespace ESM
|
|||
void setVersion(unsigned int ver = 0x3fa66666);
|
||||
void setType(int type);
|
||||
void setEncoder(ToUTF8::Utf8Encoder* encoding);
|
||||
void setAuthor(const std::string& author);
|
||||
void setDescription(const std::string& desc);
|
||||
void setAuthor(std::string_view author);
|
||||
void setDescription(std::string_view desc);
|
||||
void setHeader(const Header& value) { mHeader = value; }
|
||||
|
||||
// Set the record count for writing it in the file header
|
||||
|
@ -54,7 +54,7 @@ namespace ESM
|
|||
|
||||
void clearMaster();
|
||||
|
||||
void addMaster(const std::string& name, uint64_t size);
|
||||
void addMaster(std::string_view name, uint64_t size);
|
||||
|
||||
void save(std::ostream& file);
|
||||
///< Start saving a file by writing the TES3 header.
|
||||
|
@ -62,20 +62,20 @@ namespace ESM
|
|||
void close();
|
||||
///< \note Does not close the stream.
|
||||
|
||||
void writeHNString(NAME name, const std::string& data);
|
||||
void writeHNString(NAME name, const std::string& data, size_t size);
|
||||
void writeHNCString(NAME name, const std::string& data)
|
||||
void writeHNString(NAME name, std::string_view data);
|
||||
void writeHNString(NAME name, std::string_view data, size_t size);
|
||||
void writeHNCString(NAME name, std::string_view data)
|
||||
{
|
||||
startSubRecord(name);
|
||||
writeHCString(data);
|
||||
endRecord(name);
|
||||
}
|
||||
void writeHNOString(NAME name, const std::string& data)
|
||||
void writeHNOString(NAME name, std::string_view data)
|
||||
{
|
||||
if (!data.empty())
|
||||
writeHNString(name, data);
|
||||
}
|
||||
void writeHNOCString(NAME name, const std::string& data)
|
||||
void writeHNOCString(NAME name, std::string_view data)
|
||||
{
|
||||
if (!data.empty())
|
||||
writeHNCString(name, data);
|
||||
|
@ -140,6 +140,7 @@ namespace ESM
|
|||
// state being discarded without any error on writing or reading it. :(
|
||||
// writeHNString and friends must be used instead.
|
||||
void writeHNT(NAME name, const std::string& data) = delete;
|
||||
void writeHNT(NAME name, std::string_view data) = delete;
|
||||
|
||||
void writeT(NAME data) = delete;
|
||||
|
||||
|
@ -181,8 +182,8 @@ namespace ESM
|
|||
void endRecord(NAME name);
|
||||
void endRecord(uint32_t name);
|
||||
void writeMaybeFixedSizeString(const std::string& data, std::size_t size);
|
||||
void writeHString(const std::string& data);
|
||||
void writeHCString(const std::string& data);
|
||||
void writeHString(std::string_view data);
|
||||
void writeHCString(std::string_view data);
|
||||
|
||||
void writeMaybeFixedSizeRefId(RefId value, std::size_t size);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef OPENMW_COMPONENTS_ESM3_LANDRECORDDATA_H
|
||||
#define OPENMW_COMPONENTS_ESM3_LANDRECORDDATA_H
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
namespace ESM
|
||||
|
@ -22,24 +23,20 @@ namespace ESM
|
|||
// Initial reference height for the first vertex, only needed for filling mHeights
|
||||
float mHeightOffset = 0;
|
||||
// Height in world space for each vertex
|
||||
float mHeights[sLandNumVerts];
|
||||
std::array<float, sLandNumVerts> mHeights;
|
||||
float mMinHeight = 0;
|
||||
float mMaxHeight = 0;
|
||||
|
||||
// 24-bit normals, these aren't always correct though. Edge and corner normals may be garbage.
|
||||
std::int8_t mNormals[sLandNumVerts * 3];
|
||||
std::array<std::int8_t, 3 * sLandNumVerts> mNormals;
|
||||
|
||||
// 2D array of texture indices. An index can be used to look up an LandTexture,
|
||||
// but to do so you must subtract 1 from the index first!
|
||||
// An index of 0 indicates the default texture.
|
||||
std::uint16_t mTextures[sLandNumTextures];
|
||||
std::array<std::uint16_t, sLandNumTextures> mTextures;
|
||||
|
||||
// 24-bit RGB color for each vertex
|
||||
std::uint8_t mColours[3 * sLandNumVerts];
|
||||
|
||||
// ???
|
||||
std::uint16_t mUnk1 = 0;
|
||||
std::uint8_t mUnk2 = 0;
|
||||
std::array<std::uint8_t, 3 * sLandNumVerts> mColours;
|
||||
|
||||
int mDataLoaded = 0;
|
||||
};
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "components/esm/defs.hpp"
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/misc/concepts.hpp>
|
||||
|
||||
#include "esmreader.hpp"
|
||||
#include "esmwriter.hpp"
|
||||
|
||||
|
@ -13,27 +15,43 @@ namespace ESM
|
|||
{
|
||||
namespace
|
||||
{
|
||||
struct VHGT
|
||||
{
|
||||
float mHeightOffset;
|
||||
std::int8_t mHeightData[LandRecordData::sLandNumVerts];
|
||||
};
|
||||
|
||||
template <Misc::SameAsWithoutCvref<VHGT> T>
|
||||
void decompose(T&& v, const auto& f)
|
||||
{
|
||||
char padding[3] = { 0, 0, 0 };
|
||||
f(v.mHeightOffset, v.mHeightData, padding);
|
||||
}
|
||||
|
||||
void transposeTextureData(const std::uint16_t* in, std::uint16_t* out)
|
||||
{
|
||||
int readPos = 0; // bit ugly, but it works
|
||||
for (int y1 = 0; y1 < 4; y1++)
|
||||
for (int x1 = 0; x1 < 4; x1++)
|
||||
for (int y2 = 0; y2 < 4; y2++)
|
||||
for (int x2 = 0; x2 < 4; x2++)
|
||||
size_t readPos = 0; // bit ugly, but it works
|
||||
for (size_t y1 = 0; y1 < 4; y1++)
|
||||
for (size_t x1 = 0; x1 < 4; x1++)
|
||||
for (size_t y2 = 0; y2 < 4; y2++)
|
||||
for (size_t x2 = 0; x2 < 4; x2++)
|
||||
out[(y1 * 4 + y2) * 16 + (x1 * 4 + x2)] = in[readPos++];
|
||||
}
|
||||
|
||||
// Loads data and marks it as loaded. Return true if data is actually loaded from reader, false otherwise
|
||||
// including the case when data is already loaded.
|
||||
bool condLoad(ESMReader& reader, int flags, int& targetFlags, int dataFlag, void* ptr, std::size_t size)
|
||||
bool condLoad(ESMReader& reader, int flags, int& targetFlags, int dataFlag, auto& in)
|
||||
{
|
||||
if ((targetFlags & dataFlag) == 0 && (flags & dataFlag) != 0)
|
||||
{
|
||||
reader.getHExact(ptr, size);
|
||||
if constexpr (std::is_same_v<std::remove_cvref_t<decltype(in)>, VHGT>)
|
||||
reader.getSubComposite(in);
|
||||
else
|
||||
reader.getHT(in);
|
||||
targetFlags |= dataFlag;
|
||||
return true;
|
||||
}
|
||||
reader.skipHSubSize(size);
|
||||
reader.skipHSub();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -50,11 +68,7 @@ namespace ESM
|
|||
switch (esm.retSubName().toInt())
|
||||
{
|
||||
case fourCC("INTV"):
|
||||
esm.getSubHeader();
|
||||
if (esm.getSubSize() != 8)
|
||||
esm.fail("Subrecord size is not equal to 8");
|
||||
esm.getT(mX);
|
||||
esm.getT(mY);
|
||||
esm.getHT(mX, mY);
|
||||
hasLocation = true;
|
||||
break;
|
||||
case fourCC("DATA"):
|
||||
|
@ -94,7 +108,7 @@ namespace ESM
|
|||
mDataTypes |= DATA_VHGT;
|
||||
break;
|
||||
case fourCC("WNAM"):
|
||||
esm.getHExact(mWnam.data(), mWnam.size());
|
||||
esm.getHT(mWnam);
|
||||
mDataTypes |= DATA_WNAM;
|
||||
break;
|
||||
case fourCC("VCLR"):
|
||||
|
@ -137,12 +151,10 @@ namespace ESM
|
|||
{
|
||||
VHGT offsets;
|
||||
offsets.mHeightOffset = mLandData->mHeights[0] / HEIGHT_SCALE;
|
||||
offsets.mUnk1 = mLandData->mUnk1;
|
||||
offsets.mUnk2 = mLandData->mUnk2;
|
||||
|
||||
float prevY = mLandData->mHeights[0];
|
||||
int number = 0; // avoid multiplication
|
||||
for (int i = 0; i < LAND_SIZE; ++i)
|
||||
size_t number = 0; // avoid multiplication
|
||||
for (unsigned i = 0; i < LandRecordData::sLandSize; ++i)
|
||||
{
|
||||
float diff = (mLandData->mHeights[number] - prevY) / HEIGHT_SCALE;
|
||||
offsets.mHeightData[number]
|
||||
|
@ -151,7 +163,7 @@ namespace ESM
|
|||
float prevX = prevY = mLandData->mHeights[number];
|
||||
++number;
|
||||
|
||||
for (int j = 1; j < LAND_SIZE; ++j)
|
||||
for (unsigned j = 1; j < LandRecordData::sLandSize; ++j)
|
||||
{
|
||||
diff = (mLandData->mHeights[number] - prevX) / HEIGHT_SCALE;
|
||||
offsets.mHeightData[number]
|
||||
|
@ -161,7 +173,7 @@ namespace ESM
|
|||
++number;
|
||||
}
|
||||
}
|
||||
esm.writeHNT("VHGT", offsets, sizeof(VHGT));
|
||||
esm.writeNamedComposite("VHGT", offsets);
|
||||
}
|
||||
if (mDataTypes & Land::DATA_WNAM)
|
||||
{
|
||||
|
@ -169,13 +181,15 @@ namespace ESM
|
|||
std::int8_t wnam[LAND_GLOBAL_MAP_LOD_SIZE];
|
||||
constexpr float max = std::numeric_limits<std::int8_t>::max();
|
||||
constexpr float min = std::numeric_limits<std::int8_t>::min();
|
||||
constexpr float vertMult = static_cast<float>(Land::LAND_SIZE - 1) / LAND_GLOBAL_MAP_LOD_SIZE_SQRT;
|
||||
for (int row = 0; row < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++row)
|
||||
constexpr float vertMult
|
||||
= static_cast<float>(LandRecordData::sLandSize - 1) / LAND_GLOBAL_MAP_LOD_SIZE_SQRT;
|
||||
for (unsigned row = 0; row < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++row)
|
||||
{
|
||||
for (int col = 0; col < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++col)
|
||||
for (unsigned col = 0; col < LAND_GLOBAL_MAP_LOD_SIZE_SQRT; ++col)
|
||||
{
|
||||
float height = mLandData->mHeights[static_cast<int>(row * vertMult) * Land::LAND_SIZE
|
||||
+ static_cast<int>(col * vertMult)];
|
||||
float height
|
||||
= mLandData->mHeights[static_cast<size_t>(row * vertMult) * LandRecordData::sLandSize
|
||||
+ static_cast<size_t>(col * vertMult)];
|
||||
height /= height > 0 ? 128.f : 16.f;
|
||||
height = std::clamp(height, min, max);
|
||||
wnam[row * LAND_GLOBAL_MAP_LOD_SIZE_SQRT + col] = static_cast<std::int8_t>(height);
|
||||
|
@ -189,8 +203,8 @@ namespace ESM
|
|||
}
|
||||
if (mDataTypes & Land::DATA_VTEX)
|
||||
{
|
||||
uint16_t vtex[LAND_NUM_TEXTURES];
|
||||
transposeTextureData(mLandData->mTextures, vtex);
|
||||
uint16_t vtex[LandRecordData::sLandNumTextures];
|
||||
transposeTextureData(mLandData->mTextures.data(), vtex);
|
||||
esm.writeHNT("VTEX", vtex);
|
||||
}
|
||||
}
|
||||
|
@ -200,25 +214,23 @@ namespace ESM
|
|||
{
|
||||
setPlugin(0);
|
||||
|
||||
std::fill(std::begin(mWnam), std::end(mWnam), 0);
|
||||
mWnam.fill(0);
|
||||
|
||||
if (mLandData == nullptr)
|
||||
mLandData = std::make_unique<LandData>();
|
||||
|
||||
mLandData->mHeightOffset = 0;
|
||||
std::fill(std::begin(mLandData->mHeights), std::end(mLandData->mHeights), 0.0f);
|
||||
mLandData->mHeights.fill(0);
|
||||
mLandData->mMinHeight = 0;
|
||||
mLandData->mMaxHeight = 0;
|
||||
for (int i = 0; i < LAND_NUM_VERTS; ++i)
|
||||
for (size_t i = 0; i < LandRecordData::sLandNumVerts; ++i)
|
||||
{
|
||||
mLandData->mNormals[i * 3 + 0] = 0;
|
||||
mLandData->mNormals[i * 3 + 1] = 0;
|
||||
mLandData->mNormals[i * 3 + 2] = 127;
|
||||
}
|
||||
std::fill(std::begin(mLandData->mTextures), std::end(mLandData->mTextures), 0);
|
||||
std::fill(std::begin(mLandData->mColours), std::end(mLandData->mColours), 255);
|
||||
mLandData->mUnk1 = 0;
|
||||
mLandData->mUnk2 = 0;
|
||||
mLandData->mTextures.fill(0);
|
||||
mLandData->mColours.fill(255);
|
||||
mLandData->mDataLoaded
|
||||
= Land::DATA_VNML | Land::DATA_VHGT | Land::DATA_WNAM | Land::DATA_VCLR | Land::DATA_VTEX;
|
||||
mDataTypes = mLandData->mDataLoaded;
|
||||
|
@ -259,32 +271,32 @@ namespace ESM
|
|||
|
||||
if (reader.isNextSub("VNML"))
|
||||
{
|
||||
condLoad(reader, flags, data.mDataLoaded, DATA_VNML, data.mNormals, sizeof(data.mNormals));
|
||||
condLoad(reader, flags, data.mDataLoaded, DATA_VNML, data.mNormals);
|
||||
}
|
||||
|
||||
if (reader.isNextSub("VHGT"))
|
||||
{
|
||||
VHGT vhgt;
|
||||
if (condLoad(reader, flags, data.mDataLoaded, DATA_VHGT, &vhgt, sizeof(vhgt)))
|
||||
if (condLoad(reader, flags, data.mDataLoaded, DATA_VHGT, vhgt))
|
||||
{
|
||||
data.mMinHeight = std::numeric_limits<float>::max();
|
||||
data.mMaxHeight = -std::numeric_limits<float>::max();
|
||||
float rowOffset = vhgt.mHeightOffset;
|
||||
for (int y = 0; y < LAND_SIZE; y++)
|
||||
for (unsigned y = 0; y < LandRecordData::sLandSize; y++)
|
||||
{
|
||||
rowOffset += vhgt.mHeightData[y * LAND_SIZE];
|
||||
rowOffset += vhgt.mHeightData[y * LandRecordData::sLandSize];
|
||||
|
||||
data.mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE;
|
||||
data.mHeights[y * LandRecordData::sLandSize] = rowOffset * HEIGHT_SCALE;
|
||||
if (rowOffset * HEIGHT_SCALE > data.mMaxHeight)
|
||||
data.mMaxHeight = rowOffset * HEIGHT_SCALE;
|
||||
if (rowOffset * HEIGHT_SCALE < data.mMinHeight)
|
||||
data.mMinHeight = rowOffset * HEIGHT_SCALE;
|
||||
|
||||
float colOffset = rowOffset;
|
||||
for (int x = 1; x < LAND_SIZE; x++)
|
||||
for (unsigned x = 1; x < LandRecordData::sLandSize; x++)
|
||||
{
|
||||
colOffset += vhgt.mHeightData[y * LAND_SIZE + x];
|
||||
data.mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE;
|
||||
colOffset += vhgt.mHeightData[y * LandRecordData::sLandSize + x];
|
||||
data.mHeights[x + y * LandRecordData::sLandSize] = colOffset * HEIGHT_SCALE;
|
||||
|
||||
if (colOffset * HEIGHT_SCALE > data.mMaxHeight)
|
||||
data.mMaxHeight = colOffset * HEIGHT_SCALE;
|
||||
|
@ -292,8 +304,6 @@ namespace ESM
|
|||
data.mMinHeight = colOffset * HEIGHT_SCALE;
|
||||
}
|
||||
}
|
||||
data.mUnk1 = vhgt.mUnk1;
|
||||
data.mUnk2 = vhgt.mUnk2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,13 +311,13 @@ namespace ESM
|
|||
reader.skipHSub();
|
||||
|
||||
if (reader.isNextSub("VCLR"))
|
||||
condLoad(reader, flags, data.mDataLoaded, DATA_VCLR, data.mColours, 3 * LAND_NUM_VERTS);
|
||||
condLoad(reader, flags, data.mDataLoaded, DATA_VCLR, data.mColours);
|
||||
if (reader.isNextSub("VTEX"))
|
||||
{
|
||||
uint16_t vtex[LAND_NUM_TEXTURES];
|
||||
if (condLoad(reader, flags, data.mDataLoaded, DATA_VTEX, vtex, sizeof(vtex)))
|
||||
uint16_t vtex[LandRecordData::sLandNumTextures];
|
||||
if (condLoad(reader, flags, data.mDataLoaded, DATA_VTEX, vtex))
|
||||
{
|
||||
transposeTextureData(vtex, data.mTextures);
|
||||
transposeTextureData(vtex, data.mTextures.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,19 +86,9 @@ namespace ESM
|
|||
// total number of textures per land
|
||||
static constexpr int LAND_NUM_TEXTURES = LandRecordData::sLandNumTextures;
|
||||
|
||||
static constexpr int LAND_GLOBAL_MAP_LOD_SIZE = 81;
|
||||
static constexpr unsigned LAND_GLOBAL_MAP_LOD_SIZE = 81;
|
||||
|
||||
static constexpr int LAND_GLOBAL_MAP_LOD_SIZE_SQRT = 9;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct VHGT
|
||||
{
|
||||
float mHeightOffset;
|
||||
std::int8_t mHeightData[LAND_NUM_VERTS];
|
||||
std::uint16_t mUnk1;
|
||||
std::uint8_t mUnk2;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static constexpr unsigned LAND_GLOBAL_MAP_LOD_SIZE_SQRT = 9;
|
||||
|
||||
using LandData = ESM::LandRecordData;
|
||||
|
||||
|
@ -128,16 +118,10 @@ namespace ESM
|
|||
const LandData* getLandData(int flags) const;
|
||||
|
||||
/// Return land data without loading first anything. Can return a 0-pointer.
|
||||
const LandData* getLandData() const
|
||||
{
|
||||
return mLandData.get();
|
||||
}
|
||||
const LandData* getLandData() const { return mLandData.get(); }
|
||||
|
||||
/// Return land data without loading first anything. Can return a 0-pointer.
|
||||
LandData* getLandData()
|
||||
{
|
||||
return mLandData.get();
|
||||
}
|
||||
LandData* getLandData() { return mLandData.get(); }
|
||||
|
||||
/// \attention Must not be called on objects that aren't fully loaded.
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue