mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-19 20:23:54 +00:00
Changes to land data access in tables, also update Land once per frame in scene view.
This commit is contained in:
parent
d030b595f8
commit
25d4a0370f
6 changed files with 143 additions and 57 deletions
|
@ -9,20 +9,32 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant LandMapLodColumn::get(const Record<Land>& record) const
|
QVariant LandMapLodColumn::get(const Record<Land>& record) const
|
||||||
|
{
|
||||||
|
const int Size = Land::LAND_GLOBAL_MAP_LOD_SIZE;
|
||||||
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_WNAM))
|
||||||
{
|
{
|
||||||
// Note: original data is signed
|
// Note: original data is signed
|
||||||
const char* rawData = reinterpret_cast<const char*>(&record.get().mWnam[0]);
|
const char* rawData = reinterpret_cast<const char*>(&land.mWnam[0]);
|
||||||
return QByteArray(rawData, Land::LAND_GLOBAL_MAP_LOD_SIZE);
|
return QByteArray(rawData, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return a blank array
|
||||||
|
return QByteArray(Size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LandMapLodColumn::set(Record<Land>& record, const QVariant& data)
|
void LandMapLodColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
Land copy = record.get();
|
|
||||||
QByteArray array = data.toByteArray();
|
QByteArray array = data.toByteArray();
|
||||||
const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
|
const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
|
||||||
|
|
||||||
assert (array.count() == Land::LAND_GLOBAL_MAP_LOD_SIZE);
|
assert (array.count() == Land::LAND_GLOBAL_MAP_LOD_SIZE);
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_WNAM);
|
||||||
|
|
||||||
for (int i = 0; i < array.count(); ++i)
|
for (int i = 0; i < array.count(); ++i)
|
||||||
{
|
{
|
||||||
copy.mWnam[i] = rawData[i];
|
copy.mWnam[i] = rawData[i];
|
||||||
|
@ -44,28 +56,34 @@ namespace CSMWorld
|
||||||
|
|
||||||
QVariant LandNormalsColumn::get(const Record<Land>& record) const
|
QVariant LandNormalsColumn::get(const Record<Land>& record) const
|
||||||
{
|
{
|
||||||
const Land::LandData* landData = record.get().getLandData();
|
const int Size = Land::LAND_NUM_VERTS * 3;
|
||||||
assert(landData);
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VNML))
|
||||||
|
{
|
||||||
// Note: original data is signed
|
// Note: original data is signed
|
||||||
const char* rawData = reinterpret_cast<const char*>(&landData->mNormals[0]);
|
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mNormals[0]);
|
||||||
return QByteArray(rawData, Land::LAND_NUM_VERTS * 3);
|
return QByteArray(rawData, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return a blank array
|
||||||
|
return QByteArray(Size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LandNormalsColumn::set(Record<Land>& record, const QVariant& data)
|
void LandNormalsColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
Land copy = record.get();
|
|
||||||
Land::LandData* landData = copy.getLandData();
|
|
||||||
assert (landData);
|
|
||||||
|
|
||||||
QByteArray array = data.toByteArray();
|
QByteArray array = data.toByteArray();
|
||||||
const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
|
const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
|
||||||
|
|
||||||
assert (array.count() == Land::LAND_NUM_VERTS * 3);
|
assert (array.count() == Land::LAND_NUM_VERTS * 3);
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VNML);
|
||||||
|
|
||||||
for (int i = 0; i < array.count(); ++i)
|
for (int i = 0; i < array.count(); ++i)
|
||||||
{
|
{
|
||||||
landData->mNormals[i] = rawData[i];
|
copy.getLandData()->mNormals[i] = rawData[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
record.setModified(copy);
|
record.setModified(copy);
|
||||||
|
@ -84,29 +102,34 @@ namespace CSMWorld
|
||||||
|
|
||||||
QVariant LandHeightsColumn::get(const Record<Land>& record) const
|
QVariant LandHeightsColumn::get(const Record<Land>& record) const
|
||||||
{
|
{
|
||||||
const Land::LandData* landData = record.get().getLandData();
|
const int Size = Land::LAND_NUM_VERTS * sizeof(float);
|
||||||
assert(landData);
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VHGT))
|
||||||
|
{
|
||||||
// Note: original data is float
|
// Note: original data is float
|
||||||
const char* rawData = reinterpret_cast<const char*>(&landData->mHeights[0]);
|
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mHeights[0]);
|
||||||
return QByteArray(rawData, Land::LAND_NUM_VERTS * sizeof(float));
|
return QByteArray(rawData, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QByteArray(Size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LandHeightsColumn::set(Record<Land>& record, const QVariant& data)
|
void LandHeightsColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
Land copy = record.get();
|
|
||||||
Land::LandData* landData = copy.getLandData();
|
|
||||||
assert (landData);
|
|
||||||
|
|
||||||
QByteArray array = data.toByteArray();
|
QByteArray array = data.toByteArray();
|
||||||
const float* rawData = reinterpret_cast<const float*>(array.data());
|
const float* rawData = reinterpret_cast<const float*>(array.data());
|
||||||
|
|
||||||
assert (array.count() == Land::LAND_NUM_VERTS * sizeof(float));
|
assert (array.count() == Land::LAND_NUM_VERTS * sizeof(float));
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VHGT);
|
||||||
|
|
||||||
int count = array.count() / sizeof(float);
|
int count = array.count() / sizeof(float);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
landData->mHeights[i] = rawData[i];
|
copy.getLandData()->mHeights[i] = rawData[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
record.setModified(copy);
|
record.setModified(copy);
|
||||||
|
@ -125,28 +148,33 @@ namespace CSMWorld
|
||||||
|
|
||||||
QVariant LandColoursColumn::get(const Record<Land>& record) const
|
QVariant LandColoursColumn::get(const Record<Land>& record) const
|
||||||
{
|
{
|
||||||
const Land::LandData* landData = record.get().getLandData();
|
const int Size = Land::LAND_NUM_VERTS * 3;
|
||||||
assert(landData);
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VCLR))
|
||||||
|
{
|
||||||
// Note: original data is unsigned char
|
// Note: original data is unsigned char
|
||||||
const char* rawData = reinterpret_cast<const char*>(&landData->mColours[0]);
|
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mColours[0]);
|
||||||
return QByteArray(rawData, Land::LAND_NUM_VERTS * 3);
|
return QByteArray(rawData, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QByteArray(Size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LandColoursColumn::set(Record<Land>& record, const QVariant& data)
|
void LandColoursColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
Land copy = record.get();
|
|
||||||
Land::LandData* landData = copy.getLandData();
|
|
||||||
assert (landData);
|
|
||||||
|
|
||||||
QByteArray array = data.toByteArray();
|
QByteArray array = data.toByteArray();
|
||||||
const unsigned char* rawData = reinterpret_cast<const unsigned char*>(array.data());
|
const unsigned char* rawData = reinterpret_cast<const unsigned char*>(array.data());
|
||||||
|
|
||||||
assert (array.count() == Land::LAND_NUM_VERTS * 3);
|
assert (array.count() == Land::LAND_NUM_VERTS * 3);
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VCLR);
|
||||||
|
|
||||||
for (int i = 0; i < array.count(); ++i)
|
for (int i = 0; i < array.count(); ++i)
|
||||||
{
|
{
|
||||||
landData->mColours[i] = rawData[i];
|
copy.getLandData()->mColours[i] = rawData[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
record.setModified(copy);
|
record.setModified(copy);
|
||||||
|
@ -165,29 +193,34 @@ namespace CSMWorld
|
||||||
|
|
||||||
QVariant LandTexturesColumn::get(const Record<Land>& record) const
|
QVariant LandTexturesColumn::get(const Record<Land>& record) const
|
||||||
{
|
{
|
||||||
const Land::LandData* landData = record.get().getLandData();
|
const int Size = Land::LAND_NUM_TEXTURES * sizeof(uint16_t);
|
||||||
assert(landData);
|
const Land& land = record.get();
|
||||||
|
|
||||||
|
if (land.isDataLoaded(Land::DATA_VTEX))
|
||||||
|
{
|
||||||
// Note: original data is uint16_t
|
// Note: original data is uint16_t
|
||||||
const char* rawData = reinterpret_cast<const char*>(&landData->mTextures[0]);
|
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mTextures[0]);
|
||||||
return QByteArray(rawData, Land::LAND_NUM_TEXTURES * sizeof(uint16_t));
|
return QByteArray(rawData, Size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return QByteArray(Size, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LandTexturesColumn::set(Record<Land>& record, const QVariant& data)
|
void LandTexturesColumn::set(Record<Land>& record, const QVariant& data)
|
||||||
{
|
{
|
||||||
Land copy = record.get();
|
|
||||||
Land::LandData* landData = copy.getLandData();
|
|
||||||
assert (landData);
|
|
||||||
|
|
||||||
QByteArray array = data.toByteArray();
|
QByteArray array = data.toByteArray();
|
||||||
const uint16_t* rawData = reinterpret_cast<const uint16_t*>(array.data());
|
const uint16_t* rawData = reinterpret_cast<const uint16_t*>(array.data());
|
||||||
|
|
||||||
assert (array.count() == Land::LAND_NUM_TEXTURES * sizeof(uint16_t));
|
assert (array.count() == Land::LAND_NUM_TEXTURES * sizeof(uint16_t));
|
||||||
|
|
||||||
|
Land copy = record.get();
|
||||||
|
copy.setDataLoaded(Land::DATA_VTEX);
|
||||||
|
|
||||||
int count = array.count() / sizeof(uint16_t);
|
int count = array.count() / sizeof(uint16_t);
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
landData->mTextures[i] = rawData[i];
|
copy.getLandData()->mTextures[i] = rawData[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
record.setModified(copy);
|
record.setModified(copy);
|
||||||
|
|
|
@ -356,6 +356,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
|
||||||
|
|
||||||
// Try a direct mapping to the current plugin first. Otherwise iterate until one is found.
|
// Try a direct mapping to the current plugin first. Otherwise iterate until one is found.
|
||||||
// Iteration is deterministic to avoid duplicates.
|
// Iteration is deterministic to avoid duplicates.
|
||||||
|
int startIndex = index;
|
||||||
do {
|
do {
|
||||||
std::string newId = LandTexture::createUniqueRecordId(0, index);
|
std::string newId = LandTexture::createUniqueRecordId(0, index);
|
||||||
int newRow = idCollection()->searchId(newId);
|
int newRow = idCollection()->searchId(newId);
|
||||||
|
@ -384,7 +385,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
|
||||||
size_t Prime = (1 << 13) - 1; // A mersenne prime
|
size_t Prime = (1 << 13) - 1; // A mersenne prime
|
||||||
|
|
||||||
index = (index + Prime) % MaxIndex;
|
index = (index + Prime) % MaxIndex;
|
||||||
} while (true);
|
} while (index != startIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|
|
@ -26,6 +26,33 @@
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
|
|
||||||
|
namespace CSVRender
|
||||||
|
{
|
||||||
|
class CellNodeContainer : public osg::Referenced
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CellNodeContainer(Cell* cell) : mCell(cell) {}
|
||||||
|
|
||||||
|
Cell* getCell(){ return mCell; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Cell* mCell;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CellNodeCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
CellNodeContainer* container = static_cast<CellNodeContainer*>(node->getUserData());
|
||||||
|
container->getCell()->updateLand();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
bool CSVRender::Cell::removeObject (const std::string& id)
|
bool CSVRender::Cell::removeObject (const std::string& id)
|
||||||
{
|
{
|
||||||
std::map<std::string, Object *>::iterator iter =
|
std::map<std::string, Object *>::iterator iter =
|
||||||
|
@ -77,6 +104,11 @@ bool CSVRender::Cell::addObjects (int start, int end)
|
||||||
|
|
||||||
void CSVRender::Cell::updateLand()
|
void CSVRender::Cell::updateLand()
|
||||||
{
|
{
|
||||||
|
if (!mUpdateLand || mLandDeleted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mUpdateLand = false;
|
||||||
|
|
||||||
// Cell is deleted
|
// Cell is deleted
|
||||||
if (mDeleted)
|
if (mDeleted)
|
||||||
{
|
{
|
||||||
|
@ -116,6 +148,7 @@ void CSVRender::Cell::updateLand()
|
||||||
}
|
}
|
||||||
|
|
||||||
// No land data
|
// No land data
|
||||||
|
mLandDeleted = true;
|
||||||
unloadLand();
|
unloadLand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +164,7 @@ void CSVRender::Cell::unloadLand()
|
||||||
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
||||||
bool deleted)
|
bool deleted)
|
||||||
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
||||||
mSubModeElementMask (0)
|
mSubModeElementMask (0), mUpdateLand(true), mLandDeleted(false)
|
||||||
{
|
{
|
||||||
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
|
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
|
||||||
|
|
||||||
|
@ -139,6 +172,8 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
|
||||||
mCoordinates = result.first;
|
mCoordinates = result.first;
|
||||||
|
|
||||||
mCellNode = new osg::Group;
|
mCellNode = new osg::Group;
|
||||||
|
mCellNode->setUserData(new CellNodeContainer(this));
|
||||||
|
mCellNode->setUpdateCallback(new CellNodeCallback);
|
||||||
rootNode->addChild(mCellNode);
|
rootNode->addChild(mCellNode);
|
||||||
|
|
||||||
setCellMarker();
|
setCellMarker();
|
||||||
|
@ -325,32 +360,34 @@ void CSVRender::Cell::pathgridRemoved()
|
||||||
|
|
||||||
void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
updateLand();
|
mUpdateLand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
updateLand();
|
mLandDeleted = true;
|
||||||
|
unloadLand();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end)
|
void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
updateLand();
|
mUpdateLand = true;
|
||||||
|
mLandDeleted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
{
|
{
|
||||||
updateLand();
|
mUpdateLand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
updateLand();
|
mUpdateLand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end)
|
void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end)
|
||||||
{
|
{
|
||||||
updateLand();
|
mUpdateLand = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::reloadAssets()
|
void CSVRender::Cell::reloadAssets()
|
||||||
|
|
|
@ -57,6 +57,7 @@ namespace CSVRender
|
||||||
bool mDeleted;
|
bool mDeleted;
|
||||||
int mSubMode;
|
int mSubMode;
|
||||||
unsigned int mSubModeElementMask;
|
unsigned int mSubModeElementMask;
|
||||||
|
bool mUpdateLand, mLandDeleted;
|
||||||
|
|
||||||
/// Ignored if cell does not have an object with the given ID.
|
/// Ignored if cell does not have an object with the given ID.
|
||||||
///
|
///
|
||||||
|
@ -160,6 +161,8 @@ namespace CSVRender
|
||||||
/// Erase all overrides and restore the visual representation of the cell to its
|
/// Erase all overrides and restore the visual representation of the cell to its
|
||||||
/// true state.
|
/// true state.
|
||||||
void reset (unsigned int elementMask);
|
void reset (unsigned int elementMask);
|
||||||
|
|
||||||
|
friend class CellNodeCallback;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,15 @@ namespace ESM
|
||||||
return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes);
|
return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Land::setDataLoaded(int flags)
|
||||||
|
{
|
||||||
|
if (!mLandData)
|
||||||
|
mLandData = new LandData;
|
||||||
|
|
||||||
|
mDataTypes |= flags;
|
||||||
|
mLandData->mDataLoaded |= flags;
|
||||||
|
}
|
||||||
|
|
||||||
Land::Land (const Land& land)
|
Land::Land (const Land& land)
|
||||||
: mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin),
|
: mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin),
|
||||||
mContext (land.mContext), mDataTypes (land.mDataTypes),
|
mContext (land.mContext), mDataTypes (land.mDataTypes),
|
||||||
|
|
|
@ -135,6 +135,9 @@ struct Land
|
||||||
/// @note We only check data types that *can* be loaded (present in mDataTypes)
|
/// @note We only check data types that *can* be loaded (present in mDataTypes)
|
||||||
bool isDataLoaded(int flags) const;
|
bool isDataLoaded(int flags) const;
|
||||||
|
|
||||||
|
/// Sets the flags and creates a LandData if needed
|
||||||
|
void setDataLoaded(int flags);
|
||||||
|
|
||||||
Land (const Land& land);
|
Land (const Land& land);
|
||||||
|
|
||||||
Land& operator= (Land land);
|
Land& operator= (Land land);
|
||||||
|
|
Loading…
Reference in a new issue