本文在吸收了《最长的一帧》以及相关参考资料的基础之上解读OSG的基础数据结构,渲染方法。
在这第一部分里,要理解的是run函数的实现,因为以下这一段证明了它的重要性和强大的能力。
int main()
{
//....
osg::ref_ptr viewer = new osgViewer::Viewer;
/**如果指向的目录没有数据OSG的屏幕上不会有数据显示*/
osg::ref_ptr node = osgDB::readNodeFile("D:/OpenSceneGraph/data/cow.osg");
viewer->setSceneData(node.get());
return viewer->run();
}
按照《最长的一帧》中的说法,所有的绘制工作会在一个循环里面完成:
while( !viewer->done() )
{
viewer->frame();
}
首先,我希望通过自己实现的控制器显示场景结点数据,这个跟run函数无关,是教程里的一个小例子,至于run函数我是用了上面的这个循环替代,结果却出乎意料,在场景中看不到我加载的模型。
源代码:
int main()
{
//....
osg::ref_ptr viewer = new osgViewer::Viewer;
//osg::ref_ptr root = new osg::Group;
/**如果指向的目录没有数据OSG的屏幕上不会有数据显示*/
osg::ref_ptr 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 // 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*! 开始一个类*/
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里面的具体细节后面再讨论。