OpenNURBS 3DM Viewer
eryar@163.com
Abstract. The openNURBS Toolkit consists of C++ source code for a library that will read and write a openNURBS 3D model file(.3dm). More than 400 software development teams and applications including Rhinoceros, exchange 3-D models using the openNURBS (.3dm) file format. But there is no a simple viwer for 3dm on PC except Rhinoceros. So I want to develop a 3DM viewer based on OpenSceneGraph to visualize the 3DM file.
Key Words. OpenNURBS, 3DM Viewer, OpenSceneGraph
1. Introduction
3DM 文件格式是Rhinoceros軟件的開源開發(fā)庫openNURBS中用于三維模型數(shù)據(jù)交換的一種格式,被許多軟件開發(fā)團(tuán)隊(duì)及應(yīng)用程序用來進(jìn)行三維模型的數(shù)據(jù)交換。因?yàn)閛penNURBS開源的原因,3DM格式也是一種開放的文件格式了。
3DM文件中用于三維模型的信息完整,包括幾何、拓樸信息,光照等等,利用這些數(shù)據(jù)可以渲染出效果逼真的三維模型。
但是搜索了一下,能查看3DM模型的軟件除了Rhinoceros以外,再就是Android版本或iOS程序,沒有電腦Windows/Linux上運(yùn)行的簡單的查看3DM模型的簡單瀏覽程序,所以決定應(yīng)用OpenSceneGraph開發(fā)一個(gè)簡單的瀏覽程序,來實(shí)現(xiàn)3DM文件的模型查看功能。另外也可學(xué)習(xí)一下,如何對(duì)Brep表示的模型進(jìn)行可視化。
本文主要說明如何實(shí)現(xiàn)以線框模式Wire-Frame、渲染模式Shaded顯示三維模型。
2.Display Model in Wire-Frame
3DM中的三維模型是基于邊界表示法的Brep,所以要顯示線框模式的模型可以將邊界表示的模型的所有的邊Edge離散成點(diǎn)后進(jìn)行顯示即可。顯示邊的一種最簡單的方法就是對(duì)邊的幾何數(shù)據(jù)——曲線——進(jìn)行均勻取點(diǎn),然后連成線即可。但是這并不是高效的方式,會(huì)造成如下圖所示的問題:
Figure 2.1 Uniform sampling on a curve
如上圖所示,均勻取點(diǎn)的方式會(huì)在曲線比較平直的區(qū)域采樣到比實(shí)際需要更多的點(diǎn),而在曲率較大的區(qū)域采樣到比實(shí)際需要更少的點(diǎn)。為了提高顯示速度,應(yīng)該用盡可能少的點(diǎn)來顯示更逼真的曲線,這就需要一種細(xì)分算法:Adaptive Subdivision算法。為了簡單起見,在3DM Viewer中采用了均勻采樣的方式,顯然這種方式不是很高效,但是可以用來簡單驗(yàn)證Brep中邊的數(shù)據(jù)。對(duì)邊均勻采樣取點(diǎn)的代碼示例如下:
osg::Node* RhinoReader::BuildEdge(const ON_Brep* theBrep)
{
osg::ref_ptr<osg::Geode> aGeode = new osg::Geode();
for (int i = 0; i < theBrep->m_E.Count(); ++i)
{
osg::ref_ptr<osg::Geometry> aGeometry = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> aVertices = new osg::Vec3Array();
ON_BrepEdge* anEdge = theBrep->Edge(i);
double t0 = 0.0;
double t1 = 0.0;
double d = 0.0;
anEdge->GetDomain(&t0, &t1);
d = (t1 - t0) / 5.0;
for (double t = t0; (t - t1) < TOLERANCE_EDGE; t += d)
{
ON_3dPoint aPoint = anEdge->PointAt(t);
aVertices->push_back(osg::Vec3(aPoint.x, aPoint.y, aPoint.z));
}
aGeometry->setVertexArray(aVertices);
aGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, aVertices->size()));
aGeode->addDrawable(aGeometry);
}
return aGeode.release();
}
由上述代碼可知,通過遍歷Brep結(jié)構(gòu)中的邊,并將其均勻采樣取點(diǎn),取可得到曲線的大概輪廓了。顯示效果如下圖所示:
Figure 2.2 Display Basketball Goal Model Edges
Figure 2.3 Display Bookshelf Model Edges
由圖可知,顯示效果還不錯(cuò)。這也是常見的三維顯示中的線框模式實(shí)現(xiàn)的方式。不過在采樣點(diǎn)的算法上還有優(yōu)化空間。
3.Next...
下一步準(zhǔn)備以渲染模式Shaded來顯示3DM模型,就需要對(duì)Face進(jìn)行網(wǎng)格剖分。網(wǎng)格剖分的速度及質(zhì)量直接影響面的渲染。網(wǎng)格剖分統(tǒng)一在NURBS曲面的參數(shù)空間,且需要注意曲面的外邊界及內(nèi)邊界(即面的開孔的處理)。如下圖所示,先將面均勻采樣顯示效果如下圖所示:
Figure 3.1 Display Basketball Goal Model Faces
Figure 3.2 Display Bookshelf Model Faces
為了顯示渲染模式的曲面,還需要在此基礎(chǔ)上對(duì)曲面的參數(shù)空間進(jìn)行剖分。為了曲面光照效果,需要正確計(jì)算出曲面上點(diǎn)的法向,這是下一步的工作了。
4.Get Involved
在網(wǎng)上沒有搜到合適的3DM Viewer,只有自己來做了,做的過程也是個(gè)學(xué)習(xí)的過程。而且在Windows/Linux上一個(gè)輕量級(jí)的3DM Viewer還是有些需求的,所以在Github上創(chuàng)建了一個(gè)項(xiàng)目,感興趣的讀者也可以參與進(jìn)來,或者貢獻(xiàn)代碼,或者給些意見。項(xiàng)目地址如下:
https://github.com/eryar/3DMViewer
關(guān)于3DM格式的更多模型可以從網(wǎng)上獲取,本文中的兩個(gè)模型來自如下網(wǎng)站:
http://ad-3d.com/free-rhino-3d-nurbs-models/
5. Conclusion
通過使用OpenNURBS庫來讀取3dm文件中的模型數(shù)據(jù),并對(duì)其進(jìn)行可視化。并對(duì)顯示中常見有模式:線框、渲染模式的實(shí)現(xiàn)方法進(jìn)行介紹。通過實(shí)現(xiàn)3DM Viewer也是為了進(jìn)一步學(xué)習(xí)如何將Brep表示的模型可視化。
6. References
1. Free 3DM models: http://www.ad-3d.com/Free Rhino3D models/
2. Kelly Dempski, Focus on Curves and Surfaces, Premier Press, 2003