ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

倾斜摄影OSGB转3DTiles:ContextCapture建模到Cesium加载全流程实战

倾斜摄影OSGB转3DTiles:ContextCapture建模到Cesium加载全流程实战 我们项目里最近完成了一条完整的倾斜摄影数据链路外业无人机采集一个园区内业用ContextCapture做空三和三维重建模型成果是标准的OSGB格式。结果到了Web端展示环节同事跟我说“你直接把OSGB丢给Cesium不就行了”我当时差点没绷住——OSGB是OpenSceneGraph的二进制格式Cesium的WebGL引擎根本不认识它。折腾了一晚上之后我把ContextCapture建模和CesiumLab格式转换这条路完整趟了一遍从坐标系的坑一路踩到纹理丢失最后才把模型稳稳挂到Cesium里。这篇文章就是这次实战的完整记录核心解决一个问题用ContextCapture生成OSGB再用CesiumLab转成3DTiles最后在Cesium里正常加载。如果你是做倾斜摄影、实景三维、WebGIS展示的并且也在跟OSGB和3DTiles打交道这篇里的步骤、参数和排错经验可以直接参考。1. 为什么必须绕一趟“OSGB转3DTiles”的弯路很多第一次接触这个流程的人都会问同一个问题Cesium不是“啥模型都能加载”吗为什么OSGB不行要回答这个得先看清楚OSGB和3DTiles在底层设计上的差异。1.1 OSGB和3DTiles到底差在哪OSGB全称是OpenSceneGraph Binary属于OpenSceneGraph体系的二进制三维模型格式也是目前倾斜摄影建模软件最喜欢输出的一种格式。它的特点是按空间位置分块存储每个Tile文件夹里放着对应分块的模型文件模型内部自带纹理并且通过文件夹嵌套和文件命名来表达LOD层级。比如ContextCapture输出后你会看到这样的目录Data/ Tile_000_003/ Tile_000_003.osgb L18/ Tile_000_003.osgb L19/ Tile_000_003.osgb每个Tile_000_003是一个空间分块里面的L18、L19是对应不同细节层次的子块。OpenSceneGraph渲染器可以根据视点距离动态加载不同LOD层效果很好但问题在于浏览器里没有OpenSceneGraph运行时Cesium根本没法直接解析这种二进制组织结构。3DTiles则是Cesium团队在2015年前后推出的开源流式传输规范一切围绕WebGL和浏览器场景设计。它的核心入口是一个tileset.json用JSON树形结构描述整个场景的包围体、几何误差、子节点关系真正的地模数据则放在b3dm、i3dm、pnts等瓦片二进制文件里。渲染时Cesium会读JSON树按几何误差和屏幕空间误差动态调度瓦片整套逻辑天然适配Web端加载。两者的差异可以归纳成一张表对比项OSGB3DTiles格式来源OpenSceneGraph生态Cesium开源规范数据结构文件夹文件命名表达LODtileset.json树形结构坐标基准多为投影坐标/局部平面坐标偏向ECEF、ENU等全球坐标浏览器支持需要插件或桌面软件WebGL原生支持属性承载弱主要用于Mesh渲染可通过FeatureTable承载属性便于单体化所以说OSGB转3DTiles不是“可选项”而是在Web端使用倾斜模型数据时必须走的一步。1.2 ContextCapture明明能出3DTiles为什么还是用CesiumLab也有人会说新版ContextCapture不是已经支持输出3DTiles了吗确实Bentley近几个版本把3DTiles纳入了输出选项但实际项目里我仍然更推荐先出OSGB、再用CesiumLab转换原因很朴素第一OSGB依然是团队协作和交付的“通用语言”。多数倾斜摄影质检流程、测图软件、单体化工具默认认的都是OSGB。全流程统一用OSGB作为中间成果后续不管接Cesium还是接其他GIS平台都比较灵活。第二CC直接出3DTiles的可控性没有CesiumLab高。ContextCapture里你能调的参数更多集中在建模阶段而CesiumLab针对3DTiles做了很多专门优化比如纹理压缩格式、LOD合并级别、坐标偏移设置、瓦片顶点压缩等等。尤其是大场景数据转出来的体积和加载性能差距会非常明显。第三CesiumLab可以顺带解决很多周边需求。后面我会讲到的地形切片、shp转3DTiles、单体化支持、FBX模型转换这些CesiumLab都有对应工具。把OSGB转换统一放在CesiumLab里做整个数据生产管线更顺手。2. ContextCapture建模阶段就该为“转换”做好的几件事很多人在ContextCapture出完OSGB之后才发现转换时坐标系对不上、模型位置飞了。这些问题追根溯源往往在建模阶段就埋下了。2.1 坐标系提前把底子打对ContextCapture里空三完成后新建重建项目会让你指定重建模型的坐标系。这一步非常关键它决定了OSGB里每个顶点真实的地理位置。比如你这个项目用的是无人机RTK打的像控点平差结果大多是WGS84或CGCS2000坐标系那么在CC里生成OSGB时就要明确选好对应的地理参考。我项目里常遇到的情况是航测成果用UTM 50N或CGCS2000高斯投影CC生成OSGB时如果选了WGS84经纬度那出来的模型坐标范围就是一个比较小的经纬度数值比如116.xx, 39.xx这种如果选了高斯投影坐标就变成几十万、几百万的大数。这直接决定后面CesiumLab转换时该选哪个原始坐标系也决定转出来的3DTiles能不能贴合地球。所以建议在CC提交重建任务前把坐标系信息用截图或文本记录到项目文档里包括坐标系名称、EPSG编码、中央经线、带号、基准面这些。后面CesiumLab转换时这些就是救命的信息。2.2 OSGB目录结构和LOD层级说明CC生成OSGB后除了Data目录里的Tile分块通常在Data旁边还会有一个metadata.xml文件。这个文件记录了整个模型的坐标系、范围、原点等核心信息。CesiumLab转换OSGB时会优先读取metadata.xml里的坐标信息。所以转换时最好把整个Data目录和metadata.xml放在一起不要只拷一部分Tile进去。LOD层级方面CC会按照你设置的“细节层次”级别生成多个L层。我给新手的建议是不要为了省事把LOD层数压得太少。OSGB转3DTiles时CesiumLab会把多级LOD重新组织成3DTiles的树形结构源数据LOD层级越完整转换后Web端缩放调度的体验越平滑。如果源OSGB只有一两层LOD转出来的3DTiles往往会出现“拉近就糊、拉远就消失”的问题。2.3 分块大小和建模质量对转换的影响CC建模时有一个分块Tile大小的概念。块太大单块数据量太大转换时内存容易吃紧Cesium加载单个瓦片也吃力块太小生成的文件数量爆炸转换时间和文件系统压力都很大。我们园区项目大概1.5平方千米的数据量分块尺寸基本按CC默认设置走单块OSGB控制在几十MB级别整片数据转起来比较顺畅。还有一个经验是源模型质量不要太“虚”。如果空三质量差、模型表面有大量破洞或飞点转换后的3DTiles会把这些问题原样保留有时候还会出现黑三角或闪烁。所以建模阶段尽量保证重叠度、影像清晰度别把希望全寄托在转换时“修复”。3. CesiumLab转换实操从添加数据到参数调优CesiumLab目前市面上常见的有2和3两个大版本界面上功能入口略有差异但OSGB转3DTiles的核心逻辑基本一致。下面我以手头常用的版本为例讲一遍完整操作你如果界面略有出入对应着找同类选项就行。3.1 添加OSGB数据与坐标系选择打开CesiumLab找到“数据处理”或“数据转换”模块里的“OSGB转3DTiles”功能。点击新建任务后第一步是添加数据目录。这里注意选择路径时选到包含metadata.xml的Data目录那一层有的版本会直接要求你选Data文件夹千万别选到只含某个Tile的子目录否则转换时会提示找不到有效数据。添加完成后CesiumLab会自动尝试读取metadata.xml里的坐标系信息。我的操作习惯是即使它自动识别了也要手动核对一遍。比如metadata里写的是CGCS2000 / 3-degree Gauss-Kruger zone 39界面上不能默认选成WGS84。选错坐标系的结果就是转出来的模型坐标整体偏移几百公里飞到大洋彼岸都有可能。如果没有metadata.xml或者元数据里的坐标系和实际不一致你可以在CesiumLab里手动指定原始坐标系。这时候之前记录在项目文档里的EPSG编码就派上用场了。3.2 转换参数逐项怎么调CesiumLab转换面板里的参数不少但大多数项目真正需要关心的就这几个参数项作用我的常用建议原始坐标系告诉工具OSGB当前位于什么坐标下务必与CC建模选择一致手动核对目标坐标系/空间参考转换后3DTiles使用的坐标系一般保持与原始一致或按平台需求选坐标偏移当OSGB是局部平面坐标时用它把模型放到真实经纬度优先依赖metadata自动读取LOD合并级别控制根节点下合并多少层瓦片默认或3-4场景大可适当增大纹理压缩把纹理压缩成DXT/WebP等格式桌面端选DXT移动端选WebP谨慎用有损选项线程数/内存转换时的并行处理能力内存不够时降低别一味拉满先说LOD合并级别。合并层级越高根节点直接包含的细节越多加载时首屏越快出模型但每一帧渲染压力也大了。我们普通场景直接用默认如果后续在Cesium里滑动缩放明显卡顿再去重建合并层级小的版本。再说纹理压缩。倾斜摄影纹理非常占体积一组原始OSGB可能50GB转成不压缩的3DTiles还是50GB部署在云服务器上加载会非常吃力。压缩成DXT1或WebP后体积能降到1/4甚至更低。但这东西是双刃剑压缩太狠会影响近距离贴图观感。我的经验是先不压缩转一小块看看效果如果纹理清晰度能接受再全量压缩如果甲方对细节有要求就用JPEG级别或只做PNG转码不启用高损压缩。3.3 转换过程中的报错排查转换不是每次都能顺顺利利一次过我大概整理了这几类高频问题提示找不到数据/转换后tileset为空大概率是添加数据时目录层级选错了或者源OSGB本身不完整、缺metadata.xml。模型整体飞到天上或埋到地下坐标系或原点设置错误。先回到CesiumLab的预览界面看坐标值再用QGIS或Global Mapper打开源OSGB确认包围盒经纬度。只要源数据位置正常问题基本出在原始坐标系选择上。转换后白模没有纹理先检查纹理压缩选项比如WebGL渲染器不支持某些纹理格式时模型会显示成白色或粉紫色。另外数据路径里的中文和特殊符号也可能导致纹理读取失败建议所有路径用英文和数字。转换到一半内存暴涨直接卡死一是单块OSGB太大二是线程数设置太高。这时把线程数降到2关掉其他占用内存的程序再不行就加大系统虚拟内存。我自己遇到过最气人的一次是转完在Cesium里加载模型显示出来但位置在海里。排查了一下午最后发现是CesiumLab里原始坐标系选成了UTM 50N而ContextCapture建模用的是CGCS2000 3度带。两者在局部数据上看起来都是“高斯大数”但偏了几百公里。所以坐标系的检查一定要放在转换前而不是转换后追悔。3.4 转换完的目录结构检查转换成功后输出目录大致长这样3dtiles/ tileset.json Content/ xxx.b3dm yyy.b3dm打开tileset.json重点看asset和root.transform。CesiumLab在转换时会把源坐标转换成3DTiles需要的ECEF或ENU矩阵正常情况root.transform是一个16位矩阵数组。如果你打开文件发现根节点居然没有transform或者transform矩阵基本是单位阵说明源数据很可能是局部坐标Cesium加载出来后不会在预期位置需要前端手动给定原点和位置做纠正。4. Cesium里加载转换好的3DTiles转换只是手段最终让模型在浏览器里转起来才是目的。这一章说说加载代码和最常见的调试手段。4.1 最小加载代码假设3DTiles数据已经放到静态资源目录/data/3dtiles/加载的核心代码非常简单const viewer new Cesium.Viewer(cesiumContainer); const tileset viewer.scene.primitives.add( new Cesium.Cesium3DTileset({ url: /data/3dtiles/tileset.json }) ); viewer.zoomTo(tileset);如果CesiumLab转换时坐标信息正确这段代码就能直接把模型拉到全球正确的位置相机会自动取模型包围盒缩放到合适的视角。4.2 加载不出来、黑屏、偏移的排查链路如果转完加载一片空白先别急着怀疑CesiumLab按下面这个顺序查打开F12控制台看报错。如果Cesium3DTileset报404那就是tileset.json路径不对如果报CORS跨域问题检查静态资源服务有没有允许跨域。看tileset的boundingSphere位置。在控制台执行tileset.boundingSphere查看中心点坐标是否合理。如果中心点不在模型真实的经纬度附近说明3DTiles的transform偏了得回到数据源头查坐标系。模型有但位置偏了可以用modelMatrix做前端修正但我不建议一上来就硬调。调试时可以临时这样写快速把模型拉到某个经纬度const origin Cesium.Cartesian3.fromDegrees(116.39, 39.90, 50); tileset.modelMatrix Cesium.Transforms.eastNorthUpToFixedFrame(origin);这样能快速判断“模型本身是否正常、坐标是否正确”。但注意前端硬调位置属于修数据问题的临时手段真正可靠的做法是回到CesiumLab重新设置坐标系再转一次保证源数据根节点transform正确。模型被地形遮挡。倾斜模型加载到带地形的球上经常出现模型半截埋在地下的情况。如果CesiumLab转换用的高程基准和地形DEM高程基准一致那么应该能对齐如果仍有偏差优先调整源数据的Z坐标偏移量重新转换而不是在viewer里关闭地形测试。4.3 性能调优的几个常用选项模型能显示只是第一步Web端还要流畅。我调得最多的两个参数是maximumScreenSpaceError和skipLevelOfDetail。maximumScreenSpaceError默认是16含义是屏幕空间误差达到16像素时才开始加载更精细层级。值越大加载的瓦片越少性能越好但画面容易糊值越小画面越精细但请求数量猛增。做展示类项目我一般调到4~8做性能优先的演示场景就保持在16。skipLevelOfDetail设置为true时Cesium会跳过中间的LOD层级直接加载当前视角下最合适的瓦片对倾斜模型这种大场景数据效果立竿见影。加上这个选项后整体加载速度会明显流畅const tileset new Cesium.Cesium3DTileset({ url: /data/3dtiles/tileset.json, maximumScreenSpaceError: 8, skipLevelOfDetail: true });5. 围绕CesiumLab的几个扩展操作地形、shp、单体化、模型转换项目做多了就会发现OSGB转3DTiles往往不是终点CesiumLab里其他几个配套功能也经常用到顺手一起讲了。5.1 用DEM做地形切片很多场景不能光有建筑物模型还需要地形来衬托。CesiumLab里有“地形切片”功能就是俗称的“cesiumlab切地形”输入是GeoTIFF等格式的DEM高程数据输出是可以给Cesium用的地形瓦片。操作上比较简单新建地形切片任务添加DEM数据选好坐标系设置输出格式和最大层级开始转换。输出格式一般有两种选择一种是Cesium经典的quantized-mesh地形加载时用CesiumTerrainProvider另一种是地形3DTiles瓦片加载方式和模型3DTiles一样。注意DEM的坐标系也要和数据链路里的坐标系保持一致否则地形和模型会一个在东一个在西。5.2 shp转3dtilesshp转3dtiles这个词最近在群里问的人特别多。shp是传统GIS矢量格式但它的二维线条和面在三维场景里没法直接渲染成带高度的实体。CesiumLab的shp转3DTiles功能可以把面状shp根据属性字段拉伸成有高度的立体体块或者把线状shp转成3D线。这个功能在做规划、地籍、道路附属设施叠加的时候特别好用。比如把房屋边界shp按层数字段拉伸成体块再叠加到倾斜模型上就能在Cesium里实现“模型矢量叠加”的混合展示。转的时候重点配置拉伸高度字段、底面高程字段、颜色和透明度输出后直接用3DTiles方式加载即可。5.3 3dtiles单体化Cesium 3dtiles单体化是倾斜摄影Web应用里绕不开的话题。倾斜模型本身就是一整层三角网没有建筑、道路、树木的构件划分所以要实现“点击某栋楼弹出属性”这种效果就得做单体化。目前比较成熟的思路是借助shp面来做。CesiumLab有类似“倾斜入库”或“单体化”功能原理大致是把shp面按建筑物边界切分模型给每个切好的瓦片或三角网写入对象ID并把shp属性表挂接进去。转换后点击模型就能用Cesium的pick取到对应属性。如果不想重新转换整个模型还有一条轻量路线把shp面单独转成3DTiles叠加在倾斜模型上面前端通过拾取这个矢量3DTiles来模拟单体化效果。好处是不动原始模型数据缺点是点击精度受shp边界和模型贴合度影响。我通常先做轻量路线做原型确认甲方需求后再决定要不要走完整单体化流程。5.4 fbx转3dtilesCesiumLab的模型转换功能里fbx转3dtiles也是高频需求。FBX常用于人工精细建模比如园区里某个标志雕塑、工业设备这些精细模型如果直接在建模软件里导出成glTF再手动转3dtiles比较麻烦CesiumLab可以一键处理。操作时选好FBX文件设置坐标系和中心点再选择输出格式即可。一个很容易踩的坑是FBX引用的贴图路径不能带中文而且最好在导出FBX时勾选嵌入纹理否则转换后贴图丢失。模型单位也需要统一通常跟倾斜模型一样用米避免转出来尺寸对不上。6. 版本差异与几个我一直保留的实战习惯最后聊几个只在项目里摸爬滚打才总结出来的习惯不算什么高深理论但能省很多麻烦。第一CesiumLab版本不同功能入口和默认参数有差别我不建议直接照抄网上旧教程的截图。我刚开始用的时候就吃过亏教程里说“打开数据转换”新版里叫“数据处理”整个界面完全不同。遇到这种情况按功能逻辑去找而不是死记截图位置。第二所有中间数据路径一律英文、数字、下划线不要用中文更不要用带空格的目录。OSGB本身纹理路径、CesiumLab缓存目录中文路径下出问题概率非常高而且报错信息并不直观。为了省事我从数据源头就把目录规范统一。第三大场景转换前先做小块试转。比如整片数据有5000个Tile我先单独拷出一个小范围的Tile目录转换一次确认坐标系和纹理都正常再跑全量。全量转换动辄几个小时试转最多几分钟这笔时间投资非常划算。第四转出来的3DTiles不要直接放进源OSGB目录里生成。两个目录层级不同、文件数量巨大混在一起后面打包部署时容易出错而且如果之后要重新转换清理起来也很痛苦。第五源数据和转换成果都要保留。甲方或者平台方经常改需求比如从Web端改成移动端或者换成单体化版本。保留原始OSGB和metadata.xml下次只需要调参数重转不用回ContextCapture重跑建模。这条链路跑通之后我们园区的项目从建模、转换到Web展示就形成了一条标准流水线。后续如果再遇到加载不理想的情况我的排查顺序永远是先看坐标信息对不对再看纹理压缩是不是过度最后才去调LOD和调度参数。这套顺序帮我解决了不少问题也希望对你有点帮助。
返回列表