Fix NiFlipController

NiFlipControllers *always* affect the base texture, even if no base
texture is bound. When no base texture is bound, they default to UV set
zero and to having wrapped UV coordinates, instead of using the settings
for the disabled base texture.
pull/3007/head
AnyOldName3 4 years ago
parent 8390ba0a0c
commit b2cb98d30e

@ -449,7 +449,7 @@ void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *n
} }
FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures) FlipController::FlipController(const Nif::NiFlipController *ctrl, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures)
: mTexSlot(ctrl->mTexSlot) : mTexSlot(0) // always affects diffuse
, mDelta(ctrl->mDelta) , mDelta(ctrl->mDelta)
, mTextures(textures) , mTextures(textures)
{ {

@ -799,22 +799,23 @@ namespace NifOsg
{ {
const Nif::NiFlipController* flipctrl = static_cast<const Nif::NiFlipController*>(ctrl.getPtr()); const Nif::NiFlipController* flipctrl = static_cast<const Nif::NiFlipController*>(ctrl.getPtr());
std::vector<osg::ref_ptr<osg::Texture2D> > textures; std::vector<osg::ref_ptr<osg::Texture2D> > textures;
// inherit wrap settings from the target slot
osg::Texture2D* inherit = dynamic_cast<osg::Texture2D*>(stateset->getTextureAttribute(0, osg::StateAttribute::TEXTURE));
osg::Texture2D::WrapMode wrapS = osg::Texture2D::REPEAT;
osg::Texture2D::WrapMode wrapT = osg::Texture2D::REPEAT;
if (inherit)
{
wrapS = inherit->getWrap(osg::Texture2D::WRAP_S);
wrapT = inherit->getWrap(osg::Texture2D::WRAP_T);
}
for (unsigned int i=0; i<flipctrl->mSources.length(); ++i) for (unsigned int i=0; i<flipctrl->mSources.length(); ++i)
{ {
Nif::NiSourceTexturePtr st = flipctrl->mSources[i]; Nif::NiSourceTexturePtr st = flipctrl->mSources[i];
if (st.empty()) if (st.empty())
continue; continue;
// inherit wrap settings from the target slot
osg::Texture2D* inherit = dynamic_cast<osg::Texture2D*>(stateset->getTextureAttribute(flipctrl->mTexSlot, osg::StateAttribute::TEXTURE));
osg::Texture2D::WrapMode wrapS = osg::Texture2D::CLAMP_TO_EDGE;
osg::Texture2D::WrapMode wrapT = osg::Texture2D::CLAMP_TO_EDGE;
if (inherit)
{
wrapS = inherit->getWrap(osg::Texture2D::WRAP_S);
wrapT = inherit->getWrap(osg::Texture2D::WRAP_T);
}
osg::ref_ptr<osg::Image> image (handleSourceTexture(st.getPtr(), imageManager)); osg::ref_ptr<osg::Image> image (handleSourceTexture(st.getPtr(), imageManager));
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(image)); osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D(image));
if (image) if (image)
@ -1451,7 +1452,7 @@ 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. // 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->textures.size(); ++i)
{ {
if (texprop->textures[i].inUse) if (texprop->textures[i].inUse || (i == Nif::NiTexturingProperty::BaseTexture && !texprop->controller.empty()))
{ {
switch(i) switch(i)
{ {
@ -1477,32 +1478,44 @@ namespace NifOsg
} }
} }
const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i]; unsigned int uvSet = 0;
if(tex.texture.empty() && texprop->controller.empty())
{
if (i == 0)
Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename;
continue;
}
// 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 (!tex.texture.empty()) if (texprop->textures[i].inUse)
{ {
const Nif::NiSourceTexture *st = tex.texture.getPtr(); const Nif::NiTexturingProperty::Texture& tex = texprop->textures[i];
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager); if(tex.texture.empty() && texprop->controller.empty())
texture2d = new osg::Texture2D(image); {
if (image) if (i == 0)
texture2d->setTextureSize(image->s(), image->t()); Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename;
continue;
}
if (!tex.texture.empty())
{
const Nif::NiSourceTexture *st = tex.texture.getPtr();
osg::ref_ptr<osg::Image> image = handleSourceTexture(st, imageManager);
texture2d = new osg::Texture2D(image);
if (image)
texture2d->setTextureSize(image->s(), image->t());
}
else
texture2d = new osg::Texture2D;
bool wrapT = tex.clamp & 0x1;
bool wrapS = (tex.clamp >> 1) & 0x1;
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
} }
else else
{
// Texture only comes from NiFlipController, so tex is ignored, set defaults
texture2d = new osg::Texture2D; texture2d = new osg::Texture2D;
texture2d->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
bool wrapT = tex.clamp & 0x1; texture2d->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
bool wrapS = (tex.clamp >> 1) & 0x1; uvSet = 0;
}
texture2d->setWrap(osg::Texture::WRAP_S, wrapS ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
texture2d->setWrap(osg::Texture::WRAP_T, wrapT ? osg::Texture::REPEAT : osg::Texture::CLAMP_TO_EDGE);
unsigned int texUnit = boundTextures.size(); unsigned int texUnit = boundTextures.size();
@ -1590,7 +1603,7 @@ namespace NifOsg
break; break;
} }
boundTextures.push_back(tex.uvSet); boundTextures.push_back(uvSet);
} }
} }
handleTextureControllers(texprop, composite, imageManager, stateset, animflags); handleTextureControllers(texprop, composite, imageManager, stateset, animflags);

Loading…
Cancel
Save