Add dummy BGSM/BGEM file reader

pull/3235/head
Alexei Kotov 9 months ago
parent 2438fb4c98
commit aea7b10986

@ -107,6 +107,10 @@ add_component_dir (settings
windowmode
)
add_component_dir (bgsm
reader stream file
)
add_component_dir (bsa
bsa_file compressedbsafile ba2gnrlfile ba2dx10file ba2file memorystream
)

@ -0,0 +1,20 @@
#include "file.hpp"
#include "stream.hpp"
namespace Bgsm
{
void MaterialFile::read(BGSMStream& stream)
{
}
void BGSMFile::read(BGSMStream& stream)
{
MaterialFile::read(stream);
}
void BGEMFile::read(BGSMStream& stream)
{
MaterialFile::read(stream);
}
}

@ -0,0 +1,164 @@
#ifndef OPENMW_COMPONENTS_BGSM_FILE_HPP
#define OPENMW_COMPONENTS_BGSM_FILE_HPP
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include <osg/Vec2f>
#include <osg/Vec3f>
#include <osg/Vec4f>
namespace Bgsm
{
class BGSMStream;
enum class ShaderType
{
Lighting,
Effect,
};
struct MaterialFile
{
ShaderType mShaderType;
std::uint32_t mVersion;
std::uint32_t mClamp;
osg::Vec2f mUVOffset, mUVScale;
float mTransparency;
std::uint8_t mSourceBlendMode;
std::uint32_t mDestinationBlendMode;
std::uint32_t mAlphaTestMode;
std::uint8_t mAlphaTestRef;
bool mAlphaTest;
bool mDepthWrite, mDepthTest;
bool mSSR;
bool mWetnessControlSSR;
bool mDecal;
bool mTwoSided;
bool mDecalNoFade;
bool mNonOccluder;
bool mRefraction;
bool mRefractionFalloff;
float mRefractionPower;
bool mEnvMap;
float mEnvMapMaskScale;
bool mDepthBias;
bool mGrayscaleToPaletteColor;
std::uint8_t mMaskWrites;
MaterialFile() = default;
virtual void read(BGSMStream& stream);
virtual ~MaterialFile() {}
};
struct BGSMFile : MaterialFile
{
std::string mDiffuseMap;
std::string mNormalMap;
std::string mSmoothSpecMap;
std::string mGreyscaleMap;
std::string mGlowMap;
std::string mWrinkleMap;
std::string mSpecularMap;
std::string mLightingMap;
std::string mFlowMap;
std::string mDistanceFieldAlphaMap;
std::string mEnvMap;
std::string mInnerLayerMap;
std::string mDisplacementMap;
bool mEnableEditorAlphaRef;
bool mTranslucency;
bool mTranslucencyThickObject;
bool mTranslucencyMixAlbedoWithSubsurfaceColor;
osg::Vec4f mTranslucencySubsurfaceColor;
float mTranslucencyTransmissiveScale;
float mTranslucencyTurbulence;
bool mRimLighting;
float mRimPower;
float mBackLightPower;
bool mSursurfaceLighting;
float mSubsurfaceLightingRolloff;
bool mSpecularEnabled;
osg::Vec4f mSpecularColor;
float mSpecularMult;
float mSmoothness;
float mFresnelPower;
float mWetnessControlSpecScale;
float mWetnessControlSpecPowerScale;
float mWetnessControlSpecMinvar;
float mWetnessControlEnvMapScale;
float mWetnessControlFresnelPower;
float mWetnessControlMetalness;
bool mPBR;
bool mCustomPorosity;
float mPorosityValue;
std::string mRootMaterialPath;
bool mAnisoLighting;
bool mEmitEnabled;
osg::Vec4f mEmittanceColor;
float mEmittanceMult;
bool mModelSpaceNormals;
bool mExternalEmittance;
float mLumEmittance;
bool mUseAdaptiveEmissive;
osg::Vec3f mAdaptiveEmissiveExposureParams;
bool mBackLighting;
bool mReceiveShadows;
bool mHideSecret;
bool mCastShadows;
bool mDissolveFade;
bool mAssumeShadowmask;
bool mHasGlowMap;
bool mEnvMapWindow;
bool mEnvMapEye;
bool mHair;
osg::Vec4f mHairTintColor;
bool mTree;
bool mFacegen;
bool mSkinTint;
bool mTessellate;
osg::Vec2f mDisplacementMapParams;
osg::Vec3f mTesselationParams;
float mGrayscaleToPaletteScale;
bool mSkewSpecularAlpha;
bool mTerrain;
osg::Vec3f mTerrainParams;
void read(BGSMStream& stream) override;
};
struct BGEMFile : MaterialFile
{
std::string mBaseMap;
std::string mGrayscaleMap;
std::string mEnvMap;
std::string mNormalMap;
std::string mEnvMapMask;
std::string mSpecularMap;
std::string mLightingMap;
std::string mGlowMap;
bool mBlood;
bool mEffectLighting;
bool mFalloff;
bool mFalloffColor;
bool mGrayscaleToPaletteAlpha;
bool mSoft;
osg::Vec4f mBaseColor;
float mBaseColorScale;
osg::Vec4f mFalloffParams;
float mLightingInfluence;
std::uint8_t mEnvmapMinLOD;
float mSoftDepth;
osg::Vec4f mEmittanceColor;
osg::Vec3f mAdaptiveEmissiveExposureParams;
bool mHasGlowMap;
bool mEffectPbrSpecular;
void read(BGSMStream& stream) override;
};
using MaterialFilePtr = std::shared_ptr<const Bgsm::MaterialFile>;
}
#endif

