所謂的GraphicsContext 我這么翻譯它吧:圖形設(shè)備上下文?..就像在使用OpenGL在win32的窗口里繪制的時(shí)候.曾使用的hrc = wglCreateContext(hdc)一樣.創(chuàng)建一個(gè)圖形設(shè)備上下文 ,然后使用wglMakeCurrent(hdc,hrc)設(shè)置當(dāng)前使用的圖形設(shè)備一樣.在這之后 我們就可以使用OGL繪制圖形一樣.osg中的GraphicsContext 就是跟hrc一樣的.只是它將所有需要的內(nèi)容集成在GraphicsContext這個(gè)類當(dāng)中.這就是面向?qū)ο蟮姆庋b性>_<.
在打開(kāi)osg/GraphicsContext的頭文件當(dāng)中.我們可以找到這么一些函數(shù) swapBuffers() makeCurrent() 等與我們之前所說(shuō)的可以說(shuō)十分相同的.因此對(duì)于在OSG當(dāng)中需要最終顯示圖形的地方就是這個(gè)GraphicsContext .
相對(duì)來(lái)說(shuō),我們通常的第一個(gè)例子:

第一個(gè)例子

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

int main()


{
osg::Node* node = osgDB::readNodeFile("cow.osg");
osgViewer::Viewer viewer;
viewer.setSceneData(node);
return viewer.run();
}
這個(gè)時(shí)候我們得到的是一個(gè)全屏的窗口.這是默認(rèn)的創(chuàng)建的一個(gè)GraphicsContext.( 通常情況下只有一個(gè)).它是通過(guò)執(zhí)行 Viewer::realize()函數(shù)創(chuàng)建的. 最后執(zhí)行View::setUpViewAcrossAllScreens() 創(chuàng)建全屏的GraphicsContext你可詳看源碼 就可以發(fā)現(xiàn)它就是創(chuàng)建一個(gè)GraphicsContext..并把它附加到viewer 的主攝像機(jī)上..因此我們最后看到的結(jié)果就是在全屏上顯示一頭牛...假設(shè)沒(méi)有這個(gè)GraphicsContext 就會(huì)看不到.在后面我會(huì)用一副圖來(lái)說(shuō)明攝像機(jī)與GraphicsContext得關(guān)系.這是至關(guān)重要的.因?yàn)?每個(gè)攝像機(jī)若需要顯示場(chǎng)景.則必須要有一個(gè)GraphicsContext.來(lái)負(fù)責(zé)顯示.不管是主攝像機(jī)還是從攝像機(jī).(Viewer可以有多個(gè)攝像機(jī)).

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

創(chuàng)建窗口的API
GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits)
{
/** 獲得系統(tǒng)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;
}
當(dāng)你去詳細(xì)閱讀 GraphicsWindowWIN32.cpp 文件和GraphicsWindow 頭文件時(shí).你會(huì)發(fā)覺(jué)設(shè)計(jì)的非常巧妙. 用static全局靜態(tài)變量和 宏定義實(shí)現(xiàn)這個(gè)非常宏偉的API獲得...

Function
//函數(shù)指針的定義
extern "C"


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

// 結(jié)構(gòu)構(gòu)造
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());
}

因此 假設(shè)我們使用的是Window系統(tǒng) 那么所創(chuàng)建的GraphicsContext 則win32模式的.那么具體的窗口創(chuàng)建或者說(shuō)嵌入等.請(qǐng)?jiān)敿?xì)看GraphicsWindowWIN32.cpp 我們可以非常熟悉的看到開(kāi)頭部分所敘述的wgl等函數(shù)..很熟悉吧..
說(shuō)了這么多.我們是否應(yīng)當(dāng)創(chuàng)建一個(gè)窗口來(lái)實(shí)踐一下呢? 這將在之后的代碼當(dāng)中詳細(xì)說(shuō)出..
為了渲染與顯示圖形.. 我們需要一個(gè)視景器.osgViewer::Viewer ..Viewer當(dāng)中包含一個(gè)主攝像機(jī).因此我們不必在創(chuàng)建一個(gè)攝像機(jī)了.好了.開(kāi)始代碼的敘述.由于我們只是創(chuàng)建一個(gè)簡(jiǎn)單的WIN32窗口 并沒(méi)有嵌入MFC.只需設(shè)置一些相關(guān)的值即可.

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


{

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


/**//** 創(chuàng)建一個(gè)GraphicsContext 的特征表示*/
osg::ref_ptr<osg::GraphicsContext::Traits> _traits = new osg::GraphicsContext::Traits;


/**//** 一個(gè)顯示器設(shè)備一些信息*/
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();
}
最后許多方面的注釋將會(huì)在源代碼中給出.附源代碼下載:
下載地址
posted on 2009-08-22 21:21
米游 閱讀(6238)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
OpenGL/OSG