mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 20:53:50 +00:00
Add AlphaController and MaterialColorController
This commit is contained in:
parent
3839d6f777
commit
c54ee16748
4 changed files with 148 additions and 56 deletions
|
@ -2,8 +2,11 @@
|
|||
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Material>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <components/nif/data.hpp>
|
||||
|
||||
namespace NifOsg
|
||||
|
@ -271,5 +274,41 @@ void VisControllerValue::setValue(float time)
|
|||
mNode->setNodeMask(vis ? ~0 : 0);
|
||||
}
|
||||
|
||||
AlphaControllerValue::AlphaControllerValue(osg::StateSet *target, const Nif::NiFloatData *data)
|
||||
: mTarget(target)
|
||||
, mData(data->mKeyList)
|
||||
{
|
||||
}
|
||||
|
||||
void AlphaControllerValue::setValue(float time)
|
||||
{
|
||||
float value = interpKey(mData.mKeys, time);
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(mTarget->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (!mat)
|
||||
return;
|
||||
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.a() = value;
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
MaterialColorControllerValue::MaterialColorControllerValue(osg::StateSet *target, const Nif::NiPosData *data)
|
||||
: mTarget(target), mData(data->mKeyList)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MaterialColorControllerValue::setValue(float time)
|
||||
{
|
||||
osg::Vec3f value = interpKey(mData.mKeys, time);
|
||||
osg::Material* mat = dynamic_cast<osg::Material*>(mTarget->getAttribute(osg::StateAttribute::MATERIAL));
|
||||
if (!mat)
|
||||
return;
|
||||
|
||||
osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK);
|
||||
diffuse.set(value.x(), value.y(), value.z(), diffuse.a());
|
||||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -193,6 +193,30 @@ namespace NifOsg
|
|||
virtual void setValue(float time);
|
||||
};
|
||||
|
||||
class AlphaControllerValue : public ControllerValue, public ValueInterpolator
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
Nif::FloatKeyMap mData;
|
||||
|
||||
public:
|
||||
AlphaControllerValue(osg::StateSet* target, const Nif::NiFloatData *data);
|
||||
|
||||
virtual void setValue(float time);
|
||||
};
|
||||
|
||||
class MaterialColorControllerValue : public ControllerValue, public ValueInterpolator
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
Nif::Vector3KeyMap mData;
|
||||
|
||||
public:
|
||||
MaterialColorControllerValue(osg::StateSet* target, const Nif::NiPosData *data);
|
||||
|
||||
virtual void setValue(float time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -113,61 +113,6 @@ namespace
|
|||
collectMaterialProperties(nifNode->parent, out);
|
||||
}
|
||||
|
||||
void updateMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors)
|
||||
{
|
||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||
osg::Material* mat = new osg::Material;
|
||||
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
||||
for (std::vector<const Nif::Property*>::const_reverse_iterator it = properties.rbegin(); it != properties.rend(); ++it)
|
||||
{
|
||||
const Nif::Property* property = *it;
|
||||
switch (property->recType)
|
||||
{
|
||||
case Nif::RC_NiSpecularProperty:
|
||||
{
|
||||
specFlags = property->flags;
|
||||
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));
|
||||
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.specular, 1.f));
|
||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||
|
||||
break;
|
||||
}
|
||||
case Nif::RC_NiVertexColorProperty:
|
||||
{
|
||||
const Nif::NiVertexColorProperty* vertprop = static_cast<const Nif::NiVertexColorProperty*>(property);
|
||||
if (!hasVertexColors)
|
||||
break;
|
||||
switch (vertprop->flags)
|
||||
{
|
||||
case 0:
|
||||
mat->setColorMode(osg::Material::OFF);
|
||||
break;
|
||||
case 1:
|
||||
mat->setColorMode(osg::Material::EMISSION);
|
||||
break;
|
||||
case 2:
|
||||
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (specFlags == 0)
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f,0.f,0.f,0.f));
|
||||
|
||||
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
// NodeCallback used to update the bone matrices in skeleton space as needed for skinning.
|
||||
class UpdateBone : public osg::NodeCallback
|
||||
{
|
||||
|
@ -438,6 +383,27 @@ namespace NifOsg
|
|||
}
|
||||
}
|
||||
|
||||
void Loader::handleMaterialControllers(const Nif::Property *materialProperty, osg::StateSet *stateset)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
if (ctrl->recType == Nif::RC_NiAlphaController)
|
||||
{
|
||||
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new AlphaControllerValue(stateset, alphactrl->data.getPtr()));
|
||||
createController(alphactrl, dest, 0);
|
||||
}
|
||||
else if (ctrl->recType == Nif::RC_NiMaterialColorController)
|
||||
{
|
||||
const Nif::NiMaterialColorController* matctrl = static_cast<const Nif::NiMaterialColorController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new MaterialColorControllerValue(stateset, matctrl->data.getPtr()));
|
||||
createController(matctrl, dest, 0);
|
||||
}
|
||||
else
|
||||
std::cerr << "Unexpected material controller " << ctrl->recType << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures)
|
||||
{
|
||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||
|
@ -518,7 +484,7 @@ namespace NifOsg
|
|||
// above the actual renderable would be tedious.
|
||||
std::vector<const Nif::Property*> materialProps;
|
||||
collectMaterialProperties(triShape, materialProps);
|
||||
updateMaterialProperties(geometry->getOrCreateStateSet(), materialProps, !data->colors.empty());
|
||||
applyMaterialProperties(geometry->getOrCreateStateSet(), materialProps, !data->colors.empty());
|
||||
}
|
||||
|
||||
void Loader::handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures)
|
||||
|
@ -761,4 +727,63 @@ namespace NifOsg
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors)
|
||||
{
|
||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||
osg::Material* mat = new osg::Material;
|
||||
mat->setColorMode(hasVertexColors ? osg::Material::AMBIENT_AND_DIFFUSE : osg::Material::OFF);
|
||||
// TODO: check if the OpenGL default material values are actually the default NIF material values, for when there's no NiMaterialProperty
|
||||
for (std::vector<const Nif::Property*>::const_reverse_iterator it = properties.rbegin(); it != properties.rend(); ++it)
|
||||
{
|
||||
const Nif::Property* property = *it;
|
||||
switch (property->recType)
|
||||
{
|
||||
case Nif::RC_NiSpecularProperty:
|
||||
{
|
||||
specFlags = property->flags;
|
||||
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));
|
||||
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(matprop->data.specular, 1.f));
|
||||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||
|
||||
if (!matprop->controller.empty())
|
||||
handleMaterialControllers(matprop, stateset);
|
||||
|
||||
break;
|
||||
}
|
||||
case Nif::RC_NiVertexColorProperty:
|
||||
{
|
||||
const Nif::NiVertexColorProperty* vertprop = static_cast<const Nif::NiVertexColorProperty*>(property);
|
||||
if (!hasVertexColors)
|
||||
break;
|
||||
switch (vertprop->flags)
|
||||
{
|
||||
case 0:
|
||||
mat->setColorMode(osg::Material::OFF);
|
||||
break;
|
||||
case 1:
|
||||
mat->setColorMode(osg::Material::EMISSION);
|
||||
break;
|
||||
case 2:
|
||||
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (specFlags == 0)
|
||||
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f,0.f,0.f,0.f));
|
||||
|
||||
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@ namespace NifOsg
|
|||
|
||||
void handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode);
|
||||
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty, osg::StateSet* stateset);
|
||||
|
||||
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
||||
osg::Node* node, std::map<int, int>& boundTextures);
|
||||
|
||||
|
@ -71,6 +73,8 @@ namespace NifOsg
|
|||
// Applies the Properties of the given nifNode onto the StateSet of the given OSG node.
|
||||
void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, std::map<int, int>& boundTextures);
|
||||
|
||||
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors);
|
||||
|
||||
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
||||
|
||||
Nif::NIFFilePtr mNif;
|
||||
|
|
Loading…
Reference in a new issue