1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-26 09:35:28 +00:00

Refactor NiTexturingProperty, load everything

This commit is contained in:
Alexei Kotov 2023-09-17 21:07:49 +03:00
parent 18e4af04b3
commit 080d7d2c13
3 changed files with 121 additions and 105 deletions

View File

@ -6,50 +6,61 @@
namespace Nif namespace Nif
{ {
void NiTextureTransform::read(NIFStream* nif)
{
nif->read(mOffset);
nif->read(mScale);
nif->read(mRotation);
mTransformMethod = static_cast<Method>(nif->get<uint32_t>());
nif->read(mOrigin);
}
void NiTexturingProperty::Texture::read(NIFStream* nif) void NiTexturingProperty::Texture::read(NIFStream* nif)
{ {
nif->read(inUse); nif->read(mEnabled);
if (!inUse) if (!mEnabled)
return; return;
texture.read(nif); if (nif->getVersion() >= NIFStream::generateVersion(3, 3, 0, 13))
mSourceTexture.read(nif);
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
{ {
clamp = nif->getInt(); nif->read(mClamp);
nif->skip(4); // Filter mode. Ignoring because global filtering settings are more sensible nif->read(mFilter);
} }
else 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)) if (nif->getVersion() >= NIFStream::generateVersion(20, 5, 0, 4))
nif->getUShort(); nif->read(mMaxAnisotropy);
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB) if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
uvSet = nif->getUInt(); nif->read(mUVSet);
// Two PS2-specific shorts. // PS2 filtering settings
if (nif->getVersion() < NIFStream::generateVersion(10, 4, 0, 2)) if (nif->getVersion() <= NIFStream::generateVersion(10, 4, 0, 1))
nif->skip(4); nif->skip(4);
if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 18))
nif->skip(2); // Unknown short if (nif->getVersion() <= NIFStream::generateVersion(4, 1, 0, 12))
else if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0)) nif->skip(2); // Unknown
if (nif->getVersion() >= NIFStream::generateVersion(10, 1, 0, 0))
{ {
if (nif->get<bool>()) // Has texture transform nif->read(mHasTransform);
{ if (mHasTransform)
nif->getVector2(); // UV translation mTransform.read(nif);
nif->getVector2(); // UV scale
nif->getFloat(); // W axis rotation
nif->getUInt(); // Transform method
nif->getVector2(); // Texture rotation origin
}
} }
} }
void NiTexturingProperty::Texture::post(Reader& nif) void NiTexturingProperty::Texture::post(Reader& nif)
{ {
texture.post(nif); mSourceTexture.post(nif);
} }
void NiTexturingProperty::read(NIFStream* nif) void NiTexturingProperty::read(NIFStream* nif)
@ -58,37 +69,33 @@ namespace Nif
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD
|| nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2)) || nif->getVersion() >= NIFStream::generateVersion(20, 1, 0, 2))
flags = nif->getUShort(); nif->read(mFlags);
if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 1)) if (nif->getVersion() <= NIFStream::generateVersion(20, 1, 0, 1))
apply = nif->getUInt(); mApplyMode = static_cast<ApplyMode>(nif->get<uint32_t>());
unsigned int numTextures = nif->getUInt(); mTextures.resize(nif->get<uint32_t>());
for (size_t i = 0; i < mTextures.size(); i++)
if (!numTextures)
return;
textures.resize(numTextures);
for (unsigned int i = 0; i < numTextures; i++)
{ {
textures[i].read(nif); mTextures[i].read(nif);
if (i == 5 && textures[5].inUse) // Bump map settings
if (i == 5 && mTextures[5].mEnabled)
{ {
envMapLumaBias = nif->getVector2(); nif->read(mEnvMapLumaBias);
bumpMapMatrix = nif->getVector4(); nif->read(mBumpMapMatrix);
} }
else if (i == 7 && textures[7].inUse && nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5)) else if (i == 7 && mTextures[7].mEnabled && nif->getVersion() >= NIFStream::generateVersion(20, 2, 0, 5))
/*float parallaxOffset = */ nif->getFloat(); nif->read(mParallaxOffset);
} }
if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0)) if (nif->getVersion() >= NIFStream::generateVersion(10, 0, 1, 0))
{ {
unsigned int numShaderTextures = nif->getUInt(); mShaderTextures.resize(nif->get<uint32_t>());
shaderTextures.resize(numShaderTextures); mShaderIds.resize(mShaderTextures.size());
for (unsigned int i = 0; i < numShaderTextures; i++) for (size_t i = 0; i < mShaderTextures.size(); i++)
{ {
shaderTextures[i].read(nif); mShaderTextures[i].read(nif);
if (shaderTextures[i].inUse) if (mShaderTextures[i].mEnabled)
nif->getUInt(); // Unique identifier nif->read(mShaderIds[i]);
} }
} }
} }
@ -97,10 +104,10 @@ namespace Nif
{ {
Property::post(nif); Property::post(nif);
for (size_t i = 0; i < textures.size(); i++) for (Texture& tex : mTextures)
textures[i].post(nif); tex.post(nif);
for (size_t i = 0; i < shaderTextures.size(); i++) for (Texture& tex : mShaderTextures)
shaderTextures[i].post(nif); tex.post(nif);
} }
void BSSPParallaxParams::read(NIFStream* nif) void BSSPParallaxParams::read(NIFStream* nif)

