所謂的GraphicsContext 我這么翻譯它吧:圖形設備上下文?..就像在使用OpenGL在win32的窗口里繪制的時候.曾使用的hrc = wglCreateContext(hdc)一樣.創建一個圖形設備上下文 ,然后使用wglMakeCurrent(hdc,hrc)設置當前使用的圖形設備一樣.在這之后 我們就可以使用OGL繪制圖形一樣.osg中的GraphicsContext 就是跟hrc一樣的.只是它將所有需要的內容集成在GraphicsContext這個類當中.這就是面向對象的封裝性>_<.
在打開osg/GraphicsContext的頭文件當中.我們可以找到這么一些函數 swapBuffers() makeCurrent() 等與我們之前所說的可以說十分相同的.因此對于在OSG當中需要最終顯示圖形的地方就是這個GraphicsContext .
相對來說,我們通常的第一個例子:

第一個例子

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>

int main()


{
osg::Node* node = osgDB::readNodeFile("cow.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(node);
return viewer.run();
}
這個時候我們得到的是一個全屏的窗口.這是默認的創建的一個GraphicsContext.( 通常情況下只有一個).它是通過執行 Viewer::realize()函數創建的. 最后執行View::setUpViewAcrossAllScreens() 創建全屏的GraphicsContext你可詳看源碼 就可以發現它就是創建一個GraphicsContext..并把它附加到viewer 的主攝像機上..因此我們最后看到的結果就是在全屏上顯示一頭牛...假設沒有這個GraphicsContext 就會看不到.在后面我會用一副圖來說明攝像機與GraphicsContext得關系.這是至關重要的.因為.每個攝像機若需要顯示場景.則必須要有一個GraphicsContext.來負責顯示.不管是主攝像機還是從攝像機.(Viewer可以有多個攝像機).

在我們了解了GraphicsContext之后.其實上面這個圖已經給我們一個很大的啟發了.其實最后的GraphicsContext應當是GraphicsWindowWIN32或者GraphicsWindowX11等三個中的一個.這是面向對象多態性的體現.. 因此.我們現在就要開始創建一個GraphicsContext了.
在創建之前.我也許需要說明一個.static GraphicsContext* GraphicsContext::createGraphicsContext(Traits _traits) 需要傳入一個Traits的變量.因此我們需要了解這個Traits.
Traits.是什么呢?它GraphicsContext一些特征.我羅列一些能夠表示這些特征的屬性就能夠非常直白的說明這個對象了.
_traits->x //x偏移
_traits->y //y偏移
_traits->width //寬度
_traits->height //高度
_traits->doubleBuffer //是否支持雙緩存
_traits->sharedContext //共享GraphicsContext
_traits->windowName //窗口名稱
_traits->windowDecoration //是否支持窗口一些裝飾屬性..如最大化 最小化等
_traits->inheritedWindowData //繼承自某個窗口句柄? 這個可以用于嵌入到QT.MFC等GUI系統中.
因此只要設置這些內容.并調用上面的方法則會創建一個GraphicsContext. .而如上那個函數關于創建GraphicsContext實則應當是調用了窗口系統API 來創建的.見如下函數:

創建窗口的API
GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits)
{
/** 獲得系統API接口... */
ref_ptr<GraphicsContext::WindowingSystemInterface> &wsref = windowingSystemInterfaceRef();
if ( wsref.valid())
{
// catch any undefined values.
if (traits) traits->setUndefinedScreenDetailsToDefaultScreen();
return wsref->createGraphicsContext(traits);
}
else
return 0;
}
當你去詳細閱讀 GraphicsWindowWIN32.cpp 文件和GraphicsWindow 頭文件時.你會發覺設計的非常巧妙. 用static全局靜態變量和 宏定義實現這個非常宏偉的API獲得...

Function
//函數指針的定義
extern "C"


{
typedef void (* CGraphicsWindowFunction) (void);
}

// 結構構造
struct GraphicsWindowFunctionProxy


{

GraphicsWindowFunctionProxy(CGraphicsWindowFunction function)
{ (function)(); }
};

// 宏定義
#define USE_GRAPICSWINDOW_IMPLEMENTATION(ext) \
extern "C" void graphicswindow_##ext(void); \
static osgViewer::GraphicsWindowFunctionProxy graphicswindowproxy_##ext(graphicswindow_##ext);


