查看: 1883|回复: 16

请问这样的动画效果应该如何实现?

[复制链接]

该用户从未签到

发表于 2010-4-19 19:23:38 | 显示全部楼层 |阅读模式
比如一排柱子,从左到右依次从小增大,观察者的视点也随着从左到右移动
这样的动画效果应该用什么函数来实现呢?那么多种回调,都看晕了……
OSG刚上手,这问题可能比较菜……

该用户从未签到

发表于 2010-4-19 19:33:21 | 显示全部楼层
柱子有高度吧,假设你视点依次移动到柱子最高点,就像爬楼梯,观察视点可以使用Manipulator来实现位置变化,因为里面自动调用getViewMatrix,需要做的就是setMatrix,继承Manipulator,重写里面的handle与setMatrix。
我也是新手,建议而已

该用户从未签到

 楼主| 发表于 2010-4-19 19:40:54 | 显示全部楼层
假如把最左边的柱子编号为1,然后依次类推
我想要的效果就是,1号柱子从0增长到一定长度后不再增长(就像金箍棒那样的……),然后2号柱子再增长,然后3号…等等…
这样的效果应该如何实现呢?

该用户从未签到

发表于 2010-4-19 20:07:49 | 显示全部楼层
若柱子是一个几何节点,按照你的意思,那就是动态绘制几何体,只需改变几何对象的VertexArray中的顶点数据即可。
循环遍历每一个柱子对象,并设置updatecallback,如果想控制柱子的先后顺序,可以使用一个计数器变量,即前一个柱子高度生长完成后将计数器加1,并在调用updatecallback中判断这个计数器是否与当前柱子的编号相同,若相同,则继续,否则等待;
viewer里有一个渲染线程,而主调用函数也是一个线程,所以可能出现主函数执行完而渲染线程仍在依次执行中,可能我表达的不清楚。

还有一个,就是柱子上有纹理时,要考虑纹理映射是否出现repeat,或自动生成纹理。

我新手,只能是一起学习,等待高手指点

该用户从未签到

 楼主| 发表于 2010-4-19 20:23:38 | 显示全部楼层
ls讲的好细,大感谢:)
我主要还是updatecallback不太知道具体该怎么写
柱子逐个变化如何控制呢?

该用户从未签到

 楼主| 发表于 2010-4-19 20:43:54 | 显示全部楼层
lss的意思该不会是给每个柱子加一个updatecallback吧?

该用户从未签到

 楼主| 发表于 2010-4-19 21:54:49 | 显示全部楼层
跪求指导呀
海带泪~~
其他都可以自己解决,就是不太会逐个控制柱子。如何在updatecallback里逐个控制物体呢?重点是逐个!

该用户从未签到

发表于 2010-4-20 08:27:16 | 显示全部楼层
自己写一些标志量来控制就可以了,妥善运用nv->getTraversalNumber()来获取已运行帧数

该用户从未签到

 楼主| 发表于 2010-4-20 10:50:01 | 显示全部楼层
我其实简化了实际的情况
实际是有800多个柱子,而且在树中的结构是杂乱的……我只能通过柱子节点的名称去访问他们……
除了给每个加一个callback有什么别的建议吗

该用户从未签到

发表于 2010-4-20 12:28:59 | 显示全部楼层
用一个callback就可以了,然后在其中保存一个<名字,节点指针>的映射表,这之后就可以随时通过名称去访问和操作对应的节点,控制一个或多个柱子运动。其他的方法也没有问题,这完全取决于您的程序结构,而不取决于OSG~~

该用户从未签到

 楼主| 发表于 2010-4-20 13:37:44 | 显示全部楼层
一直不明白,callback怎么同时控制多个节点?
array能给个例子吗?

该用户从未签到

发表于 2010-4-20 14:25:52 | 显示全部楼层
这只是一个C++类结构的问题,如果您有这样一个派生类
class YourCallback : public osg:: NodeCallback
{
    ...
    std::map<std::string, osg::Node*> _nodeMap;
};
并且您已经向这个map中记录了所有的节点指针,那么在operator中操作其中任何一个节点都是可行的

