概述
本文在吸收了《最長的一幀》以及相關參考資料的基礎之上解讀OSG的基礎數據結構,渲染方法。
實現
在這第一部分裏,要理解的是run函數的實現,因爲以下這一段證明了它的重要性和強大的能力。
int main()
{
//....
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
/**如果指向的目錄沒有數據OSG的屏幕上不會有數據顯示*/
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("D:/OpenSceneGraph/data/cow.osg");
viewer->setSceneData(node.get());
return viewer->run();
}
按照《最長的一幀》中的說法,所有的繪製工作會在一個循環裏面完成:
while( !viewer->done() )
{
viewer->frame();
}
但在第一段並沒有出現相關的代碼,可以確定這些實現細節必須在run函數中實現了。
首先,我希望通過自己實現的控制器顯示場景結點數據,這個跟run函數無關,是教程裏的一個小例子,至於run函數我是用了上面的這個循環替代,結果卻出乎意料,在場景中看不到我加載的模型。
源代碼:
int main()
{
//....
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
//osg::ref_ptr<osg::Group> root = new osg::Group;
/**如果指向的目錄沒有數據OSG的屏幕上不會有數據顯示*/
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("D:/OpenSceneGraph/data/cow.osg");
//........................
viewer->setSceneData(node.get());
viewer->setCameraManipulator(new RunImplement);
//仿真渲染初始化
viewer->realize();
/**最長的一幀 實踐版*/
//渲染每一幀
while(!viewer->done())
{
viewer->frame();
}
return 0;
}
如果控制器設置爲TrackballManipulator,就可以在場景中看到模型。這讓我納悶,在實現RunImplement這個控制器的時候是缺少了什麼東西才導致這樣的意外的呢?目前我現了幾個osgGA::OrbitManipulator中的虛函數,這些函數是顯示節點場景數據的接口。具體實現如下:
#include "run.h"
RunImplement::RunImplement()
{
m_vPosition = osg::Vec3d(10,10,2);
m_vRotation = osg::Vec3d(0,0,0);
}
osg::Matrixd RunImplement::getMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
return mat * osg::Matrixd::rotate(m_vRotation[0],osg::X_AXIS,m_vRotation[1],osg::Y_AXIS,m_vRotation[2],osg::Z_AXIS);
}
osg::Matrixd RunImplement::getInverseMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
return mat * osg::Matrixd::inverse(osg::Matrixd::rotate(m_vRotation[0],osg::X_AXIS,m_vRotation[1],osg::Y_AXIS,m_vRotation[2],osg::Z_AXIS));
}
void RunImplement::setByInverseMatrix( const osg::Matrixd& matrix )
{
}
void RunImplement::setByMatrix( const osg::Matrixd& matrix )
{
}
頭文件:run.h
/**
*
*最長的一幀,實例演示
*/
#ifndef RUN_H__
#define RUN_H__
#include <windows.h> // gl.h 大量引用該文件中的接口
#if _DEBUG
#pragma comment( lib, "opengl32")
#pragma comment( lib, "osgd")
#pragma comment( lib, "osgViewerd")
#pragma comment( lib, "osgDBd")
#pragma comment( lib, "OpenThreadsd")
#pragma comment( lib, "osgUtild")
#pragma comment( lib, "osgGAd")
#else
#pragma comment( lib, "opengl32")
#pragma comment( lib, "osg")
#pragma comment( lib, "osgViewer")
#pragma comment( lib, "osgDB")
#pragma comment( lib, "OpenThreads")
#pragma comment( lib, "osgUtil")
#pragma comment( lib, "osgGA")
#endif
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osg/PositionAttitudeTransform>
#include <osg/MatrixTransform>
#include <osg/Matrixd>
#include <osg/AnimationPath>
#include <iostream>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/OrbitManipulator>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osgGA/TrackballManipulator>
/*! 開始一個類*/
class RunImplement: public osgGA::OrbitManipulator
{
public:
RunImplement();
public:
virtual void setByMatrix( const osg::Matrixd& matrix );
virtual void setByInverseMatrix( const osg::Matrixd& matrix );
virtual osg::Matrixd getMatrix() const;
virtual osg::Matrixd getInverseMatrix() const;
private:
osg::Vec3d m_vPosition;
osg::Vec3d m_vRotation;
};
#endif /* END_OF_RUNIMPLEMENT */
解決問題
思之再三,覺得看不到節點數據的原因無非就兩個:
一、數據沒有被加載到場景中,二、加載了節點數據,但是由於參數不正確,導致數據不可見。
OSG在OrbitManipulator中設置了許多顯示設置的參數,所以場景結點數據就得到正確的顯示,在子類TrackballManipulator中構造函數直接使用了StandardManipulator中的setVerticalAxisFixed(false)這個函數,鑑於目前只是實現run函數中的流程,對於osg::Displaysettings裏面的具體細節後面再討論。