#if defined(_WIN32)
#define USE_GRAPHICSWINDOW() USE_GRAPICSWINDOW_IMPLEMENTATION(Win32)
#elif defined(__APPLE__)
#define USE_GRAPHICSWINDOW() USE_GRAPICSWINDOW_IMPLEMENTATION(Carbon)
#else
#define USE_GRAPHICSWINDOW() USE_GRAPICSWINDOW_IMPLEMENTATION(X11)
#endif

}

GetInterface
struct RegisterWindowingSystemInterfaceProxy


{
RegisterWindowingSystemInterfaceProxy()

{
osg::GraphicsContext::setWindowingSystemInterface(Win32WindowingSystem::getInterface());
}

~RegisterWindowingSystemInterfaceProxy()

{
if (osg::Referenced::getDeleteHandler())

{
osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
osg::Referenced::getDeleteHandler()->flushAll();
}

osg::GraphicsContext::setWindowingSystemInterface(0);
}
};

static RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;

} // namespace OsgViewer


// declare C entry point for static compilation.
extern "C" void graphicswindow_Win32(void)


{
osg::GraphicsContext::setWindowingSystemInterface(osgViewer::Win32WindowingSystem::getInterface());
}

因此 假設我們使用的是Window系統 那么所創建的GraphicsContext 則win32模式的.那么具體的窗口創建或者說嵌入等.請詳細看GraphicsWindowWIN32.cpp 我們可以非常熟悉的看到開頭部分所敘述的wgl等函數..很熟悉吧..
說了這么多.我們是否應當創建一個窗口來實踐一下呢? 這將在之后的代碼當中詳細說出..
為了渲染與顯示圖形.. 我們需要一個視景器.osgViewer::Viewer ..Viewer當中包含一個主攝像機.因此我們不必在創建一個攝像機了.好了.開始代碼的敘述.由于我們只是創建一個簡單的WIN32窗口 并沒有嵌入MFC.只需設置一些相關的值即可.

Window
void Window::init(int width,int height)


{

/**//** 獲得窗口系統的API接口*/
osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();


/**//** 創建一個GraphicsContext 的特征表示*/
osg::ref_ptr<osg::GraphicsContext::Traits> _traits = new osg::GraphicsContext::Traits;


/**//** 一個顯示器設備一些信息*/
osg::GraphicsContext::ScreenIdentifier is;
is.readDISPLAY();

/**//** get display setting and get the scene width and height*/
unsigned int scenewidth ;
unsigned int sceneheight;
wsi->getScreenResolution(is,scenewidth,sceneheight);


/**//** set window attribute*/
_traits->x = (scenewidth - width)/2;
_traits->y = (sceneheight - height)/2;
_traits->width = width;
_traits->height = height;
_traits->doubleBuffer = true;
_traits->sharedContext = 0;
_traits->windowName = "OSG_CITY";
_traits->windowDecoration =true;

//_traits->useCursor = false;


/**//** create grahicscontext for viewer camara*/
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(_traits.get());


if(!gc.valid())
{
string error("Error: can't create graphiscontext!
..");
throw error;
}
_gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
if(!_gw.valid())

{
string error("Error: can't get the graphisWindow for handle input!
");
throw error;
}

//_gw->setCursor(osgViewer::GraphicsWindow::NoCursor);


/**//** set context and viewport*/
_sceneviewer->getCamera()->setGraphicsContext(gc.get());
_sceneviewer->getCamera()->setViewport(0,0,width,height);


/**//** adjust the projectionmatrix*/
double fovy,aspect,znear,zfar;
_sceneviewer->getCamera()->getProjectionMatrixAsPerspective(fovy,aspect,znear,zfar);
double aspectchange = (double)width/(double)height/aspect;
if(aspectchange !=1.0)
_sceneviewer->getCamera()->getProjectionMatrix() *=osg::Matrixd::scale(aspectchange,1.0,1.0);


/**//** set the double buffer */
GLenum buffer = _traits->doubleBuffer ? GL_BACK : GL_FRONT;
_sceneviewer->getCamera()->setDrawBuffer(buffer);
_sceneviewer->getCamera()->setReadBuffer(buffer);


/**//** realize*/
_sceneviewer->realize();
}
最后許多方面的注釋將會在源代碼中給出.附源代碼下載:
下載地址
posted on 2009-08-22 21:21
米游 閱讀(6200)
評論(0) 編輯 收藏 引用 所屬分類:
OpenGL/OSG