1. 程式人生 > >用OpenInventor實現的NeHe OpenGL教程-第二十四課

用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程式設計技巧。到目前為止(200711月),NeHe教程一共有48節。我的計劃是使用OpenInventor來實現所有48節課程同樣的效果。目的是複習和鞏固OpenGL的知識,同時與各位讀者交流OpenInventor的使用技巧。

因為篇幅的限制,我不會介紹NeHe教程中OpenGL的實現過程,因為NeHe的教程已經講解的很清楚了,目前網路中也有NeHe的中文版本。我將使用VC 2003作為主要的編譯器。程式框架採用和NeHe一樣的Win32程式框架,不使用MFC。程式也可以在VC ExpressVC 2005/2008中編譯。我採用的OpenInventor開發環境是Coin,這是一個免費開源的OpenInventor開發庫。文章介紹瞭如何在VC中使用Coin。我使用的Coin版本是2.5。讀者可以到中免費下載。

讀者可以在遵循GNU協議的條件下自由使用、修改本文的程式碼。水平的原因,程式碼可能不是最優化的,我隨時期待讀者的指正和交流。轉載請註明。謝謝。

我的聯絡方式: