From bb6e0088014ed44bcefcb77455547aaa516d46cd Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Thu, 31 Aug 2023 22:05:55 +0300 Subject: [PATCH] Modernize dynamic effects --- components/nif/effect.cpp | 94 +++++++++++++++------------------ components/nif/effect.hpp | 64 ++++++++++++---------- components/nifosg/nifloader.cpp | 25 +++++---- 3 files changed, 92 insertions(+), 91 deletions(-) diff --git a/components/nif/effect.cpp b/components/nif/effect.cpp index e5dd2282b6..36407f8dc2 100644 --- a/components/nif/effect.cpp +++ b/components/nif/effect.cpp @@ -9,55 +9,61 @@ namespace Nif void NiDynamicEffect::read(NIFStream* nif) { Node::read(nif); - if (nif->getVersion() >= nif->generateVersion(10, 1, 0, 106) - && nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4) - nif->getBoolean(); // Switch state - if (nif->getVersion() <= NIFFile::VER_MW - || (nif->getVersion() >= nif->generateVersion(10, 1, 0, 0) - && nif->getBethVersion() < NIFFile::BethVersion::BETHVER_FO4)) - { - size_t numAffectedNodes = nif->get(); - nif->skip(numAffectedNodes * 4); - } + + if (nif->getVersion() > NIFFile::VER_MW && nif->getVersion() < nif->generateVersion(10, 1, 0, 0)) + return; + + if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_FO4) + return; + + if (nif->getVersion() >= nif->generateVersion(10, 1, 0, 106)) + nif->read(mSwitchState); + size_t numAffectedNodes = nif->get(); + nif->skip(numAffectedNodes * 4); } void NiLight::read(NIFStream* nif) { NiDynamicEffect::read(nif); - dimmer = nif->getFloat(); - ambient = nif->getVector3(); - diffuse = nif->getVector3(); - specular = nif->getVector3(); + mDimmer = nif->getFloat(); + mAmbient = nif->getVector3(); + mDiffuse = nif->getVector3(); + mSpecular = nif->getVector3(); } - void NiTextureEffect::read(NIFStream* nif) + void NiPointLight::read(NIFStream* nif) { - NiDynamicEffect::read(nif); - - // Model Projection Matrix - nif->skip(3 * 3 * sizeof(float)); - - // Model Projection Transform - nif->skip(3 * sizeof(float)); - - // Texture Filtering - nif->skip(4); - - // Max anisotropy samples - if (nif->getVersion() >= NIFStream::generateVersion(20, 5, 0, 4)) - nif->skip(2); + NiLight::read(nif); - clamp = nif->getUInt(); + mConstantAttenuation = nif->getFloat(); + mLinearAttenuation = nif->getFloat(); + mQuadraticAttenuation = nif->getFloat(); + } - textureType = (TextureType)nif->getUInt(); + void NiSpotLight::read(NIFStream* nif) + { + NiPointLight::read(nif); - coordGenType = (CoordGenType)nif->getUInt(); + mCutoff = nif->getFloat(); + mExponent = nif->getFloat(); + } - texture.read(nif); + void NiTextureEffect::read(NIFStream* nif) + { + NiDynamicEffect::read(nif); - nif->skip(1); // Use clipping plane - nif->skip(16); // Clipping plane dimensions vector + nif->read(mProjectionRotation); + nif->read(mProjectionPosition); + nif->read(mFilterMode); + if (nif->getVersion() >= NIFStream::generateVersion(20, 5, 0, 4)) + nif->read(mMaxAnisotropy); + nif->read(mClampMode); + mTextureType = static_cast(nif->get()); + mCoordGenType = static_cast(nif->get()); + mTexture.read(nif); + nif->read(mEnableClipPlane); + mClipPlane = osg::Plane(nif->get()); if (nif->getVersion() <= NIFStream::generateVersion(10, 2, 0, 0)) nif->skip(4); // PS2-specific shorts if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 12)) @@ -67,24 +73,8 @@ namespace Nif void NiTextureEffect::post(Reader& nif) { NiDynamicEffect::post(nif); - texture.post(nif); - } - - void NiPointLight::read(NIFStream* nif) - { - NiLight::read(nif); - - constantAttenuation = nif->getFloat(); - linearAttenuation = nif->getFloat(); - quadraticAttenuation = nif->getFloat(); - } - - void NiSpotLight::read(NIFStream* nif) - { - NiPointLight::read(nif); - cutoff = nif->getFloat(); - exponent = nif->getFloat(); + mTexture.post(nif); } } diff --git a/components/nif/effect.hpp b/components/nif/effect.hpp index ea9e21f003..06f85cd5d5 100644 --- a/components/nif/effect.hpp +++ b/components/nif/effect.hpp @@ -29,67 +29,75 @@ namespace Nif { + // Abstract struct NiDynamicEffect : public Node { + bool mSwitchState{ true }; void read(NIFStream* nif) override; }; - // Used as base for NiAmbientLight, NiDirectionalLight, NiPointLight and NiSpotLight. + // Abstract light source struct NiLight : NiDynamicEffect { - float dimmer; - osg::Vec3f ambient; - osg::Vec3f diffuse; - osg::Vec3f specular; + float mDimmer; + osg::Vec3f mAmbient; + osg::Vec3f mDiffuse; + osg::Vec3f mSpecular; void read(NIFStream* nif) override; }; struct NiPointLight : public NiLight { - float constantAttenuation; - float linearAttenuation; - float quadraticAttenuation; + float mConstantAttenuation; + float mLinearAttenuation; + float mQuadraticAttenuation; void read(NIFStream* nif) override; }; struct NiSpotLight : public NiPointLight { - float cutoff; - float exponent; + float mCutoff; + float mExponent; void read(NIFStream* nif) override; }; struct NiTextureEffect : NiDynamicEffect { - NiSourceTexturePtr texture; - unsigned int clamp; - - enum TextureType + enum class TextureType : uint32_t { - Projected_Light = 0, - Projected_Shadow = 1, - Environment_Map = 2, - Fog_Map = 3 + ProjectedLight = 0, + ProjectedShadow = 1, + EnvironmentMap = 2, + FogMap = 3, }; - TextureType textureType; - enum CoordGenType + enum class CoordGenType : uint32_t { - World_Parallel = 0, - World_Perspective, - Sphere_Map, - Specular_Cube_Map, - Diffuse_Cube_Map + WorldParallel = 0, + WorldPerspective = 1, + SphereMap = 2, + SpecularCubeMap = 3, + DiffuseCubeMap = 4, }; - CoordGenType coordGenType; + + Matrix3 mProjectionRotation; + osg::Vec3f mProjectionPosition; + uint32_t mFilterMode; + NiSourceTexturePtr mTexture; + uint16_t mMaxAnisotropy{ 0 }; + uint32_t mClampMode; + TextureType mTextureType; + CoordGenType mCoordGenType; + uint8_t mEnableClipPlane; + osg::Plane mClipPlane; void read(NIFStream* nif) override; void post(Reader& nif) override; - bool wrapT() const { return clamp & 1; } - bool wrapS() const { return (clamp >> 1) & 1; } + bool wrapT() const { return mClampMode & 1; } + bool wrapS() const { return mClampMode & 2; } }; } // Namespace diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index c8c89a0660..88e470bae2 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -537,38 +537,41 @@ namespace NifOsg } const Nif::NiTextureEffect* textureEffect = static_cast(nifNode); - if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map) + if (!textureEffect->mSwitchState) + return false; + + if (textureEffect->mTextureType != Nif::NiTextureEffect::TextureType::EnvironmentMap) { - Log(Debug::Info) << "Unhandled NiTextureEffect type " << textureEffect->textureType << " in " - << mFilename; + Log(Debug::Info) << "Unhandled NiTextureEffect type " + << static_cast(textureEffect->mTextureType) << " in " << mFilename; return false; } - if (textureEffect->texture.empty()) + if (textureEffect->mTexture.empty()) { Log(Debug::Info) << "NiTextureEffect missing source texture in " << mFilename; return false; } osg::ref_ptr texGen(new osg::TexGen); - switch (textureEffect->coordGenType) + switch (textureEffect->mCoordGenType) { - case Nif::NiTextureEffect::World_Parallel: + case Nif::NiTextureEffect::CoordGenType::WorldParallel: texGen->setMode(osg::TexGen::OBJECT_LINEAR); break; - case Nif::NiTextureEffect::World_Perspective: + case Nif::NiTextureEffect::CoordGenType::WorldPerspective: texGen->setMode(osg::TexGen::EYE_LINEAR); break; - case Nif::NiTextureEffect::Sphere_Map: + case Nif::NiTextureEffect::CoordGenType::SphereMap: texGen->setMode(osg::TexGen::SPHERE_MAP); break; default: - Log(Debug::Info) << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType - << " in " << mFilename; + Log(Debug::Info) << "Unhandled NiTextureEffect CoordGenType " + << static_cast(textureEffect->mCoordGenType) << " in " << mFilename; return false; } - osg::ref_ptr image(handleSourceTexture(textureEffect->texture.getPtr(), imageManager)); + osg::ref_ptr image(handleSourceTexture(textureEffect->mTexture.getPtr(), imageManager)); osg::ref_ptr texture2d(new osg::Texture2D(image)); if (image) texture2d->setTextureSize(image->s(), image->t());