正交投影模式下如何实现点云LoD过滤?
正交投影模式下点云LoD加载内存过高的解决方案
我基于Qt参考Potree实现了点云渲染软件,层级过滤逻辑如下:
- 将整个点云划分为不同层级的小点云块
- 执行视锥体剔除,过滤视野外的块
- 计算每个点云块在屏幕上的投影尺寸,以此判断是否加载对应等级的LoD
但Potree未提供正交投影模式下的解决方案,原代码仅留有TODO注释:
// TODO ortho visibility let bb = child.getBoundingBox(); let distance = child.getBoundingSphere().center.distanceTo(camObjPos); let diagonal = bb.max.clone().sub(bb.min).length(); //weight = diagonal / distance; weight = diagonal;
问题根源
透视投影模式下,点云呈现近大远小的效果,相机仅为近处物体加载高等级LoD,远处用低等级LoD,内存占用可控。但正交投影中,物体投影到屏幕的尺寸与距离无关——视野内所有可见点云块都会加载高等级LoD,直接导致内存占用过高。
解决办法
针对正交投影特性,重新设计LoD加载判断逻辑即可,核心是基于点云块的屏幕实际像素占比+动态阈值调整,具体实现方向如下:
计算正交投影下的屏幕像素占比
正交投影中,屏幕像素与世界空间的对应关系固定,可通过相机正交参数和屏幕分辨率计算点云块的实际屏幕占比:- 以Qt为例,先获取相机的正交宽度/高度(
QCamera::orthoWidth())和视口宽高 - 计算点云块包围盒在相机轴向的长度,再换算为屏幕像素数
示例代码(C++/Qt):
float orthoWidth = camera->orthoWidth(); float screenWidth = ui->viewport->width(); // 点云块包围盒X轴方向长度 float bbXLen = boundingBox.maximum().x() - boundingBox.minimum().x(); // 计算该块在屏幕上的像素宽度 float screenPixelWidth = (bbXLen / orthoWidth) * screenWidth;用这个
screenPixelWidth替代原有的diagonal/distance作为LoD等级判断依据——仅当像素宽度超过设定阈值时,才加载高等级LoD。- 以Qt为例,先获取相机的正交宽度/高度(
动态调整LoD阈值
根据当前内存占用和可见块数量自动调整阈值:- 内存占用过高时,调高阈值,仅让占比更大的块加载高LoD
- 内存充足时,调低阈值,提升更多区域的渲染精度
给焦点区域优先加载高LoD
正交模式下用户通常聚焦特定区域,可增加鼠标悬浮或视图中心区域的优先级:- 焦点区域内的块优先加载高LoD
- 非焦点区域的块即使可见,也先加载低LoD,待用户聚焦后再升级
合并小尺寸点云块
对正交视角下显示极小的点云块,加载时自动合并为大区块,减少Draw Call、降低LoD切换频率,同时节省内存
可视化效果对比
- 透视模式效果:

- 正交模式效果:

内容的提问来源于stack exchange,提问作者MR-DAI
相关产品推荐
相关产品推荐

