OSG加载倾斜摄影数据

简介: OSG加载倾斜摄影数据

OSG加载倾斜摄影数据

目录

1. 概述

ContextCapture(Smart3D)生成的倾斜摄影模型数据一般都形如如下组织结构:

在Data目录下包含了分块的瓦片数据,每个瓦片都是一个LOD文件夹。osg能够直接读取osgb格式,理论上只需要依次加载每个LOD的金字塔层级最高的osgb,整个倾斜摄影模型数据就加载进来了。不过有点麻烦的是这类数据缺乏一个整体加载的入口,如果每次加载都遍历整个文件夹加载的话,会影响加载的效率。所以一般的数据查看软件都会为其增加一个索引。

这里就给倾斜摄影数据添加一个osgb格式的索引文件,生成后就可以通过OSG直接加载整个倾斜摄影模型数据。

2. 实例

2.1. 代码

具体的实现代码如下:

#include <iostream>
#include <string>
#include <QDir>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
using namespace std;
//查找目录下所有的文件夹
static void findDir(string dir, vector<string>& subDirs)
{
  //
  subDirs.clear();
  QDir fromDir(QString::fromLocal8Bit(dir.c_str()));
  QStringList filters;
  //
  QFileInfoList fileInfoList = fromDir.entryInfoList(filters, QDir::AllDirs | QDir::Files);
  foreach(QFileInfo fileInfo, fileInfoList)
  {
    if (fileInfo.fileName() == "." || fileInfo.fileName() == "..")
    {
      continue;
    }
    if (fileInfo.isDir())
    {
      QByteArray dir = fileInfo.filePath().toLocal8Bit();
      subDirs.push_back(dir.data());
    }
  }
}
//得到文件路径的文件名   C:\\b\\a(.txt) -> a
static std::string DirOrPathGetName(std::string filePath)
{
  size_t m = filePath.find_last_of('/');
  if (m == string::npos)
  {
    return filePath;
  }
  size_t p = filePath.find_last_of('.');
  if (p != string::npos && p > m)       //没有点号或者
  {
    filePath.erase(p);
  }
  std::string dirPath = filePath;
  dirPath.erase(0, m + 1);
  return dirPath;
}
void createObliqueIndexes(std::string fileDir)
{
  string dataDir = fileDir + "/Data";
  osg::ref_ptr<osg::Group> group = new osg::Group();
  vector<string> subDirs;
  findDir(dataDir, subDirs);
  for (size_t i = 0; i < subDirs.size(); i++)
  {
    string name = DirOrPathGetName(subDirs[i]);
    string path = subDirs[i] + "/" + name + ".osgb";
    osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(path);
    osg::ref_ptr<osg::PagedLOD> lod = new osg::PagedLOD();
    auto bs = node->getBound();
    auto c = bs.center();
    auto r = bs.radius();
    lod->setCenter(c);
    lod->setRadius(r);
    lod->setRangeMode(osg::LOD::RangeMode::PIXEL_SIZE_ON_SCREEN);
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->getOrCreateStateSet();
    lod->addChild(geode.get());
    std::string relativeFilePath = "./Data/" + name + "/" + name + ".osgb";  //相对路径
    lod->setFileName(0, "");
    lod->setFileName(1, relativeFilePath);
    lod->setRange(0, 0, 1.0);                                             //第一层不可见
    lod->setRange(1, 1.0, FLT_MAX);
    lod->setDatabasePath("");
    group->addChild(lod);
  }
  std::string outputLodFile = fileDir + "/Data.osgb";
  osgDB::writeNodeFile(*group, outputLodFile);
}
int main(int argc, char *argv[])
{
  string fileDir = "D:/Data/scene/city";
  std::string outputLodFile = fileDir + "/Data.osgb";
  createObliqueIndexes(fileDir);
  osgViewer::Viewer viewer;
  osg::Node * node = new osg::Node;
  node = osgDB::readNodeFile(outputLodFile);
  viewer.setSceneData(node);
  return viewer.run();
}

2.2. 解析

如果直接读取每一块的LOD然后通过osgDB::writeNodeFile写入到一个osgb文件,这个文件就会保存所有块的LOD第一层信息。这样在第二册加载的时候还是会比较慢,所以这里就创建了一个空的节点,形成了索引所有LOD块的数据结构。对于每一块数据,新建两层LOD,第一层为自身的空白节点,第二层为分块LOD的第一层数据:

osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(path);
osg::ref_ptr<osg::PagedLOD> lod = new osg::PagedLOD();
auto bs = node->getBound();
auto c = bs.center();
auto r = bs.radius();
lod->setCenter(c);
lod->setRadius(r);
lod->setRangeMode(osg::LOD::RangeMode::PIXEL_SIZE_ON_SCREEN);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->getOrCreateStateSet();
lod->addChild(geode.get());
std::string relativeFilePath = "./Data/" + name + "/" + name + ".osgb";  //相对路径
lod->setFileName(0, "");
lod->setFileName(1, relativeFilePath);
lod->setRange(0, 0, 1.0);                                             //第一层不可见
lod->setRange(1, 1.0, FLT_MAX);
lod->setDatabasePath("");
group->addChild(lod);

LOD的Center和Radius都非常重要,需要预先设置好;setRangeMode设置了细节层级调度的模式,一般都为PIXEL_SIZE_ON_SCREEN;setFileName设置了每一层的数据路径,setRange确定了当前层级的范围。由于这个LOD只是个索引文件,所以会设置第二层为极大的可见范围值。

3. 结果

可以像加载普通OSGB文件一样加载这个索引文件,通过osgviewer加载的效果如下:

分类: OSG

标签: 倾斜摄影 , OSG

相关文章
|
存储 传感器 自动驾驶
几种常见的点云格式数据解析与在线预览
3D模型在线转换网站支持pcd、pts、xyz、las、laz、asc、ply等点云格式文件在线预览,同时支持将点云格式在线转换为ply、xyz等模型格式。
9287 1
|
Linux iOS开发 MacOS
typora下载和破解(仅供学习)
Typora 一款 Markdown 编辑器和阅读器 风格极简 / 多种主题 / 支持 macOS,Windows 及 Linux 实时预览 / 图片与文字 / 代码块 / 数学公式 / 图表 目录大纲 / 文件管理 / 导入与导出 ……
168337 12
typora下载和破解(仅供学习)
|
人工智能 IDE 程序员
Qoder用户上手指南:安装、登录、快捷键、功能亮点(新用户免费领300credits,首购2美元/月)
这个容易让程序员上瘾的 Agentic Coding 平台有哪些上头的功能?对于小白开发者和资深开发者如何用好Qoder呢?
20400 6
Qoder用户上手指南:安装、登录、快捷键、功能亮点(新用户免费领300credits,首购2美元/月)
|
定位技术 索引
osgEarth使用笔记3——加载倾斜摄影数据
osgEarth使用笔记3——加载倾斜摄影数据
1181 1
|
缓存 Ubuntu 编译器
从源码编译安装gdal3.6.2库的操作指南。
以上步骤概要了从源码编译安装GDAL库的基本流程,实际操作中可能会遇到各种配置上的问题。如果在编译或安装过程中遇到错误,通常需要根据终端输出的信息来判断问题所在,并根据需要安装缺失的依赖库,或是调整编译参数解决问题。
824 0
|
SQL 数据库 Docker
【赵渝强老师】在Docker中运行达梦数据库
本文介绍了在Docker容器中部署达梦数据库(DM 8)的具体步骤,包括创建文件夹、下载安装包、导入镜像、启动容器、登录数据库及查看状态等操作。同时,通过视频讲解辅助理解。文中还分析了将数据库服务容器化的潜在问题,如数据安全性、硬件资源争用、网络带宽占用和额外隔离带来的挑战,指出数据库服务在生产环境中可能不适合容器化的原因。
2273 4
【赵渝强老师】在Docker中运行达梦数据库
|
缓存 JavaScript 前端开发
拿下奇怪的前端报错(三):npm install卡住了一个钟- 从原理搞定安装的全链路问题
本文详细分析了 `npm install` 过程中可能出现的卡顿问题及解决方法,包括网络问题、Node.js 版本不兼容、缓存问题、权限问题、包冲突、过时的 npm 版本、系统资源不足和脚本问题等,并提供了相应的解决策略。同时,还介绍了开启全部日志、使用替代工具和使用 Docker 提供 Node 环境等其他处理方法。
16924 2
|
存储 前端开发 定位技术
osgEarth使用笔记4——加载矢量数据
osgEarth使用笔记4——加载矢量数据
999 0
|
算法 API 开发者
【Qt UI相关】Qt中如何控制 窗口的最大化、最小化和关闭按钮?一文带你掌握用法
【Qt UI相关】Qt中如何控制 窗口的最大化、最小化和关闭按钮?一文带你掌握用法
4143 1
|
C语言 C++
Visual Studio 2019 详细安装教程(图文版)
下载安装包 官网下载安装包 百度网盘下载安装包 安装步骤 运行并创建一个项目 【官网下载安装包步骤有些繁琐,官网反应速度有点慢】 【建议直接从百度网盘继续下载安装包!!!】
10867 25