osg::MatrixTransform節點花式父子關係設置及矩陣節點相對座標系實例解析(這怕是本博最乾的一篇文了哈哈)

前幾天總結了一下節點的父子關係,本以爲以後就能一路順風了~沒想到啊,今天出了一個問題浪費了一下午,下面是出問題的效果:
在這裏插入圖片描述
因爲父子節點的問題,導致檢查了非常多遍本該順利實現的效果(如下圖)無法實現,後竊以爲是座標的問題,還去撿起高數知識去做了個函數,費了老大的力氣最後卻是白費功夫。

(張宇說,解決問題要抓主要矛盾)
在這裏插入圖片描述
所以先來整理一下原先的父子節點的關係圖~
不管葉子節點有多複雜(回調函數中調用的繪圖函數返回的node節點),且不論Matrixtransform節點指針的得到的有多麼麻煩(設置名字,然後在類外通過對組節點中節點的名字進行遍歷得到節點指針),我們都只把目光放在葉子節點和MatrixTransform節點上就好,先寫出來就一目瞭然了~結構如下:

完美的表格
在這裏插入圖片描述
上面自上而下爲根節點到葉子節點,經過提煉出來的結構還算明瞭,但是程序裏就夠嗆了,其中mt1和mt2節點爲父子節點,實際上實現的就是create()函數中創建的回調動畫(類似粒子效果)掛在mt1節點的模型上。下面是關鍵的一句話:

*** 對於一個節點的所有屬性不一定要在一個Mt節點下設置完畢,可以將影響子節點的屬性摘出,留下父子節點都需要,且不衝突的屬性進行設置,摘出的屬性令設mt節點掛載模型***

功力有限~只能提煉到這種程度,上面的表格可以看出是mt1的旋轉rotate設置導致了mt2節點方向的預期外偏離,所以將其摘出另設mt節點。修改後的mt關係如下:
在這裏插入圖片描述
這裏將mtrotate功能單獨摘出,這樣的組織結構就讓mt2不受mt節點的rotate節點影響,並且mtmt2始終共享縮放scale和平移translate操作的效果。
在這裏插入圖片描述

正常來說到這兒,這篇文章就結束了,但是,就這麼結束怎麼能叫最乾的文章呢~
經過這次的事情,讓我起了徹底弄懂父子節點和座標軸關係的問題。

下半部分第一句話,由今天的一個新知道的知識開篇(撒花感謝師兄!真的太強了我師兄!)

模型座標系

模型座標系模型出廠時(在外部軟件如3DMAX被製作等)確定的,有些模型不加任何設置加載至osg中並不是頭尾方向爲X軸(翻滾軸)左右面爲Y軸(俯仰軸),上下爲Z軸(偏航軸)的,如下爲符合osg規範的模型加載模樣:
在這裏插入圖片描述
爲什麼說這個呢,因爲想要說明一點,在考慮姿態問題的時候,不 需 要 過度思考模型的座標系是什麼。因爲模型的座標系是不會變的,屬於模型的硬件屬性,出廠就決定了(可以導入外部軟件修改),我們看到的模型變化施加在模型節點的MatrixTransform類的效果

相對座標系

顧名思義,相對座標裏的座標都是相對座標,是有一個參照物的,作爲子節點(尤其是作爲一個設置了旋轉的父MatrixTransform節點)

MatrixTransform節點, MatrixTransform節點就像一個惡棍,任意擺佈我們的模型,讓模型的姿態變得和 MatrixTransform節點一樣,就像個buff一樣,對模型產生着影響,一個 MatrixTransform節點做了rotate操作後可以在理解上認爲其座標系也發生了變化

即:在旋轉前後分別做translate(osg::Vec3(10,0,0));效果是不一樣的。

這裏我們繪製一個3軸長度爲200單位的座標軸作爲模擬的osg世界座標系,如下:

    //創建模擬世界座標系
    osg::ref_ptr<osg::Geode> AxisWorld = makeCoordinate(200,200,200);
    root->addChild(AxisWorld);

在這裏插入圖片描述
再做一個3軸長度爲30單位的座標系以模擬MatrixTransform節點的座標軸,爲了顯示清楚,先對模擬矩陣座標軸的座標軸做一個平移操作移動至(60,60,60):

    //創建模擬矩陣座標系的座標軸
    osg::ref_ptr<osg::Geode> Axis2 = makeCoordinate(50,50,50);
    //創建矩陣移動節點
    osg::ref_ptr<osg::MatrixTransform> MtgAxis2= new osg::MatrixTransform;
    //設置矩陣變換,移動至(30,30,30)
    MtgAxis2->setMatrix(osg::Matrix::translate(osg::Vec3(60,60,60)));
    //將繪製的矩陣幾何體加入矩陣變化節點
    MtgAxis2->addChild(Axis2);
    //加入根節點
    root->addChild(MtgAxis2);

在這裏插入圖片描述
對模擬矩陣座標軸做rotate操作,選擇其中的from-to重載。

inline Matrixd Matrixd::rotate(const Vec3f& from, const Vec3f& to )

這裏的from-to,是任取一條向量作爲起始向量from,轉至目標向量to,如果我們選擇from是(0,0,1)或是(0,0,10000)都一樣,處在同一方向的向量都一樣,選擇to爲(1,0,0),期待的效果是捏着Z軸,其他部分不動,轉至X軸,X軸順勢向下,Y不變,程序代碼及運行結果如下:

    //設置矩陣變換,先旋轉z軸後移動至(30,30,30)
    MtgAxis2->setMatrix(osg::Matrix::rotate(osg::Vec3(0,0,1), osg::Vec3(1,0,0))
    				  * osg::Matrix::translate(osg::Vec3(60,60,60)));

在這裏插入圖片描述
所有符合osg座標規範的模型加載進來,如果作爲該變換矩陣的節點,就會從世界座標系(大)變換爲MatrixTransform變換矩陣(小)的姿態,下面先用根節點root加入一個模型節點cow.osg:

        //加入模型
    osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("../data/cow.osg");
    //直接在根節點加入模型,加載進來會符合osg座標系規範
    root->addChild(cow);

在這裏插入圖片描述
放大點:
在這裏插入圖片描述
姿態確實符合所繪製的座標系,下面將這牛作爲模擬矩陣變換座標軸的子節點,看其姿態變化:

    //加入模型
    osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("../data/cow.osg");
    //直接在根節點加入模型,加載進來會符合osg座標系規範
//    root->addChild(cow);
    //模擬矩陣加入模型
    MtgAxis2->addChild(cow);

在這裏插入圖片描述
放大點:
在這裏插入圖片描述
確實如預料一般變化了姿態。

現在試驗相對座標,將在這個牛作爲組節點,再添加一個模型,並設置translate(osg::Vec3(20,0,0));

預期模型應往圖中的小座標系的X軸方向移動,而不是符合世界座標大X軸的小座標系的Z軸方向移動:

    //牛老二
    osg::ref_ptr<osg::Node> cow2 = osgDB::readNodeFile("../data/cow.osg");
    //定義一個移動牛老二的矩陣節點
    osg::ref_ptr<osg::MatrixTransform> MtCow2= new osg::MatrixTransform;
    //設置平移
    MtCow2->setMatrix(osg::Matrix::translate(osg::Vec3(20,0,0)));
    //添加子節點
    MtCow2->setChild(cow2);
    //牛老大添加子節點,其實應該用MtgAxis2來添加cow2,這裏實驗就不計較了
    cow->asGroup()->addChild(MtCow2);


在這裏插入圖片描述
放大點:
在這裏插入圖片描述
符合預期。

總結:

模型的座標系不需要關注,出廠即設定好了,只要符合osg座標系統就行。

對矩陣節點做旋轉後,矩陣節點的座標系也發生了變化,旋轉後的平移是按照旋轉後的座標系來移動,而不是世界座標,這也是相對座標系的概念。

感謝觀看~

發佈了28 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章