From 9ae1077808ba8857428318937bfe3bda6abcd80a Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 17 Sep 2023 18:29:30 +0300 Subject: [PATCH] Update NIF property loading, first pass Revise all FO3+ shader properties (attempt reading FO4, FO76 and Starfield properties) Use constants for most instances of property flags Drop invalid usage of non-existent double-sided flag for BSShader Make formatting more consistent, drop unnecessary comments --- .../nifosg/testnifloader.cpp | 6 +- components/nif/property.cpp | 301 +++++++++++++++--- components/nif/property.hpp | 238 ++++++++++---- components/nifosg/nifloader.cpp | 22 +- 4 files changed, 432 insertions(+), 135 deletions(-) diff --git a/apps/openmw_test_suite/nifosg/testnifloader.cpp b/apps/openmw_test_suite/nifosg/testnifloader.cpp index c8bc57bf4b..86a2df2135 100644 --- a/apps/openmw_test_suite/nifosg/testnifloader.cpp +++ b/apps/openmw_test_suite/nifosg/testnifloader.cpp @@ -187,9 +187,9 @@ osg::Group { init(node); Nif::BSShaderPPLightingProperty property; property.recType = Nif::RC_BSShaderPPLightingProperty; - property.textureSet = nullptr; + property.mTextureSet = nullptr; property.mController = nullptr; - property.type = GetParam().mShaderType; + property.mType = GetParam().mShaderType; node.mProperties.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); @@ -217,7 +217,7 @@ osg::Group { property.recType = Nif::RC_BSLightingShaderProperty; property.mTextureSet = nullptr; property.mController = nullptr; - property.type = GetParam().mShaderType; + property.mType = GetParam().mShaderType; node.mProperties.push_back(Nif::RecordPtrT(&property)); Nif::NIFFile file("test.nif"); file.mRoots.push_back(&node); diff --git a/components/nif/property.cpp b/components/nif/property.cpp index 3569fd55cc..8dd2be40f4 100644 --- a/components/nif/property.cpp +++ b/components/nif/property.cpp @@ -55,6 +55,7 @@ namespace Nif void NiTexturingProperty::read(NIFStream* nif) { Property::read(nif); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD || nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2)) flags = nif->getUShort(); @@ -95,103 +96,247 @@ namespace Nif void NiTexturingProperty::post(Reader& nif) { Property::post(nif); + for (size_t i = 0; i < textures.size(); i++) textures[i].post(nif); for (size_t i = 0; i < shaderTextures.size(); i++) shaderTextures[i].post(nif); } + void BSSPParallaxParams::read(NIFStream* nif) + { + nif->read(mMaxPasses); + nif->read(mScale); + } + + void BSSPRefractionParams::read(NIFStream* nif) + { + nif->read(mStrength); + nif->read(mPeriod); + } + void BSShaderProperty::read(NIFStream* nif) { NiShadeProperty::read(nif); + if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) { - type = nif->getUInt(); - flags1 = nif->getUInt(); - flags2 = nif->getUInt(); - envMapIntensity = nif->getFloat(); + nif->read(mType); + nif->read(mShaderFlags1); + nif->read(mShaderFlags2); + nif->read(mEnvMapScale); } } void BSShaderLightingProperty::read(NIFStream* nif) { BSShaderProperty::read(nif); + if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) - clamp = nif->getUInt(); + nif->read(mClamp); } void BSShaderPPLightingProperty::read(NIFStream* nif) { BSShaderLightingProperty::read(nif); - textureSet.read(nif); - if (nif->getBethVersion() <= 14) - return; - refraction.strength = nif->getFloat(); - refraction.period = nif->getInt(); - if (nif->getBethVersion() <= 24) - return; - parallax.passes = nif->getFloat(); - parallax.scale = nif->getFloat(); + + mTextureSet.read(nif); + if (nif->getBethVersion() >= 15) + mRefraction.read(nif); + if (nif->getBethVersion() >= 25) + mParallax.read(nif); } void BSShaderPPLightingProperty::post(Reader& nif) { BSShaderLightingProperty::post(nif); - textureSet.post(nif); + + mTextureSet.post(nif); } void BSShaderNoLightingProperty::read(NIFStream* nif) { BSShaderLightingProperty::read(nif); - filename = nif->getSizedString(); + + mFilename = nif->getSizedString(); if (nif->getBethVersion() >= 27) - falloffParams = nif->getVector4(); + nif->read(mFalloffParams); } + void BSSPLuminanceParams::read(NIFStream* nif) + { + nif->read(mLumEmittance); + nif->read(mExposureOffset); + nif->read(mFinalExposureMin); + nif->read(mFinalExposureMax); + }; + + void BSSPWetnessParams::read(NIFStream* nif) + { + nif->read(mSpecScale); + nif->read(mSpecPower); + nif->read(mMinVar); + if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_FO4) + nif->read(mEnvMapScale); + nif->read(mFresnelPower); + nif->read(mMetalness); + if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO4) + nif->skip(4); // Unknown + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->skip(4); // Unknown + }; + + void BSSPMLParallaxParams::read(NIFStream* nif) + { + nif->read(mInnerLayerThickness); + nif->read(mRefractionScale); + nif->read(mInnerLayerTextureScale); + nif->read(mEnvMapScale); + }; + + void BSSPTranslucencyParams::read(NIFStream* nif) + { + nif->read(mSubsurfaceColor); + nif->read(mTransmissiveScale); + nif->read(mTurbulence); + nif->read(mThickObject); + nif->read(mMixAlbedo); + }; + void BSLightingShaderProperty::read(NIFStream* nif) { - type = nif->getUInt(); + if (nif->getBethVersion() <= 139) + nif->read(mType); + BSShaderProperty::read(nif); - flags1 = nif->getUInt(); - flags2 = nif->getUInt(); - nif->skip(8); // UV offset - nif->skip(8); // UV scale + + if (nif->getBethVersion() <= 130) + { + nif->read(mShaderFlags1); + nif->read(mShaderFlags2); + } + else if (nif->getBethVersion() >= 132) + { + uint32_t numShaderFlags1 = 0, numShaderFlags2 = 0; + nif->read(numShaderFlags1); + if (nif->getBethVersion() >= 152) + nif->read(numShaderFlags2); + nif->readVector(mShaderFlags1Hashes, numShaderFlags1); + nif->readVector(mShaderFlags2Hashes, numShaderFlags2); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->read(mType); + + nif->read(mUVOffset); + nif->read(mUVScale); mTextureSet.read(nif); - mEmissive = nif->getVector3(); - mEmissiveMult = nif->getFloat(); - mClamp = nif->getUInt(); - mAlpha = nif->getFloat(); - nif->getFloat(); // Refraction strength - mGlossiness = nif->getFloat(); - mSpecular = nif->getVector3(); - mSpecStrength = nif->getFloat(); - nif->skip(8); // Lighting effects - switch (static_cast(type)) + nif->read(mEmissive); + nif->read(mEmissiveMult); + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) + nif->read(mRootMaterial); + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF) + nif->skip(4); // Unknown float + + nif->read(mClamp); + nif->read(mAlpha); + nif->read(mRefractionStrength); + + if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) + nif->read(mGlossiness); + else + nif->read(mSmoothness); + + nif->read(mSpecular); + nif->read(mSpecStrength); + + if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) + nif->readArray(mLightingEffects); + else if (nif->getBethVersion() <= 139) + { + nif->read(mSubsurfaceRolloff); + nif->read(mRimlightPower); + if (mRimlightPower == std::numeric_limits::max()) + nif->read(mBacklightPower); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) + { + nif->read(mGrayscaleToPaletteScale); + nif->read(mFresnelPower); + mWetness.read(nif); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF) + mLuminance.read(nif); + + if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76) + { + nif->read(mDoTranslucency); + if (mDoTranslucency) + mTranslucency.read(nif); + if (nif->get() != 0) + { + mTextureArrays.resize(nif->get()); + for (std::vector& textureArray : mTextureArrays) + nif->getSizedStrings(textureArray, nif->get()); + } + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF) + { + nif->skip(4); // Unknown + nif->skip(4); // Unknown + nif->skip(2); // Unknown + } + + // TODO: consider separating this switch for pre-FO76 and FO76+ + switch (static_cast(mType)) { case BSLightingShaderType::ShaderType_EnvMap: - nif->skip(4); // Environment map scale + if (nif->getBethVersion() <= 139) + nif->read(mEnvMapScale); + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) + { + nif->read(mUseSSR); + nif->read(mWetnessUseSSR); + } + break; + case BSLightingShaderType::ShaderType_FaceTint: + // Skin tint shader in FO76+ + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->read(mSkinTintColor); break; case BSLightingShaderType::ShaderType_SkinTint: + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->read(mHairTintColor); + else if (nif->getBethVersion() <= 130) + mSkinTintColor = { nif->get(), 1.f }; + else if (nif->getBethVersion() <= 139) + nif->read(mSkinTintColor); + // Hair tint shader in FO76+ + else if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + nif->read(mHairTintColor); + break; case BSLightingShaderType::ShaderType_HairTint: - nif->skip(12); // Tint color + if (nif->getBethVersion() <= 139) + nif->read(mHairTintColor); break; case BSLightingShaderType::ShaderType_ParallaxOcc: - nif->skip(4); // Max passes - nif->skip(4); // Scale + mParallax.read(nif); break; case BSLightingShaderType::ShaderType_MultiLayerParallax: - nif->skip(4); // Inner layer thickness - nif->skip(4); // Refraction scale - nif->skip(8); // Inner layer texture scale - nif->skip(4); // Environment map strength + mMultiLayerParallax.read(nif); break; case BSLightingShaderType::ShaderType_SparkleSnow: - nif->skip(16); // Sparkle parameters + nif->read(mSparkle); break; case BSLightingShaderType::ShaderType_EyeEnvmap: - nif->skip(4); // Cube map scale - nif->skip(12); // Left eye cube map offset - nif->skip(12); // Right eye cube map offset + nif->read(mCubeMapScale); + nif->read(mLeftEyeReflectionCenter); + nif->read(mRightEyeReflectionCenter); break; default: break; @@ -201,31 +346,80 @@ namespace Nif void BSLightingShaderProperty::post(Reader& nif) { BSShaderProperty::post(nif); + mTextureSet.post(nif); } void BSEffectShaderProperty::read(NIFStream* nif) { BSShaderProperty::read(nif); - flags1 = nif->getUInt(); - flags2 = nif->getUInt(); - mUVOffset = nif->getVector2(); - mUVScale = nif->getVector2(); + + if (nif->getBethVersion() <= 130) + { + nif->read(mShaderFlags1); + nif->read(mShaderFlags2); + } + else if (nif->getBethVersion() >= 132) + { + uint32_t numShaderFlags1 = 0, numShaderFlags2 = 0; + nif->read(numShaderFlags1); + if (nif->getBethVersion() >= 152) + nif->read(numShaderFlags2); + nif->readVector(mShaderFlags1Hashes, numShaderFlags1); + nif->readVector(mShaderFlags2Hashes, numShaderFlags2); + } + + nif->read(mUVOffset); + nif->read(mUVScale); mSourceTexture = nif->getSizedString(); - unsigned int miscParams = nif->getUInt(); + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF) + nif->skip(4); // Unknown + + uint32_t miscParams = nif->get(); mClamp = miscParams & 0xFF; mLightingInfluence = (miscParams >> 8) & 0xFF; mEnvMapMinLOD = (miscParams >> 16) & 0xFF; - mFalloffParams = nif->getVector4(); - mBaseColor = nif->getVector4(); - mBaseColorScale = nif->getFloat(); - mFalloffDepth = nif->getFloat(); + nif->read(mFalloffParams); + + if (nif->getBethVersion() == NIFFile::BethVersion::BETHVER_F76) + nif->read(mRefractionPower); + + nif->read(mBaseColor); + nif->read(mBaseColorScale); + nif->read(mFalloffDepth); mGreyscaleTexture = nif->getSizedString(); + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) + { + mEnvMapTexture = nif->getSizedString(); + mNormalTexture = nif->getSizedString(); + mEnvMaskTexture = nif->getSizedString(); + nif->read(mEnvMapScale); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76) + { + nif->read(mRefractionPower); + mReflectanceTexture = nif->getSizedString(); + mLightingTexture = nif->getSizedString(); + nif->read(mEmittanceColor); + mEmitGradientTexture = nif->getSizedString(); + mLuminance.read(nif); + } + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF) + { + nif->skip(7); // Unknown bytes + nif->skip(6 * sizeof(float)); // Unknown floats + nif->skip(1); // Unknown byte + } } void NiFogProperty::read(NIFStream* nif) { Property::read(nif); + mFlags = nif->getUShort(); mFogDepth = nif->getFloat(); mColour = nif->getVector3(); @@ -249,6 +443,7 @@ namespace Nif void NiVertexColorProperty::read(NIFStream* nif) { Property::read(nif); + mFlags = nif->getUShort(); if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) { diff --git a/components/nif/property.hpp b/components/nif/property.hpp index d9574f31d6..1e7d7a78da 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -1,26 +1,3 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: https://openmw.org/ - - This file (property.h) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - https://www.gnu.org/licenses/ . - - */ - #ifndef OPENMW_COMPONENTS_NIF_PROPERTY_HPP #define OPENMW_COMPONENTS_NIF_PROPERTY_HPP @@ -109,19 +86,18 @@ namespace Nif void read(NIFStream* nif) override; }; - // These contain no other data than the 'flags' field struct NiShadeProperty : public Property { - unsigned short flags{ 0u }; + uint16_t mFlags{ 0u }; void read(NIFStream* nif) override { Property::read(nif); if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3) - flags = nif->getUShort(); + nif->read(mFlags); } }; - enum class BSShaderType : unsigned int + enum class BSShaderType : uint32_t { ShaderType_TallGrass = 0, ShaderType_Default = 1, @@ -133,42 +109,55 @@ namespace Nif ShaderType_NoLighting = 33 }; + enum BSShaderFlags1 + { + BSSFlag1_Specular = 0x00000001, + BSSFlag1_Decal = 0x04000000, + }; + + struct BSSPParallaxParams + { + float mMaxPasses; + float mScale; + + void read(NIFStream* nif); + }; + + struct BSSPRefractionParams + { + float mStrength; + int32_t mPeriod; + + void read(NIFStream* nif); + }; + struct BSShaderProperty : public NiShadeProperty { - unsigned int type{ 0u }, flags1{ 0u }, flags2{ 0u }; - float envMapIntensity{ 0.f }; + uint32_t mType{ 0u }, mShaderFlags1{ 0u }, mShaderFlags2{ 0u }; + float mEnvMapScale{ 0.f }; + void read(NIFStream* nif) override; - bool specular() const { return flags1 & 1; } - bool doubleSided() const { return (flags2 >> 4) & 1; } - bool treeAnim() const { return (flags2 >> 29) & 1; } - bool decal() const { return (flags1 >> 26) & 1; } + // These flags are shared between BSShader and BSLightingShader + // Shader-specific flag methods must be handled on per-record basis + bool specular() const { return mShaderFlags1 & BSSFlag1_Specular; } + bool decal() const { return mShaderFlags1 & BSSFlag1_Decal; } }; struct BSShaderLightingProperty : public BSShaderProperty { - unsigned int clamp{ 0u }; + unsigned int mClamp{ 0u }; void read(NIFStream* nif) override; - bool wrapT() const { return clamp & 1; } - bool wrapS() const { return (clamp >> 1) & 1; } + bool wrapT() const { return mClamp & 1; } + bool wrapS() const { return mClamp & 2; } }; struct BSShaderPPLightingProperty : public BSShaderLightingProperty { - BSShaderTextureSetPtr textureSet; - struct RefractionSettings - { - float strength{ 0.f }; - int period{ 0 }; - }; - struct ParallaxSettings - { - float passes{ 0.f }; - float scale{ 0.f }; - }; - RefractionSettings refraction; - ParallaxSettings parallax; + BSShaderTextureSetPtr mTextureSet; + BSSPRefractionParams mRefraction; + BSSPParallaxParams mParallax; void read(NIFStream* nif) override; void post(Reader& nif) override; @@ -176,13 +165,13 @@ namespace Nif struct BSShaderNoLightingProperty : public BSShaderLightingProperty { - std::string filename; - osg::Vec4f falloffParams; + std::string mFilename; + osg::Vec4f mFalloffParams; void read(NIFStream* nif) override; }; - enum class BSLightingShaderType : unsigned int + enum class BSLightingShaderType : uint32_t { ShaderType_Default = 0, ShaderType_EnvMap = 1, @@ -207,43 +196,146 @@ namespace Nif ShaderType_Dismemberment = 20 }; + enum BSLightingShaderFlags1 + { + BSLSFlag1_Falloff = 0x00000040, + }; + + enum BSLightingShaderFlags2 + { + BSLSFlag2_DoubleSided = 0x00000010, + BSLSFlag2_TreeAnim = 0x20000000, + }; + + struct BSSPLuminanceParams + { + float mLumEmittance; + float mExposureOffset; + float mFinalExposureMin, mFinalExposureMax; + + void read(NIFStream* nif); + }; + + struct BSSPWetnessParams + { + float mSpecScale; + float mSpecPower; + float mMinVar; + float mEnvMapScale; + float mFresnelPower; + float mMetalness; + + void read(NIFStream* nif); + }; + + struct BSSPMLParallaxParams + { + float mInnerLayerThickness; + float mRefractionScale; + osg::Vec2f mInnerLayerTextureScale; + float mEnvMapScale; + + void read(NIFStream* nif); + }; + + struct BSSPTranslucencyParams + { + osg::Vec3f mSubsurfaceColor; + float mTransmissiveScale; + float mTurbulence; + bool mThickObject; + bool mMixAlbedo; + + void read(NIFStream* nif); + }; + struct BSLightingShaderProperty : public BSShaderProperty { + std::vector mShaderFlags1Hashes, mShaderFlags2Hashes; + osg::Vec2f mUVOffset, mUVScale; BSShaderTextureSetPtr mTextureSet; - unsigned int mClamp{ 0u }; + osg::Vec3f mEmissive; + float mEmissiveMult; + std::string mRootMaterial; + uint32_t mClamp; float mAlpha; - float mGlossiness; - osg::Vec3f mEmissive, mSpecular; - float mEmissiveMult, mSpecStrength; + float mRefractionStrength; + float mGlossiness{ 80.f }; + float mSmoothness{ 1.f }; + osg::Vec3f mSpecular; + float mSpecStrength; + std::array mLightingEffects; + float mSubsurfaceRolloff; + float mRimlightPower; + float mBacklightPower; + float mGrayscaleToPaletteScale{ 1.f }; + float mFresnelPower{ 5.f }; + BSSPWetnessParams mWetness; + bool mDoTranslucency{ false }; + BSSPTranslucencyParams mTranslucency; + std::vector> mTextureArrays; + BSSPLuminanceParams mLuminance; + + bool mUseSSR; + bool mWetnessUseSSR; + + osg::Vec4f mSkinTintColor; + osg::Vec3f mHairTintColor; + + BSSPParallaxParams mParallax; + BSSPMLParallaxParams mMultiLayerParallax; + osg::Vec4f mSparkle; + + float mCubeMapScale; + osg::Vec3f mLeftEyeReflectionCenter; + osg::Vec3f mRightEyeReflectionCenter; void read(NIFStream* nif) override; void post(Reader& nif) override; + + bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; } + bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; } }; struct BSEffectShaderProperty : public BSShaderProperty { + std::vector mShaderFlags1Hashes, mShaderFlags2Hashes; osg::Vec2f mUVOffset, mUVScale; std::string mSourceTexture; - unsigned char mClamp; - unsigned char mLightingInfluence; - unsigned char mEnvMapMinLOD; + uint8_t mClamp; + uint8_t mLightingInfluence; + uint8_t mEnvMapMinLOD; osg::Vec4f mFalloffParams; + float mRefractionPower; osg::Vec4f mBaseColor; float mBaseColorScale; float mFalloffDepth; std::string mGreyscaleTexture; + std::string mEnvMapTexture; + std::string mNormalTexture; + std::string mEnvMaskTexture; + float mEnvMapScale; + std::string mReflectanceTexture; + std::string mLightingTexture; + osg::Vec3f mEmittanceColor; + std::string mEmitGradientTexture; + BSSPLuminanceParams mLuminance; void read(NIFStream* nif) override; - bool useFalloff() const { return (flags >> 6) & 1; } + bool useFalloff() const { return mShaderFlags1 & BSLSFlag1_Falloff; } + bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; } + bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; } }; struct NiDitherProperty : public Property { unsigned short flags; + void read(NIFStream* nif) override { Property::read(nif); + flags = nif->getUShort(); } }; @@ -252,9 +344,11 @@ namespace Nif { unsigned short flags; unsigned int testFunction; + void read(NIFStream* nif) override { Property::read(nif); + flags = nif->getUShort(); testFunction = (flags >> 2) & 0x7; if (nif->getVersion() >= NIFStream::generateVersion(4, 1, 0, 12) @@ -264,15 +358,17 @@ namespace Nif bool depthTest() const { return flags & 1; } - bool depthWrite() const { return (flags >> 1) & 1; } + bool depthWrite() const { return flags & 2; } }; struct NiSpecularProperty : public Property { unsigned short flags; + void read(NIFStream* nif) override { Property::read(nif); + flags = nif->getUShort(); } @@ -282,9 +378,11 @@ namespace Nif struct NiWireframeProperty : public Property { unsigned short flags; + void read(NIFStream* nif) override { Property::read(nif); + flags = nif->getUShort(); } @@ -301,6 +399,7 @@ namespace Nif void read(NIFStream* nif) override { Property::read(nif); + flags = nif->getUShort(); data.read(nif); } @@ -400,12 +499,19 @@ namespace Nif struct NiAlphaProperty : public StructPropT { - bool useAlphaBlending() const { return flags & 1; } + enum Flags + { + Flag_Blending = 0x0001, + Flag_Testing = 0x0200, + Flag_NoSorter = 0x2000, + }; + + bool useAlphaBlending() const { return flags & Flag_Blending; } + bool useAlphaTesting() const { return flags & Flag_Testing; } + bool noSorter() const { return flags & Flag_NoSorter; } + int sourceBlendMode() const { return (flags >> 1) & 0xF; } int destinationBlendMode() const { return (flags >> 5) & 0xF; } - bool noSorter() const { return (flags >> 13) & 1; } - - bool useAlphaTesting() const { return (flags >> 9) & 1; } int alphaTestMode() const { return (flags >> 10) & 0x7; } }; @@ -460,5 +566,5 @@ namespace Nif } }; -} // Namespace +} #endif diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 05f42db05a..00001581d5 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -2202,18 +2202,16 @@ namespace NifOsg { auto texprop = static_cast(property); bool shaderRequired = true; - node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->type))); + node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->mType))); node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); - if (!texprop->textureSet.empty()) + if (!texprop->mTextureSet.empty()) { - auto textureSet = texprop->textureSet.getPtr(); + auto textureSet = texprop->mTextureSet.getPtr(); handleTextureSet( - textureSet, texprop->clamp, node->getName(), stateset, imageManager, boundTextures); + textureSet, texprop->mClamp, node->getName(), stateset, imageManager, boundTextures); } handleTextureControllers(texprop, composite, imageManager, stateset, animflags); - if (texprop->doubleSided()) - stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); break; } case Nif::RC_BSShaderNoLightingProperty: @@ -2221,10 +2219,10 @@ namespace NifOsg auto texprop = static_cast(property); bool shaderRequired = true; bool useFalloff = false; - node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->type))); + node->setUserValue("shaderPrefix", std::string(getBSShaderPrefix(texprop->mType))); node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); - if (!texprop->filename.empty()) + if (!texprop->mFilename.empty()) { if (!boundTextures.empty()) { @@ -2233,7 +2231,7 @@ namespace NifOsg boundTextures.clear(); } std::string filename - = Misc::ResourceHelpers::correctTexturePath(texprop->filename, imageManager->getVFS()); + = Misc::ResourceHelpers::correctTexturePath(texprop->mFilename, imageManager->getVFS()); osg::ref_ptr image = imageManager->getImage(filename); osg::ref_ptr texture2d = new osg::Texture2D(image); texture2d->setName("diffuseMap"); @@ -2247,20 +2245,18 @@ namespace NifOsg if (mBethVersion >= 27) { useFalloff = true; - stateset->addUniform(new osg::Uniform("falloffParams", texprop->falloffParams)); + stateset->addUniform(new osg::Uniform("falloffParams", texprop->mFalloffParams)); } } stateset->addUniform(new osg::Uniform("useFalloff", useFalloff)); handleTextureControllers(texprop, composite, imageManager, stateset, animflags); - if (texprop->doubleSided()) - stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF); break; } case Nif::RC_BSLightingShaderProperty: { auto texprop = static_cast(property); bool shaderRequired = true; - node->setUserValue("shaderPrefix", std::string(getBSLightingShaderPrefix(texprop->type))); + node->setUserValue("shaderPrefix", std::string(getBSLightingShaderPrefix(texprop->mType))); node->setUserValue("shaderRequired", shaderRequired); osg::StateSet* stateset = node->getOrCreateStateSet(); if (!texprop->mTextureSet.empty())