mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 22:09:42 +00:00
Merge branch 'nifcouriersix' into 'master'
Modernize NIF loader, part 6 See merge request OpenMW/openmw!3435
This commit is contained in:
commit
3ae189dda1
10 changed files with 895 additions and 592 deletions
|
@ -38,7 +38,7 @@ bool isNIF(const std::filesystem::path& filename)
|
|||
/// See if the file has the "bsa" extension.
|
||||
bool isBSA(const std::filesystem::path& filename)
|
||||
{
|
||||
return hasExtension(filename, ".bsa");
|
||||
return hasExtension(filename, ".bsa") || hasExtension(filename, ".ba2");
|
||||
}
|
||||
|
||||
std::unique_ptr<VFS::Archive> makeBsaArchive(const std::filesystem::path& path)
|
||||
|
@ -216,7 +216,7 @@ int main(int argc, char** argv)
|
|||
else
|
||||
{
|
||||
std::cerr << "ERROR: \"" << Files::pathToUnicodeString(path)
|
||||
<< "\" is not a nif file, bsa file, or directory!" << std::endl;
|
||||
<< "\" is not a nif file, bsa/ba2 file, or directory!" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
|
|
|
@ -187,10 +187,10 @@ 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;
|
||||
node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
|
||||
property.mType = GetParam().mShaderType;
|
||||
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
|
||||
Nif::NIFFile file("test.nif");
|
||||
file.mRoots.push_back(&node);
|
||||
auto result = Loader::load(file, &mImageManager);
|
||||
|
@ -217,8 +217,8 @@ osg::Group {
|
|||
property.recType = Nif::RC_BSLightingShaderProperty;
|
||||
property.mTextureSet = nullptr;
|
||||
property.mController = nullptr;
|
||||
property.type = GetParam().mShaderType;
|
||||
node.mProperties.push_back(Nif::RecordPtrT<Nif::Property>(&property));
|
||||
property.mType = GetParam().mShaderType;
|
||||
node.mProperties.push_back(Nif::RecordPtrT<Nif::NiProperty>(&property));
|
||||
Nif::NIFFile file("test.nif");
|
||||
file.mRoots.push_back(&node);
|
||||
auto result = Loader::load(file, &mImageManager);
|
||||
|
|
|
@ -26,27 +26,27 @@ namespace Nif
|
|||
{
|
||||
NiDynamicEffect::read(nif);
|
||||
|
||||
mDimmer = nif->getFloat();
|
||||
mAmbient = nif->getVector3();
|
||||
mDiffuse = nif->getVector3();
|
||||
mSpecular = nif->getVector3();
|
||||
nif->read(mDimmer);
|
||||
nif->read(mAmbient);
|
||||
nif->read(mDiffuse);
|
||||
nif->read(mSpecular);
|
||||
}
|
||||
|
||||
void NiPointLight::read(NIFStream* nif)
|
||||
{
|
||||
NiLight::read(nif);
|
||||
|
||||
mConstantAttenuation = nif->getFloat();
|
||||
mLinearAttenuation = nif->getFloat();
|
||||
mQuadraticAttenuation = nif->getFloat();
|
||||
nif->read(mConstantAttenuation);
|
||||
nif->read(mLinearAttenuation);
|
||||
nif->read(mQuadraticAttenuation);
|
||||
}
|
||||
|
||||
void NiSpotLight::read(NIFStream* nif)
|
||||
{
|
||||
NiPointLight::read(nif);
|
||||
|
||||
mCutoff = nif->getFloat();
|
||||
mExponent = nif->getFloat();
|
||||
nif->read(mCutoff);
|
||||
nif->read(mExponent);
|
||||
}
|
||||
|
||||
void NiTextureEffect::read(NIFStream* nif)
|
||||
|
|
|
@ -146,16 +146,6 @@ namespace Nif
|
|||
|
||||
/// Read a sequence of null-terminated strings
|
||||
std::string getStringPalette();
|
||||
|
||||
/// DEPRECATED: Use read() or get()
|
||||
char getChar() { return get<char>(); }
|
||||
unsigned short getUShort() { return get<unsigned short>(); }
|
||||
int getInt() { return get<int>(); }
|
||||
unsigned int getUInt() { return get<unsigned int>(); }
|
||||
float getFloat() { return get<float>(); }
|
||||
osg::Vec2f getVector2() { return get<osg::Vec2f>(); }
|
||||
osg::Vec3f getVector3() { return get<osg::Vec3f>(); }
|
||||
osg::Vec4f getVector4() { return get<osg::Vec4f>(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
|
@ -433,60 +433,63 @@ namespace Nif
|
|||
|
||||
void BSVertexData::read(NIFStream* nif, uint16_t flags)
|
||||
{
|
||||
uint16_t vertexFlag = flags & BSVertexDesc::VertexAttribute::Vertex;
|
||||
uint16_t tangentsFlag = flags & BSVertexDesc::VertexAttribute::Tangents;
|
||||
uint16_t UVsFlag = flags & BSVertexDesc::VertexAttribute::UVs;
|
||||
uint16_t normalsFlag = flags & BSVertexDesc::VertexAttribute::Normals;
|
||||
bool fullPrecision = true;
|
||||
if (nif->getBethVersion() != NIFFile::BethVersion::BETHVER_SSE)
|
||||
fullPrecision = flags & BSVertexDesc::VertexAttribute::Full_Precision;
|
||||
|
||||
if (vertexFlag == BSVertexDesc::VertexAttribute::Vertex)
|
||||
bool hasVertex = flags & BSVertexDesc::VertexAttribute::Vertex;
|
||||
bool hasTangent = flags & BSVertexDesc::VertexAttribute::Tangents;
|
||||
bool hasUV = flags & BSVertexDesc::VertexAttribute::UVs;
|
||||
bool hasNormal = flags & BSVertexDesc::VertexAttribute::Normals;
|
||||
bool hasVertexColor = flags & BSVertexDesc::VertexAttribute::Vertex_Colors;
|
||||
bool hasSkinData = flags & BSVertexDesc::VertexAttribute::Skinned;
|
||||
bool hasEyeData = flags & BSVertexDesc::VertexAttribute::Eye_Data;
|
||||
|
||||
if (hasVertex)
|
||||
{
|
||||
nif->read(mVertex);
|
||||
if (fullPrecision)
|
||||
{
|
||||
nif->read(mVertex);
|
||||
if (hasTangent)
|
||||
nif->read(mBitangentX);
|
||||
else
|
||||
nif->skip(4); // Unused
|
||||
}
|
||||
else
|
||||
{
|
||||
nif->readArray(mHalfVertex);
|
||||
if (hasTangent)
|
||||
nif->read(mHalfBitangentX);
|
||||
else
|
||||
nif->skip(2); // Unused
|
||||
}
|
||||
}
|
||||
|
||||
if ((vertexFlag | tangentsFlag)
|
||||
== (BSVertexDesc::VertexAttribute::Vertex | BSVertexDesc::VertexAttribute::Tangents))
|
||||
{
|
||||
nif->read(mBitangentX);
|
||||
}
|
||||
|
||||
if ((vertexFlag | tangentsFlag) == BSVertexDesc::VertexAttribute::Vertex)
|
||||
{
|
||||
nif->read(mUnusedW);
|
||||
}
|
||||
|
||||
if (UVsFlag == BSVertexDesc::VertexAttribute::UVs)
|
||||
{
|
||||
if (hasUV)
|
||||
nif->readArray(mUV);
|
||||
}
|
||||
|
||||
if (normalsFlag)
|
||||
if (hasNormal)
|
||||
{
|
||||
nif->readArray(mNormal);
|
||||
nif->read(mBitangentY);
|
||||
if (hasTangent)
|
||||
{
|
||||
nif->readArray(mTangent);
|
||||
nif->read(mBitangentZ);
|
||||
}
|
||||
}
|
||||
|
||||
if ((normalsFlag | tangentsFlag)
|
||||
== (BSVertexDesc::VertexAttribute::Normals | BSVertexDesc::VertexAttribute::Tangents))
|
||||
{
|
||||
nif->readArray(mTangent);
|
||||
nif->read(mBitangentZ);
|
||||
}
|
||||
if (hasVertexColor)
|
||||
nif->readArray(mVertColor);
|
||||
|
||||
if (flags & BSVertexDesc::VertexAttribute::Vertex_Colors)
|
||||
{
|
||||
nif->readArray(mVertColors);
|
||||
}
|
||||
|
||||
if (flags & BSVertexDesc::VertexAttribute::Skinned)
|
||||
if (hasSkinData)
|
||||
{
|
||||
nif->readArray(mBoneWeights);
|
||||
nif->readArray(mBoneIndices);
|
||||
}
|
||||
|
||||
if (flags & BSVertexDesc::VertexAttribute::Eye_Data)
|
||||
{
|
||||
if (hasEyeData)
|
||||
nif->read(mEyeData);
|
||||
}
|
||||
}
|
||||
|
||||
void BSValueNode::read(NIFStream* nif)
|
||||
|
|
|
@ -82,7 +82,7 @@ namespace Nif
|
|||
uint32_t mFlags;
|
||||
NiTransform mTransform;
|
||||
osg::Vec3f mVelocity;
|
||||
PropertyList mProperties;
|
||||
NiPropertyList mProperties;
|
||||
BoundingVolume mBounds;
|
||||
NiCollisionObjectPtr mCollision;
|
||||
// Parent nodes for the node. Only types derived from NiNode can be parents.
|
||||
|
@ -339,14 +339,15 @@ namespace Nif
|
|||
struct BSVertexData
|
||||
{
|
||||
osg::Vec3f mVertex;
|
||||
std::array<Misc::float16_t, 3> mHalfVertex;
|
||||
float mBitangentX;
|
||||
uint32_t mUnusedW;
|
||||
Misc::float16_t mHalfBitangentX;
|
||||
std::array<Misc::float16_t, 2> mUV;
|
||||
std::array<char, 3> mNormal;
|
||||
char mBitangentY;
|
||||
std::array<char, 3> mTangent;
|
||||
char mBitangentZ;
|
||||
std::array<char, 4> mVertColors;
|
||||
std::array<char, 4> mVertColor;
|
||||
std::array<Misc::float16_t, 4> mBoneWeights;
|
||||
std::array<char, 4> mBoneIndices;
|
||||
float mEyeData;
|
||||
|
|
|
@ -6,192 +6,368 @@
|
|||
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)
|
||||
{
|
||||
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<bool>()) // 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)
|
||||
{
|
||||
Property::read(nif);
|
||||
NiProperty::read(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<ApplyMode>(nif->get<uint32_t>());
|
||||
|
||||
unsigned int numTextures = nif->getUInt();
|
||||
|
||||
if (!numTextures)
|
||||
return;
|
||||
|
||||
textures.resize(numTextures);
|
||||
for (unsigned int i = 0; i < numTextures; i++)
|
||||
mTextures.resize(nif->get<uint32_t>());
|
||||
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<uint32_t>());
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
NiProperty::post(nif);
|
||||
|
||||
for (Texture& tex : mTextures)
|
||||
tex.post(nif);
|
||||
for (Texture& tex : mShaderTextures)
|
||||
tex.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)
|
||||
{
|
||||
if (nif->getBethVersion() < NIFFile::BethVersion::BETHVER_F76 && recType == RC_BSLightingShaderProperty)
|
||||
nif->read(mType);
|
||||
|
||||
NiShadeProperty::read(nif);
|
||||
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
||||
|
||||
if (nif->getUserVersion() <= 11)
|
||||
{
|
||||
type = nif->getUInt();
|
||||
flags1 = nif->getUInt();
|
||||
flags2 = nif->getUInt();
|
||||
envMapIntensity = nif->getFloat();
|
||||
nif->read(mType);
|
||||
nif->read(mShaderFlags1);
|
||||
nif->read(mShaderFlags2);
|
||||
nif->read(mEnvMapScale);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mName.empty() && nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
|
||||
return;
|
||||
|
||||
if (nif->getBethVersion() <= 131)
|
||||
{
|
||||
nif->read(mShaderFlags1);
|
||||
nif->read(mShaderFlags2);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 && recType == RC_BSLightingShaderProperty)
|
||||
{
|
||||
nif->read(mType);
|
||||
|
||||
// Remap FO76+ shader types to FO4 system so that we can actually use them
|
||||
// TODO: NifTools spec doesn't do anything about the misplaced EyeEnvmap. Bug or feature?
|
||||
switch (mType)
|
||||
{
|
||||
case 3:
|
||||
mType = static_cast<uint32_t>(BSLightingShaderType::ShaderType_FaceTint);
|
||||
break;
|
||||
case 4:
|
||||
mType = static_cast<uint32_t>(BSLightingShaderType::ShaderType_SkinTint);
|
||||
break;
|
||||
case 5:
|
||||
mType = static_cast<uint32_t>(BSLightingShaderType::ShaderType_HairTint);
|
||||
break;
|
||||
case 12:
|
||||
mType = static_cast<uint32_t>(BSLightingShaderType::ShaderType_EyeEnvmap);
|
||||
break;
|
||||
case 17:
|
||||
mType = static_cast<uint32_t>(BSLightingShaderType::ShaderType_Terrain);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nif->read(mUVOffset);
|
||||
nif->read(mUVScale);
|
||||
}
|
||||
|
||||
void BSShaderLightingProperty::read(NIFStream* nif)
|
||||
{
|
||||
BSShaderProperty::read(nif);
|
||||
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
||||
clamp = nif->getUInt();
|
||||
|
||||
if (nif->getUserVersion() <= 11)
|
||||
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->getUserVersion() == 11)
|
||||
{
|
||||
if (nif->getBethVersion() >= 15)
|
||||
mRefraction.read(nif);
|
||||
if (nif->getBethVersion() >= 25)
|
||||
mParallax.read(nif);
|
||||
}
|
||||
else if (nif->getUserVersion() >= 12)
|
||||
nif->read(mEmissiveColor);
|
||||
}
|
||||
|
||||
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();
|
||||
BSShaderProperty::read(nif);
|
||||
flags1 = nif->getUInt();
|
||||
flags2 = nif->getUInt();
|
||||
nif->skip(8); // UV offset
|
||||
nif->skip(8); // UV scale
|
||||
|
||||
if (!mName.empty() && nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
|
||||
return;
|
||||
|
||||
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<BSLightingShaderType>(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<float>::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<uint8_t>() != 0)
|
||||
{
|
||||
mTextureArrays.resize(nif->get<uint32_t>());
|
||||
for (std::vector<std::string>& textureArray : mTextureArrays)
|
||||
nif->getSizedStrings(textureArray, nif->get<uint32_t>());
|
||||
}
|
||||
}
|
||||
|
||||
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
|
||||
{
|
||||
nif->skip(4); // Unknown
|
||||
nif->skip(4); // Unknown
|
||||
nif->skip(2); // Unknown
|
||||
}
|
||||
|
||||
switch (static_cast<BSLightingShaderType>(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_SkinTint:
|
||||
nif->read(mSkinTintColor);
|
||||
if (nif->getBethVersion() > NIFFile::BethVersion::BETHVER_FO4)
|
||||
nif->read(mSkinTintAlpha);
|
||||
break;
|
||||
case BSLightingShaderType::ShaderType_HairTint:
|
||||
nif->skip(12); // Tint color
|
||||
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,59 +377,160 @@ 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 (!mName.empty() && nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_F76)
|
||||
return;
|
||||
|
||||
mSourceTexture = nif->getSizedString();
|
||||
unsigned int miscParams = nif->getUInt();
|
||||
|
||||
if (nif->getBethVersion() >= NIFFile::BethVersion::BETHVER_STF)
|
||||
nif->skip(4); // Unknown
|
||||
|
||||
uint32_t miscParams = nif->get<uint32_t>();
|
||||
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 NiAlphaProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
nif->read(mFlags);
|
||||
nif->read(mThreshold);
|
||||
}
|
||||
|
||||
void NiDitherProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
nif->read(mFlags);
|
||||
}
|
||||
|
||||
void NiFogProperty::read(NIFStream* nif)
|
||||
{
|
||||
Property::read(nif);
|
||||
mFlags = nif->getUShort();
|
||||
mFogDepth = nif->getFloat();
|
||||
mColour = nif->getVector3();
|
||||
NiProperty::read(nif);
|
||||
|
||||
nif->read(mFlags);
|
||||
nif->read(mFogDepth);
|
||||
nif->read(mColour);
|
||||
}
|
||||
|
||||
void S_MaterialProperty::read(NIFStream* nif)
|
||||
void NiMaterialProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
|
||||
nif->read(mFlags);
|
||||
if (nif->getBethVersion() < 26)
|
||||
{
|
||||
ambient = nif->getVector3();
|
||||
diffuse = nif->getVector3();
|
||||
nif->read(mAmbient);
|
||||
nif->read(mDiffuse);
|
||||
}
|
||||
specular = nif->getVector3();
|
||||
emissive = nif->getVector3();
|
||||
glossiness = nif->getFloat();
|
||||
alpha = nif->getFloat();
|
||||
nif->read(mSpecular);
|
||||
nif->read(mEmissive);
|
||||
nif->read(mGlossiness);
|
||||
nif->read(mAlpha);
|
||||
if (nif->getBethVersion() >= 22)
|
||||
emissiveMult = nif->getFloat();
|
||||
nif->read(mEmissiveMult);
|
||||
}
|
||||
|
||||
void NiShadeProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
||||
nif->read(mFlags);
|
||||
}
|
||||
|
||||
void NiSpecularProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
mEnable = nif->get<uint16_t>() & 1;
|
||||
}
|
||||
|
||||
void NiStencilProperty::read(NIFStream* nif)
|
||||
{
|
||||
NiProperty::read(nif);
|
||||
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||
{
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
|
||||
nif->read(mFlags);
|
||||
mEnabled = nif->get<uint8_t>() != 0;
|
||||
mTestFunction = static_cast<TestFunc>(nif->get<uint32_t>());
|
||||
nif->read(mStencilRef);
|
||||
nif->read(mStencilMask);
|
||||
mFailAction = static_cast<Action>(nif->get<uint32_t>());
|
||||
mZFailAction = static_cast<Action>(nif->get<uint32_t>());
|
||||
mPassAction = static_cast<Action>(nif->get<uint32_t>());
|
||||
mDrawMode = static_cast<DrawMode>(nif->get<uint32_t>());
|
||||
}
|
||||
else
|
||||
{
|
||||
nif->read(mFlags);
|
||||
mEnabled = mFlags & 0x1;
|
||||
mFailAction = static_cast<Action>((mFlags >> 1) & 0x7);
|
||||
mZFailAction = static_cast<Action>((mFlags >> 4) & 0x7);
|
||||
mPassAction = static_cast<Action>((mFlags >> 7) & 0x7);
|
||||
mDrawMode = static_cast<DrawMode>((mFlags >> 10) & 0x3);
|
||||
mTestFunction = static_cast<TestFunc>((mFlags >> 12) & 0x7);
|
||||
nif->read(mStencilRef);
|
||||
nif->read(mStencilMask);
|
||||
}
|
||||
}
|
||||
|
||||
void NiVertexColorProperty::read(NIFStream* nif)
|
||||
{
|
||||
Property::read(nif);
|
||||
mFlags = nif->getUShort();
|
||||
NiProperty::read(nif);
|
||||
|
||||
nif->read(mFlags);
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||
{
|
||||
mVertexMode = static_cast<VertexMode>(nif->getUInt());
|
||||
mLightingMode = static_cast<LightMode>(nif->getUInt());
|
||||
mVertexMode = static_cast<VertexMode>(nif->get<uint32_t>());
|
||||
mLightingMode = static_cast<LightMode>(nif->get<uint32_t>());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -262,36 +539,23 @@ namespace Nif
|
|||
}
|
||||
}
|
||||
|
||||
void S_AlphaProperty::read(NIFStream* nif)
|
||||
void NiWireframeProperty::read(NIFStream* nif)
|
||||
{
|
||||
threshold = nif->getChar();
|
||||
NiProperty::read(nif);
|
||||
|
||||
mEnable = nif->get<uint16_t>() & 1;
|
||||
}
|
||||
|
||||
void S_StencilProperty::read(NIFStream* nif)
|
||||
void NiZBufferProperty::read(NIFStream* nif)
|
||||
{
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||
{
|
||||
enabled = nif->getChar();
|
||||
compareFunc = nif->getInt();
|
||||
stencilRef = nif->getUInt();
|
||||
stencilMask = nif->getUInt();
|
||||
failAction = nif->getInt();
|
||||
zFailAction = nif->getInt();
|
||||
zPassAction = nif->getInt();
|
||||
drawMode = nif->getInt();
|
||||
}
|
||||
NiProperty::read(nif);
|
||||
|
||||
nif->read(mFlags);
|
||||
if (nif->getVersion() >= NIFStream::generateVersion(4, 1, 0, 12)
|
||||
&& nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||
nif->read(mTestFunction);
|
||||
else
|
||||
{
|
||||
unsigned short flags = nif->getUShort();
|
||||
enabled = flags & 0x1;
|
||||
failAction = (flags >> 1) & 0x7;
|
||||
zFailAction = (flags >> 4) & 0x7;
|
||||
zPassAction = (flags >> 7) & 0x7;
|
||||
drawMode = (flags >> 10) & 0x3;
|
||||
compareFunc = (flags >> 12) & 0x7;
|
||||
stencilRef = nif->getUInt();
|
||||
stencilMask = nif->getUInt();
|
||||
}
|
||||
mTestFunction = (mFlags >> 2) & 0x7;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
@ -29,57 +6,42 @@
|
|||
namespace Nif
|
||||
{
|
||||
|
||||
struct Property : public NiObjectNET
|
||||
struct NiProperty : NiObjectNET
|
||||
{
|
||||
};
|
||||
|
||||
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 : NiProperty
|
||||
{
|
||||
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,
|
||||
|
@ -90,38 +52,48 @@ namespace Nif
|
|||
DecalTexture = 6,
|
||||
};
|
||||
|
||||
std::vector<Texture> textures;
|
||||
std::vector<Texture> 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<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 post(Reader& nif) override;
|
||||
};
|
||||
|
||||
struct NiFogProperty : public Property
|
||||
struct NiShadeProperty : NiProperty
|
||||
{
|
||||
unsigned short mFlags;
|
||||
float mFogDepth;
|
||||
osg::Vec3f mColour;
|
||||
uint16_t mFlags{ 0u };
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
// These contain no other data than the 'flags' field
|
||||
struct NiShadeProperty : public Property
|
||||
{
|
||||
unsigned short flags{ 0u };
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
if (nif->getBethVersion() <= NIFFile::BethVersion::BETHVER_FO3)
|
||||
flags = nif->getUShort();
|
||||
}
|
||||
};
|
||||
|
||||
enum class BSShaderType : unsigned int
|
||||
enum class BSShaderType : uint32_t
|
||||
{
|
||||
ShaderType_TallGrass = 0,
|
||||
ShaderType_Default = 1,
|
||||
|
@ -133,56 +105,73 @@ namespace Nif
|
|||
ShaderType_NoLighting = 33
|
||||
};
|
||||
|
||||
struct BSShaderProperty : public NiShadeProperty
|
||||
enum BSShaderFlags1
|
||||
{
|
||||
unsigned int type{ 0u }, flags1{ 0u }, flags2{ 0u };
|
||||
float envMapIntensity{ 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; }
|
||||
BSSFlag1_Specular = 0x00000001,
|
||||
BSSFlag1_Decal = 0x04000000,
|
||||
};
|
||||
|
||||
struct BSShaderLightingProperty : public BSShaderProperty
|
||||
struct BSSPParallaxParams
|
||||
{
|
||||
unsigned int clamp{ 0u };
|
||||
void read(NIFStream* nif) override;
|
||||
float mMaxPasses{ 4.f };
|
||||
float mScale{ 1.f };
|
||||
|
||||
bool wrapT() const { return clamp & 1; }
|
||||
bool wrapS() const { return (clamp >> 1) & 1; }
|
||||
void read(NIFStream* nif);
|
||||
};
|
||||
|
||||
struct BSShaderPPLightingProperty : public BSShaderLightingProperty
|
||||
struct BSSPRefractionParams
|
||||
{
|
||||
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;
|
||||
float mStrength{ 0.f };
|
||||
int32_t mPeriod{ 0 };
|
||||
|
||||
void read(NIFStream* nif);
|
||||
};
|
||||
|
||||
struct BSShaderProperty : NiShadeProperty
|
||||
{
|
||||
uint32_t mType{ 0u }, mShaderFlags1{ 0u }, mShaderFlags2{ 0u };
|
||||
float mEnvMapScale{ 0.f };
|
||||
std::vector<uint32_t> mShaderFlags1Hashes, mShaderFlags2Hashes;
|
||||
osg::Vec2f mUVOffset, mUVScale;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
|
||||
// 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 : BSShaderProperty
|
||||
{
|
||||
uint32_t mClamp{ 3 };
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
|
||||
bool wrapT() const { return mClamp & 1; }
|
||||
bool wrapS() const { return mClamp & 2; }
|
||||
};
|
||||
|
||||
struct BSShaderPPLightingProperty : BSShaderLightingProperty
|
||||
{
|
||||
BSShaderTextureSetPtr mTextureSet;
|
||||
BSSPRefractionParams mRefraction;
|
||||
BSSPParallaxParams mParallax;
|
||||
osg::Vec4f mEmissiveColor;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
void post(Reader& nif) override;
|
||||
};
|
||||
|
||||
struct BSShaderNoLightingProperty : public BSShaderLightingProperty
|
||||
struct BSShaderNoLightingProperty : 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,
|
||||
|
@ -204,120 +193,157 @@ namespace Nif
|
|||
ShaderType_Cloud = 17,
|
||||
ShaderType_LODNoise = 18,
|
||||
ShaderType_MultitexLandLODBlend = 19,
|
||||
ShaderType_Dismemberment = 20
|
||||
ShaderType_Dismemberment = 20,
|
||||
ShaderType_Terrain = 21, // FO76+, technically 17
|
||||
};
|
||||
|
||||
struct BSLightingShaderProperty : public BSShaderProperty
|
||||
enum BSLightingShaderFlags1
|
||||
{
|
||||
BSShaderTextureSetPtr mTextureSet;
|
||||
unsigned int mClamp{ 0u };
|
||||
float mAlpha;
|
||||
float mGlossiness;
|
||||
osg::Vec3f mEmissive, mSpecular;
|
||||
float mEmissiveMult, mSpecStrength;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
void post(Reader& nif) override;
|
||||
BSLSFlag1_Falloff = 0x00000040,
|
||||
};
|
||||
|
||||
struct BSEffectShaderProperty : public BSShaderProperty
|
||||
enum BSLightingShaderFlags2
|
||||
{
|
||||
osg::Vec2f mUVOffset, mUVScale;
|
||||
std::string mSourceTexture;
|
||||
unsigned char mClamp;
|
||||
unsigned char mLightingInfluence;
|
||||
unsigned char mEnvMapMinLOD;
|
||||
osg::Vec4f mFalloffParams;
|
||||
osg::Vec4f mBaseColor;
|
||||
float mBaseColorScale;
|
||||
float mFalloffDepth;
|
||||
std::string mGreyscaleTexture;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
|
||||
bool useFalloff() const { return (flags >> 6) & 1; }
|
||||
BSLSFlag2_DoubleSided = 0x00000010,
|
||||
BSLSFlag2_TreeAnim = 0x20000000,
|
||||
};
|
||||
|
||||
struct NiDitherProperty : public Property
|
||||
struct BSSPLuminanceParams
|
||||
{
|
||||
unsigned short flags;
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
flags = nif->getUShort();
|
||||
}
|
||||
};
|
||||
|
||||
struct NiZBufferProperty : public Property
|
||||
{
|
||||
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)
|
||||
&& nif->getVersion() <= NIFFile::NIFVersion::VER_OB)
|
||||
testFunction = nif->getUInt();
|
||||
}
|
||||
|
||||
bool depthTest() const { return flags & 1; }
|
||||
|
||||
bool depthWrite() const { return (flags >> 1) & 1; }
|
||||
};
|
||||
|
||||
struct NiSpecularProperty : public Property
|
||||
{
|
||||
unsigned short flags;
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
flags = nif->getUShort();
|
||||
}
|
||||
|
||||
bool isEnabled() const { return flags & 1; }
|
||||
};
|
||||
|
||||
struct NiWireframeProperty : public Property
|
||||
{
|
||||
unsigned short flags;
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
flags = nif->getUShort();
|
||||
}
|
||||
|
||||
bool isEnabled() const { return flags & 1; }
|
||||
};
|
||||
|
||||
// The rest are all struct-based
|
||||
template <typename T>
|
||||
struct StructPropT : Property
|
||||
{
|
||||
T data;
|
||||
unsigned short flags;
|
||||
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
flags = nif->getUShort();
|
||||
data.read(nif);
|
||||
}
|
||||
};
|
||||
|
||||
struct S_MaterialProperty
|
||||
{
|
||||
// The vector components are R,G,B
|
||||
osg::Vec3f ambient{ 1.f, 1.f, 1.f }, diffuse{ 1.f, 1.f, 1.f };
|
||||
osg::Vec3f specular, emissive;
|
||||
float glossiness{ 0.f }, alpha{ 0.f }, emissiveMult{ 1.f };
|
||||
float mLumEmittance;
|
||||
float mExposureOffset;
|
||||
float mFinalExposureMin, mFinalExposureMax;
|
||||
|
||||
void read(NIFStream* nif);
|
||||
};
|
||||
|
||||
struct S_AlphaProperty
|
||||
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 : BSShaderProperty
|
||||
{
|
||||
BSShaderTextureSetPtr mTextureSet;
|
||||
osg::Vec3f mEmissive;
|
||||
float mEmissiveMult;
|
||||
std::string mRootMaterial;
|
||||
uint32_t mClamp;
|
||||
float mAlpha;
|
||||
float mRefractionStrength;
|
||||
float mGlossiness{ 80.f };
|
||||
float mSmoothness{ 1.f };
|
||||
osg::Vec3f mSpecular;
|
||||
float mSpecStrength;
|
||||
std::array<float, 2> mLightingEffects;
|
||||
float mSubsurfaceRolloff;
|
||||
float mRimlightPower;
|
||||
float mBacklightPower;
|
||||
float mGrayscaleToPaletteScale{ 1.f };
|
||||
float mFresnelPower{ 5.f };
|
||||
BSSPWetnessParams mWetness;
|
||||
bool mDoTranslucency{ false };
|
||||
BSSPTranslucencyParams mTranslucency;
|
||||
std::vector<std::vector<std::string>> mTextureArrays;
|
||||
BSSPLuminanceParams mLuminance;
|
||||
|
||||
bool mUseSSR;
|
||||
bool mWetnessUseSSR;
|
||||
|
||||
osg::Vec3f mSkinTintColor;
|
||||
float mSkinTintAlpha{ 1.f };
|
||||
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 : BSShaderProperty
|
||||
{
|
||||
std::string mSourceTexture;
|
||||
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 mShaderFlags1 & BSLSFlag1_Falloff; }
|
||||
bool doubleSided() const { return mShaderFlags2 & BSLSFlag2_DoubleSided; }
|
||||
bool treeAnim() const { return mShaderFlags2 & BSLSFlag2_TreeAnim; }
|
||||
};
|
||||
|
||||
struct NiAlphaProperty : NiProperty
|
||||
{
|
||||
enum Flags
|
||||
{
|
||||
Flag_Blending = 0x0001,
|
||||
Flag_Testing = 0x0200,
|
||||
Flag_NoSorter = 0x2000,
|
||||
};
|
||||
|
||||
uint16_t mFlags;
|
||||
uint8_t mThreshold;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
|
||||
bool useAlphaBlending() const { return mFlags & Flag_Blending; }
|
||||
bool useAlphaTesting() const { return mFlags & Flag_Testing; }
|
||||
bool noSorter() const { return mFlags & Flag_NoSorter; }
|
||||
|
||||
/*
|
||||
NiAlphaProperty blend modes (glBlendFunc):
|
||||
0000 GL_ONE
|
||||
|
@ -346,119 +372,132 @@ namespace Nif
|
|||
http://niftools.sourceforge.net/doc/nif/NiAlphaProperty.html
|
||||
*/
|
||||
|
||||
// Tested against when certain flags are set (see above.)
|
||||
unsigned char threshold;
|
||||
|
||||
void read(NIFStream* nif);
|
||||
int sourceBlendMode() const { return (mFlags >> 1) & 0xF; }
|
||||
int destinationBlendMode() const { return (mFlags >> 5) & 0xF; }
|
||||
int alphaTestMode() const { return (mFlags >> 10) & 0x7; }
|
||||
};
|
||||
|
||||
/*
|
||||
Docs taken from:
|
||||
http://niftools.sourceforge.net/doc/nif/NiStencilProperty.html
|
||||
*/
|
||||
struct S_StencilProperty
|
||||
struct NiDitherProperty : NiProperty
|
||||
{
|
||||
// Is stencil test enabled?
|
||||
unsigned char enabled;
|
||||
uint16_t mFlags;
|
||||
|
||||
/*
|
||||
0 TEST_NEVER
|
||||
1 TEST_LESS
|
||||
2 TEST_EQUAL
|
||||
3 TEST_LESS_EQUAL
|
||||
4 TEST_GREATER
|
||||
5 TEST_NOT_EQUAL
|
||||
6 TEST_GREATER_EQUAL
|
||||
7 TEST_NEVER (though nifskope comment says TEST_ALWAYS, but ingame it is TEST_NEVER)
|
||||
*/
|
||||
int compareFunc;
|
||||
unsigned stencilRef;
|
||||
unsigned stencilMask;
|
||||
/*
|
||||
Stencil test fail action, depth test fail action and depth test pass action:
|
||||
0 ACTION_KEEP
|
||||
1 ACTION_ZERO
|
||||
2 ACTION_REPLACE
|
||||
3 ACTION_INCREMENT
|
||||
4 ACTION_DECREMENT
|
||||
5 ACTION_INVERT
|
||||
*/
|
||||
int failAction;
|
||||
int zFailAction;
|
||||
int zPassAction;
|
||||
/*
|
||||
Face draw mode:
|
||||
0 DRAW_CCW_OR_BOTH
|
||||
1 DRAW_CCW [default]
|
||||
2 DRAW_CW
|
||||
3 DRAW_BOTH
|
||||
*/
|
||||
int drawMode;
|
||||
|
||||
void read(NIFStream* nif);
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiAlphaProperty : public StructPropT<S_AlphaProperty>
|
||||
struct NiFogProperty : NiProperty
|
||||
{
|
||||
bool useAlphaBlending() const { return flags & 1; }
|
||||
int sourceBlendMode() const { return (flags >> 1) & 0xF; }
|
||||
int destinationBlendMode() const { return (flags >> 5) & 0xF; }
|
||||
bool noSorter() const { return (flags >> 13) & 1; }
|
||||
uint16_t mFlags;
|
||||
float mFogDepth;
|
||||
osg::Vec3f mColour;
|
||||
|
||||
bool useAlphaTesting() const { return (flags >> 9) & 1; }
|
||||
int alphaTestMode() const { return (flags >> 10) & 0x7; }
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiVertexColorProperty : public Property
|
||||
struct NiMaterialProperty : NiProperty
|
||||
{
|
||||
enum class VertexMode : unsigned int
|
||||
uint16_t mFlags{ 0u };
|
||||
osg::Vec3f mAmbient{ 1.f, 1.f, 1.f };
|
||||
osg::Vec3f mDiffuse{ 1.f, 1.f, 1.f };
|
||||
osg::Vec3f mSpecular;
|
||||
osg::Vec3f mEmissive;
|
||||
float mGlossiness{ 0.f };
|
||||
float mAlpha{ 0.f };
|
||||
float mEmissiveMult{ 1.f };
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiSpecularProperty : NiProperty
|
||||
{
|
||||
bool mEnable;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiStencilProperty : NiProperty
|
||||
{
|
||||
enum class TestFunc : uint32_t
|
||||
{
|
||||
Never = 0,
|
||||
Less = 1,
|
||||
Equal = 2,
|
||||
LessEqual = 3,
|
||||
Greater = 4,
|
||||
NotEqual = 5,
|
||||
GreaterEqual = 6,
|
||||
Always = 7,
|
||||
};
|
||||
|
||||
enum class Action : uint32_t
|
||||
{
|
||||
Keep = 0,
|
||||
Zero = 1,
|
||||
Replace = 2,
|
||||
Increment = 3,
|
||||
Decrement = 4,
|
||||
Invert = 5,
|
||||
};
|
||||
|
||||
enum class DrawMode : uint32_t
|
||||
{
|
||||
Default = 0,
|
||||
CounterClockwise = 1,
|
||||
Clockwise = 2,
|
||||
Both = 3,
|
||||
};
|
||||
|
||||
uint16_t mFlags{ 0u };
|
||||
bool mEnabled;
|
||||
TestFunc mTestFunction;
|
||||
uint32_t mStencilRef;
|
||||
uint32_t mStencilMask;
|
||||
Action mFailAction;
|
||||
Action mZFailAction;
|
||||
Action mPassAction;
|
||||
DrawMode mDrawMode;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiVertexColorProperty : NiProperty
|
||||
{
|
||||
enum class VertexMode : uint32_t
|
||||
{
|
||||
VertMode_SrcIgnore = 0,
|
||||
VertMode_SrcEmissive = 1,
|
||||
VertMode_SrcAmbDif = 2
|
||||
};
|
||||
|
||||
enum class LightMode : unsigned int
|
||||
enum class LightMode : uint32_t
|
||||
{
|
||||
LightMode_Emissive = 0,
|
||||
LightMode_EmiAmbDif = 1
|
||||
};
|
||||
|
||||
unsigned short mFlags;
|
||||
uint16_t mFlags;
|
||||
VertexMode mVertexMode;
|
||||
LightMode mLightingMode;
|
||||
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiStencilProperty : public Property
|
||||
struct NiWireframeProperty : NiProperty
|
||||
{
|
||||
S_StencilProperty data;
|
||||
unsigned short flags{ 0u };
|
||||
bool mEnable;
|
||||
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
if (nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
|
||||
flags = nif->getUShort();
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFStream* nif) override;
|
||||
};
|
||||
|
||||
struct NiMaterialProperty : public Property
|
||||
struct NiZBufferProperty : NiProperty
|
||||
{
|
||||
S_MaterialProperty data;
|
||||
unsigned short flags{ 0u };
|
||||
uint16_t mFlags;
|
||||
uint32_t mTestFunction;
|
||||
|
||||
void read(NIFStream* nif) override
|
||||
{
|
||||
Property::read(nif);
|
||||
if (nif->getVersion() >= NIFStream::generateVersion(3, 0, 0, 0)
|
||||
&& nif->getVersion() <= NIFFile::NIFVersion::VER_OB_OLD)
|
||||
flags = nif->getUShort();
|
||||
data.read(nif);
|
||||
}
|
||||
void read(NIFStream* nif) override;
|
||||
|
||||
bool depthTest() const { return mFlags & 1; }
|
||||
bool depthWrite() const { return mFlags & 2; }
|
||||
};
|
||||
|
||||
} // Namespace
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -112,7 +112,7 @@ namespace Nif
|
|||
|
||||
struct NiAVObject;
|
||||
struct Extra;
|
||||
struct Property;
|
||||
struct NiProperty;
|
||||
struct NiUVData;
|
||||
struct NiPosData;
|
||||
struct NiVisData;
|
||||
|
@ -191,7 +191,7 @@ namespace Nif
|
|||
using BSMultiBoundDataPtr = RecordPtrT<BSMultiBoundData>;
|
||||
|
||||
using NiAVObjectList = RecordListT<NiAVObject>;
|
||||
using PropertyList = RecordListT<Property>;
|
||||
using NiPropertyList = RecordListT<NiProperty>;
|
||||
using ExtraList = RecordListT<Extra>;
|
||||
using NiSourceTextureList = RecordListT<NiSourceTexture>;
|
||||
using NiInterpolatorList = RecordListT<NiInterpolator>;
|
||||
|
|
|
@ -103,7 +103,7 @@ namespace
|
|||
// Collect all properties affecting the given drawable that should be handled on drawable basis rather than on the
|
||||
// node hierarchy above it.
|
||||
void collectDrawableProperties(
|
||||
const Nif::NiAVObject* nifNode, const Nif::Parent* parent, std::vector<const Nif::Property*>& out)
|
||||
const Nif::NiAVObject* nifNode, const Nif::Parent* parent, std::vector<const Nif::NiProperty*>& out)
|
||||
{
|
||||
if (parent != nullptr)
|
||||
collectDrawableProperties(&parent->mNiNode, parent->mParent, out);
|
||||
|
@ -412,7 +412,7 @@ namespace NifOsg
|
|||
{
|
||||
const Nif::NiStencilProperty* stencilprop
|
||||
= static_cast<const Nif::NiStencilProperty*>(property.getPtr());
|
||||
if (stencilprop->data.enabled != 0)
|
||||
if (stencilprop->mEnabled)
|
||||
{
|
||||
hasStencilProperty = true;
|
||||
break;
|
||||
|
@ -959,7 +959,7 @@ namespace NifOsg
|
|||
}
|
||||
}
|
||||
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty,
|
||||
void handleMaterialControllers(const Nif::NiProperty* materialProperty,
|
||||
SceneUtil::CompositeStateSetUpdater* composite, int animflags, const osg::Material* baseMaterial)
|
||||
{
|
||||
for (Nif::NiTimeControllerPtr ctrl = materialProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||
|
@ -1008,8 +1008,9 @@ namespace NifOsg
|
|||
}
|
||||
}
|
||||
|
||||
void handleTextureControllers(const Nif::Property* texProperty, SceneUtil::CompositeStateSetUpdater* composite,
|
||||
Resource::ImageManager* imageManager, osg::StateSet* stateset, int animflags)
|
||||
void handleTextureControllers(const Nif::NiProperty* texProperty,
|
||||
SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager,
|
||||
osg::StateSet* stateset, int animflags)
|
||||
{
|
||||
for (Nif::NiTimeControllerPtr ctrl = texProperty->mController; !ctrl.empty(); ctrl = ctrl->mNext)
|
||||
{
|
||||
|
@ -1316,7 +1317,7 @@ namespace NifOsg
|
|||
// localToWorldMatrix for transforming to particle space
|
||||
handleParticlePrograms(partctrl->mModifier, partctrl->mCollider, parentNode, partsys.get(), rf);
|
||||
|
||||
std::vector<const Nif::Property*> drawableProps;
|
||||
std::vector<const Nif::NiProperty*> drawableProps;
|
||||
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
||||
|
||||
|
@ -1462,7 +1463,7 @@ namespace NifOsg
|
|||
// - if there are no vertex colors, we need to disable colorMode.
|
||||
// - there are 3 "overlapping" nif properties that all affect the osg::Material, handling them
|
||||
// above the actual renderable would be tedious.
|
||||
std::vector<const Nif::Property*> drawableProps;
|
||||
std::vector<const Nif::NiProperty*> drawableProps;
|
||||
collectDrawableProperties(nifNode, parent, drawableProps);
|
||||
applyDrawableProperties(parentNode, drawableProps, composite, !niGeometryData->mColors.empty(), animflags);
|
||||
}
|
||||
|
@ -1616,50 +1617,54 @@ namespace NifOsg
|
|||
}
|
||||
}
|
||||
|
||||
osg::Stencil::Function getStencilFunction(int func)
|
||||
osg::Stencil::Function getStencilFunction(Nif::NiStencilProperty::TestFunc func)
|
||||
{
|
||||
using TestFunc = Nif::NiStencilProperty::TestFunc;
|
||||
switch (func)
|
||||
{
|
||||
case 0:
|
||||
case TestFunc::Never:
|
||||
return osg::Stencil::NEVER;
|
||||
case 1:
|
||||
case TestFunc::Less:
|
||||
return osg::Stencil::LESS;
|
||||
case 2:
|
||||
case TestFunc::Equal:
|
||||
return osg::Stencil::EQUAL;
|
||||
case 3:
|
||||
case TestFunc::LessEqual:
|
||||
return osg::Stencil::LEQUAL;
|
||||
case 4:
|
||||
case TestFunc::Greater:
|
||||
return osg::Stencil::GREATER;
|
||||
case 5:
|
||||
case TestFunc::NotEqual:
|
||||
return osg::Stencil::NOTEQUAL;
|
||||
case 6:
|
||||
case TestFunc::GreaterEqual:
|
||||
return osg::Stencil::GEQUAL;
|
||||
case 7:
|
||||
case TestFunc::Always:
|
||||
return osg::Stencil::ALWAYS;
|
||||
default:
|
||||
Log(Debug::Info) << "Unexpected stencil function: " << func << " in " << mFilename;
|
||||
Log(Debug::Info) << "Unexpected stencil function: " << static_cast<uint32_t>(func) << " in "
|
||||
<< mFilename;
|
||||
return osg::Stencil::NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
osg::Stencil::Operation getStencilOperation(int op)
|
||||
osg::Stencil::Operation getStencilOperation(Nif::NiStencilProperty::Action op)
|
||||
{
|
||||
using Action = Nif::NiStencilProperty::Action;
|
||||
switch (op)
|
||||
{
|
||||
case 0:
|
||||
case Action::Keep:
|
||||
return osg::Stencil::KEEP;
|
||||
case 1:
|
||||
case Action::Zero:
|
||||
return osg::Stencil::ZERO;
|
||||
case 2:
|
||||
case Action::Replace:
|
||||
return osg::Stencil::REPLACE;
|
||||
case 3:
|
||||
case Action::Increment:
|
||||
return osg::Stencil::INCR;
|
||||
case 4:
|
||||
case Action::Decrement:
|
||||
return osg::Stencil::DECR;
|
||||
case 5:
|
||||
case Action::Invert:
|
||||
return osg::Stencil::INVERT;
|
||||
default:
|
||||
Log(Debug::Info) << "Unexpected stencil operation: " << op << " in " << mFilename;
|
||||
Log(Debug::Info) << "Unexpected stencil operation: " << static_cast<uint32_t>(op) << " in "
|
||||
<< mFilename;
|
||||
return osg::Stencil::KEEP;
|
||||
}
|
||||
}
|
||||
|
@ -1827,9 +1832,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 +1859,10 @@ namespace NifOsg
|
|||
unsigned int uvSet = 0;
|
||||
// create a new texture, will later attempt to share using the SharedStateManager
|
||||
osg::ref_ptr<osg::Texture2D> 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 +1870,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<osg::Image> image = handleSourceTexture(st, imageManager);
|
||||
texture2d = new osg::Texture2D(image);
|
||||
if (image)
|
||||
|
@ -1878,7 +1883,7 @@ namespace NifOsg
|
|||
|
||||
handleTextureWrapping(texture2d, tex.wrapS(), tex.wrapT());
|
||||
|
||||
uvSet = tex.uvSet;
|
||||
uvSet = tex.mUVSet;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1926,10 +1931,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)
|
||||
{
|
||||
|
@ -2098,6 +2103,7 @@ namespace NifOsg
|
|||
case Nif::BSLightingShaderType::ShaderType_LODNoise:
|
||||
case Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend:
|
||||
case Nif::BSLightingShaderType::ShaderType_Dismemberment:
|
||||
case Nif::BSLightingShaderType::ShaderType_Terrain:
|
||||
Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename;
|
||||
return "bs/default";
|
||||
}
|
||||
|
@ -2105,7 +2111,7 @@ namespace NifOsg
|
|||
return "bs/default";
|
||||
}
|
||||
|
||||
void handleProperty(const Nif::Property* property, osg::Node* node,
|
||||
void handleProperty(const Nif::NiProperty* property, osg::Node* node,
|
||||
SceneUtil::CompositeStateSetUpdater* composite, Resource::ImageManager* imageManager,
|
||||
std::vector<unsigned int>& boundTextures, int animflags, bool hasStencilProperty)
|
||||
{
|
||||
|
@ -2114,14 +2120,17 @@ namespace NifOsg
|
|||
case Nif::RC_NiStencilProperty:
|
||||
{
|
||||
const Nif::NiStencilProperty* stencilprop = static_cast<const Nif::NiStencilProperty*>(property);
|
||||
|
||||
osg::ref_ptr<osg::FrontFace> frontFace = new osg::FrontFace;
|
||||
switch (stencilprop->data.drawMode)
|
||||
using DrawMode = Nif::NiStencilProperty::DrawMode;
|
||||
switch (stencilprop->mDrawMode)
|
||||
{
|
||||
case 2:
|
||||
case DrawMode::Clockwise:
|
||||
frontFace->setMode(osg::FrontFace::CLOCKWISE);
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
case DrawMode::Default:
|
||||
case DrawMode::CounterClockwise:
|
||||
case DrawMode::Both:
|
||||
default:
|
||||
frontFace->setMode(osg::FrontFace::COUNTER_CLOCKWISE);
|
||||
break;
|
||||
|
@ -2130,20 +2139,20 @@ namespace NifOsg
|
|||
|
||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||
stateset->setAttribute(frontFace, osg::StateAttribute::ON);
|
||||
stateset->setMode(GL_CULL_FACE,
|
||||
stencilprop->data.drawMode == 3 ? osg::StateAttribute::OFF : osg::StateAttribute::ON);
|
||||
if (stencilprop->mDrawMode == DrawMode::Both)
|
||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||
else
|
||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
||||
|
||||
if (stencilprop->data.enabled != 0)
|
||||
if (stencilprop->mEnabled)
|
||||
{
|
||||
mHasStencilProperty = true;
|
||||
osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil;
|
||||
stencil->setFunction(getStencilFunction(stencilprop->data.compareFunc),
|
||||
stencilprop->data.stencilRef, stencilprop->data.stencilMask);
|
||||
stencil->setStencilFailOperation(getStencilOperation(stencilprop->data.failAction));
|
||||
stencil->setStencilPassAndDepthFailOperation(
|
||||
getStencilOperation(stencilprop->data.zFailAction));
|
||||
stencil->setStencilPassAndDepthPassOperation(
|
||||
getStencilOperation(stencilprop->data.zPassAction));
|
||||
stencil->setFunction(getStencilFunction(stencilprop->mTestFunction), stencilprop->mStencilRef,
|
||||
stencilprop->mStencilMask);
|
||||
stencil->setStencilFailOperation(getStencilOperation(stencilprop->mFailAction));
|
||||
stencil->setStencilPassAndDepthFailOperation(getStencilOperation(stencilprop->mZFailAction));
|
||||
stencil->setStencilPassAndDepthPassOperation(getStencilOperation(stencilprop->mPassAction));
|
||||
stencil = shareAttribute(stencil);
|
||||
|
||||
stateset->setAttributeAndModes(stencil, osg::StateAttribute::ON);
|
||||
|
@ -2155,7 +2164,7 @@ namespace NifOsg
|
|||
const Nif::NiWireframeProperty* wireprop = static_cast<const Nif::NiWireframeProperty*>(property);
|
||||
osg::ref_ptr<osg::PolygonMode> mode = new osg::PolygonMode;
|
||||
mode->setMode(osg::PolygonMode::FRONT_AND_BACK,
|
||||
wireprop->isEnabled() ? osg::PolygonMode::LINE : osg::PolygonMode::FILL);
|
||||
wireprop->mEnable ? osg::PolygonMode::LINE : osg::PolygonMode::FILL);
|
||||
mode = shareAttribute(mode);
|
||||
node->getOrCreateStateSet()->setAttributeAndModes(mode, osg::StateAttribute::ON);
|
||||
break;
|
||||
|
@ -2202,18 +2211,16 @@ namespace NifOsg
|
|||
{
|
||||
auto texprop = static_cast<const Nif::BSShaderPPLightingProperty*>(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 +2228,10 @@ namespace NifOsg
|
|||
auto texprop = static_cast<const Nif::BSShaderNoLightingProperty*>(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 +2240,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<osg::Image> image = imageManager->getImage(filename);
|
||||
osg::ref_ptr<osg::Texture2D> texture2d = new osg::Texture2D(image);
|
||||
texture2d->setName("diffuseMap");
|
||||
|
@ -2247,20 +2254,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<const Nif::BSLightingShaderProperty*>(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())
|
||||
|
@ -2365,7 +2370,7 @@ namespace NifOsg
|
|||
return *found;
|
||||
}
|
||||
|
||||
void applyDrawableProperties(osg::Node* node, const std::vector<const Nif::Property*>& properties,
|
||||
void applyDrawableProperties(osg::Node* node, const std::vector<const Nif::NiProperty*>& properties,
|
||||
SceneUtil::CompositeStateSetUpdater* composite, bool hasVertexColors, int animflags)
|
||||
{
|
||||
// Specular lighting is enabled by default, but there's a quirk...
|
||||
|
@ -2390,7 +2395,7 @@ namespace NifOsg
|
|||
float emissiveMult = 1.f;
|
||||
float specStrength = 1.f;
|
||||
|
||||
for (const Nif::Property* property : properties)
|
||||
for (const Nif::NiProperty* property : properties)
|
||||
{
|
||||
switch (property->recType)
|
||||
{
|
||||
|
@ -2399,21 +2404,20 @@ namespace NifOsg
|
|||
// Specular property can turn specular lighting off.
|
||||
// FIXME: NiMaterialColorController doesn't care about this.
|
||||
auto specprop = static_cast<const Nif::NiSpecularProperty*>(property);
|
||||
specEnabled = specprop->isEnabled();
|
||||
specEnabled = specprop->mEnable;
|
||||
break;
|
||||
}
|
||||
case Nif::RC_NiMaterialProperty:
|
||||
{
|
||||
const Nif::NiMaterialProperty* matprop = static_cast<const Nif::NiMaterialProperty*>(property);
|
||||
|
||||
mat->setDiffuse(
|
||||
osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.diffuse, matprop->data.alpha));
|
||||
mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.ambient, 1.f));
|
||||
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.emissive, 1.f));
|
||||
emissiveMult = matprop->data.emissiveMult;
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->mDiffuse, matprop->mAlpha));
|
||||
mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->mAmbient, 1.f));
|
||||
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->mEmissive, 1.f));
|
||||
emissiveMult = matprop->mEmissiveMult;
|
||||
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.specular, 1.f));
|
||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->mSpecular, 1.f));
|
||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->mGlossiness);
|
||||
|
||||
if (!matprop->mController.empty())
|
||||
{
|
||||
|
@ -2428,29 +2432,31 @@ namespace NifOsg
|
|||
const Nif::NiVertexColorProperty* vertprop
|
||||
= static_cast<const Nif::NiVertexColorProperty*>(property);
|
||||
|
||||
using VertexMode = Nif::NiVertexColorProperty::VertexMode;
|
||||
switch (vertprop->mVertexMode)
|
||||
{
|
||||
case Nif::NiVertexColorProperty::VertexMode::VertMode_SrcIgnore:
|
||||
case VertexMode::VertMode_SrcIgnore:
|
||||
{
|
||||
mat->setColorMode(osg::Material::OFF);
|
||||
break;
|
||||
}
|
||||
case Nif::NiVertexColorProperty::VertexMode::VertMode_SrcEmissive:
|
||||
case VertexMode::VertMode_SrcEmissive:
|
||||
{
|
||||
mat->setColorMode(osg::Material::EMISSION);
|
||||
break;
|
||||
}
|
||||
case Nif::NiVertexColorProperty::VertexMode::VertMode_SrcAmbDif:
|
||||
case VertexMode::VertMode_SrcAmbDif:
|
||||
{
|
||||
lightmode = vertprop->mLightingMode;
|
||||
using LightMode = Nif::NiVertexColorProperty::LightMode;
|
||||
switch (lightmode)
|
||||
{
|
||||
case Nif::NiVertexColorProperty::LightMode::LightMode_Emissive:
|
||||
case LightMode::LightMode_Emissive:
|
||||
{
|
||||
mat->setColorMode(osg::Material::OFF);
|
||||
break;
|
||||
}
|
||||
case Nif::NiVertexColorProperty::LightMode::LightMode_EmiAmbDif:
|
||||
case LightMode::LightMode_EmiAmbDif:
|
||||
default:
|
||||
{
|
||||
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
|
@ -2503,7 +2509,7 @@ namespace NifOsg
|
|||
if (alphaprop->useAlphaTesting())
|
||||
{
|
||||
osg::ref_ptr<osg::AlphaFunc> alphaFunc(new osg::AlphaFunc(
|
||||
getTestMode(alphaprop->alphaTestMode()), alphaprop->data.threshold / 255.f));
|
||||
getTestMode(alphaprop->alphaTestMode()), alphaprop->mThreshold / 255.f));
|
||||
alphaFunc = shareAttribute(alphaFunc);
|
||||
node->getOrCreateStateSet()->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue