日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

osg中三维模型的位置变换

發(fā)布時(shí)間:2023/12/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 osg中三维模型的位置变换 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對(duì)模型的平移和旋轉(zhuǎn)等操作是我們在做三維軟件開發(fā)時(shí)必然會(huì)解決的事情。但是由于基本變換默認(rèn)是以世界坐標(biāo)系的原點(diǎn)為變換中心,所以我們在進(jìn)行平移旋轉(zhuǎn)等操作時(shí)往往會(huì)發(fā)現(xiàn)其并非如我們想象的那樣去執(zhí)行。舉個(gè)簡單的例子:當(dāng)對(duì)物體進(jìn)行先x軸方向20個(gè)單位的平移操作,再將物體繞自身z軸旋轉(zhuǎn)60度的操作時(shí)。我們希望的是左圖所示結(jié)果,但往往我們得到的是右圖的結(jié)果(Z軸未標(biāo)出)。

?

問題出現(xiàn)的原因就在于我們想要的是以物體自身的中心為變換中心,而實(shí)際得到的卻是以世界坐標(biāo)的原點(diǎn)為變換中心的。為了解決這個(gè)問題,最好的辦法就是先將物體的變換中心移到世界坐標(biāo)的原點(diǎn),再進(jìn)行級(jí)聯(lián)變換,然后再將物體移回原先的位置。

在osg中可以按照以下步驟進(jìn)行:

1)osg場景中的物體通常是以Node節(jié)點(diǎn)的形式存在的,所以我們需將變換的物體轉(zhuǎn)換成osg::MatrixTransform類型,再通過getMatrix()方法得到當(dāng)前矩陣。

2)為了將物體中心同世界坐標(biāo)原點(diǎn)重合,需獲得物體中心。可以采用getBound()或getSphere()方法獲取模型包圍盒,再采用包圍盒的center()方法獲得包圍盒中心即為物體中心。

3)按上述方法變換模型。

實(shí)現(xiàn)代碼如下所示:

osg::MatrixTransform* picked= static_cast<osg::MatrixTransform*>(pNode); //轉(zhuǎn)換成MatrixTransformosg::Vec3d center= picked->getBound().center(); //獲得包圍盒中心osg::Matrixd originPos= picked->getMatrix(); //獲得當(dāng)前矩陣picked->setMatrix(originPos*osg::Matrixd::translate(-center) //先將物體中心平移到世界坐標(biāo)的原點(diǎn) *osg::Matrixd::scale(0.5,0.5, 0.5) //縮放 *osg::Matrixd::rotate(osg::DegreesToRadians(60.0),0,0,1)//旋轉(zhuǎn)*osg::Matrixd::translate(20,0,0)//平移*osg::Matrixd::translate(center));//變換后再將物體移回

?

對(duì)于單一的矩陣掛接,上述問題似乎很容易就得到了解決。但是,在實(shí)際的模型或許并沒那么簡單,往往是在多重的矩陣掛接下才得到模型的位置。而我們通過上述的getMatrix()方法得到的僅僅是模型的當(dāng)前矩陣,還有父級(jí)矩陣甚至是父父級(jí)矩陣等。此時(shí)我們需要做的步驟仍是上述操作,但是需先得到物體世界坐標(biāo)位置,并將其移到世界坐標(biāo)原點(diǎn),再進(jìn)行級(jí)聯(lián)變換,最后將其移回原先位置。

我們先來看一個(gè)這樣的例子,場景如下:

根據(jù)上述討論我們知道,最后模型的世界坐標(biāo)被變換為:

N*M*M2

現(xiàn)在,若對(duì)模型進(jìn)行平移變換T,由于我們本意是對(duì)模型N本身坐標(biāo)系進(jìn)行變換,所以本應(yīng)得到以下變換公式:

設(shè)矩陣B= osg::Matrix::translate(-(center*M*M2))?//移回坐標(biāo)原點(diǎn)

? ? ? ? ? ? C=osg::Matrix::translate(center*M*M2) ?//移回原先位置

N*M*M2*B*T*C

顯然,我們所需要變換的僅僅是矩陣M,而不能在ROOT和M2之間加一個(gè)B*T*C,因此就有了下列公式:

M重新賦值為 N*(M*M2)*B*T*C*inv(M*M2)*M

這樣,新的場景圖則對(duì)應(yīng)于:

N*(M*M2)*B*T*C*inv(M*M2)*M*M2=N*M*M2*B*T*C

具體代碼如下:

osg::MatrixTransform* picked= static_cast<osg::MatrixTransform*>(pNode);osg::Matrixd originPos= picked->getMatrix();osg::Vec3d center= picked->getBound().center();osg::Node* pParentNode;osg::MatrixTransform* pParent;pParentNode= pNode->getParent(0);pParent= dynamic_cast<osg::MatrixTransform*>(pParentNode);while(pParent!= NULL){originPos= originPos*pParent->getMatrix();pParentNode= pParentNode->getParent(0);pParent= dynamic_cast<osg::MatrixTransform*>(pParentNode);}osg::Matrixd inverseAll= osg::Matrixd::inverse(originPos)*picked->getMatrix();osg::Vec3d originCenter=center*(osg::Matrixd::inverse(picked->getMatrix())*originPos);picked->setMatrix(originPos*osg::Matrix::translate(-originCenter)*osg::Matrixd::scale(0.5,0.5, 0.5)*osg::Matrix::rotate(osg::Quat(osg::DegreesToRadians(60.0),0,0,1))*osg::Matrix::translate(20,0, 0)*osg::Matrix::translate(originCenter)*invertAll);

?在上述代碼中,originPos最終得到的是模型在世界坐標(biāo)下的變換矩陣,osg中常常將其命名為localToWorld,也就是局部到世界的轉(zhuǎn)變,而對(duì)其求逆則稱為worldToLocal,顯然是世界到局部的轉(zhuǎn)變。關(guān)于這兩個(gè)矩陣獲得,osg中還有一些自帶的函數(shù)去獲得(上述方法可以說是最原始的獲取方法),具體可以查看osg源碼或幫助文檔中MatrixTransform類或是osgManipulator類等,在此就不在詳細(xì)討論。

本文摘自:https://blog.csdn.net/wxx19945/article/details/72808442?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

?

?

總結(jié)

以上是生活随笔為你收集整理的osg中三维模型的位置变换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。