简介
DatabasePager类,也就是常说的数据库分页技术,简单来说,就是在进行数据库查找时,有可能满足条件的数据很多,为了提高相应速度我们进行数据查找时进行分页查找与显示,当点击下一页时才会进行下一次的查找动作。Osg就是把这个原理应用在了三维大场景中,当我们需要加载一个城市级数据时,因为数据量非常大,而我们感兴趣的范围在某一时刻一般都是很小的一部分,所以我们也可以应用数据分页的技术,对大数据进行”分页”查找并显示。
在osg中DatabasePager执行的动作只有一步,就是在每一帧的更新循环中使用updateSceneGraph函数,把过期的数据卸载掉。并将新加入的数据载入到当前scene中。这些数据都是在用户视野中显示的。所以我们就把用户的视野比作”页面”。我们都知道数据的加载都是非常耗时的操作,更何况是三维模型这种大体量的数据,所以osg把DatabasePager的操作放到了另一个独立于渲染线程之外的线程上进行。
那我们就进入osgDB::DatabasePager中查看这个特殊的线程都进行了什么工作。
osgDB::DatabasePager成员介绍
DatabasePager::DatabaseThread::run()。我们在上面一节中介绍过openThread的用法。在进入DatabaseThread::run()之前我们先对DatabasePager中的一些成员变量进行简单的介绍:
1、DatabasePager::DatabaseThread 类:这是分页数据库的核心处理线程,它负责实现场景元素的定期清理,加载以及合并工作;但是让它一直处于检查各个数据列表的循环状态,这未免太过耗费系统资源。因此,这个线程在平常状态下应当被阻塞,需要时再予以唤醒。
2、DatabasePager::DatabaseRequest 结构体:这个结构体保存了用户的单个数据请求,包括数据文件名,请求时间,数据加载后存入的节点,以及要进行合并的父节点等;除此之外还有一个重要的编译映射表_dataToCompileMap,这个映射表负责保存图形设备 ID 与编译对象(几何体显示列表,纹理等)的映射关系。
3、DatabasePager::RequestQueue 结构体:它负责保存和管理一个“数据请求列表”_requestList,也就是由 DatabaseRequest 对象组成的向量组,除此之外还负责对列表中的数据按请求时间排序。上图中所示的_dataToCompileList 和_dataToMergeList 实际上都是RequestQueue 类型的对象,不过它们所保存的“请求列表”事实上是已经完成加载的“待编译/待合并列表”了。
4、DatabasePager::ReadQueue 结构体:这个结构体继承自 RequestQueue,不过还增加了一个“弃用对象列表”_childrenToDeleteList,也就是 osg::Object 对象组成的向量组。它是数据处理线程中最重要的对象之一,除了可以随时向两个列表里追加数据请求和弃用对象之外,这个结构体还包括了一个 updateBlock 函数,负责阻塞或者放行 DatabaseThread 线程,其根据是:列表中是否存在新的数据请求或弃用对象需要处理,以及用户是否通过函数设置暂时不要启用线程(DatabasePager ::setDatabasePagerThreadPause)。
DatabasePager::DatabaseThread::run()
好,那我们就可以进入DatabasePager::DatabaseThread::run()内部进行解剖了。首先osg会对读取数据的模式按照本地数据和网络数据进行划分。划分的目的是osg会根据不同类型创建不同的线程进行处理,并且网络数据还可以设置缓存路径(OSG_FILE_CACHE)缓存到本地。
然后会对线程安全的队列read_queue上锁,以便在判断过期的数据(childrenToDeleteList)进行清空操作。随后,使用 DatabasePager::ReadQueue::takeFirst 函数,从当前线程对应的 ReadQueue 对象(_fileRequestQueue 或_httpRequestQueue)的队列中取出并清除第一个数据加载请求(DatabaseRequest)。并且在DatabasePager::RequestQueue::takeFirst函数中遍历所有的请求列表(_requestList)判断要加载的数据是否过期,得到最上层的要加载的数据。
再往下看,当databaseRequest->_loadOptions是url数据时并且指定了OSG_FILE_CACHE的路径,那么osg就需要进行缓存工作,然后把databaseRequest 保存到将要合并的列表中(_pager->_dataToMergeList->addNoLock(databaseRequest.get());),再剩下的步骤就是对数据进行编译以及合并到scene中。
原文链接 http://www.3wwang.cn/blog/article.ftl?id=26
相关推荐
5. 载入自定义数据:如果需要,还可以通过OSGEarth::Feature类加载自定义的几何和属性数据。 6. 渲染与交互:最后,OSGEarth提供了一系列API,允许用户进行交互式操作,如平移、缩放、旋转视角,以及查询地理坐标等...
同一个osg::Geometry或osg::Geode或osg::Group对象 在不同的位置 用不同的颜色、大小、角度显示
通过osg::ShapeDrawable实现简单的点线面标绘。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
OSG提供了丰富的图形特性,如`osg::Light`, `osg::Material`, 和`osg::Texture2D`等,可以根据需要自定义场景的外观。 总的来说,OSG通过其强大的文件读取和场景管理能力,使得加载和展示地形及3D模型变得简单易行...
modelOptions.location() = osg::Vec3d(111.0763, 42.34425, 1000.0); // 北京地区的坐标 map->addModelLayer(new ModelLayer("modelLayer", modelOptions)); // 设置视图 osg::ref_ptr<osgViewer::Viewer> ...
例如,你可以使用osg::Geode和osg::Shape类创建几何物体,使用osg::Texture和osg::Image加载纹理,使用osg::Switch控制节点的可见性,以及使用osg::MatrixTransform进行几何变换。 多窗口渲染的一个常见应用场景是...
- **osg::Fog**: OSG提供了`osg::Fog`类,用于设置场景中的雾效。你可以创建一个`osg::Fog`对象,设置其颜色(通常为灰色或白色)、类型(线性或指数)以及距离参数。 - **Fog属性**: 雾的密度可以通过`setDensity...
Qt加载Osg的老方式是使用osg3.4以及以前的某些版本中提供的osgQt项目加载osg,不过这种方式,在3.6等新版本中不再支持,更改起来比较麻烦,由于osg::GraphicsContext类不再提供osg::GraphicsContext::...
Qt加载Osg的老方式是使用osg3.4以及以前的某些版本中提供的osgQt项目加载osg,不过这种方式,在3.6等新版本中不再支持,更改起来比较麻烦,osg::GraphicsContext类不再提供osg::GraphicsContext::...
osg::HeightField是osgTerrain中的核心类,它定义了一种二维的高度数组,用于存储地形的海拔信息。HeightField可以基于各种数据源创建,如ASCII或二进制文件、栅格图像或者直接由代码生成。每一点的海拔值可以通过...
1. **创建场景根节点**: 在OpenSceneGraph中,所有的图形元素都位于一个场景图中,需要创建一个`osg::Group`作为根节点。 2. **添加地图节点到场景**: 将`MapNode`插入场景图的根节点,使地图在3D视图中可见。 **第...
首先,我们需要创建一个`osg::Fog`对象,这是osg库中用于表示雾的类。你可以通过`osg::Fog::Ptr fog = osg::Fog::create()`来创建一个雾实例。 2. **设置雾类型**: `osg::Fog`提供了多种雾类型,如线性雾、指数...
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D; texture->setDataVariance(osg::Object::DYNAMIC); texture->setImage(image.get()); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);...
创建一个`NodeVisitor`的派生类,并重写`apply(osg::Node& node)`方法,这样每次访问到一个节点时,都会调用这个方法。然后使用`node.accept(yourNodeVisitor)`来启动遍历。 ```cpp class MyNodeVisitor : public ...
#### 一、OSG简介及历史 - **OpenSceneGraph (OSG)**:是一款跨平台、开源的场景图形API,主要用于三维图形的应用开发。 - **发展历程**: - OSG最初由Garth Zeglin在1999年创建。 - 随着时间的发展,OSG逐渐成为...
1. **场景创建**:使用OSG,你可以创建复杂的3D场景,通过`osg::Group`来组织节点,使用`osg::Geode`来加载几何对象,利用`osg::StateSet`来设置材质和纹理。 2. **数据加载**:osgEarth则提供了丰富的数据加载接口...
在OSG中,纹理主要通过`osg::Texture2D`类来实现,它可以加载和管理纹理图像。 ### 自动方式添加纹理 自动方式是OSG最简单且常用的纹理映射方法。当你加载一个带有纹理坐标的数据文件(如OBJ或STL格式)时,OSG会...
osg::ref_ptr<osg::Box> box = new osg::Box(osg::Vec3(0.0, 0.0, 0.0), 1.0); // 1.0表示立方体的边长 osg::ref_ptr<osg::ShapeDrawable> drawable = new osg::ShapeDrawable(box); geode->addDrawable(drawable...
stateset->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL), osg::StateAttribute::ON); // 返回几何体对象 return gtess; } ``` #### 四、总结 通过...
osg提供`osg::Light`和`osg::LightSource`类来处理光照。创建一个光源,将其添加到场景图中,并调整其位置和方向: ```cpp osg::ref_ptr<osg::Light> light = new osg::Light(); light->setPosition(osg::Vec4(0.0f...