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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

osg中三维模型的位置变换

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

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

?

問題出現的原因就在于我們想要的是以物體自身的中心為變換中心,而實際得到的卻是以世界坐標的原點為變換中心的。為了解決這個問題,最好的辦法就是先將物體的變換中心移到世界坐標的原點,再進行級聯變換,然后再將物體移回原先的位置。

在osg中可以按照以下步驟進行:

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

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

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

實現代碼如下所示:

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

?

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

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

根據上述討論我們知道,最后模型的世界坐標被變換為:

N*M*M2

現在,若對模型進行平移變換T,由于我們本意是對模型N本身坐標系進行變換,所以本應得到以下變換公式:

設矩陣B= osg::Matrix::translate(-(center*M*M2))?//移回坐標原點

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

N*M*M2*B*T*C

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

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

這樣,新的場景圖則對應于:

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最終得到的是模型在世界坐標下的變換矩陣,osg中常常將其命名為localToWorld,也就是局部到世界的轉變,而對其求逆則稱為worldToLocal,顯然是世界到局部的轉變。關于這兩個矩陣獲得,osg中還有一些自帶的函數去獲得(上述方法可以說是最原始的獲取方法),具體可以查看osg源碼或幫助文檔中MatrixTransform類或是osgManipulator類等,在此就不在詳細討論。

本文摘自: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

?

?

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。