用OpenInventor實現的NeHe OpenGL教程-第二十四課
NeHe教程在這節課中向我們介紹瞭如何讀取顯卡支持的OpenGL的擴展,如何使用Targa(TGA)圖像文件作爲紋理,以及如何利用OpenGL的剪裁區域來滾動屏幕文字。
在OpenInventor中沒有相關的函數來獲取OpenGL的擴展信息,我們只能通過直接調用OpenGL來獲得這些信息。OpenInventor的紋理節點自動支持使用Targa(TGA)圖像文件作爲紋理,所以我們不必像NeHe教程中那樣分析TGA文件格式了。
下面這個函數是根據輸入的字符串來創建紋理字符場景,這個函數在前面的課程中已經使用過多次,這裏就不在詳細介紹了
SoSeparator* OivPrint(int x, int y, int set, const char *fmt,...)
{
..........................
}
我們將在函數BuildScene中創建場景數據。
void BuildScene(void)
{
SoEventCallback* pEventCallback = new SoEventCallback;
pEventCallback->addEventCallback(SoKeyboardEvent::getClassTypeId(),KeyboardEventCB,g_pOivSceneRoot);
g_pOivSceneRoot->addChild(pEventCallback);
///////////////////////////////////////////////////////////////////////////////////
//構造線框場景
SoCoordinate3 *pLineCoords = new SoCoordinate3;
pLineCoords->point.set1Value(0,TX(639),TY(417),0);
pLineCoords->point.set1Value(1,TX(0) ,TY(417),0);
pLineCoords->point.set1Value(2,TX(0) ,TY(480),0);
pLineCoords->point.set1Value(3,TX(639),TY(480),0);
pLineCoords->point.set1Value(4,TX(639),TY(128),0);
pLineCoords->point.set1Value(5,TX(0) ,TY(128),0);
pLineCoords->point.set1Value(6,TX(639),TY(128),0);
pLineCoords->point.set1Value(7,TX(639),TY(1),0);
pLineCoords->point.set1Value(8,TX(0) ,TY(1),0);
pLineCoords->point.set1Value(9,TX(0) ,TY(417),0);
g_pOivSceneRoot->addChild(pLineCoords);
SoLineSet *pLineSet = new SoLineSet;
pLineSet->numVertices.set1Value(0,10);
g_pOivSceneRoot->addChild(pLineSet);
/////////////////////////////////////////////////////////////////////////////////////
SoComplexity *pTextureComplexity = new SoComplexity;
pTextureComplexity->textureQuality = 1.0;
g_pOivSceneRoot->addChild(pTextureComplexity);
//這裏我們直接使用tga文件作爲紋理節點的輸入圖像文件
SoTexture2 *pFontTexture = new SoTexture2;
pFontTexture->filename.setValue("../Data/Font.tga");
pFontTexture->model = SoTexture2::MODULATE;
g_pOivSceneRoot->addChild(pFontTexture);
SoBaseColor *pBrightRedColor = new SoBaseColor;
pBrightRedColor->rgb.setValue(1.0f,0.5f,0.5f);
g_pOivSceneRoot->addChild(pBrightRedColor);
g_pOivSceneRoot->addChild(OivPrint(TX(50),TY(56),1,"Renderer"));
g_pOivSceneRoot->addChild(OivPrint(TX(80),TY(88),1,"Vendor"));
g_pOivSceneRoot->addChild(OivPrint(TX(66),TY(120),1,"Version"));
SoBaseColor *pBrightBlueColor = new SoBaseColor;
pBrightBlueColor->rgb.setValue(0.5f,0.5f,1.0f);
g_pOivSceneRoot->addChild(pBrightBlueColor);
g_pOivSceneRoot->addChild(OivPrint(TX(192),TY(472),1,"NeHe Productions"));
//通過回調函數來獲得OpenGL的擴展信息。
SoCallback *pGlInfoCallback = new SoCallback();
pGlInfoCallback->setCallback(GlInfoCB, NULL);
g_pOivSceneRoot->addChild(pGlInfoCallback);
}
下面的函數用於獲得OpenGL的擴展信息
void GlInfoCB(void *data, SoAction *action)
{
if (action->isOfType(SoGLRenderAction::getClassTypeId()))
{
static bool bBuild = false;
if(!bBuild)
{
bBuild = true;
if(g_pOivSceneRoot)
{
SoBaseColor *pOrangeColor = new SoBaseColor;
pOrangeColor->rgb.setValue(1.0f,0.7f,0.4f);
g_pOivSceneRoot->addChild(pOrangeColor);
g_pOivSceneRoot->addChild(OivPrint(TX(200),TY(56),1,
(char *)glGetString(GL_RENDERER)));
g_pOivSceneRoot->addChild(OivPrint(TX(200),TY(88),1,
(char *)glGetString(GL_VENDOR)));
g_pOivSceneRoot->addChild(OivPrint(TX(200),TY(120),1,
(char *)glGetString(GL_VERSION)));
g_pGLExtensionTrans = new SoTranslation;
g_pOivSceneRoot->addChild(g_pGLExtensionTrans);
SoBaseColor *pYellowColor = new SoBaseColor;
pYellowColor->rgb.setValue(1.0f,1.0f,0.5f);
g_pOivSceneRoot->addChild(pYellowColor);
SoCallback *pGlEnableScissorCallback = new SoCallback();
pGlEnableScissorCallback->setCallback(GlScissorCB, 0);
g_pOivSceneRoot->addChild(pGlEnableScissorCallback);
char* text=(char *)malloc(strlen((char *)glGetString(GL_EXTENSIONS)) + 1); strcpy (text,(char *)glGetString(GL_EXTENSIONS)); int cnt = 0;
char *token = strtok(text," "); while(token != NULL) {
cnt++; // Increase The Counter
if (cnt > maxtokens) // Is 'maxtokens' Less Than 'cnt'
maxtokens = cnt; // If So, Set 'maxtokens' Equal To 'cnt'
g_pOivSceneRoot->addChild(
OivPrint(TX(10),TY(40 + 96 + (cnt * 36)),0,"%2i %s",cnt,token));
token = strtok(NULL," "); // Search For The Next Token
}
free(text); // Free Allocated Memory
SoCallback *pGlDisableScissorCallback = new SoCallback();
pGlDisableScissorCallback->setCallback(GlScissorCB, (void *)1);
g_pOivSceneRoot->addChild(pGlDisableScissorCallback);
}
}
}
}
現在編譯運行我們程序,屏幕會顯示出用戶所使用的OpenGL驅動程序中提供的擴展函數。按下上下方向鍵,可以滾動顯示這些文字。效果和NeHe第二十四是相同的。
本課的完整代碼下載。(VC 2003 + Coin2.5)
後記
OpenInventor是一種基於OpenGL的面向對象的三維圖形軟件開發包。使用這個開發包,程序員可以快速、簡潔地開發出各種類型的交互式三維圖形軟件。這裏不對OpenInventor做詳細的介紹,讀者如果感興趣,可以閱讀我的blog中的這篇文章《OpenInventor 簡介》。
NeHe教程是目前針對初學者來說最好的OpenGL教程,它可以帶領讀者由淺入深,循序漸進地掌握OpenGL編程技巧。到目前爲止(2007年11月),NeHe教程一共有48節。我的計劃是使用OpenInventor來實現所有48節課程同樣的效果。目的是複習和鞏固OpenGL的知識,同時與各位讀者交流OpenInventor的使用技巧。
因爲篇幅的限制,我不會介紹NeHe教程中OpenGL的實現過程,因爲NeHe的教程已經講解的很清楚了,目前網絡中也有NeHe的中文版本。我將使用VC 2003作爲主要的編譯器。程序框架採用和NeHe一樣的Win32程序框架,不使用MFC。程序也可以在VC Express,VC 2005/2008中編譯。我採用的OpenInventor開發環境是Coin,這是一個免費開源的OpenInventor開發庫。文章 《OpenInventor-Coin3D開發環境》 介紹瞭如何在VC中使用Coin。我使用的Coin版本是2.5。讀者可以到 www.coin3d.org 中免費下載。
讀者可以在遵循GNU協議的條件下自由使用、修改本文的代碼。水平的原因,代碼可能不是最優化的,我隨時期待讀者的指正和交流。轉載請註明。謝謝。
我的聯繫方式:
E-mail: < [email protected] > < [email protected] >
Blog: < http://blog.csdn.net/RobinHao >
Site: < http://www.openinventor.cn >