@ -0,0 +1,35 @@
#include "reader.hpp"
#include <array>
#include <stdexcept>
#include <string>
#include "file.hpp"
#include "stream.hpp"
namespace Bgsm
{
void Reader::parse(Files::IStreamPtr&& inputStream)
{
BGSMStream stream(*this, std::move(inputStream));
std::array<char, 4> signature;
stream.readArray(signature);
std::string shaderType(signature.data(), 4);
if (shaderType == "BGEM")
{
mFile = std::make_unique<BGEMFile>();
mFile->mShaderType = Bgsm::ShaderType::Effect;
}
else if (shaderType == "BGSM")
{
mFile = std::make_unique<BGSMFile>();
mFile->mShaderType = Bgsm::ShaderType::Lighting;
}
else
throw std::runtime_error("Invalid material file");
mFile->read(stream);
}
}

@ -0,0 +1,25 @@
#ifndef OPENMW_COMPONENTS_BGSM_READER_HPP
#define OPENMW_COMPONENTS_BGSM_READER_HPP
#include <atomic>
#include <cstdint>
#include <memory>
#include <vector>
#include <components/files/istreamptr.hpp>
#include "file.hpp"
namespace Bgsm
{
class Reader
{
std::unique_ptr<MaterialFile> mFile;
public:
void parse(Files::IStreamPtr&& stream);
std::uint32_t getVersion() const { return mFile->mVersion; }
};
}
#endif

@ -0,0 +1,110 @@
#include "stream.hpp"
#include <span>
#include "reader.hpp"
namespace
{
// Read a range of elements into a dynamic buffer per-element
// This one should be used if the type cannot be read contiguously
// (e.g. quaternions)
template <class T>
void readRange(Bgsm::BGSMStream& stream, T* dest, size_t size)
{
for (T& value : std::span(dest, size))
stream.read(value);
}
// Read a range of elements into a dynamic buffer
// This one should be used if the type can be read contiguously as an array of a different type
// (e.g. osg::VecXf can be read as a float array of X elements)
template <class elementType, size_t numElements, class T>
void readAlignedRange(Files::IStreamPtr& stream, T* dest, size_t size)
{
static_assert(std::is_standard_layout_v<T>);
static_assert(std::alignment_of_v<T> == std::alignment_of_v<elementType>);
static_assert(sizeof(T) == sizeof(elementType) * numElements);
Bgsm::readDynamicBufferOfType(stream, reinterpret_cast<elementType*>(dest), size * numElements);
}
}
namespace Bgsm
{
std::uint32_t BGSMStream::getVersion() const
{
return mReader.getVersion();
}
std::string BGSMStream::getSizedString(size_t length)
{
std::string str(length, '\0');
mStream->read(str.data(), length);
if (mStream->bad())
throw std::runtime_error("Failed to read sized string of " + std::to_string(length) + " chars");
size_t end = str.find('\0');
if (end != std::string::npos)
str.erase(end);
return str;
}
void BGSMStream::getSizedStrings(std::vector<std::string>& vec, size_t size)
{
vec.resize(size);
for (size_t i = 0; i < vec.size(); i++)
vec[i] = getSizedString();
}
template <>
void BGSMStream::read<osg::Vec2f>(osg::Vec2f& vec)
{
readBufferOfType(mStream, vec._v);
}
template <>
void BGSMStream::read<osg::Vec3f>(osg::Vec3f& vec)
{
readBufferOfType(mStream, vec._v);
}
template <>
void BGSMStream::read<osg::Vec4f>(osg::Vec4f& vec)
{
readBufferOfType(mStream, vec._v);
}
template <>
void BGSMStream::read<std::string>(std::string& str)
{
str = getSizedString();
}
template <>
void BGSMStream::read<osg::Vec2f>(osg::Vec2f* dest, size_t size)
{
readAlignedRange<float, 2>(mStream, dest, size);
}
template <>
void BGSMStream::read<osg::Vec3f>(osg::Vec3f* dest, size_t size)
{
readAlignedRange<float, 3>(mStream, dest, size);
}
template <>
void BGSMStream::read<osg::Vec4f>(osg::Vec4f* dest, size_t size)
{
readAlignedRange<float, 4>(mStream, dest, size);
}
template <>
void BGSMStream::read<std::string>(std::string* dest, size_t size)
{
for (std::string& value : std::span(dest, size))
value = getSizedString();
}
}

