Add AlphaController and MaterialColorController

pull/638/head
scrawl 10 years ago
parent 3839d6f777
commit c54ee16748

@ -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…
Cancel
Save