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等模型格式。
8021 1
|
JSON 前端开发 JavaScript
开源表单方案 Formily 的核心设计思路
Formily 是一个数据+协议驱动的表单解决方案,它站在Reactive响应式编程巨人的肩膀上,构建出了从基础表单到低代码领域的高性能通用基础能力,同时其配套的跨框架+跨终端组件生态体系,也能让用户更高效的开发日常业务表单,尽可能的减少了重复冗余的逻辑实现。本篇内容来自白玄在第十六届D2前端技术论坛的分享,将为你介绍如何在高复杂业务场景下提高我们的表单性能与表单开发效率。
6258 1
开源表单方案 Formily 的核心设计思路
vscode ctrl+/ 注释快捷键失效
首次安装vscode 不知道为何会快捷键失效,首先想到的就是键位冲突! 于是解决了。
6750 0
vscode ctrl+/ 注释快捷键失效
|
人工智能 IDE 程序员
Qoder用户上手指南:安装、登录、快捷键、功能亮点(新用户免费领300credits,首购2美元/月)
这个容易让程序员上瘾的 Agentic Coding 平台有哪些上头的功能?对于小白开发者和资深开发者如何用好Qoder呢?
12502 6
Qoder用户上手指南:安装、登录、快捷键、功能亮点(新用户免费领300credits,首购2美元/月)
|
定位技术 索引
osgEarth使用笔记3——加载倾斜摄影数据
osgEarth使用笔记3——加载倾斜摄影数据
901 1
|
11月前
|
SQL 数据库 Docker
【赵渝强老师】在Docker中运行达梦数据库
本文介绍了在Docker容器中部署达梦数据库(DM 8)的具体步骤,包括创建文件夹、下载安装包、导入镜像、启动容器、登录数据库及查看状态等操作。同时,通过视频讲解辅助理解。文中还分析了将数据库服务容器化的潜在问题,如数据安全性、硬件资源争用、网络带宽占用和额外隔离带来的挑战,指出数据库服务在生产环境中可能不适合容器化的原因。
1252 4
【赵渝强老师】在Docker中运行达梦数据库
|
网络协议
Qt中的网络编程(Tcp和Udp)运用详解以及简单示范案例
Tcp和Udp是我们学习网络编程中经常接触到的两个通讯协议,在Qt也被Qt封装成了自己的库供我们调用,对于需要进行网络交互的项目中无疑是很重要的,希望这篇文章可以帮助到大家。 是关于Qt中TCP和UDP的基本使用和特点:
2245 7
|
关系型数据库 Serverless 定位技术
PostgreSQL GIS函数判断两条线有交点的函数是什么?
PostgreSQL GIS函数判断两条线有交点的函数是什么?
1007 60
|
数据采集 数据可视化 定位技术
倾斜摄影教程:无人机航拍后使用ContextCapture生成 3D模型
倾斜摄影建模利用多角度影像生成高精度三维模型,广泛应用于城市规划、遗产保护等领域。通过无人机拍摄与专业软件处理,实现真实感强、自动化程度高的实景建模。
倾斜摄影教程:无人机航拍后使用ContextCapture生成 3D模型
|
安全 算法 Java
多线程写入同一个文件时,如何保证写入正常
【9月更文挑战第3天】多线程写入同一个文件时,如何保证写入正常
1826 8

热门文章

最新文章