@ -0,0 +1,143 @@
#ifndef OPENMW_COMPONENTS_BGSM_STREAM_HPP
#define OPENMW_COMPONENTS_BGSM_STREAM_HPP
#include <array>
#include <cassert>
#include <istream>
#include <stdexcept>
#include <cstdint>
#include <string>
#include <type_traits>
#include <vector>
#include <components/files/istreamptr.hpp>
#include <components/misc/endianness.hpp>
#include <osg/Vec3f>
#include <osg/Vec4f>
namespace Bgsm
{
class Reader;
template <std::size_t numInstances, typename T>
inline void readBufferOfType(Files::IStreamPtr& pIStream, T* dest)
{
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
pIStream->read((char*)dest, numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") buffer of "
+ std::to_string(numInstances) + " instances");
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);
}
template <std::size_t numInstances, typename T>
inline void readBufferOfType(Files::IStreamPtr& pIStream, T (&dest)[numInstances])
{
readBufferOfType<numInstances>(pIStream, static_cast<T*>(dest));
}
template <typename T>
inline void readDynamicBufferOfType(Files::IStreamPtr& pIStream, T* dest, std::size_t numInstances)
{
static_assert(std::is_arithmetic_v<T>, "Buffer element type is not arithmetic");
pIStream->read((char*)dest, numInstances * sizeof(T));
if (pIStream->bad())
throw std::runtime_error("Failed to read typed (" + std::string(typeid(T).name()) + ") dynamic buffer of "
+ std::to_string(numInstances) + " instances");
if constexpr (Misc::IS_BIG_ENDIAN)
for (std::size_t i = 0; i < numInstances; i++)
Misc::swapEndiannessInplace(dest[i]);
}
class BGSMStream
{
const Reader& mReader;
Files::IStreamPtr mStream;
public:
explicit BGSMStream(
const Reader& reader, Files::IStreamPtr&& stream)
: mReader(reader)
, mStream(std::move(stream))
{
}
const Reader& getFile() const { return mReader; }
std::uint32_t getVersion() const;
void skip(size_t size) { mStream->ignore(size); }
/// Read into a single instance of type
template <class T>
void read(T& data)
{
readBufferOfType<1>(mStream, &data);
}
/// Read multiple instances of type into an array
template <class T, size_t size>
void readArray(std::array<T, size>& arr)
{
readBufferOfType<size>(mStream, arr.data());
}
/// Read instances of type into a dynamic buffer
template <class T>
void read(T* dest, size_t size)
{
readDynamicBufferOfType<T>(mStream, dest, size);
}
/// Read multiple instances of type into a vector
template <class T>
void readVector(std::vector<T>& vec, size_t size)
{
if (size == 0)
return;
vec.resize(size);
read(vec.data(), size);
}
/// Extract an instance of type
template <class T>
T get()
{
T data;
read(data);
return data;
}
/// Read a string of the given length
std::string getSizedString(size_t length);
/// Read a string of the length specified in the file
std::string getSizedString() { return getSizedString(get<uint32_t>()); }
/// Read a list of strings
void getSizedStrings(std::vector<std::string>& vec, size_t size);
};
template <>
void BGSMStream::read<osg::Vec2f>(osg::Vec2f& vec);
template <>
void BGSMStream::read<osg::Vec3f>(osg::Vec3f& vec);
template <>
void BGSMStream::read<osg::Vec4f>(osg::Vec4f& vec);
template <>
void BGSMStream::read<std::string>(std::string& str);
template <>
void BGSMStream::read<osg::Vec2f>(osg::Vec2f* dest, size_t size);
template <>
void BGSMStream::read<osg::Vec3f>(osg::Vec3f* dest, size_t size);
template <>
void BGSMStream::read<osg::Vec4f>(osg::Vec4f* dest, size_t size);
template <>
void BGSMStream::read<std::string>(std::string* dest, size_t size);
}
#endif
Loading…
Cancel
Save