因为之前用过一段时间osg,所以这个例子对我来说最难的地方居然是:osgWidget :sob:。虽然也借着这个例子深入的看了一些相关的类,但还是有一些东西不太明白。因为osg有专门例子介绍这一块,所以这里暂时不深入了解了。
就这个例子而言,主要讲的是osg自带的一些时间曲线插值算法。
EaseMotion
说是EaseMotion,其实这是一个大类,在这个cpp里包含了很多的时间插值算法,比如OutQuad、InQuad等等。这个例子把所有的算法都做了一个演示。看着好像很多,其实跳到cpp里细看的话,会发现其实就是一个个getValueAt函数而已,随便摘抄一段:
```c++
/// Linear function
struct LinearFunction
{
inline static void getValueAt(float t, float& result) { result = t;}
};
/// Quad function
struct OutQuadFunction
{
inline static void getValueAt(float t, float& result) { result = - (t * (t -2.0));}
};
struct InQuadFunction
{
inline static void getValueAt(float t, float& result) { result = t*t;}
};
参数t是当前时间,result是插值出来的结果,很简单的吧。对算法有兴趣的可以深入了解哦。
绕的有点远,回来接着说EaseMotion。想用这个类需要4个参数:
- startValue 初始值,一般给0
- duration 持续时间,我理解为插值范围,比如你想让插的值在0-10之间,就可以把这个值设为10
- changeValue 看网上一些博客里是把这个值称为改变值,不过在源码里这个值是这样用的`result = result * _changeValue + _startValue;`,所以看上去更像是个系数或倍数
- TimeBehaviour 插值的方式,可选clamp、loop,前一个在给的值超出duration会取极值,后者是会将值映射到duration范围内后再插值。把你讲晕了吧,那我的目的就达到了:laughing:
new出EaseMotion后,想用的时候,就把时间值传进去,得到一个插值的值来用。在这个例子里使用了两种方式来取插值结果:
### getValueAt
直接取。给一个值,返回一个值。
```c++
for (float i=0; i<M_DURATION; i+=M_DURATION/256.)
v->push_back(osg::Vec3(i*30, motion->getValueAt(i)*30, 0)); // 采样值放大30倍
update & getValue
持续的取。就是给一个增量值,然后取出当前的插值结果。这种方法一般用在回调函数中来持续的进行更新。
```c++
_motion->update(t - _previous);
_previous = t;
mt->setMatrix(osg::Matrix::translate(_pos * _motion->getValue()));
# NodeCallback
在osg里除了EventHandler这种“全局”的处理器之外,如果想对某个节点单独处理的话,就可以用osg::NodeCallback这个类了。这个类的虚函数`operator()`方法会在每次view更新的时候调用。在这个例子里就实现了一个这样的类来更新小球的位置:
```c++
class EaseMotionSampler : public osg::NodeCallback
{
public:
......
void operator()(osg::Node* node, osg::NodeVisitor* nv) {
if (!_motion.valid()) return;
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);
if (!mt) return;
double t = nv->getFrameStamp()->getSimulationTime();
if (_previous == 0) _previous = t;
_motion->update(t - _previous);
_previous = t;
mt->setMatrix(osg::Matrix::translate(_pos * _motion->getValue()));
}
......
};
代码很简单,不多解释。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。