osgAnimation.TemplateLinearInterpolator是OpenSceneGraph中的一种模板类,用于在动画中进行线性插值计算。
namespace osgAnimation
{
template<typename T> class TemplateLinearInterpolator : public osg::Referenced
{
public:
TemplateLinearInterpolator() {}
TemplateLinearInterpolator(const TemplateLinearInterpolator& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(osgAnimation, TemplateLinearInterpolator)
// 设置关键帧
void setValues(const std::vector<float>& inputTimes, const std::vector<T>& inputValues);
// 获取时间序列
const std::vector<float>& getInputTimes() const;
// 获取值序列
const std::vector<T>& getInputValues() const;
// 计算给定时间节点的插值结果
T operator()(float t) const;
// 拷贝函数
virtual osg::Object* cloneType() const { return new TemplateLinearInterpolator<T>(); }
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new TemplateLinearInterpolator<T>(*this, copyop); }
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const TemplateLinearInterpolator<T>*>(obj)!=NULL; }
virtual const char* className() const { return "TemplateLinearInterpolator"; }
virtual const char* libraryName() const { return "osgAnimation"; }
protected:
// 解决插值线性方程
static void SolveLinearSystem(float a, float b, float c, float d, float& x, float& y, float& z);
virtual ~TemplateLinearInterpolator() {}
std::vector<float> _inputTimes;
std::vector<T> _inputValues;
// 存储线性方程系数
std::vector<float> _factors;
// 存储每段的斜率
std::vector<T> _slopeFactors;
};
}
setValues
void setValues(const std::vector<float>& inputTimes, const std::vector<T>& inputValues);
该函数用于设置关键帧。
参数说明:
getInputTimes
const std::vector<float>& getInputTimes() const;
该函数用于获取时间序列。
返回值:时间向量,表示每个关键帧的时间点,以秒为单位。
getInputValues
const std::vector<T>& getInputValues() const;
该函数用于获取值序列。
返回值:值向量,表示每个关键帧的数值。
operator()
T operator()(float t) const;
该函数用于计算给定时间节点的插值结果。在插值计算中,会根据离该时间节点最近的两个关键帧进行插值计算。
参数说明:
返回值:插值结果,即该时间点对应的数值。
#include <osg/AnimationPath>
#include <osg/Notify>
#include <osgDB/ReadFile>
void test_animation(osg::ref_ptr<osg::Node> root)
{
osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;
transform->addChild(root.get());
// 创建路径动画
osg::ref_ptr<osg::AnimationPath> animationPath = new osg::AnimationPath;
animationPath->setLoopMode(osg::AnimationPath::LOOP);
animationPath->insert(0.0, osg::AnimationPath::ControlPoint(osg::Vec3(0.0, 0.0, 0.0)));
animationPath->insert(1.0, osg::AnimationPath::ControlPoint(osg::Vec3(0.0, 0.0, 5.0)));
animationPath->insert(2.0, osg::AnimationPath::ControlPoint(osg::Vec3(0.0, 0.0, 0.0)));
animationPath->insert(3.0, osg::AnimationPath::ControlPoint(osg::Vec3(0.0, 0.0, -5.0)));
animationPath->insert(4.0, osg::AnimationPath::ControlPoint(osg::Vec3(0.0, 0.0, 0.0)));
// 创建路径动画器
osg::ref_ptr<osg::AnimationPathCallback> animationCallback = new osg::AnimationPathCallback;
animationCallback->setAnimationPath(animationPath.get());
// 将路径动画器绑定到模型节点
transform->setUpdateCallback(animationCallback.get());
// 创建线性插值
osg::ref_ptr<osgAnimation::TemplateLinearInterpolator<osg::Vec3>> interpolator = new osgAnimation::TemplateLinearInterpolator<osg::Vec3>;
// 设置关键帧
std::vector<float> inputTimes{ 0.0, 1.0, 2.0, 3.0, 4.0 };
std::vector<osg::Vec3> inputValues{ osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 0.0, 1.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 0.0, -1.0), osg::Vec3(0.0, 0.0, 0.0) };
interpolator->setValues(inputTimes, inputValues);
// 创建插值动画器
osg::ref_ptr<osgAnimation::Vec3LinearSampler> linearSampler = new osgAnimation::Vec3LinearSampler;
linearSampler->setInterpolator(interpolator.get());
osg::ref_ptr<osgAnimation::Vec3LinearChannel> linearChannel = new osgAnimation::Vec3LinearChannel;
linearChannel->setSampler(linearSampler.get());
linearChannel->setTargetName("position");
osg::ref_ptr<osgAnimation::Animation> animation = new osgAnimation::Animation;
animation->addChannel(linearChannel.get());
// 将插值动画器绑定到模型节点
transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setAttributeAndModes(new osg::BlendFunc, osg::StateAttribute::ON);
transform->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
transform->getOrCreateStateSet()->setAttributeAndModes(animation.get());
// 创建场景根节点
osg::ref_ptr<osg::Group> rootnode = new osg::Group;
rootnode->addChild(transform.get());
// 创建视窗
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setUpViewInWindow(50, 50, 800, 600);
viewer->setSceneData(rootnode.get());
viewer->realize();
viewer->run();
}
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("cow.osgt");
test_animation(model);
return 0;
}
示例代码将模型绑定到动画路径和插值动画器上,实现了物体在动画路径上运动,并在其中穿插着值的插值变化。