该用户从未签到

 楼主| 发表于 2010-4-20 18:12:41 | 显示全部楼层
本帖最后由 ZV1 于 2010-4-20 20:14 编辑

我还是不太明白callback的机制,那里面的traverse做什么用的?
是说能遍历所有的节点,执行相应的操作吗?
我写了一下,貌似不是啊= =

该用户从未签到

发表于 2010-4-21 08:32:04 | 显示全部楼层
traverse能遍历所有的节点,执行相应的操作吗
很显然没有这样的说法,您需要仔细学习一下《快速入门指导》
NodeCallback是可以累积的,也就是说,一个回调执行中可以直接调用它的邻近回调(NestedCallback),方法就是使用traverse()

该用户从未签到

 楼主| 发表于 2010-4-21 16:42:08 | 显示全部楼层
快速入门,OSG三维渲染引擎设计与实践,还有OSG程序设计教程中关于callback的段落我都反复的阅读过了……
里面所有的例子都在callback类重写operator时最后写了一句traverse,但这些例子都没有添加nestedcallback。这时traverse又有什么用呢?traverse函数里具体执行了什么操作?
还有个问题,operator函数的两个参数,osg::Node* node, osg::NodeVisitor* nv,是在运行时都是自动传入的吗?传入的都是什么呢?NodeVisitor不是不能实例化的吗?

该用户从未签到

 楼主| 发表于 2010-4-21 16:48:35 | 显示全部楼层
//nodevisitor可以判断出哪个是需要的结点
virtual void operator() (osg::Node* node, osg::NodeVisitor* nv)
{
    //验证得到的结点是不是MatrixTransform
    osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
    //如果是的
    if (nv && transform && nv->getFrameStamp())
    {
    //得到参考时间与当前时间差,用来计算cos然后改变移动值
        double time = nv->getFrameStamp()->getReferenceTime();
        transform->setMatrix(osg::Matrix::translate(0.0f,1.0f+cosf(time*m_angularVelocity),0.0f));
    }
    //向下遍历node,以便找到transform
    traverse(node,nv);
}

我摘了OSG程序设计里的例子。作者提到:“向下遍历node,以便找到transform”,所以我才留下了“遍历所有的节点,执行相应的操作”的印象。不知我的理解和作者原意的偏差在哪里?以及,traverse已经是遍历了,nv作为参数填在里面做何用?

我这只大菜鸟已经把这个地方灌的全是浓浓的菜味了。实在抱歉:)

该用户从未签到

发表于 2010-4-22 08:36:29 | 显示全部楼层
但这些例子都没有添加nestedcallback。这时traverse又有什么用呢?traverse函数里具体执行了什么操作?
我上次可能忘了说了,NodeVisitor的遍历也是需要traverse()来继续的,NodeCallback的执行是通过系统内部的UpdateVisitor来完成的,因此回调中的traverse()不可或缺。当然,如果您希望立即中断更新回调访问器的遍历,那么也可以反过来操作

osg::Node* node, osg::NodeVisitor* nv,是在运行时都是自动传入的吗?传入的都是什么呢?
是自动传入的,即设置和执行回调的节点本身,以及更新访问器UpdateVisitor的实例

NodeVisitor不是不能实例化的吗
您如何得出这样的结论?

我这只大菜鸟已经把这个地方灌的全是浓浓的菜味了
一个可以迅速提高自己,并且不用每天等待别人来看您的问题的秘籍——当您对某个函数,例如traverse的实现有疑问时,去看一看它的实现代码,这简直是手到擒来的事情。我已经给了您足够的提示:UpdateVisitor用来遍历所有有回调的节点,traverse用于继续节点树的访问。那么,下一步该做什么就一目了然了。不要用“菜”这个词来作借口,我不相信您读不懂100行左右的代码内容,并且它还是十分规范的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表