Allow animations to take an object as the centre and axis.
Applicable to / works with rotate, translate and knob. Once the axis object-name has been used it will be hidden, however it still can be used for object-name animations. The hiding of the axis object is a useful guide as to what is left to be wired up to animations.
This allows the follow to work (on a combined ASI / Mach instrument).
<animation>
<type>rotate</type>
<object-name>asi-needle</object-name>
...
<axis>
<object-name>airspeed-asi-axis</object-name>
</axis>
</animation>
<animation>
<type>rotate</type>
<object-name>asi-mach-scale</object-name>
...
<axis>
<object-name>airspeed-asi-axis</object-name>
</axis>
</animation>
This commit is contained in:
@@ -122,9 +122,8 @@ private:
|
||||
std::vector<SGLineSegmentf> _lineSegments;
|
||||
};
|
||||
|
||||
SGInteractionAnimation::SGInteractionAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGInteractionAnimation::SGInteractionAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
class SGInteractionAnimation : public SGAnimation {
|
||||
public:
|
||||
SGInteractionAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGInteractionAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual void install(osg::Node& node);
|
||||
private:
|
||||
class LineCollector;
|
||||
|
||||
@@ -93,12 +93,8 @@ public:
|
||||
double _prev_value;
|
||||
};
|
||||
|
||||
SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options,
|
||||
const std::string &path, int i) :
|
||||
SGAnimation(configNode, modelRoot),
|
||||
_options(options)
|
||||
SGLightAnimation::SGLightAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData), _options(modelData.getOptions())
|
||||
{
|
||||
_light_type = getConfig()->getStringValue("light-type");
|
||||
_position = SGVec3d( getConfig()->getDoubleValue("position/x"), getConfig()->getDoubleValue("position/y"), getConfig()->getDoubleValue("position/z") );
|
||||
@@ -113,11 +109,11 @@ SGLightAnimation::SGLightAnimation(const SGPropertyNode* configNode,
|
||||
_cutoff = getConfig()->getDoubleValue("cutoff");
|
||||
_near = getConfig()->getDoubleValue("near-m");
|
||||
_far = getConfig()->getDoubleValue("far-m");
|
||||
_key = path + ";" + boost::lexical_cast<std::string>( i );
|
||||
_key = modelData.getPath() + ";" + boost::lexical_cast<std::string>(modelData.getIndex() );
|
||||
|
||||
SGConstPropertyNode_ptr dim_factor = configNode->getChild("dim-factor");
|
||||
SGConstPropertyNode_ptr dim_factor = modelData.getConfigNode()->getChild("dim-factor");
|
||||
if (dim_factor.valid()) {
|
||||
_animationValue = read_value(dim_factor, modelRoot, "", 0, 1);
|
||||
_animationValue = read_value(dim_factor, modelData.getModelRoot(), "", 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -416,15 +416,11 @@ private:
|
||||
} // namespace
|
||||
|
||||
|
||||
SGMaterialAnimation::SGMaterialAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options*
|
||||
options, const string &path) :
|
||||
SGAnimation(configNode, modelRoot),
|
||||
texturePathList(options->getDatabasePathList())
|
||||
SGMaterialAnimation::SGMaterialAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData), texturePathList(modelData.getOptions()->getDatabasePathList())
|
||||
{
|
||||
if (configNode->hasChild("global"))
|
||||
SG_LOG(SG_IO, SG_ALERT, path <<
|
||||
if (modelData.getConfigNode()->hasChild("global"))
|
||||
SG_LOG(SG_IO, SG_ALERT, modelData.getPath() <<
|
||||
": Use of <global> in material animation is "
|
||||
"no longer supported.");
|
||||
}
|
||||
|
||||
@@ -21,9 +21,7 @@
|
||||
|
||||
class SGMaterialAnimation : public SGAnimation {
|
||||
public:
|
||||
SGMaterialAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options,const std::string &path);
|
||||
SGMaterialAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
virtual void install(osg::Node& node);
|
||||
static SGPropertyNode_ptr makeEffectProperties(const SGPropertyNode* animProp);
|
||||
|
||||
@@ -301,12 +301,10 @@ private:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SGPickAnimation::SGPickAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGPickAnimation::SGPickAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
std::vector<SGPropertyNode_ptr> names =
|
||||
configNode->getChildren("proxy-name");
|
||||
std::vector<SGPropertyNode_ptr> names = modelData.getConfigNode()->getChildren("proxy-name");
|
||||
for (unsigned i = 0; i < names.size(); ++i) {
|
||||
_proxyNames.push_back(names[i]->getStringValue());
|
||||
}
|
||||
@@ -373,12 +371,12 @@ osg::StateSet* sharedHighlightStateSet()
|
||||
}
|
||||
|
||||
void
|
||||
SGPickAnimation::apply(osg::Group& group)
|
||||
SGPickAnimation::apply(simgear::SGTransientModelData &modelData)
|
||||
{
|
||||
if (_objectNames.empty() && _proxyNames.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Group& group = *modelData.getNode()->asGroup();
|
||||
group.traverse(*this);
|
||||
|
||||
// iterate over all group children
|
||||
@@ -738,16 +736,15 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGKnobAnimation::SGKnobAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGPickAnimation(configNode, modelRoot)
|
||||
SGKnobAnimation::SGKnobAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGPickAnimation(modelData)
|
||||
{
|
||||
SGSharedPtr<SGExpressiond> value = read_value(configNode, modelRoot, "-deg",
|
||||
SGSharedPtr<SGExpressiond> value = read_value(modelData.getConfigNode(), modelData.getModelRoot(), "-deg",
|
||||
-SGLimitsd::max(), SGLimitsd::max());
|
||||
_animationValue = value->simplify();
|
||||
|
||||
|
||||
readRotationCenterAndAxis(_center, _axis);
|
||||
readRotationCenterAndAxis(modelData.getNode(), _center, _axis, modelData);
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
@@ -807,15 +804,14 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGSliderAnimation::SGSliderAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGPickAnimation(configNode, modelRoot)
|
||||
SGSliderAnimation::SGSliderAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGPickAnimation(modelData)
|
||||
{
|
||||
SGSharedPtr<SGExpressiond> value = read_value(configNode, modelRoot, "-m",
|
||||
SGSharedPtr<SGExpressiond> value = read_value(modelData.getConfigNode(), modelData.getModelRoot(), "-m",
|
||||
-SGLimitsd::max(), SGLimitsd::max());
|
||||
_animationValue = value->simplify();
|
||||
|
||||
_axis = readTranslateAxis(configNode);
|
||||
_axis = readTranslateAxis(modelData.getConfigNode());
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
|
||||
@@ -35,11 +35,10 @@ class SGSceneUserData;
|
||||
|
||||
class SGPickAnimation : public SGAnimation {
|
||||
public:
|
||||
SGPickAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGPickAnimation(simgear::SGTransientModelData &modelData);
|
||||
|
||||
// override so we can treat object-name specially
|
||||
virtual void apply(osg::Group& group);
|
||||
virtual void apply(simgear::SGTransientModelData &modelData);
|
||||
|
||||
void apply(osg::Node* node);
|
||||
protected:
|
||||
@@ -59,8 +58,7 @@ private:
|
||||
class SGKnobAnimation : public SGPickAnimation
|
||||
{
|
||||
public:
|
||||
SGKnobAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGKnobAnimation(simgear::SGTransientModelData &modelData);
|
||||
|
||||
/**
|
||||
* by default mouse wheel up corresponds to increment (CW)
|
||||
@@ -101,8 +99,7 @@ private:
|
||||
class SGSliderAnimation : public SGPickAnimation
|
||||
{
|
||||
public:
|
||||
SGSliderAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGSliderAnimation(simgear::SGTransientModelData &modelData);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@@ -266,7 +266,7 @@ sgLoad3DModel_internal(const SGPath& path,
|
||||
|
||||
osg::ref_ptr<SGReaderWriterOptions> options;
|
||||
options = SGReaderWriterOptions::copyOrCreate(dbOptions);
|
||||
|
||||
|
||||
SGPath modelpath(path);
|
||||
SGPath texturepath(path);
|
||||
SGPath modelDir(modelpath.dir());
|
||||
@@ -525,6 +525,8 @@ sgLoad3DModel_internal(const SGPath& path,
|
||||
group = static_cast<Group*>(modelWithEffects.get());
|
||||
}
|
||||
|
||||
simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.local8BitStr());
|
||||
|
||||
for (unsigned i = 0; i < animation_nodes.size(); ++i) {
|
||||
if (previewMode && animation_nodes[i]->hasChild("nopreview")) {
|
||||
PropertyList names(animation_nodes[i]->getChildren("object-name"));
|
||||
@@ -533,10 +535,13 @@ sgLoad3DModel_internal(const SGPath& path,
|
||||
} // of object-names in the animation
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the model data for the node currently being animated.
|
||||
*/
|
||||
modelData.LoadAnimationValuesForElement(animation_nodes[i], i);
|
||||
|
||||
/// OSGFIXME: duh, why not only model?????
|
||||
SGAnimation::animate(group.get(), animation_nodes[i], prop_root,
|
||||
options.get(), path.local8BitStr(), i);
|
||||
SGAnimation::animate(modelData);
|
||||
}
|
||||
|
||||
if (!needTransform && group->getNumChildren() < 2) {
|
||||
|
||||
@@ -373,25 +373,23 @@ class SGTrackToAnimation::UpdateCallback:
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
SGTrackToAnimation::SGTrackToAnimation( osg::Node* node,
|
||||
const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot ):
|
||||
SGAnimation(configNode, modelRoot),
|
||||
SGTrackToAnimation::SGTrackToAnimation(simgear::SGTransientModelData &modelData):
|
||||
SGAnimation(modelData),
|
||||
_target_group(0),
|
||||
_slave_group(0)
|
||||
{
|
||||
std::string target = configNode->getStringValue("target-name");
|
||||
std::string target = modelData.getConfigNode()->getStringValue("target-name");
|
||||
FindGroupVisitor target_finder(target);
|
||||
node->accept(target_finder);
|
||||
modelData.getNode()->accept(target_finder);
|
||||
|
||||
if( !(_target_group = target_finder.getGroup()) )
|
||||
log(SG_ALERT, "target not found: '" + target + '\'');
|
||||
|
||||
std::string slave = configNode->getStringValue("slave-name");
|
||||
std::string slave = modelData.getConfigNode()->getStringValue("slave-name");
|
||||
if( !slave.empty() )
|
||||
{
|
||||
FindGroupVisitor slave_finder(slave);
|
||||
node->accept(slave_finder);
|
||||
modelData.getNode()->accept(slave_finder);
|
||||
_slave_group = slave_finder.getGroup();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ class SGTrackToAnimation:
|
||||
public SGAnimation
|
||||
{
|
||||
public:
|
||||
SGTrackToAnimation( osg::Node* node,
|
||||
const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot );
|
||||
SGTrackToAnimation(simgear::SGTransientModelData &modelData);
|
||||
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
#include <osgDB/Registry>
|
||||
#include <osgDB/Input>
|
||||
#include <osgDB/ParameterOutput>
|
||||
#include <osg/TemplatePrimitiveFunctor>
|
||||
|
||||
#include <simgear/bvh/BVHGroup.hxx>
|
||||
#include <simgear/bvh/BVHLineGeometry.hxx>
|
||||
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
@@ -46,6 +50,8 @@
|
||||
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||
#include <simgear/scene/util/SGStateAttributeVisitor.hxx>
|
||||
#include <simgear/scene/util/StateAttributeFactory.hxx>
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/util/SGTransientModelData.hxx>
|
||||
|
||||
#include "vg/vgu.h"
|
||||
|
||||
@@ -71,6 +77,99 @@ using namespace simgear;
|
||||
// Static utility functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/*
|
||||
* collect line segments from nodes within the hierarchy.
|
||||
*/
|
||||
class LineCollector : public osg::NodeVisitor {
|
||||
struct LineCollector_LinePrimitiveFunctor {
|
||||
LineCollector_LinePrimitiveFunctor() : _lineCollector(0) { }
|
||||
void operator() (const osg::Vec3&, bool) { }
|
||||
void operator() (const osg::Vec3& v1, const osg::Vec3& v2, bool)
|
||||
{
|
||||
if (_lineCollector) _lineCollector->addLine(v1, v2);
|
||||
}
|
||||
void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&, bool) { }
|
||||
void operator() (const osg::Vec3&, const osg::Vec3&, const osg::Vec3&, const osg::Vec3&, bool) { }
|
||||
LineCollector* _lineCollector;
|
||||
};
|
||||
|
||||
public:
|
||||
LineCollector() : osg::NodeVisitor(osg::NodeVisitor::NODE_VISITOR, osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { }
|
||||
|
||||
virtual void apply(osg::Geode& geode)
|
||||
{
|
||||
osg::TemplatePrimitiveFunctor<LineCollector_LinePrimitiveFunctor> pf;
|
||||
pf._lineCollector = this;
|
||||
for (unsigned i = 0; i < geode.getNumDrawables(); ++i) {
|
||||
geode.getDrawable(i)->accept(pf);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
virtual void apply(osg::Transform& transform)
|
||||
{
|
||||
osg::Matrix matrix = _matrix;
|
||||
if (transform.computeLocalToWorldMatrix(_matrix, this))
|
||||
traverse(transform);
|
||||
_matrix = matrix;
|
||||
}
|
||||
|
||||
const std::vector<SGLineSegmentf>& getLineSegments() const
|
||||
{
|
||||
return _lineSegments;
|
||||
}
|
||||
|
||||
void addLine(const osg::Vec3& v1, const osg::Vec3& v2)
|
||||
{
|
||||
// Trick to get the ends in the right order.
|
||||
// Use the x axis in the original coordinate system. Choose the
|
||||
// most negative x-axis as the one pointing forward
|
||||
SGVec3f tv1(toSG(_matrix.preMult(v1)));
|
||||
SGVec3f tv2(toSG(_matrix.preMult(v2)));
|
||||
if (tv1[0] > tv2[0])
|
||||
_lineSegments.push_back(SGLineSegmentf(tv1, tv2));
|
||||
else
|
||||
_lineSegments.push_back(SGLineSegmentf(tv2, tv1));
|
||||
}
|
||||
|
||||
void addBVHElements(osg::Node& node, simgear::BVHLineGeometry::Type type)
|
||||
{
|
||||
if (_lineSegments.empty())
|
||||
return;
|
||||
|
||||
SGSceneUserData* userData;
|
||||
userData = SGSceneUserData::getOrCreateSceneUserData(&node);
|
||||
|
||||
simgear::BVHNode* bvNode = userData->getBVHNode();
|
||||
if (!bvNode && _lineSegments.size() == 1) {
|
||||
simgear::BVHLineGeometry* bvLine;
|
||||
bvLine = new simgear::BVHLineGeometry(_lineSegments.front(), type);
|
||||
userData->setBVHNode(bvLine);
|
||||
return;
|
||||
}
|
||||
|
||||
simgear::BVHGroup* group = new simgear::BVHGroup;
|
||||
if (bvNode)
|
||||
group->addChild(bvNode);
|
||||
|
||||
for (unsigned i = 0; i < _lineSegments.size(); ++i) {
|
||||
simgear::BVHLineGeometry* bvLine;
|
||||
bvLine = new simgear::BVHLineGeometry(_lineSegments[i], type);
|
||||
group->addChild(bvLine);
|
||||
}
|
||||
userData->setBVHNode(group);
|
||||
}
|
||||
|
||||
private:
|
||||
osg::Matrix _matrix;
|
||||
std::vector<SGLineSegmentf> _lineSegments;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up the transform matrix for a translation.
|
||||
*/
|
||||
@@ -325,17 +424,16 @@ struct DoDrawArraysVisitor : public osg::NodeVisitor {
|
||||
};
|
||||
}
|
||||
|
||||
SGAnimation::SGAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation::SGAnimation(simgear::SGTransientModelData &modelData) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_found(false),
|
||||
_configNode(configNode),
|
||||
_modelRoot(modelRoot)
|
||||
_configNode(modelData.getConfigNode()),
|
||||
_modelRoot(modelData.getModelRoot())
|
||||
{
|
||||
_name = configNode->getStringValue("name", "");
|
||||
_enableHOT = configNode->getBoolValue("enable-hot", true);
|
||||
_name = modelData.getConfigNode()->getStringValue("name", "");
|
||||
_enableHOT = modelData.getConfigNode()->getBoolValue("enable-hot", true);
|
||||
std::vector<SGPropertyNode_ptr> objectNames =
|
||||
configNode->getChildren("object-name");
|
||||
modelData.getConfigNode()->getChildren("object-name");
|
||||
for (unsigned i = 0; i < objectNames.size(); ++i)
|
||||
_objectNames.push_back(objectNames[i]->getStringValue());
|
||||
}
|
||||
@@ -363,79 +461,76 @@ SGAnimation::~SGAnimation()
|
||||
}
|
||||
|
||||
bool
|
||||
SGAnimation::animate(osg::Node* node, const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options,
|
||||
const std::string &path, int i)
|
||||
SGAnimation::animate(simgear::SGTransientModelData &modelData)
|
||||
{
|
||||
std::string type = configNode->getStringValue("type", "none");
|
||||
std::string type = modelData.getConfigNode()->getStringValue("type", "none");
|
||||
if (type == "alpha-test") {
|
||||
SGAlphaTestAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGAlphaTestAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "billboard") {
|
||||
SGBillboardAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGBillboardAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "blend") {
|
||||
SGBlendAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGBlendAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "dist-scale") {
|
||||
SGDistScaleAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGDistScaleAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "flash") {
|
||||
SGFlashAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGFlashAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "interaction") {
|
||||
SGInteractionAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGInteractionAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "material") {
|
||||
SGMaterialAnimation animInst(configNode, modelRoot, options, path);
|
||||
animInst.apply(node);
|
||||
SGMaterialAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "noshadow") {
|
||||
SGShadowAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGShadowAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "pick") {
|
||||
SGPickAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGPickAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "knob") {
|
||||
SGKnobAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGKnobAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "slider") {
|
||||
SGSliderAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGSliderAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "range") {
|
||||
SGRangeAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGRangeAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "rotate" || type == "spin") {
|
||||
SGRotateAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGRotateAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "scale") {
|
||||
SGScaleAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGScaleAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "select") {
|
||||
SGSelectAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGSelectAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "shader") {
|
||||
SGShaderAnimation animInst(configNode, modelRoot, options);
|
||||
animInst.apply(node);
|
||||
SGShaderAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "textranslate" || type == "texrotate" ||
|
||||
type == "textrapezoid" || type == "texmultiple") {
|
||||
SGTexTransformAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGTexTransformAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "timed") {
|
||||
SGTimedAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGTimedAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "locked-track") {
|
||||
SGTrackToAnimation animInst(node, configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGTrackToAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "translate") {
|
||||
SGTranslateAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGTranslateAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "light") {
|
||||
SGLightAnimation animInst(configNode, modelRoot, options, path, i);
|
||||
animInst.apply(node);
|
||||
SGLightAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else if (type == "null" || type == "none" || type.empty()) {
|
||||
SGGroupAnimation animInst(configNode, modelRoot);
|
||||
animInst.apply(node);
|
||||
SGGroupAnimation anim(modelData);
|
||||
anim.apply(modelData);
|
||||
} else
|
||||
return false;
|
||||
|
||||
@@ -479,19 +574,25 @@ SGAnimation::createAnimationGroup(osg::Group& parent)
|
||||
void
|
||||
SGAnimation::apply(osg::Group& group)
|
||||
{
|
||||
// the trick is to first traverse the children and then
|
||||
// possibly splice in a new group node if required.
|
||||
// Else we end up in a recursive loop where we infinitly insert new
|
||||
// groups in between
|
||||
traverse(group);
|
||||
// the trick is to first traverse the children and then
|
||||
// possibly splice in a new group node if required.
|
||||
// Else we end up in a recursive loop where we infinitly insert new
|
||||
// groups in between
|
||||
traverse(group);
|
||||
|
||||
// Note that this algorithm preserves the order of the child objects
|
||||
// like they appear in the object-name tags.
|
||||
// The timed animations require this
|
||||
osg::ref_ptr<osg::Group> animationGroup;
|
||||
std::list<std::string>::const_iterator nameIt;
|
||||
for (nameIt = _objectNames.begin(); nameIt != _objectNames.end(); ++nameIt)
|
||||
installInGroup(*nameIt, group, animationGroup);
|
||||
// Note that this algorithm preserves the order of the child objects
|
||||
// like they appear in the object-name tags.
|
||||
// The timed animations require this
|
||||
osg::ref_ptr<osg::Group> animationGroup;
|
||||
std::list<std::string>::const_iterator nameIt;
|
||||
for (nameIt = _objectNames.begin(); nameIt != _objectNames.end(); ++nameIt)
|
||||
installInGroup(*nameIt, group, animationGroup);
|
||||
}
|
||||
|
||||
void
|
||||
SGAnimation::apply(simgear::SGTransientModelData &modelData)
|
||||
{
|
||||
apply(modelData.getNode());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -553,13 +654,138 @@ SGVec3d SGAnimation::readVec3( const std::string& name,
|
||||
{
|
||||
return readVec3(*_configNode, name, suffix, def);
|
||||
}
|
||||
/**
|
||||
* Visitor to find a group by its name.
|
||||
*/
|
||||
class FindGroupVisitor :
|
||||
public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
FindGroupVisitor(const std::string& name) :
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),
|
||||
_name(name),
|
||||
_group(0)
|
||||
{
|
||||
if (name.empty())
|
||||
SG_LOG(SG_IO, SG_WARN, "FindGroupVisitor: empty name provided");
|
||||
}
|
||||
|
||||
osg::Group* getGroup() const
|
||||
{
|
||||
return _group;
|
||||
}
|
||||
|
||||
virtual void apply(osg::Group& group)
|
||||
{
|
||||
if (_name != group.getName())
|
||||
return traverse(group);
|
||||
|
||||
if (!_group)
|
||||
_group = &group;
|
||||
|
||||
// Different paths can exists for example with a picking animation (pick
|
||||
// render group)
|
||||
else if (_group != &group)
|
||||
SG_LOG
|
||||
(
|
||||
SG_IO,
|
||||
SG_WARN,
|
||||
"FindGroupVisitor: name not unique '" << _name << "'"
|
||||
);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::string _name;
|
||||
osg::Group *_group;
|
||||
};
|
||||
|
||||
/*
|
||||
* If an object is specified in the axis tag it is assumed to be a single line segment with two vertices.
|
||||
* This function will take action when axis has an object-name tag and the corresponding object
|
||||
* can be found within the hierarchy.
|
||||
*/
|
||||
bool SGAnimation::setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& center, SGVec3d &axis, simgear::SGTransientModelData &modelData) const
|
||||
{
|
||||
if (_configNode->hasValue("axis/object-name"))
|
||||
{
|
||||
std::string axis_object_name = _configNode->getStringValue("axis/object-name");
|
||||
|
||||
if (!axis_object_name.empty())
|
||||
{
|
||||
/*
|
||||
* First search the currently loaded cache map to see if this axis object has already been located.
|
||||
* If we find it, we use it.
|
||||
*/
|
||||
const SGLineSegment<double> *axisSegment = modelData.getAxisDefinition(axis_object_name);
|
||||
if (!axisSegment)
|
||||
{
|
||||
/*
|
||||
* Find the object by name
|
||||
*/
|
||||
FindGroupVisitor axis_object_name_finder(axis_object_name);
|
||||
rootNode->accept(axis_object_name_finder);
|
||||
osg::Group *object_group = axis_object_name_finder.getGroup();
|
||||
|
||||
if (object_group)
|
||||
{
|
||||
/*
|
||||
* we have found the object group (for the axis). This should be two vertices
|
||||
* Now process this (with the line collector) to get the vertices.
|
||||
* Once we have that we can then calculate the center and the affected axes.
|
||||
*/
|
||||
object_group->setNodeMask(0xffffffff);
|
||||
LineCollector lineCollector;
|
||||
object_group->accept(lineCollector);
|
||||
std::vector<SGLineSegmentf> segs = lineCollector.getLineSegments();
|
||||
|
||||
if (!segs.empty())
|
||||
{
|
||||
/*
|
||||
* Store the axis definition in the map; as once hidden it will not be possible
|
||||
* to locate it again (and in any case it will be quicker to do it this way)
|
||||
* This makes the axis/center static; there could be a use case for making this
|
||||
* dynamic (and rebuilding the transforms), in which case this would need to
|
||||
* do something different with the object; possibly storing a reference to the node
|
||||
* so it can be extracted for dynamic processing.
|
||||
*/
|
||||
SGLineSegmentd segd(*(segs.begin()));
|
||||
axisSegment = modelData.addAxisDefinition(axis_object_name,segd);
|
||||
/*
|
||||
* Hide the axis object. This also helps the modeller to know which axis animations are unassigned.
|
||||
*/
|
||||
object_group->setNodeMask(0);
|
||||
}
|
||||
else
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Could find a valid line segment for animation: " << axis_object_name);
|
||||
}
|
||||
else
|
||||
SG_LOG(SG_INPUT, SG_ALERT, "Could not find at least one of the following objects for axis animation: " << axis_object_name);
|
||||
}
|
||||
if (axisSegment)
|
||||
{
|
||||
center = 0.5*(axisSegment->getStart() + axisSegment->getEnd());
|
||||
axis = axisSegment->getEnd() - axisSegment->getStart();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// factored out to share with SGKnobAnimation
|
||||
void SGAnimation::readRotationCenterAndAxis( SGVec3d& center,
|
||||
SGVec3d& axis ) const
|
||||
void SGAnimation::readRotationCenterAndAxis(osg::Node *_rootNode, SGVec3d& center,
|
||||
SGVec3d& axis, simgear::SGTransientModelData &modelData) const
|
||||
{
|
||||
center = SGVec3d::zeros();
|
||||
if (setCenterAndAxisFromObject(_rootNode, center, axis, modelData))
|
||||
{
|
||||
if (8 * SGLimitsd::min() < norm(axis))
|
||||
axis = normalize(axis);
|
||||
return;
|
||||
}
|
||||
|
||||
if( _configNode->hasValue("axis/x1-m") )
|
||||
{
|
||||
SGVec3d v1 = readVec3("axis", "1-m"), // axis/[xyz]1-m
|
||||
@@ -663,9 +889,8 @@ SGAnimation::getCondition() const
|
||||
// Ok, that is to build a subgraph from different other
|
||||
// graph nodes. I guess that this stems from the time where modellers
|
||||
// could not build hierarchical trees ...
|
||||
SGGroupAnimation::SGGroupAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot):
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGGroupAnimation::SGGroupAnimation(simgear::SGTransientModelData &modelData):
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -705,13 +930,12 @@ public:
|
||||
SGSharedPtr<SGExpressiond const> _animationValue;
|
||||
};
|
||||
|
||||
SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGTranslateAnimation::SGTranslateAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
_condition = getCondition();
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = read_value(configNode, modelRoot, "-m",
|
||||
value = read_value(modelData.getConfigNode(), modelData.getModelRoot(), "-m",
|
||||
-SGLimitsd::max(), SGLimitsd::max());
|
||||
_animationValue = value->simplify();
|
||||
if (_animationValue)
|
||||
@@ -719,7 +943,9 @@ SGTranslateAnimation::SGTranslateAnimation(const SGPropertyNode* configNode,
|
||||
else
|
||||
_initialValue = 0;
|
||||
|
||||
_axis = readTranslateAxis(configNode);
|
||||
SGVec3d _center;
|
||||
if (modelData.getNode() && !setCenterAndAxisFromObject(modelData.getNode(), _center, _axis, modelData))
|
||||
_axis = readTranslateAxis(modelData.getConfigNode());
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
@@ -932,16 +1158,15 @@ SGVec3d readTranslateAxis(const SGPropertyNode* configNode)
|
||||
return axis;
|
||||
}
|
||||
|
||||
SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGRotateAnimation::SGRotateAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
std::string type = configNode->getStringValue("type", "");
|
||||
std::string type = modelData.getConfigNode()->getStringValue("type", "");
|
||||
_isSpin = (type == "spin");
|
||||
|
||||
_condition = getCondition();
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = read_value(configNode, modelRoot, "-deg",
|
||||
value = read_value(modelData.getConfigNode(), modelData.getModelRoot(), "-deg",
|
||||
-SGLimitsd::max(), SGLimitsd::max());
|
||||
_animationValue = value->simplify();
|
||||
if (_animationValue)
|
||||
@@ -949,7 +1174,7 @@ SGRotateAnimation::SGRotateAnimation(const SGPropertyNode* configNode,
|
||||
else
|
||||
_initialValue = 0;
|
||||
|
||||
readRotationCenterAndAxis(_center, _axis);
|
||||
readRotationCenterAndAxis(modelData.getNode(), _center, _axis, modelData);
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
@@ -1012,92 +1237,91 @@ public:
|
||||
SGSharedPtr<SGExpressiond const> _animationValue[3];
|
||||
};
|
||||
|
||||
SGScaleAnimation::SGScaleAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGScaleAnimation::SGScaleAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
_condition = getCondition();
|
||||
|
||||
// default offset/factor for all directions
|
||||
double offset = configNode->getDoubleValue("offset", 0);
|
||||
double factor = configNode->getDoubleValue("factor", 1);
|
||||
double offset = modelData.getConfigNode()->getDoubleValue("offset", 0);
|
||||
double factor = modelData.getConfigNode()->getDoubleValue("factor", 1);
|
||||
|
||||
SGSharedPtr<SGExpressiond> inPropExpr;
|
||||
|
||||
std::string inputPropertyName;
|
||||
inputPropertyName = configNode->getStringValue("property", "");
|
||||
inputPropertyName = modelData.getConfigNode()->getStringValue("property", "");
|
||||
if (inputPropertyName.empty()) {
|
||||
inPropExpr = new SGConstExpression<double>(0);
|
||||
} else {
|
||||
SGPropertyNode* inputProperty;
|
||||
inputProperty = modelRoot->getNode(inputPropertyName, true);
|
||||
inputProperty = modelData.getModelRoot()->getNode(inputPropertyName, true);
|
||||
inPropExpr = new SGPropertyExpression<double>(inputProperty);
|
||||
}
|
||||
|
||||
SGInterpTable* interpTable = read_interpolation_table(configNode);
|
||||
SGInterpTable* interpTable = read_interpolation_table(modelData.getConfigNode());
|
||||
if (interpTable) {
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = new SGInterpTableExpression<double>(inPropExpr, interpTable);
|
||||
_animationValue[0] = value->simplify();
|
||||
_animationValue[1] = value->simplify();
|
||||
_animationValue[2] = value->simplify();
|
||||
} else if (configNode->getBoolValue("use-personality", false)) {
|
||||
} else if (modelData.getConfigNode()->getBoolValue("use-personality", false)) {
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, modelData.getConfigNode(),
|
||||
"x-factor", "x-offset",
|
||||
factor, offset);
|
||||
double minClip = configNode->getDoubleValue("x-min", 0);
|
||||
double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
|
||||
double minClip = modelData.getConfigNode()->getDoubleValue("x-min", 0);
|
||||
double maxClip = modelData.getConfigNode()->getDoubleValue("x-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[0] = value->simplify();
|
||||
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, modelData.getConfigNode(),
|
||||
"y-factor", "y-offset",
|
||||
factor, offset);
|
||||
minClip = configNode->getDoubleValue("y-min", 0);
|
||||
maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
|
||||
minClip = modelData.getConfigNode()->getDoubleValue("y-min", 0);
|
||||
maxClip = modelData.getConfigNode()->getDoubleValue("y-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[1] = value->simplify();
|
||||
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, configNode,
|
||||
value = new SGPersonalityScaleOffsetExpression(inPropExpr, modelData.getConfigNode(),
|
||||
"z-factor", "z-offset",
|
||||
factor, offset);
|
||||
minClip = configNode->getDoubleValue("z-min", 0);
|
||||
maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
|
||||
minClip = modelData.getConfigNode()->getDoubleValue("z-min", 0);
|
||||
maxClip = modelData.getConfigNode()->getDoubleValue("z-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[2] = value->simplify();
|
||||
} else {
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = read_factor_offset(configNode, inPropExpr, "x-factor", "x-offset");
|
||||
double minClip = configNode->getDoubleValue("x-min", 0);
|
||||
double maxClip = configNode->getDoubleValue("x-max", SGLimitsd::max());
|
||||
value = read_factor_offset(modelData.getConfigNode(), inPropExpr, "x-factor", "x-offset");
|
||||
double minClip = modelData.getConfigNode()->getDoubleValue("x-min", 0);
|
||||
double maxClip = modelData.getConfigNode()->getDoubleValue("x-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[0] = value->simplify();
|
||||
|
||||
value = read_factor_offset(configNode, inPropExpr, "y-factor", "y-offset");
|
||||
minClip = configNode->getDoubleValue("y-min", 0);
|
||||
maxClip = configNode->getDoubleValue("y-max", SGLimitsd::max());
|
||||
value = read_factor_offset(modelData.getConfigNode(), inPropExpr, "y-factor", "y-offset");
|
||||
minClip = modelData.getConfigNode()->getDoubleValue("y-min", 0);
|
||||
maxClip = modelData.getConfigNode()->getDoubleValue("y-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[1] = value->simplify();
|
||||
|
||||
value = read_factor_offset(configNode, inPropExpr, "z-factor", "z-offset");
|
||||
minClip = configNode->getDoubleValue("z-min", 0);
|
||||
maxClip = configNode->getDoubleValue("z-max", SGLimitsd::max());
|
||||
value = read_factor_offset(modelData.getConfigNode(), inPropExpr, "z-factor", "z-offset");
|
||||
minClip = modelData.getConfigNode()->getDoubleValue("z-min", 0);
|
||||
maxClip = modelData.getConfigNode()->getDoubleValue("z-max", SGLimitsd::max());
|
||||
value = new SGClipExpression<double>(value, minClip, maxClip);
|
||||
_animationValue[2] = value->simplify();
|
||||
}
|
||||
_initialValue[0] = configNode->getDoubleValue("x-starting-scale", 1);
|
||||
_initialValue[0] *= configNode->getDoubleValue("x-factor", factor);
|
||||
_initialValue[0] += configNode->getDoubleValue("x-offset", offset);
|
||||
_initialValue[1] = configNode->getDoubleValue("y-starting-scale", 1);
|
||||
_initialValue[1] *= configNode->getDoubleValue("y-factor", factor);
|
||||
_initialValue[1] += configNode->getDoubleValue("y-offset", offset);
|
||||
_initialValue[2] = configNode->getDoubleValue("z-starting-scale", 1);
|
||||
_initialValue[2] *= configNode->getDoubleValue("z-factor", factor);
|
||||
_initialValue[2] += configNode->getDoubleValue("z-offset", offset);
|
||||
_center[0] = configNode->getDoubleValue("center/x-m", 0);
|
||||
_center[1] = configNode->getDoubleValue("center/y-m", 0);
|
||||
_center[2] = configNode->getDoubleValue("center/z-m", 0);
|
||||
_initialValue[0] = modelData.getConfigNode()->getDoubleValue("x-starting-scale", 1);
|
||||
_initialValue[0] *= modelData.getConfigNode()->getDoubleValue("x-factor", factor);
|
||||
_initialValue[0] += modelData.getConfigNode()->getDoubleValue("x-offset", offset);
|
||||
_initialValue[1] = modelData.getConfigNode()->getDoubleValue("y-starting-scale", 1);
|
||||
_initialValue[1] *= modelData.getConfigNode()->getDoubleValue("y-factor", factor);
|
||||
_initialValue[1] += modelData.getConfigNode()->getDoubleValue("y-offset", offset);
|
||||
_initialValue[2] = modelData.getConfigNode()->getDoubleValue("z-starting-scale", 1);
|
||||
_initialValue[2] *= modelData.getConfigNode()->getDoubleValue("z-factor", factor);
|
||||
_initialValue[2] += modelData.getConfigNode()->getDoubleValue("z-offset", offset);
|
||||
_center[0] = modelData.getConfigNode()->getDoubleValue("center/x-m", 0);
|
||||
_center[1] = modelData.getConfigNode()->getDoubleValue("center/y-m", 0);
|
||||
_center[2] = modelData.getConfigNode()->getDoubleValue("center/z-m", 0);
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
@@ -1234,9 +1458,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGDistScaleAnimation::SGDistScaleAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGDistScaleAnimation::SGDistScaleAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1390,9 +1613,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGFlashAnimation::SGFlashAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGFlashAnimation::SGFlashAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1475,9 +1697,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGBillboardAnimation::SGBillboardAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGBillboardAnimation::SGBillboardAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1548,39 +1769,38 @@ private:
|
||||
double _maxStaticValue;
|
||||
};
|
||||
|
||||
SGRangeAnimation::SGRangeAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGRangeAnimation::SGRangeAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
_condition = getCondition();
|
||||
|
||||
std::string inputPropertyName;
|
||||
inputPropertyName = configNode->getStringValue("min-property", "");
|
||||
inputPropertyName = modelData.getConfigNode()->getStringValue("min-property", "");
|
||||
if (!inputPropertyName.empty()) {
|
||||
SGPropertyNode* inputProperty;
|
||||
inputProperty = modelRoot->getNode(inputPropertyName, true);
|
||||
inputProperty = modelData.getModelRoot()->getNode(inputPropertyName, true);
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = new SGPropertyExpression<double>(inputProperty);
|
||||
|
||||
value = read_factor_offset(configNode, value, "min-factor", "min-offset");
|
||||
value = read_factor_offset(modelData.getConfigNode(), value, "min-factor", "min-offset");
|
||||
_minAnimationValue = value->simplify();
|
||||
}
|
||||
inputPropertyName = configNode->getStringValue("max-property", "");
|
||||
inputPropertyName = modelData.getConfigNode()->getStringValue("max-property", "");
|
||||
if (!inputPropertyName.empty()) {
|
||||
SGPropertyNode* inputProperty;
|
||||
inputProperty = modelRoot->getNode(inputPropertyName.c_str(), true);
|
||||
inputProperty = modelData.getModelRoot()->getNode(inputPropertyName.c_str(), true);
|
||||
|
||||
SGSharedPtr<SGExpressiond> value;
|
||||
value = new SGPropertyExpression<double>(inputProperty);
|
||||
|
||||
value = read_factor_offset(configNode, value, "max-factor", "max-offset");
|
||||
value = read_factor_offset(modelData.getConfigNode(), value, "max-factor", "max-offset");
|
||||
_maxAnimationValue = value->simplify();
|
||||
}
|
||||
|
||||
_initialValue[0] = configNode->getDoubleValue("min-m", 0);
|
||||
_initialValue[0] *= configNode->getDoubleValue("min-factor", 1);
|
||||
_initialValue[1] = configNode->getDoubleValue("max-m", SGLimitsf::max());
|
||||
_initialValue[1] *= configNode->getDoubleValue("max-factor", 1);
|
||||
_initialValue[0] = modelData.getConfigNode()->getDoubleValue("min-m", 0);
|
||||
_initialValue[0] *= modelData.getConfigNode()->getDoubleValue("min-factor", 1);
|
||||
_initialValue[1] = modelData.getConfigNode()->getDoubleValue("max-m", SGLimitsf::max());
|
||||
_initialValue[1] *= modelData.getConfigNode()->getDoubleValue("max-factor", 1);
|
||||
}
|
||||
|
||||
osg::Group*
|
||||
@@ -1610,9 +1830,8 @@ SGRangeAnimation::createAnimationGroup(osg::Group& parent)
|
||||
// Implementation of a select animation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SGSelectAnimation::SGSelectAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGSelectAnimation::SGSelectAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1640,9 +1859,8 @@ SGSelectAnimation::createAnimationGroup(osg::Group& parent)
|
||||
// Implementation of alpha test animation
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SGAlphaTestAnimation::SGAlphaTestAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGAlphaTestAnimation::SGAlphaTestAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1793,10 +2011,8 @@ public:
|
||||
};
|
||||
|
||||
|
||||
SGBlendAnimation::SGBlendAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot)
|
||||
: SGAnimation(configNode, modelRoot),
|
||||
_animationValue(read_value(configNode, modelRoot, "", 0, 1))
|
||||
SGBlendAnimation::SGBlendAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData), _animationValue(read_value(modelData.getConfigNode(), modelData.getModelRoot(), "", 0, 1))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1919,9 +2135,8 @@ private:
|
||||
};
|
||||
|
||||
|
||||
SGTimedAnimation::SGTimedAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot)
|
||||
: SGAnimation(configNode, modelRoot)
|
||||
SGTimedAnimation::SGTimedAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1960,9 +2175,8 @@ private:
|
||||
SGSharedPtr<const SGCondition> _condition;
|
||||
};
|
||||
|
||||
SGShadowAnimation::SGShadowAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGShadowAnimation::SGShadowAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2130,9 +2344,8 @@ private:
|
||||
osg::Matrix _matrix;
|
||||
};
|
||||
|
||||
SGTexTransformAnimation::SGTexTransformAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGTexTransformAnimation::SGTexTransformAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
#include <simgear/structure/SGExpression.hxx>
|
||||
#include <simgear/scene/util/SGTransientModelData.hxx>
|
||||
|
||||
// Has anyone done anything *really* stupid, like making min and max macros?
|
||||
#ifdef min
|
||||
@@ -42,21 +43,19 @@ SGVec3d readTranslateAxis(const SGPropertyNode* configNode);
|
||||
*/
|
||||
class SGAnimation : protected osg::NodeVisitor {
|
||||
public:
|
||||
SGAnimation(const SGPropertyNode* configNode, SGPropertyNode* modelRoot);
|
||||
SGAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual ~SGAnimation();
|
||||
|
||||
static bool animate(osg::Node* node, const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options,
|
||||
const std::string &path, int i);
|
||||
static bool animate(simgear::SGTransientModelData &modelData);
|
||||
|
||||
protected:
|
||||
void apply(osg::Node* node);
|
||||
virtual void apply(osg::Group& group);
|
||||
|
||||
virtual void install(osg::Node& node);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
|
||||
virtual void apply(osg::Group& group);
|
||||
virtual void apply(simgear::SGTransientModelData &modelData);
|
||||
|
||||
/**
|
||||
* Read a 3d vector from the configuration property node.
|
||||
@@ -77,7 +76,8 @@ protected:
|
||||
const std::string& suffix = "",
|
||||
const SGVec3d& def = SGVec3d::zeros() ) const;
|
||||
|
||||
void readRotationCenterAndAxis(SGVec3d& center, SGVec3d& axis) const;
|
||||
void readRotationCenterAndAxis(osg::Node *rootNode, SGVec3d& center, SGVec3d& axis, simgear::SGTransientModelData &modelData) const;
|
||||
bool setCenterAndAxisFromObject(osg::Node *rootNode, SGVec3d& center, SGVec3d &axis, simgear::SGTransientModelData &modelData) const;
|
||||
|
||||
SGExpressiond* readOffsetValue(const char* tag_name) const;
|
||||
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
|
||||
class SGGroupAnimation : public SGAnimation {
|
||||
public:
|
||||
SGGroupAnimation(const SGPropertyNode*, SGPropertyNode*);
|
||||
SGGroupAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
};
|
||||
|
||||
@@ -139,8 +139,7 @@ public:
|
||||
|
||||
class SGTranslateAnimation : public SGAnimation {
|
||||
public:
|
||||
SGTranslateAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGTranslateAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -157,8 +156,7 @@ private:
|
||||
|
||||
class SGRotateAnimation : public SGAnimation {
|
||||
public:
|
||||
SGRotateAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGRotateAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
SGSharedPtr<const SGCondition> _condition;
|
||||
@@ -176,8 +174,7 @@ private:
|
||||
|
||||
class SGScaleAnimation : public SGAnimation {
|
||||
public:
|
||||
SGScaleAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGScaleAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -194,8 +191,7 @@ private:
|
||||
|
||||
class SGDistScaleAnimation : public SGAnimation {
|
||||
public:
|
||||
SGDistScaleAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGDistScaleAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
class Transform;
|
||||
};
|
||||
@@ -207,8 +203,7 @@ public:
|
||||
|
||||
class SGFlashAnimation : public SGAnimation {
|
||||
public:
|
||||
SGFlashAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGFlashAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
public:
|
||||
class Transform;
|
||||
@@ -221,8 +216,7 @@ public:
|
||||
|
||||
class SGBillboardAnimation : public SGAnimation {
|
||||
public:
|
||||
SGBillboardAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGBillboardAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
class Transform;
|
||||
};
|
||||
@@ -234,8 +228,7 @@ public:
|
||||
|
||||
class SGRangeAnimation : public SGAnimation {
|
||||
public:
|
||||
SGRangeAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGRangeAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -252,8 +245,7 @@ private:
|
||||
|
||||
class SGSelectAnimation : public SGAnimation {
|
||||
public:
|
||||
SGSelectAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGSelectAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
};
|
||||
|
||||
@@ -264,8 +256,7 @@ public:
|
||||
|
||||
class SGAlphaTestAnimation : public SGAnimation {
|
||||
public:
|
||||
SGAlphaTestAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGAlphaTestAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual void install(osg::Node& node);
|
||||
};
|
||||
|
||||
@@ -276,8 +267,7 @@ public:
|
||||
|
||||
class SGBlendAnimation : public SGAnimation {
|
||||
public:
|
||||
SGBlendAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGBlendAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
virtual void install(osg::Node& node);
|
||||
private:
|
||||
@@ -293,8 +283,7 @@ private:
|
||||
|
||||
class SGTimedAnimation : public SGAnimation {
|
||||
public:
|
||||
SGTimedAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGTimedAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -307,8 +296,7 @@ private:
|
||||
|
||||
class SGShadowAnimation : public SGAnimation {
|
||||
public:
|
||||
SGShadowAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGShadowAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -321,8 +309,7 @@ private:
|
||||
|
||||
class SGTexTransformAnimation : public SGAnimation {
|
||||
public:
|
||||
SGTexTransformAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot);
|
||||
SGTexTransformAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class Transform;
|
||||
@@ -349,9 +336,7 @@ private:
|
||||
|
||||
class SGShaderAnimation : public SGAnimation {
|
||||
public:
|
||||
SGShaderAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options);
|
||||
SGShaderAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
private:
|
||||
class UpdateCallback;
|
||||
@@ -364,10 +349,7 @@ private:
|
||||
|
||||
class SGLightAnimation : public SGAnimation {
|
||||
public:
|
||||
SGLightAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options* options,
|
||||
const std::string &path, int i);
|
||||
SGLightAnimation(simgear::SGTransientModelData &modelData);
|
||||
virtual osg::Group* createAnimationGroup(osg::Group& parent);
|
||||
virtual void install(osg::Node& node);
|
||||
private:
|
||||
|
||||
@@ -185,15 +185,12 @@ static void create_specular_highlights(osg::Node *node)
|
||||
#endif
|
||||
|
||||
|
||||
SGShaderAnimation::SGShaderAnimation(const SGPropertyNode* configNode,
|
||||
SGPropertyNode* modelRoot,
|
||||
const osgDB::Options*
|
||||
options) :
|
||||
SGAnimation(configNode, modelRoot)
|
||||
SGShaderAnimation::SGShaderAnimation(simgear::SGTransientModelData &modelData) :
|
||||
SGAnimation(modelData)
|
||||
{
|
||||
const SGPropertyNode* node = configNode->getChild("texture");
|
||||
const SGPropertyNode* node = modelData.getConfigNode()->getChild("texture");
|
||||
if (node)
|
||||
_effect_texture = SGLoadTexture2D(node->getStringValue(), options);
|
||||
_effect_texture = SGLoadTexture2D(node->getStringValue(), modelData.getOptions());
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -23,6 +23,7 @@ set(HEADERS
|
||||
SGSceneUserData.hxx
|
||||
SGStateAttributeVisitor.hxx
|
||||
SGTextureStateAttributeVisitor.hxx
|
||||
SGTransientModelData.hxx
|
||||
SGUpdateVisitor.hxx
|
||||
SplicingVisitor.hxx
|
||||
StateAttributeFactory.hxx
|
||||
|
||||
@@ -151,6 +151,7 @@ private:
|
||||
|
||||
osg::Node *(*_load_panel)(SGPropertyNode *);
|
||||
osg::ref_ptr<SGModelData> _model_data;
|
||||
|
||||
bool _instantiateEffects;
|
||||
bool _instantiateMaterialEffects;
|
||||
string _materialName;
|
||||
|
||||
98
simgear/scene/util/SGTransientModelData.hxx
Normal file
98
simgear/scene/util/SGTransientModelData.hxx
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2017 Richard Harrison rjh@zaretto.com
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifndef SGTRANSIENTMODELDATA_HXX
|
||||
#define SGTRANSIENTMODELDATA_HXX 1
|
||||
#include <simgear/math/SGGeometry.hxx>
|
||||
|
||||
namespace simgear
|
||||
{
|
||||
typedef std::map<std::string, SGLineSegment<double>> SGAxisDefinitionMap;
|
||||
|
||||
/*
|
||||
* Transient data that is used with a given context for any given model.
|
||||
* Currently used during the model load to provide a consistent set of data when creating the animations.
|
||||
* - provides a map to allow reuse of axis definitions
|
||||
* Expected possible future expansion for improvements to model light animations.
|
||||
* - typical usage for the SGAnimation::animate() call would be to create one of these like this
|
||||
* simgear::SGTransientModelData modelData(group.get(), prop_root, options.get(), path.local8BitStr());
|
||||
* This will create the basic transient model data that doesn't change between invocations of animate()
|
||||
* then to adapt the model data for an animation element use the LoadAnimationValuesForElement method, e.g.
|
||||
* modelData.LoadAnimationValuesForElement(animation_nodes[i], i);
|
||||
*/
|
||||
class SGTransientModelData {
|
||||
public:
|
||||
// fully specified constructor. Probably not relevant as creating an object this specified implies setting up for an individual animation element, which will preclude
|
||||
// the use of the axis definition cache between objects.
|
||||
SGTransientModelData(osg::Node* _node, const SGPropertyNode* _configNode, SGPropertyNode* _modelRoot, osgDB::Options* _options, const std::string &_path, int _i)
|
||||
: node(_node), configNode(_configNode), modelRoot(_modelRoot), options(_options), path(_path), index(_i)
|
||||
{}
|
||||
// usual form of construction - setup the elements that are constant, and specify the config node and index via LoadAnimationValuesForElement
|
||||
SGTransientModelData(osg::Node* _node, SGPropertyNode* _modelRoot, osgDB::Options* _options, const std::string &_path)
|
||||
: node(_node), configNode(nullptr), modelRoot(_modelRoot), options(_options), path(_path), index(0)
|
||||
{}
|
||||
|
||||
/*
|
||||
* Loads the animation values required for a specific element.
|
||||
*/
|
||||
void LoadAnimationValuesForElement(const SGPropertyNode* _configNode, int _index)
|
||||
{
|
||||
configNode = _configNode;
|
||||
index = _index;
|
||||
}
|
||||
|
||||
osg::Node* getNode() { return node; }
|
||||
const SGPropertyNode* getConfigNode() { return configNode; }
|
||||
SGPropertyNode* getModelRoot() { return modelRoot; }
|
||||
const osgDB::Options* getOptions() { return options; }
|
||||
const std::string &getPath() { return path; }
|
||||
int getIndex() { return index; }
|
||||
|
||||
/*
|
||||
* Find an already located axis definition object line segment. Returns null if nothing found.
|
||||
*/
|
||||
const SGLineSegment<double> *getAxisDefinition(const std::string axis_object_name)
|
||||
{
|
||||
SGAxisDefinitionMap::const_iterator axisDefinition = axisDefinitions.find(axis_object_name);
|
||||
|
||||
if (axisDefinition != axisDefinitions.end())
|
||||
{
|
||||
return &(axisDefinition->second);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Add an axis definition line segment. Always returns the line segment that has been added.
|
||||
*/
|
||||
const SGLineSegment<double> *addAxisDefinition(const std::string object_name, const SGLineSegment<double> &line)
|
||||
{
|
||||
axisDefinitions[object_name] = line;
|
||||
return getAxisDefinition(object_name);
|
||||
}
|
||||
|
||||
private:
|
||||
osg::Node* node = nullptr;
|
||||
const SGPropertyNode* configNode = nullptr;
|
||||
SGPropertyNode* modelRoot = nullptr;
|
||||
const osgDB::Options* options = nullptr;
|
||||
const std::string path;
|
||||
int index = 0;
|
||||
SGAxisDefinitionMap axisDefinitions;
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user