View File

@ -10,53 +10,38 @@ namespace Nif
{ {
}; };
struct NiTexturingProperty : public Property struct NiTextureTransform
{ {
unsigned short flags{ 0u }; enum class Method : uint32_t
// A sub-texture
struct Texture
{ {
/* Clamp mode // Back = inverse of mOrigin.
0 - clampS clampT // FromMaya = inverse of the V axis with a positive translation along V of 1 unit.
1 - clampS wrapT MayaLegacy = 0, // mOrigin * mRotation * Back * mOffset * mScale
2 - wrapS clampT Max = 1, // mOrigin * mScale * mRotation * mOffset * Back
3 - wrapS wrapT Maya = 2, // mOrigin * mRotation * Back * FromMaya * mOffset * mScale
*/
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; }
}; };
/* Apply mode: osg::Vec2f mOffset;
0 - replace osg::Vec2f mScale;
1 - decal float mRotation;
2 - modulate Method mTransformMethod;
3 - hilight // These two are for PS2 only? osg::Vec2f mOrigin;
4 - hilight2
*/
unsigned int apply{ 0 };
/* void read(NIFStream* nif);
* The textures in this list are as follows: };
*
* 0 - Base texture struct NiTexturingProperty : public Property
* 1 - Dark texture {
* 2 - Detail texture enum class ApplyMode : uint32_t
* 3 - Gloss texture {
* 4 - Glow texture Replace = 0,
* 5 - Bump map texture Decal = 1,
* 6 - Decal texture Modulate = 2,
*/ Hilight = 3, // PS2-specific?
enum TextureType : uint32_t Hilight2 = 4, // Used for Oblivion parallax
};
enum TextureType
{ {
BaseTexture = 0, BaseTexture = 0,
DarkTexture = 1, DarkTexture = 1,
@ -67,11 +52,35 @@ namespace Nif
DecalTexture = 6, DecalTexture = 6,
}; };
std::vector<Texture> textures; // A sub-texture
std::vector<Texture> shaderTextures; 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; void read(NIFStream* nif);
osg::Vec4f bumpMapMatrix; 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<Texture> mTextures;
std::vector<Texture> mShaderTextures;
std::vector<uint32_t> mShaderIds;
osg::Vec2f mEnvMapLumaBias;
osg::Vec4f mBumpMapMatrix;
float mParallaxOffset;
void read(NIFStream* nif) override; void read(NIFStream* nif) override;
void post(Reader& nif) override; void post(Reader& nif) override;

View File

@ -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 // 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. // 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())) || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->mController.empty()))
{ {
switch (i) switch (i)
@ -1854,10 +1854,10 @@ namespace NifOsg
unsigned int uvSet = 0; unsigned int uvSet = 0;
// create a new texture, will later attempt to share using the SharedStateManager // create a new texture, will later attempt to share using the SharedStateManager
osg::ref_ptr<osg::Texture2D> texture2d; osg::ref_ptr<osg::Texture2D> texture2d;
if (texprop->textures[i].inUse) if (texprop->mTextures[i].mEnabled)
{ {
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; const Nif::NiTexturingProperty::Texture& tex = texprop->mTextures[i];
if (tex.texture.empty() && texprop->mController.empty()) if (tex.mSourceTexture.empty() && texprop->mController.empty())
{ {
if (i == 0) if (i == 0)
Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName
@ -1865,9 +1865,9 @@ namespace NifOsg
continue; 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<osg::Image> image = handleSourceTexture(st, imageManager); osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
texture2d = new osg::Texture2D(image); texture2d = new osg::Texture2D(image);
if (image) if (image)
@ -1878,7 +1878,7 @@ namespace NifOsg
handleTextureWrapping(texture2d, tex.wrapS(), tex.wrapT()); handleTextureWrapping(texture2d, tex.wrapS(), tex.wrapT());
uvSet = tex.uvSet; uvSet = tex.mUVSet;
} }
else else
{ {
@ -1926,10 +1926,10 @@ namespace NifOsg
// Bump maps offset the environment map. // Bump maps offset the environment map.
// Set this texture to Off by default since we can't render it with the fixed-function pipeline // 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); stateset->setTextureMode(texUnit, GL_TEXTURE_2D, osg::StateAttribute::OFF);
osg::Matrix2 bumpMapMatrix(texprop->bumpMapMatrix.x(), texprop->bumpMapMatrix.y(), osg::Matrix2 bumpMapMatrix(texprop->mBumpMapMatrix.x(), texprop->mBumpMapMatrix.y(),
texprop->bumpMapMatrix.z(), texprop->bumpMapMatrix.w()); texprop->mBumpMapMatrix.z(), texprop->mBumpMapMatrix.w());
stateset->addUniform(new osg::Uniform("bumpMapMatrix", bumpMapMatrix)); 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) else if (i == Nif::NiTexturingProperty::GlossTexture)
{ {