用OpenInventor實現的NeHe OpenGL教程-第二十四課
用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));intcnt = 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中的這篇文章《》。
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開發庫。文章《》介紹瞭如何在VC中使用Coin。我使用的Coin版本是2.5。讀者可以到中免費下載。
讀者可以在遵循GNU協議的條件下自由使用、修改本文的程式碼。水平的原因,程式碼可能不是最優化的,我隨時期待讀者的指正和交流。轉載請註明。謝謝。
我的聯絡方式: