查看: 1492|回复: 5

关于大量数据加载到场景中

[复制链接]

该用户从未签到

发表于 2010-5-27 08:30:42 | 显示全部楼层 |阅读模式
在场景中涉及大量数据加载时,我用类似以下的模式:
首选,我重写了osg::NodeCallback类,如下
class DataOperaterCallBack: public osg::NodeCallback

{

public:

DataOperaterCallBack();

~DataOperaterCallBack(){}

virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);//
必须实现的关键函数

void getDataOperator(DataOperator& _DataOperator){_DataOperator=m_DataOperator;}

void setDataOperator(const DataOperator& _DataOperator){m_DataOperator=_DataOperator;}

void getDataSource(DataSource& _DataSource){_DataSource=m_DataSource;}

void setDataSource(const DataSource& _DataSource){m_DataSource=_DataSource;}

private:

DataOperator m_DataOperator;//
数据操作状态

DataSource m_DataSource;//
数据源,这样声明就有了先后依赖性

};

实现operator()虚函数

void DataOperaterCallBack::operator ()(osg::Node *node, osg::NodeVisitor *nv)

{

switch(m_DataOperator)

{

case ADDOPTION://
加载数据

{

DataReader _reader;

osg::ref_ptr<osg::Group> scenedata=dynamic_cast<osg::Group*>(node);

_reader.Reader(m_DataSource,scenedata);

break;

}
……

}
//traverse(node,nv);

}

加载数据时调用这个类,如下:
osg::ref_ptr<DataOperaterCallBack> m_SceneNodeCallback=new DataOperaterCallBack;

m_SceneNodeCallback.get()->setDataSource(_dataSource);

m_SceneNodeCallback.get()->setDataOperator(ADDOPTION);

m_SceneData.get()->setUpdateCallback(m_SceneNodeCallback);

通过这种方法实现加载节点,会比
m_SceneData.get()->AddChild(..)性能好一点,可是有时还是免不了出错,那么还有其它方法,请高手提供一些思路。
另外:
在以上代码中
1、osg::ref_ptr<osg::Group> scenedata=dynamic_cast<osg::Group*>(node);
的转换代价有多大,而且不明白,为什么可以这样,因为C++里是“没有从基类到派生类的转换”?

2在这个类中实现Operator(),我把traverse(node,nv)去掉了,如果不去掉会问题的,加上traverse(node,nv)在这里会起什么作用呢?

该用户从未签到

发表于 2010-5-27 13:22:45 | 显示全部楼层
首先您为什么不使用PagedLOD来加载海量数据呢?这是OSG显示大数据的首选方案

出错的原因抱歉我无法判断,因为您提供的代码片断中并不包含这些信息

dynamic_cast的转换消耗大概是static_cast的百倍左右,此外您所说的“C++里没有从基类到派生类的转换”,这句话似乎没有道理

加上traverse(node,nv)可以保证系统正确遍历更新时的节点树并执行到下一个节点,这里不应当去掉;如果您认为不去掉会出问题,那恐怕说明您的代码内部存在问题

该用户从未签到

 楼主| 发表于 2010-5-27 13:41:57 | 显示全部楼层
嗯,确实不能排除我程序内部有问题。

那么,
1、如果通过PagedLOD来加载数据,那么是这个类的addChild、setFileName()方法直接设置数据源呢?还是像我上面一样,给PagedLod写一个NodeCallback回调,然后在回调里加载数据?(其实我不明白在回调里加载数据出现问题就会少一点,因为在回调加载数据,最终也是用这个节点的addChild等方法)

2、C++里没有从基类到派生类的“自动”转换,而强制转换是可以的,这点我记错了。

该用户从未签到

发表于 2010-5-27 17:05:14 | 显示全部楼层
1、用setFileName设置数据源,并用setRange设置范围。PagedLOD在加载后会自动根据当前与视点的远近来加载或卸载子节点

2、dynamic_cast也不能称作强制转换,呵呵。它事实上就是专用于类层次之间的变换的,并且会在运行时进行自动的类型检查来完成变换。使用dynamic_cast是十分安全的,因为它无法把不同继承关系的类强制相互转换

该用户从未签到

 楼主| 发表于 2010-5-27 17:12:59 | 显示全部楼层
我知道“用setFileName设置数据源,并用setRange设置范围”需不需要在回调里做这件事呢?好像还少回答这个问题吧!

该用户从未签到

发表于 2010-5-28 08:40:55 | 显示全部楼层
为什么要在回调里做这种事?这些事情应该是在构建模型的时候就做好的,而不是在显示模型的时候
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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