天天看點

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裡面的具體細節後面再讨論。