#ifndef OPENMW_ESM_LAND_H #define OPENMW_ESM_LAND_H #include #include #include #include #include "components/esm/defs.hpp" #include "components/esm/esmcommon.hpp" #include "landrecorddata.hpp" namespace ESM { class ESMReader; class ESMWriter; /* * Landscape data. */ struct Land { constexpr static RecNameInts sRecordId = REC_LAND; /// Return a string descriptor for this record type. Currently used for debugging / error logs only. static std::string_view getRecordType() { return "Land"; } Land() = default; Land(const Land& land); Land(Land&& other) = default; Land& operator=(const Land& land); Land& operator=(Land&& land) = default; // Only first four bits seem to be used, don't know what they mean. std::uint32_t mFlags = 0; // Map coordinates. std::int32_t mX = 0; std::int32_t mY = 0; // Plugin index, used to reference the correct material palette. int getPlugin() const { return mContext.index; } void setPlugin(int index) { mContext.index = index; } // File context. This allows the ESM reader to be 'reset' to this // location later when we are ready to load the full data set. // In the editor, there may not be a file associated with the Land, // in which case the filename will be empty. ESM_Context mContext; int mDataTypes = 0; enum { DATA_VNML = 1, DATA_VHGT = 2, DATA_WNAM = 4, DATA_VCLR = 8, DATA_VTEX = 16 }; // default height to use in case there is no Land record static constexpr int DEFAULT_HEIGHT = -2048; // number of vertices per side static constexpr int LAND_SIZE = LandRecordData::sLandSize; // cell terrain size in world coords static constexpr int REAL_SIZE = Constants::CellSizeInUnits; // total number of vertices static constexpr int LAND_NUM_VERTS = LandRecordData::sLandNumVerts; static constexpr int HEIGHT_SCALE = 8; // number of textures per side of land static constexpr int LAND_TEXTURE_SIZE = LandRecordData::sLandTextureSize; // 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 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) using LandData = ESM::LandRecordData; // low-LOD heightmap (used for rendering the global map) std::array mWnam; void load(ESMReader& esm, bool& isDeleted); void save(ESMWriter& esm, bool isDeleted = false) const; void blank(); void loadData(int flags) const; void loadData(int flags, LandData& data) const; /** * Frees memory allocated for mLandData */ void unloadData(); /// Check if given data type is loaded bool isDataLoaded(int flags) const; /// Return land data with at least the data types specified in \a flags loaded (if they /// are available). Will return a 0-pointer if there is no data for any of the /// specified types. 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(); } /// Return land data without loading first anything. Can return a 0-pointer. LandData* getLandData() { return mLandData.get(); } /// \attention Must not be called on objects that aren't fully loaded. /// /// \note Added data fields will be uninitialised void add(int flags); private: mutable std::unique_ptr mLandData; }; } #endif