osg 节点渲染 重新渲染模型 (已解决)
以下內容來自:
1、《OpenSceneGraph三維渲染引擎編程指南》肖鵬 劉更代 徐明亮 清華大學出版社
2、《OpenSceneGraph三維渲染引擎設計與實踐》王銳 錢學雷 清華大學出版社
3、自己的總結
下載完整工程OSG_8_RenderClipeNode
創建C++項目后,首先需要配置OSG環境,具體步驟看OSG學習:WIN10系統下OSG+VS2017編譯及運行第六步:新建OSG項目測試。
本篇文章通過分析裁剪節點ClipNode,結合更新回調節點NodeCallback和空間變換矩陣類MatrixTransform來看如何在OSG使用渲染狀態。直接來看例子:
// stdafx.h #include <osg/Node> #include <osg/Geometry> #include <osg/Geode> //是個幾何節點,可以說是一個幾何Group節點,一般的可繪制幾何體都是通過它來傳向root進行渲染,是OSG幾何繪制的最高管理節點 #include <osg/Group> //對節點起到組織作用,一般作為父節點或者根節點出現 #include <osg/ClipNode> //繼承自osg::Group,定義場景中裁剪面的位置 (與之相似的有osg::ClipPlane,繼承自osg::StateAttribute,定義一個裁剪面) #include <osg/PolygonMode> //指定多邊形的繪制模式(點/線框/填充) #include <osg/MatrixTransform> //移動節點的矩陣類,最常用的移動節點的類。可隨動、旋轉控制節點 #include <osg/PositionAttitudeTransform> //位置變換節點類,提供模型的位置變換、大小縮放、原點位置的設置、坐標系的變換 #include <osg/AnimationPath> //動畫類,封裝了一個隨時間變化的轉型過程,可用于更新相機位置和模型對象的位置 #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgViewer/Viewer> #include <osgUtil/Optimizer> //.cpp #include "stdafx.h" /* 裁剪模型 創建裁剪節點,設置包圍盒和裁剪平面 雖然設置了范圍,但實際上這個節點什么也沒有繪制,當有什么模型添加到該節點中,這個節點就裁剪什么模型,包圍盒內顯示,盒外不顯示 創建更新回調節點和空間變換節點,空間變換節點調用更新回調節點的更新回調方法,并將裁剪節點添加到空間變換矩陣節點中 也即是clipnode節點截取的是什么模型,此處旋轉的就是什么模型 創建未被裁剪的節點,獲取裁剪節點的渲染狀態,并添加模型節點 因此該節點也有了包圍盒和裁剪平面,它添加了什么模型節點,它就裁剪什么模型 創建組節點為多邊形模型節點,并設置其渲染狀態為多邊形線形模型,并添加物體模型 則這個物體模型是線形的 創建組結點為根節點,將空間變換節點、未被裁剪節點和線形模型節點添加到其中 */ osg::ref_ptr<osg::Node> createClipNode(osg::ref_ptr<osg::Node> subgraph) {//獲取中心點和半徑 osg::BoundingSphere用于封閉節點/對象/頂點的通用邊界球類 osg::BoundingSphere bs = subgraph->getBound();//設置半徑長度為原來的0.4倍bs.radius() *= 0.4f;//設置裁剪節點的包圍盒,包圍盒的長度為改變后的半徑值,盒以外的都將裁剪掉osg::BoundingBox bb;bb.expandBy(bs);//創建裁剪節點osg::ref_ptr<osg::ClipNode> clipnode = new osg::ClipNode();//根據前面指定的包圍盒創建6個裁剪平面clipnode->createClipBox(bb);//禁用揀選(揀選即顯示一些東西不顯示一些東西)clipnode->setCullingActive(false);//釋放下面這句話,然后將root添加的節點clippedNode改為clipnode,另外兩個不變,則轉動裁剪后的填充模型//clipnode->addChild(subgraph.get());//更新回調,實現動態裁剪,需要將更新回調類和矩陣變換節點類相結合,更新回調類改變當前節點,矩陣變換類改變節點位置//創建一個動畫路徑來產生關于一個點的旋轉 參數1坐標原點const osg::Vec3d &pivot 參數2坐標軸const osg::Vec3d &axis 參數3旋轉角度float angularVelocity)//getBound().center() 獲取節點的通用邊界球的中心點,osg::inDegrees(45.0f)將45角度轉換為弧度osg::ref_ptr<osg::NodeCallback> nc = new osg::AnimationPathCallback(subgraph->getBound().center(), osg::Vec3(0.0f, 0.0f, 1.0f), osg::inDegrees(45.0f));//創建空間變換矩陣節點對象MatrixTransformosg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform();transform->setUpdateCallback(nc.get());transform->addChild(clipnode.get());//創建未被裁剪的節點osg::ref_ptr<osg::Group> clippedNode = new osg::Group();clippedNode->setStateSet(clipnode->getStateSet());clippedNode->addChild(subgraph.get());//多邊形模型繪制,繪制面為正面和反面,繪制模式為線形osg::ref_ptr<osg::PolygonMode> polynmode = new osg::PolygonMode();polynmode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);//實例化一個渲染狀態osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();//啟用與上面相對應的多邊形線形繪制模式,并應用將上面設置的模式//制定狀態繼承屬性為OVERRIDE(所有子節點都將繼承這一屬性或模式,子節點對其更改無效)stateset->setAttributeAndModes(polynmode, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);//多邊形線形繪制節點osg::ref_ptr<osg::Group> wireframe_subgraph = new osg::Group();//設置渲染狀態wireframe_subgraph->setStateSet(stateset.get());wireframe_subgraph->addChild(subgraph.get());/*注釋掉后兩句,只添加空間變換矩陣節點,不顯示模型,因為此時沒有基礎模型存在注釋掉前后兩句,只添加未被裁剪的節點,顯示填充完的模型(原始飛機模型)注釋掉前兩句,只添加多邊形線形繪制節點,顯示線形模型注釋掉第一句,不添加空間變換矩陣節點,顯示填充完的模型(原始飛機模型)注釋掉第二句,不添加未被裁剪的節點,顯示線形模型注釋掉最后一句,不添加多邊形線形繪制節點,在填充模型(原始飛機模型)基礎上進行動態裁剪 不注釋任何語句,在填充模型(原始飛機模型)基礎上進行動態裁剪,裁剪部分顯示線形模型非裁剪節點獲取了裁剪節點的渲染狀態,但動態更新這個方法并不能一起獲取但是裁剪節點的動態更新方法使得其包圍盒變成了一個動態的包圍盒,包圍盒是一種渲染狀態,而非裁剪節點的包圍盒與其一致,因此也是動態更新的,則出現了這種動態裁剪將空間變換矩陣節點transform改為裁剪節點clipnode,顯示靜態的裁剪模型,非裁剪部分顯示填充模型(原始飛機模型),裁剪部分顯示線形模型*/osg::ref_ptr<osg::Group> root = new osg::Group();//添加空間變換矩陣節點root->addChild(transform.get());//添加未被裁剪的節點root->addChild(clippedNode.get());//添加多邊形線形繪制節點root->addChild(wireframe_subgraph.get());return root.release(); } int main() { //加載模型osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cessna.osg");osg::ref_ptr<osg::Node> root = createClipNode(node.get());//優化場景數據 osgUtil::Optimizer optimizer;optimizer.optimize(root.get());//顯示模型 osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();viewer->setSceneData(root.get());viewer->realize();return viewer->run(); }來看結果:
?
具體的解釋全都在代碼中了。
上面的結果,是將代碼原封不動地運行后的結果。在第71行到83行的注釋中寫出,通過使根節點root添加的節點不同,給出了其他幾種情況不同的情況。此處主要說明第38行的意思:
當把以上的代碼中的39句取消注釋后,再使root添加的節點從非裁剪節點clippedNode改為裁剪節點clipnode,情況將大不相同:
clipnode->addChild(subgraph.get()); osg::ref_ptr<osg::Group> root = new osg::Group(); root->addChild(transform.get()); root->addChild(clipnode.get()); root->addChild(wireframe_subgraph.get());?
?
在第6行到第22行的注釋中寫到:當裁剪節點添加了什么樣的模型節點,什么模型就被裁剪(包圍盒內顯示,包圍盒外不顯示)。而在上面這個例子中,將傳入的填充飛機模型節點添加到裁剪節點中,因此填充飛機模型被裁剪。根節點添加了三個節點:
第一個是空間變換矩陣節點,它還使用了更新回調方法,它用于實時更新裁剪節點,也就是實時更新包圍盒;而由于裁剪節點里有填充飛機的節點,因此填充飛機實時一直旋轉。注意:它里面的裁剪節點、飛機節點等都屬于在原位置對該節點進行深拷貝,它們并不是原始的節點。
第二個是裁剪節點,由于裁剪節點只有一個包圍盒,它里面有填充飛機的節點,因此填充飛機被裁剪后保持靜止。
第三個是線性模型,顯示線性飛機。
總結
以上是生活随笔為你收集整理的osg 节点渲染 重新渲染模型 (已解决)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 单点登出_CAS单点登出的原理
- 下一篇: skimage.morphology.m