OGG几何内核算法研究-大型装配模型快速载入研究
OGG/OCCT几何内核加载大型STEP模型文件时,速度较慢。通过打散模型、多线程并行加载,可以极大提升模型加载速度。本文通过一个16.2M的实际模型文件,采用两种算法进行加载,对比了前后效果,速度提升40%左右。
OGG几何内核fork自OCCT。STEP文件读取的性能,也是让用户和开发人员着急的地方。
一、需求
本人的兄弟公司的客户的关键诉求之一是:大型模型如1G左右或复杂结构(零件特征较多)打开速度慢。 是否有提升模型打开速度的方案?下面客户给出的目标:
本人的某知名制造业客户,也提出了类似的诉求:模型加载慢、渲染效果不理想。
二、STEP有几种读法你知道吗?
“谁要你教,不是草头底下一个来回的回字么?”
孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“对呀对呀!……回字有四样写法,你知道么?”
方法一
参考示例代码
char * fname="a.stp";
STEPControl_Reader reader;
reader.ReadFile(fname);
reader.TransferRoots();
reader.NbRootsForTransfer();
reader.NbShapes();
TopoDS_Shape shape = reader.OneShape();
Handle(AIS_Shape) aisShape = new AIS_Shape(shape);
occView->display(aisShape);
缺点:
1、模型大了,必卡,也容易失败。
2、模型有问题,程序会崩溃。
3、装配模型给打包成一个Compound。
4、不能进一步读取颜色以及别的信息。
方法二
参考示例代码
char * fname="a.stp";
STEPCAFControl_Reader reader;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.ReadFile(fname) ;
Handle(TDocStd_Document) m_OcafDoc;
XCAFApp_Application::GetApplication()->NewDocument("name", m_OcafDoc);
reader.Transfer(m_OcafDoc);
TDF_Label label=pDoc->GetData()->Root();
Handle(TDataStd_Name) name;
label.FindAttribute(TDataStd_Name::GetID(), name);
Handle(TDF_Attribute) attr;
label.FindAttribute(TNaming_NamedShape::GetID(), attr);
TopoDS_Shape shape = Handle(TNaming_NamedShape)::DownCast(attr)->Get();
Handle(AIS_Shape) aisShape = new AIS_Shape(shape);
occView->display(aisShape);
这只是一个简单的示例。但可以进一步读取很多模型信息,比如颜色、名称等。
问题:模型显示效果不好,还需要程序员去读取颜色,设置模型颜色等。
方法三
参考示例代码
STEPCAFControl_Reader reader;
TDF_LabelSequence FreeShapeLabel;
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.ReadFile(fname);
Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) doc;
anApp->NewDocument("MDTV-XCAF", doc);
reader.Transfer(doc);
TDF_Label mainLabel = doc->Main();
auto ShapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
// ColorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
ShapeTool->GetFreeShapes(FreeShapeLabel); //获取 all top-level shapes
auto Roots = FreeShapeLabel.Length();
for (int index = 1; index <= Roots; index++)
{
TDF_Label label = FreeShapeLabel.Value(index);
readLabel(label,item, TopLoc_Location(),"");//读取当前模型信息
makeTree(label);//读取子模型信息
QApplication::processEvents(QEventLoop::AllEvents, 100);
}
完整的代码太多,太复杂,涉及到qtreewidget载入显示等内容,就不全展示了。
读取显示效果如下图:
该机器人模型16M,采用OCCT自身的多线程方法,用时10.732秒。
展示了模型树,装配模型的颜色、名称等信息都读取出来。
问题:界面会卡死。
方法四
采用多线程。
QFuture<void> future = QtConcurrent::run([fname, &reader, &FreeShapeLabel](){
reader.SetColorMode(true);
reader.SetNameMode(true);
reader.ReadFile(fname);
Handle(XCAFApp_Application) anApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) doc;
anApp->NewDocument("MDTV-XCAF", doc);
reader.Transfer(doc);
TDF_Label mainLabel = doc->Main();
auto ShapeTool = XCAFDoc_DocumentTool::ShapeTool(mainLabel);
// ColorTool = XCAFDoc_DocumentTool::ColorTool(mainLabel);
ShapeTool->GetFreeShapes(FreeShapeLabel); //获取 all top-level shapes
});
优点:界面不卡死
不足:还是没有加速效果。
三、STEP模型加载关键卡点分析
以16.2M的变形金刚机器人.stp文件为例:
reader.ReadFile用时:1.415000秒
reader.Transfer用时:5.024000秒
----> 总共用时:10.408000
其中ReadFile与Transfer用了6.435秒。
装配树及渲染显示用时约4秒。
又研究了一下OCCT的多线程、并行等参数。
确实使用了多线程,但CPU占用并不高。
四、加速思路
单纯依赖OCCT的STEPCAFControl_Reader自身或想通过配置参数来加速,目前看不到希望。
还得靠应用层采用新架构与技术思路来实现加速。
打散模型,多线程并行加载。
加载效果如下:
read & Transfer用时:2.127000秒
总计用时:5.912000秒
提速约 40%。