mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 20:45:33 +00:00
Add FlipController
This commit is contained in:
parent
6c8613ae35
commit
2a92fb57f7
4 changed files with 130 additions and 40 deletions
|
@ -3,6 +3,7 @@
|
|||
#include <osg/MatrixTransform>
|
||||
#include <osg/TexMat>
|
||||
#include <osg/Material>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
#include <osg/io_utils>
|
||||
|
@ -310,5 +311,25 @@ void MaterialColorControllerValue::setValue(float time)
|
|||
mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse);
|
||||
}
|
||||
|
||||
FlipControllerValue::FlipControllerValue(osg::StateSet* target, const Nif::NiFlipController *ctrl,
|
||||
std::vector<osg::ref_ptr<osg::Image> > textures)
|
||||
: mTexSlot(ctrl->mTexSlot)
|
||||
, mDelta(ctrl->mDelta)
|
||||
, mTextures(textures)
|
||||
, mTarget(target)
|
||||
{
|
||||
}
|
||||
|
||||
void FlipControllerValue::setValue(float time)
|
||||
{
|
||||
if (mDelta == 0)
|
||||
return;
|
||||
int curTexture = int(time / mDelta) % mTextures.size();
|
||||
osg::Texture2D* tex = dynamic_cast<osg::Texture2D*>(mTarget->getAttribute(osg::StateAttribute::TEXTURE));
|
||||
if (!tex)
|
||||
return;
|
||||
tex->setImage(mTextures[curTexture].get());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
|
||||
#include <set> //UVController
|
||||
|
||||
// FlipController
|
||||
#include <osg/Image>
|
||||
#include <osg/ref_ptr>
|
||||
|
||||
#include <osg/Timer>
|
||||
|
||||
|
||||
|
@ -217,6 +221,21 @@ namespace NifOsg
|
|||
virtual void setValue(float time);
|
||||
};
|
||||
|
||||
// untested
|
||||
class FlipControllerValue : public ControllerValue
|
||||
{
|
||||
private:
|
||||
osg::StateSet* mTarget;
|
||||
int mTexSlot;
|
||||
float mDelta;
|
||||
std::vector<osg::ref_ptr<osg::Image> > mTextures;
|
||||
|
||||
public:
|
||||
FlipControllerValue(osg::StateSet* target, const Nif::NiFlipController* ctrl, std::vector<osg::ref_ptr<osg::Image> > textures);
|
||||
|
||||
virtual void setValue(float time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -220,7 +220,7 @@ namespace NifOsg
|
|||
}
|
||||
|
||||
mRootNode = parentNode;
|
||||
handleNode(nifNode, parentNode, false, std::map<int, int>());
|
||||
handleNode(nifNode, parentNode, false, std::map<int, int>(), 0);
|
||||
}
|
||||
|
||||
void Loader::loadAsSkeleton(Nif::NIFFilePtr nif, osg::Group *parentNode)
|
||||
|
@ -249,16 +249,16 @@ namespace NifOsg
|
|||
mSkeleton = skel;
|
||||
mRootNode->addChild(mSkeleton);
|
||||
|
||||
handleNode(nifNode, mSkeleton, true, std::map<int, int>());
|
||||
handleNode(nifNode, mSkeleton, true, std::map<int, int>(), 0);
|
||||
}
|
||||
|
||||
void Loader::applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, std::map<int, int>& boundTextures)
|
||||
void Loader::applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
const Nif::PropertyList& props = nifNode->props;
|
||||
for (size_t i = 0; i <props.length();++i)
|
||||
{
|
||||
if (!props[i].empty())
|
||||
handleProperty(props[i].getPtr(), nifNode, applyTo, boundTextures);
|
||||
handleProperty(props[i].getPtr(), nifNode, applyTo, boundTextures, animflags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +276,7 @@ namespace NifOsg
|
|||
}
|
||||
|
||||
void Loader::handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
||||
std::map<int, int> boundTextures)
|
||||
std::map<int, int> boundTextures, int animflags, bool collisionNode)
|
||||
{
|
||||
osg::ref_ptr<osg::MatrixTransform> transformNode;
|
||||
if (createSkeleton)
|
||||
|
@ -294,11 +294,16 @@ namespace NifOsg
|
|||
transformNode->setMatrix(toMatrix(nifNode->trafo));
|
||||
}
|
||||
|
||||
if (nifNode->recType == Nif::RC_NiBSAnimationNode)
|
||||
animflags |= nifNode->flags;
|
||||
|
||||
// Hide collision shapes, but don't skip the subgraph
|
||||
// We still need to animate the hidden bones so the physics system can access them
|
||||
// FIXME: skip creation of the TriShapes
|
||||
if (nifNode->recType == Nif::RC_RootCollisionNode)
|
||||
{
|
||||
collisionNode = true;
|
||||
transformNode->setNodeMask(0);
|
||||
}
|
||||
|
||||
// We could probably skip hidden nodes entirely if they don't have a VisController that
|
||||
// might make them visible later
|
||||
|
@ -308,22 +313,22 @@ namespace NifOsg
|
|||
// Insert bones at position 0 to prevent update order problems (see comment in osg Skeleton.cpp)
|
||||
parentNode->insertChild(0, transformNode);
|
||||
|
||||
applyNodeProperties(nifNode, transformNode, boundTextures);
|
||||
applyNodeProperties(nifNode, transformNode, boundTextures, animflags);
|
||||
|
||||
if (nifNode->recType == Nif::RC_NiTriShape)
|
||||
if (nifNode->recType == Nif::RC_NiTriShape && !collisionNode)
|
||||
{
|
||||
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
|
||||
if (!createSkeleton || triShape->skin.empty())
|
||||
handleTriShape(triShape, transformNode, boundTextures);
|
||||
handleTriShape(triShape, transformNode, boundTextures, animflags);
|
||||
else
|
||||
handleSkinnedTriShape(triShape, transformNode, boundTextures);
|
||||
handleSkinnedTriShape(triShape, transformNode, boundTextures, animflags);
|
||||
|
||||
if (!nifNode->controller.empty())
|
||||
handleMeshControllers(nifNode, transformNode, boundTextures);
|
||||
handleMeshControllers(nifNode, transformNode, boundTextures, animflags);
|
||||
}
|
||||
|
||||
if (!nifNode->controller.empty())
|
||||
handleNodeControllers(nifNode, transformNode);
|
||||
handleNodeControllers(nifNode, transformNode, animflags);
|
||||
|
||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
||||
if(ninode)
|
||||
|
@ -332,12 +337,12 @@ namespace NifOsg
|
|||
for(size_t i = 0;i < children.length();++i)
|
||||
{
|
||||
if(!children[i].empty())
|
||||
handleNode(children[i].getPtr(), transformNode, createSkeleton, boundTextures);
|
||||
handleNode(children[i].getPtr(), transformNode, createSkeleton, boundTextures, animflags, collisionNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::handleMeshControllers(const Nif::Node *nifNode, osg::MatrixTransform *transformNode, const std::map<int, int> &boundTextures)
|
||||
void Loader::handleMeshControllers(const Nif::Node *nifNode, osg::MatrixTransform *transformNode, const std::map<int, int> &boundTextures, int animflags)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
|
@ -349,12 +354,12 @@ namespace NifOsg
|
|||
texUnits.insert(it->first);
|
||||
boost::shared_ptr<ControllerValue> dest(new UVControllerValue(transformNode->getOrCreateStateSet()
|
||||
, uvctrl->data.getPtr(), texUnits));
|
||||
createController(uvctrl, dest, 0);
|
||||
createController(uvctrl, dest, animflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode)
|
||||
void Loader::handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags)
|
||||
{
|
||||
bool seenKeyframeCtrl = false;
|
||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
|
@ -372,7 +377,7 @@ namespace NifOsg
|
|||
boost::shared_ptr<ControllerValue> dest(new KeyframeControllerValue(transformNode, mNif, key->data.getPtr(),
|
||||
transformNode->getMatrix().getRotate(), nifNode->trafo.scale));
|
||||
|
||||
createController(key, dest, 0);
|
||||
createController(key, dest, animflags);
|
||||
seenKeyframeCtrl = true;
|
||||
}
|
||||
}
|
||||
|
@ -380,12 +385,12 @@ namespace NifOsg
|
|||
{
|
||||
const Nif::NiVisController* visctrl = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
||||
boost::shared_ptr<ControllerValue> dest(new VisControllerValue(transformNode, visctrl->data.getPtr()));
|
||||
createController(visctrl, dest, 0);
|
||||
createController(visctrl, dest, animflags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::handleMaterialControllers(const Nif::Property *materialProperty, osg::StateSet *stateset)
|
||||
void Loader::handleMaterialControllers(const Nif::Property *materialProperty, osg::StateSet *stateset, int animflags)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
|
@ -393,20 +398,59 @@ namespace NifOsg
|
|||
{
|
||||
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);
|
||||
createController(alphactrl, dest, animflags);
|
||||
}
|
||||
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);
|
||||
createController(matctrl, dest, animflags);
|
||||
}
|
||||
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::handleTextureControllers(const Nif::Property *texProperty, osg::StateSet *stateset, int animflags)
|
||||
{
|
||||
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
if (ctrl->recType == Nif::RC_NiFlipController)
|
||||
{
|
||||
const Nif::NiFlipController* flipctrl = static_cast<const Nif::NiFlipController*>(ctrl.getPtr());
|
||||
std::vector<osg::ref_ptr<osg::Image> > textures;
|
||||
for (unsigned int i=0; i<flipctrl->mSources.length(); ++i)
|
||||
{
|
||||
Nif::NiSourceTexturePtr st = flipctrl->mSources[i];
|
||||
if (st.empty())
|
||||
continue;
|
||||
|
||||
// FIXME: replace by ResourceHelpers
|
||||
std::string filename (st->filename);
|
||||
Misc::StringUtils::toLower(filename);
|
||||
filename = "textures\\" + filename;
|
||||
size_t found = filename.find(".tga");
|
||||
if (found == std::string::npos)
|
||||
found = filename.find(".bmp");
|
||||
if (found != std::string::npos)
|
||||
filename.replace(found, 4, ".dds");
|
||||
|
||||
// tx_creature_werewolf.dds isn't loading in the correct format without this option
|
||||
osgDB::Options* opts = new osgDB::Options;
|
||||
opts->setOptionString("dds_dxt1_detect_rgba");
|
||||
osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("dds");
|
||||
osgDB::ReaderWriter::ReadResult result = reader->readImage(*resourceManager->getFile(filename.c_str()), opts);
|
||||
textures.push_back(osg::ref_ptr<osg::Image>(result.getImage()));
|
||||
}
|
||||
boost::shared_ptr<ControllerValue> dest(new FlipControllerValue(stateset, flipctrl, textures));
|
||||
createController(flipctrl, dest, animflags);
|
||||
}
|
||||
else
|
||||
std::cerr << "Unexpected texture controller " << ctrl->recName << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||
|
||||
|
@ -486,10 +530,10 @@ namespace NifOsg
|
|||
// above the actual renderable would be tedious.
|
||||
std::vector<const Nif::Property*> materialProps;
|
||||
collectMaterialProperties(triShape, materialProps);
|
||||
applyMaterialProperties(geometry->getOrCreateStateSet(), materialProps, !data->colors.empty());
|
||||
applyMaterialProperties(geometry->getOrCreateStateSet(), materialProps, !data->colors.empty(), animflags);
|
||||
}
|
||||
|
||||
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, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geometry;
|
||||
if(!triShape->controller.empty())
|
||||
|
@ -510,7 +554,7 @@ namespace NifOsg
|
|||
|
||||
if (!geometry.get())
|
||||
geometry = new osg::Geometry;
|
||||
triShapeToGeometry(triShape, geometry.get(), boundTextures);
|
||||
triShapeToGeometry(triShape, geometry.get(), boundTextures, animflags);
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(geometry.get());
|
||||
|
@ -518,10 +562,10 @@ namespace NifOsg
|
|||
parentNode->addChild(geode.get());
|
||||
}
|
||||
|
||||
void Loader::handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures)
|
||||
void Loader::handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||
triShapeToGeometry(triShape, geometry.get(), boundTextures);
|
||||
triShapeToGeometry(triShape, geometry.get(), boundTextures, animflags);
|
||||
|
||||
osg::ref_ptr<osgAnimation::RigGeometry> rig(new osgAnimation::RigGeometry);
|
||||
rig->setSourceGeometry(geometry);
|
||||
|
@ -569,7 +613,7 @@ namespace NifOsg
|
|||
}
|
||||
|
||||
void Loader::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, int animflags)
|
||||
{
|
||||
osg::StateSet* stateset = node->getOrCreateStateSet();
|
||||
|
||||
|
@ -693,6 +737,8 @@ namespace NifOsg
|
|||
std::cerr << "Warning: unhandled internal texture " << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: replace by ResourceHelpers
|
||||
std::string filename (st->filename);
|
||||
Misc::StringUtils::toLower(filename);
|
||||
filename = "textures\\" + filename;
|
||||
|
@ -758,6 +804,7 @@ namespace NifOsg
|
|||
stateset->setTextureAttributeAndModes(i, new osg::Texture2D, osg::StateAttribute::OFF);
|
||||
boundTextures.erase(i);
|
||||
}
|
||||
handleTextureControllers(texprop, stateset, animflags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -773,7 +820,7 @@ namespace NifOsg
|
|||
}
|
||||
}
|
||||
|
||||
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors)
|
||||
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors, int animflags)
|
||||
{
|
||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||
osg::Material* mat = new osg::Material;
|
||||
|
@ -801,7 +848,7 @@ namespace NifOsg
|
|||
mat->setShininess(osg::Material::FRONT_AND_BACK, matprop->data.glossiness);
|
||||
|
||||
if (!matprop->controller.empty())
|
||||
handleMaterialControllers(matprop, stateset);
|
||||
handleMaterialControllers(matprop, stateset, animflags);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -50,30 +50,33 @@ namespace NifOsg
|
|||
private:
|
||||
|
||||
/// @param createSkeleton If true, use an osgAnimation::Bone for NIF nodes, otherwise an osg::MatrixTransform.
|
||||
void handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton, std::map<int, int> boundTextures);
|
||||
void handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
||||
std::map<int, int> boundTextures, int animflags, bool collisionNode=false);
|
||||
|
||||
void handleMeshControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, const std::map<int, int>& boundTextures);
|
||||
void handleMeshControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
void handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode);
|
||||
void handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags);
|
||||
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty, osg::StateSet* stateset);
|
||||
void handleMaterialControllers(const Nif::Property* materialProperty, osg::StateSet* stateset, int animflags);
|
||||
|
||||
void handleTextureControllers(const Nif::Property* texProperty, osg::StateSet* stateset, int animflags);
|
||||
|
||||
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, int animflags);
|
||||
|
||||
// Creates an osg::Geometry object for the given TriShape, populates it, and attaches it to the given node.
|
||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures);
|
||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
// Fills the vertex data for the given TriShape into the given Geometry.
|
||||
void triShapeToGeometry(const Nif::NiTriShape* triShape, osg::Geometry* geom, const std::map<int, int>& boundTextures);
|
||||
void triShapeToGeometry(const Nif::NiTriShape* triShape, osg::Geometry* geom, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
// Creates a skinned osg::Geometry object for the given TriShape, populates it, and attaches it to the given node.
|
||||
void handleSkinnedTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures);
|
||||
void handleSkinnedTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
||||
|
||||
// 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, int animflags);
|
||||
|
||||
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors);
|
||||
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors, int animflags);
|
||||
|
||||
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
||||
|
||||
|
|
Loading…
Reference in a new issue