From 080d7d2c135ca95c89121597d307da66ff6bd09e Mon Sep 17 00:00:00 2001 From: Alexei Kotov Date: Sun, 17 Sep 2023 21:07:49 +0300 Subject: [PATCH] Refactor NiTexturingProperty, load everything --- components/nif/property.cpp | 103 +++++++++++++++++--------------- components/nif/property.hpp | 101 +++++++++++++++++-------------- components/nifosg/nifloader.cpp | 22 +++---- 3 files changed, 121 insertions(+), 105 deletions(-) diff --git a/components/nif/property.cpp b/components/nif/property.cpp index 8dd2be40f4..308c3a42e2 100644 --- a/components/nif/property.cpp +++ b/components/nif/property.cpp @@ -6,50 +6,61 @@ namespace Nif { + void NiTextureTransform::read(NIFStream* nif) + { + nif->read(mOffset); + nif->read(mScale); + nif->read(mRotation); + mTransformMethod = static_cast(nif->get()); + nif->read(mOrigin); + } + void NiTexturingProperty::Texture::read(NIFStream* nif) { - nif->read(inUse); - if (!inUse) + nif->read(mEnabled); + if (!mEnabled) return; - texture.read(nif); + if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13)) + mSourceTexture.read(nif); + if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) { - clamp = nif->getInt(); - nif->skip(4); // Filter mode. Ignoring because global filtering settings are more sensible + nif->read(mClamp); + nif->read(mFilter); } else { - clamp = nif->getUShort() & 0xF; + uint16_t flags; + nif->read(flags); + mClamp = flags & 0xF; + mFilter = (flags >> 4) & 0xF; } - // Max anisotropy. I assume we'll always only use the global anisotropy setting. + if (nif->getVersion() >= NIFStream::generateVersion(20, 5, 0, 4)) - nif->getUShort(); + nif->read(mMaxAnisotropy); if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) - uvSet = nif->getUInt(); + nif->read(mUVSet); - // Two PS2-specific shorts. - if (nif->getVersion() < NIFStream::generateVersion(10, 4, 0, 2)) + // PS2 filtering settings + if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1)) nif->skip(4); - if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 18)) - nif->skip(2); // Unknown short - else if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) + + if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 12)) + nif->skip(2); // Unknown + + if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) { - if (nif->get()) // Has texture transform - { - nif->getVector2(); // UV translation - nif->getVector2(); // UV scale - nif->getFloat(); // W axis rotation - nif->getUInt(); // Transform method - nif->getVector2(); // Texture rotation origin - } + nif->read(mHasTransform); + if (mHasTransform) + mTransform.read(nif); } } void NiTexturingProperty::Texture::post(Reader& nif) { - texture.post(nif); + mSourceTexture.post(nif); } void NiTexturingProperty::read(NIFStream* nif) @@ -58,37 +69,33 @@ namespace Nif if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD || nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2)) - flags = nif->getUShort(); + nif->read(mFlags); if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 1)) - apply = nif->getUInt(); + mApplyMode = static_cast(nif->get()); - unsigned int numTextures = nif->getUInt(); - - if (!numTextures) - return; - - textures.resize(numTextures); - for (unsigned int i = 0; i < numTextures; i++) + mTextures.resize(nif->get()); + for (size_t i = 0; i < mTextures.size(); i++) { - textures[i].read(nif); - if (i == 5 && textures[5].inUse) // Bump map settings + mTextures[i].read(nif); + + if (i == 5 && mTextures[5].mEnabled) { - envMapLumaBias = nif->getVector2(); - bumpMapMatrix = nif->getVector4(); + nif->read(mEnvMapLumaBias); + nif->read(mBumpMapMatrix); } - else if (i == 7 && textures[7].inUse && nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) - /*float parallaxOffset = */ nif->getFloat(); + else if (i == 7 && mTextures[7].mEnabled && nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) + nif->read(mParallaxOffset); } if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) { - unsigned int numShaderTextures = nif->getUInt(); - shaderTextures.resize(numShaderTextures); - for (unsigned int i = 0; i < numShaderTextures; i++) + mShaderTextures.resize(nif->get()); + mShaderIds.resize(mShaderTextures.size()); + for (size_t i = 0; i < mShaderTextures.size(); i++) { - shaderTextures[i].read(nif); - if (shaderTextures[i].inUse) - nif->getUInt(); // Unique identifier + mShaderTextures[i].read(nif); + if (mShaderTextures[i].mEnabled) + nif->read(mShaderIds[i]); } } } @@ -97,10 +104,10 @@ namespace 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); + for (Texture& tex : mTextures) + tex.post(nif); + for (Texture& tex : mShaderTextures) + tex.post(nif); } void BSSPParallaxParams::read(NIFStream* nif) diff --git a/components/nif/property.hpp b/components/nif/property.hpp index 1e7d7a78da..c4cf947d4e 100644 --- a/components/nif/property.hpp +++ b/components/nif/property.hpp @@ -10,53 +10,38 @@ namespace Nif { }; - struct NiTexturingProperty : public Property + struct NiTextureTransform { - unsigned short flags{ 0u }; - - // A sub-texture - struct Texture + enum class Method : uint32_t { - /* Clamp mode - 0 - clampS clampT - 1 - clampS wrapT - 2 - wrapS clampT - 3 - wrapS wrapT - */ - - bool inUse; - NiSourceTexturePtr texture; - - unsigned int clamp, uvSet; - - void read(NIFStream* nif); - void post(Reader& nif); - - bool wrapT() const { return clamp & 1; } - bool wrapS() const { return (clamp >> 1) & 1; } + // Back = inverse of mOrigin. + // FromMaya = inverse of the V axis with a positive translation along V of 1 unit. + MayaLegacy = 0, // mOrigin * mRotation * Back * mOffset * mScale + Max = 1, // mOrigin * mScale * mRotation * mOffset * Back + Maya = 2, // mOrigin * mRotation * Back * FromMaya * mOffset * mScale }; - /* Apply mode: - 0 - replace - 1 - decal - 2 - modulate - 3 - hilight // These two are for PS2 only? - 4 - hilight2 - */ - unsigned int apply{ 0 }; + osg::Vec2f mOffset; + osg::Vec2f mScale; + float mRotation; + Method mTransformMethod; + osg::Vec2f mOrigin; - /* - * The textures in this list are as follows: - * - * 0 - Base texture - * 1 - Dark texture - * 2 - Detail texture - * 3 - Gloss texture - * 4 - Glow texture - * 5 - Bump map texture - * 6 - Decal texture - */ - enum TextureType : uint32_t + void read(NIFStream* nif); + }; + + struct NiTexturingProperty : public Property + { + enum class ApplyMode : uint32_t + { + Replace = 0, + Decal = 1, + Modulate = 2, + Hilight = 3, // PS2-specific? + Hilight2 = 4, // Used for Oblivion parallax + }; + + enum TextureType { BaseTexture = 0, DarkTexture = 1, @@ -67,11 +52,35 @@ namespace Nif DecalTexture = 6, }; - std::vector textures; - std::vector shaderTextures; + // A sub-texture + struct Texture + { + bool mEnabled; + NiSourceTexturePtr mSourceTexture; + uint32_t mClamp; + uint32_t mFilter; + uint16_t mMaxAnisotropy; + uint32_t mUVSet; + bool mHasTransform; + NiTextureTransform mTransform; - osg::Vec2f envMapLumaBias; - osg::Vec4f bumpMapMatrix; + void read(NIFStream* nif); + void post(Reader& nif); + + bool wrapT() const { return mClamp & 1; } + bool wrapS() const { return mClamp & 2; } + }; + + uint16_t mFlags{ 0u }; + ApplyMode mApplyMode{ ApplyMode::Modulate }; + + std::vector mTextures; + std::vector mShaderTextures; + std::vector mShaderIds; + + osg::Vec2f mEnvMapLumaBias; + osg::Vec4f mBumpMapMatrix; + float mParallaxOffset; void read(NIFStream* nif) override; void post(Reader& nif) override; diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 00001581d5..10997c8558 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1827,9 +1827,9 @@ namespace NifOsg // If this loop is changed such that the base texture isn't guaranteed to end up in texture unit 0, the // shadow casting shader will need to be updated accordingly. - for (size_t i = 0; i < texprop->textures.size(); ++i) + for (size_t i = 0; i < texprop->mTextures.size(); ++i) { - if (texprop->textures[i].inUse + if (texprop->mTextures[i].mEnabled || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->mController.empty())) { switch (i) @@ -1854,10 +1854,10 @@ namespace NifOsg unsigned int uvSet = 0; // create a new texture, will later attempt to share using the SharedStateManager osg::ref_ptr texture2d; - if (texprop->textures[i].inUse) + if (texprop->mTextures[i].mEnabled) { - const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; - if (tex.texture.empty() && texprop->mController.empty()) + const Nif::NiTexturingProperty::Texture& tex = texprop->mTextures[i]; + if (tex.mSourceTexture.empty() && texprop->mController.empty()) { if (i == 0) Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName @@ -1865,9 +1865,9 @@ namespace NifOsg continue; } - if (!tex.texture.empty()) + if (!tex.mSourceTexture.empty()) { - const Nif::NiSourceTexture* st = tex.texture.getPtr(); + const Nif::NiSourceTexture* st = tex.mSourceTexture.getPtr(); osg::ref_ptr image = handleSourceTexture(st, imageManager); texture2d = new osg::Texture2D(image); if (image) @@ -1878,7 +1878,7 @@ namespace NifOsg handleTextureWrapping(texture2d, tex.wrapS(), tex.wrapT()); - uvSet = tex.uvSet; + uvSet = tex.mUVSet; } else { @@ -1926,10 +1926,10 @@ namespace NifOsg // Bump maps offset the environment map. // Set this texture to Off by default since we can't render it with the fixed-function pipeline stateset->setTextureMode(texUnit, GL_TEXTURE_2D, osg::StateAttribute::OFF); - osg::Matrix2 bumpMapMatrix(texprop->bumpMapMatrix.x(), texprop->bumpMapMatrix.y(), - texprop->bumpMapMatrix.z(), texprop->bumpMapMatrix.w()); + osg::Matrix2 bumpMapMatrix(texprop->mBumpMapMatrix.x(), texprop->mBumpMapMatrix.y(), + texprop->mBumpMapMatrix.z(), texprop->mBumpMapMatrix.w()); stateset->addUniform(new osg::Uniform("bumpMapMatrix", bumpMapMatrix)); - stateset->addUniform(new osg::Uniform("envMapLumaBias", texprop->envMapLumaBias)); + stateset->addUniform(new osg::Uniform("envMapLumaBias", texprop->mEnvMapLumaBias)); } else if (i == Nif::NiTexturingProperty::GlossTexture) {