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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

第8节 实例-写个简单的操作器

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第8节 实例-写个简单的操作器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緣由

應四川的群友:挑戰高起點 的要求,我給大家寫一個最簡單的操作器,讀完本文以最大程度讓讀者掌握在OSG中寫個操作器是咋回事兒。代碼在最后一個代碼塊,直接新建OSG工程,拷貝進去就可以運行。特別感謝這位網友,要不然真的不知道怎么為大家好呀。

另外如果您也想我來為您就某個功能寫個例子,分享給大家,則只需要在本文評論區回復即可。或在本文出現的群里回復。

本節所有代碼在網盤中:

【擊此打開網盤資源鏈接】

功能說明
首先繪制一個場景如下,場景中間放著模型axes.osgt這個模型,它指明了xyz軸的方向,然后我們在xy方向,從-5~5,間隔0.5繪制網格,如下圖所示。

然后我們操作器的功能是:點擊a圍繞z軸,眼睛看著(0,0,0)點,高度在5,逆時針旋轉
點擊d則順時針旋轉。

實現要點
1. 寫個類繼承自osgGA::CameraManipulator,就我們的功能而言,有兩個函數就可以了,一個是virtual osg::Matrixd getInverseMatrix() const,它要返回camera的ViewMatrix,也就是我說的,Camera會在事件遍歷的時候,調用這個函數來設置他的ViewMatrix。所以我們要實現它。

實現它也很簡單,自己寫三個變量做成員函數:_eye(人頭的位置), _center(人頭在往哪看), _up(人頭頂的朝向),自己想想自己的頭,就能想明白這三個量一定,你在哪朝哪看就定了,接著直接構造ViewMatrix就可以了,代碼如下:

virtual osg::Matrixd getInverseMatrix() const{return osg::Matrix::lookAt(_eye, _center, _up);};

看看簡單吧。那么現在的任務就是根據事件要來設置_eye了,因為根據我們的功能設想,_center始終是0,0,0,up始終是0,0,1。

2. _Eye的更新在事件處理中,也就是另一個要實現的虛函數:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us),我們定義了一個成員變量_theta,點A的時候就把它加一度,點D的時候就減一度。然后立即更新_eye的值,按半徑是sqrt(55+55)來算:

//事件處理,我們要點擊A就圍著Z軸順時針轉動,點D就逆時針轉動,轉的時候始終朝0 0 0 點看著virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us){if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN){//若是A鍵if ((ea.getKey() == 'A') || (ea.getKey() == 'a')){_theta += 1.0;}if ((ea.getKey() == 'D') || (ea.getKey() == 'd')){_theta -= 1.0;}_eye = osg::Vec3(_r * std::cos(osg::DegreesToRadians(_theta)), _r * std::sin(osg::DegreesToRadians(_theta)), 5.0);}return false;}

3. 關鍵代碼就是上面那些。要寫自己的操作器就是要看看自己按照事件怎么操作_eye,_center,_up這三個值了。多說一句,如果要讓相機按著某個路徑運動,可以使用AnimationPathManipulator類,它還支持將路徑存在文件,然后讀起來用。具體用法可以參考:applications/osgviewer/osgviewer.cpp這個程序的具體實現,主要看RecordCameraPathHandler這個類。

4. 最后下面是這個示例的所有代碼,大家直接拷貝就可以使用,是完整的,沒有依賴的,依賴的axes.osgt是OSG自帶的模型。就算讀不了來只是軸不顯示,也不影響其它的功能。

#include <osgViewer/viewer> #include <osgDB/ReadFile> #include <osg/Geode> #include <osg/Geometry> #include <osgGA/CameraManipulator>class MyCameraManipulator : public osgGA::CameraManipulator { public:MyCameraManipulator() {_theta = 0.0;_center = osg::Vec3(0.0, 0.0, 0.0);_up = osg::Vec3(0.0, 0.0, 1.0);_r = std::sqrt(5 * 5 + 5 * 5);_eye = osg::Vec3(_r*std::cos(osg::DegreesToRadians(_theta)), _r * std::sin(osg::DegreesToRadians(_theta)), 5.0);}//這三個純虛函數本例不會使用virtual void setByMatrix(const osg::Matrixd& matrix) {};virtual void setByInverseMatrix(const osg::Matrixd& matrix) {};virtual osg::Matrixd getMatrix() const { return osg::Matrix::identity(); };//最關鍵的是這個,這個返回的就是ViewMatrixvirtual osg::Matrixd getInverseMatrix() const{return osg::Matrix::lookAt(_eye, _center, _up);};//事件處理,我們要點擊A就圍著Z軸順時針轉動,點D就逆時針轉動,轉的時候始終朝0 0 0 點看著virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us){if (ea.getEventType() == osgGA::GUIEventAdapter::KEYDOWN){//若是A鍵if ((ea.getKey() == 'A') || (ea.getKey() == 'a')){_theta += 1.0;}if ((ea.getKey() == 'D') || (ea.getKey() == 'd')){_theta -= 1.0;}_eye = osg::Vec3(_r * std::cos(osg::DegreesToRadians(_theta)), _r * std::sin(osg::DegreesToRadians(_theta)), 5.0);}return false;}//視點位置osg::Vec3d _eye;//視點看向哪里osg::Vec3d _center;//頭頂的朝向osg::Vec3d _up;//視點看向0 0 0的角度float _theta;//視點離0 0 0的距離float _r; };osg::Node* createScene() {osg::Group* root = new osg::Group();root->addChild(osgDB::readNodeFile("axes.osgt"));osg::Geode* gnode = new osg::Geode;root->addChild(gnode);osg::Geometry* geom = new osg::Geometry;gnode->addChild(geom);osg::Vec3Array* vertex = new osg::Vec3Array;geom->setVertexArray(vertex);//沿xy平面畫線,間隔0.5米,從-5,畫到5for (float i = -5; i <= 5; i += 0.5){vertex->push_back(osg::Vec3(i, -5, 0));vertex->push_back(osg::Vec3(i, 5, 0));vertex->push_back(osg::Vec3(-5, i, 0));vertex->push_back(osg::Vec3(5, i, 0));}geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, vertex->size()));osg::Vec4Array* color = new osg::Vec4Array();color->push_back(osg::Vec4(0.7, 0.7, 0.7, 1.0));geom->setColorArray(color, osg::Array::BIND_OVERALL);geom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);return root; }int main() {osgViewer::Viewer viewer;viewer.setCameraManipulator(new MyCameraManipulator());viewer.setSceneData(createScene());return viewer.run(); }

總結

以上是生活随笔為你收集整理的第8节 实例-写个简单的操作器的全部內容,希望文章能夠幫你解決所遇到的問題。

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