mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-12 22:14:42 +00:00
Add AlphaController and MaterialColorController
This commit is contained in:
parent
3839d6f777
commit
c54ee16748
@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
#include <osg/TexMat>
|
#include <osg/TexMat>
|
||||||
|
#include <osg/Material>
|
||||||
#include <osgAnimation/MorphGeometry>
|
#include <osgAnimation/MorphGeometry>
|
||||||
|
|
||||||
|
#include <osg/io_utils>
|
||||||
|
|
||||||
#include <components/nif/data.hpp>
|
#include <components/nif/data.hpp>
|
||||||
|
|
||||||
namespace NifOsg
|
namespace NifOsg
|
||||||
@ -271,5 +274,41 @@ void VisControllerValue::setValue(float time)
|
|||||||
mNode->setNodeMask(vis ? ~0 : 0);
|
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);
|
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
|
#endif
|
||||||
|
@ -113,61 +113,6 @@ namespace
|
|||||||
collectMaterialProperties(nifNode->parent, out);
|
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.
|
// NodeCallback used to update the bone matrices in skeleton space as needed for skinning.
|
||||||
class UpdateBone : public osg::NodeCallback
|
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)
|
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures)
|
||||||
{
|
{
|
||||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||||
@ -518,7 +484,7 @@ namespace NifOsg
|
|||||||
// above the actual renderable would be tedious.
|
// above the actual renderable would be tedious.
|
||||||
std::vector<const Nif::Property*> materialProps;
|
std::vector<const Nif::Property*> materialProps;
|
||||||
collectMaterialProperties(triShape, 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)
|
void Loader::handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures)
|
||||||
@ -761,4 +727,63 @@ namespace NifOsg
|
|||||||
break;
|
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 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,
|
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
||||||
osg::Node* node, std::map<int, int>& boundTextures);
|
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.
|
// 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 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);
|
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
||||||
|
|
||||||
Nif::NIFFilePtr mNif;
|
Nif::NIFFilePtr mNif;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user