mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 16:29:55 +00:00
Add dummy BGSM/BGEM file reader
This commit is contained in:
parent
2438fb4c98
commit
aea7b10986
7 changed files with 501 additions and 0 deletions
|
@ -107,6 +107,10 @@ add_component_dir (settings
|
||||||
windowmode
|
windowmode
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_component_dir (bgsm
|
||||||
|
reader stream file
|
||||||
|
)
|
||||||
|
|
||||||
add_component_dir (bsa
|
add_component_dir (bsa
|
||||||
bsa_file compressedbsafile ba2gnrlfile ba2dx10file ba2file memorystream
|
bsa_file compressedbsafile ba2gnrlfile ba2dx10file ba2file memorystream
|
||||||
)
|
)
|
||||||
|
|
20
components/bgsm/file.cpp
Normal file
20
components/bgsm/file.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
164
components/bgsm/file.hpp
Normal file
164
components/bgsm/file.hpp
Normal file
|
@ -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
|
35
components/bgsm/reader.cpp
Normal file
35
components/bgsm/reader.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
components/bgsm/reader.hpp
Normal file
25
components/bgsm/reader.hpp
Normal file
|
@ -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
|
110
components/bgsm/stream.cpp
Normal file
110
components/bgsm/stream.cpp
Normal file
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
143
components/bgsm/stream.hpp
Normal file
143
components/bgsm/stream.hpp
Normal file
|
@ -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…
Reference in a new issue