osgEarth開發之OSG解構——失敗的嘗試

概述

本文在吸收了《最長的一幀》以及相關參考資料的基礎之上解讀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裏面的具體細節後面再討論。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章