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:
Richard Harrison
2017-05-10 09:32:24 +02:00
parent 19a86a6f0d
commit 77517b15fd
16 changed files with 550 additions and 276 deletions

View File

@@ -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)
{
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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.");
}

View File

@@ -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);

View File

@@ -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*

View File

@@ -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:

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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)
{
}

View File

@@ -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:

View File

@@ -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 {

View File

@@ -23,6 +23,7 @@ set(HEADERS
SGSceneUserData.hxx
SGStateAttributeVisitor.hxx
SGTextureStateAttributeVisitor.hxx
SGTransientModelData.hxx
SGUpdateVisitor.hxx
SplicingVisitor.hxx
StateAttributeFactory.hxx

View File

@@ -151,6 +151,7 @@ private:
osg::Node *(*_load_panel)(SGPropertyNode *);
osg::ref_ptr<SGModelData> _model_data;
bool _instantiateEffects;
bool _instantiateMaterialEffects;
string _materialName;

View 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