查看: 2924|回复: 10

实现随手画线为什么不正确?

[复制链接]

该用户从未签到

发表于 2009-12-17 10:02:38 | 显示全部楼层 |阅读模式
我用这样的EventHandler实现随手画线,为什么只有第一条线会出现,但是在第二次点击鼠标的时候才出现,而以后再画的线就不出现了?


    case osgGA::GUIEventAdapter:USH:
        current_geometry_ = new Geometry;
        geode_->addDrawable(current_geometry_.get());
        vertices = new Vec2Array;
        vertices->push_back(Vec2(ea.getX(), ea.getY()));
        current_geometry_->setVertexArray(vertices);
        colors = new Vec3Array;
        colors->push_back(Vec3(1, 0, 0));
        current_geometry_->setColorArray(colors);
        colors = NULL;
        current_geometry_->setColorBinding(Geometry::BIND_OVERALL);
        current_geometry_->addPrimitiveSet(new DrawArrays(GL_LINE_STRIP, 0, 1));
        return true;

    case osgGA::GUIEventAdapter:RAG:
        vertices = dynamic_cast<Vec2Array*>(current_geometry_->getVertexArray());
        vertices->push_back(Vec2(ea.getX(), ea.getY()));
        dynamic_cast<DrawArrays*>(current_geometry_->getPrimitiveSet(0))->setCount(vertices->size());
        return true;

    case osgGA::GUIEventAdapter::RELEASE:
        current_geometry_ = NULL;
        return true;

其中current_geometry_和geode_为类变量,并且我已经将geode_设为Object::DYNAMIC了

该用户从未签到

发表于 2009-12-17 12:11:27 | 显示全部楼层
您可以尝试在绘制结束后执行dirtyBound()来更新节点的包围体层次,不过说实话您的做法估计比较浪费内存,分配一个Geometry就够了,不必每次按键都新建Geometry~~

该用户从未签到

 楼主| 发表于 2009-12-17 12:28:36 | 显示全部楼层
根据您的说法,我在RELEASE,DRAG,PUSH返回之前都调用了一下geode_->dirtyBound()
但貌似没什么效果

该用户从未签到

发表于 2009-12-17 13:21:29 | 显示全部楼层
看起来您是要在DRAG过程中不断增加点,那么还需要在每次DRAG事件结束前更新显示列表和图元:
current_geometry_->getPrimitiveSet(0)->dirty();
current_geometry_->dirtyDisplayList();

说实话这种做法也就是试验一下,效率实在过低了~~如果是实际应用的要求,那么(1)不要每次都重新分配对象,只操作一个对象即可,(2)动态绘制的对象不要用显示列表,而是用VBO

该用户从未签到

 楼主| 发表于 2009-12-17 13:26:15 | 显示全部楼层
好,谢谢,这样可以出现我要的那个DRAG过程中增加点的效果了
关于您说的(1)不要每次都重新分配对象,这个我了解,然后大概也知道该怎么做
不过(2)用VBO,是什么东西?

该用户从未签到

发表于 2009-12-17 13:34:32 | 显示全部楼层
VertexBufferObject
用getVertexArray获取数组指针,并可以更改数组指针存放的数据。最后调用此数组dirty()完成更新。

该用户从未签到

 楼主| 发表于 2009-12-17 14:04:21 | 显示全部楼层
您的意思是在
Geometry::setUseVertexBufferObjects(true)
Geometry::getOrCreateBufferData()得到VertexBufferData,然后每次PUSH的时候调用VertexBufferData::addArray()?

该用户从未签到

发表于 2009-12-17 14:39:31 | 显示全部楼层
有关VBO的相关信息请参见OpenGL文档,这是OpenGL中目前效率最高的动态绘制解决方案,当然立即模式也可以;显示列表在动态绘制方面最不得力,它更适于静态物体的表现。

setUseVertexBufferObjects(true)是正确的,然后您完全不用自己操作VBO对象。只需要在修改了Vec3Array* array的数据之后,执行array->dirty()就可以了,其它操作均不变

该用户从未签到

 楼主| 发表于 2009-12-17 14:58:11 | 显示全部楼层
您的意思是?
INIT: {geometry.setUseVertexBufferObjects(true)}
PUSH:{buffer=geometry.getOrCreateVertexBufferObject()
          array=new Array
          array->push_back(x,y,z)
          buffer->push_back(array)
          buffer->dirty()}
DRAG:{array->push_back(x,y,z)
           buffer->dirty()}

该用户从未签到

发表于 2009-12-17 16:46:12 | 显示全部楼层
没有buffer什么事情,就像我之前说的那样:您完全不用自己操作VBO对象
要做的只是
array->push_back()
array->dirty()

如果还不理解的话,我的书《OSG三维渲染引擎设计与实践》中有一个专门的VBO动态绘制例子,不妨一看~~

该用户从未签到

发表于 2009-12-17 16:48:36 | 显示全部楼层
我用过geometry::getVertexArray(),并修改数组里面的值。
至于VertexBufferData::addArray(),这个没用过。好像这样并不能增加几何体吧?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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