用OpenInventor實現的NeHe OpenGL教程-第二十八課
NeHe教程在這節課中向我們介紹了貝塞爾曲面,貝塞爾曲面是一種可以只使用很少的參數就可以描述出複雜曲面的一種數學工具。對於使用OpenInventor的程序員來說,創建貝塞爾曲面是非常容易的事情,OpenInventor已經對貝塞爾曲面,Nurbs曲面等都做了相應的支持。
首先定義一些程序中使用的全局變量:
SoRotation* g_pZRotation = NULL;//旋轉貝塞爾曲面
SoDrawStyle* g_pDrawStyle = NULL;
const float pts[16][3] = {
{-0.75, -0.75, -0.5},
{-0.25, -0.75, 0.0},
……….
} //定義貝塞爾曲面的控制點位置
創建貝塞爾曲面場景節點
SoSeparator* BuildSurface(void)
{
SoSeparator *surfSep = new SoSeparator();
SoComplexity *complexity = new SoComplexity;
complexity->value = 1.0f;
surfSep->addChild(complexity);
SoTexture2 *pTexture = new SoTexture2;
pTexture->filename.setValue("../Data/NeHe.png");
surfSep->addChild(pTexture);
SoCoordinate3 *controlPts = new SoCoordinate3;//加載控制點參數
controlPts->point.setValues(0, 16, pts);
surfSep->addChild(controlPts);
// The knot vector
float knots[8] = {0, 0, 0, 0, 1, 1, 1, 1};
SoNurbsSurface *surface = new SoNurbsSurface;//定義貝塞爾曲面節點
surface->numUControlPoints = 4;
surface->numVControlPoints = 4;
surface->uKnotVector.setValues(0, 8, knots);
surface->vKnotVector.setValues(0, 8, knots);
surfSep->addChild(surface);
return surfSep;
}
創建控制點場景
SoSeparator* BuildCtrlPt(void)
{
SoSeparator *pCtrlPtSep = new SoSeparator();
g_pDrawStyle = new SoDrawStyle;
g_pDrawStyle->style = SoDrawStyleElement::INVISIBLE;
pCtrlPtSep->addChild(g_pDrawStyle);
SoBaseColor *pCtrlPtColor = new SoBaseColor;
pCtrlPtColor->rgb.setValue(1.0,0.0,0.0);
pCtrlPtSep->addChild(pCtrlPtColor);
SoCoordinate3 *controlPts = new SoCoordinate3;
controlPts->point.setValues(0, 16, pts);
pCtrlPtSep->addChild(controlPts);
int32_t coordIndex[ 8 * 5],iIndex = 0;
for(int i = 0;i < 4; i++)
{
for(int j = 0;j < 4; j++)
coordIndex[iIndex++] = i * 4 + j;
coordIndex[iIndex++] = SO_END_LINE_INDEX;
}
for(int i = 0;i < 4; i++)
{
for(int j = 0;j < 4; j++)
coordIndex[iIndex++] = j * 4 + i;
coordIndex[iIndex++] = SO_END_LINE_INDEX;
}
SoIndexedLineSet *pLineSet = new SoIndexedLineSet;
pLineSet->coordIndex.setValues(0,8 * 5,coordIndex);
pCtrlPtSep->addChild(pLineSet);
return pCtrlPtSep;
}
創建整個場景
void BuildScene(void)
{
SoEventCallback* pEventCallback = new SoEventCallback;
pEventCallback->addEventCallback(SoKeyboardEvent::getClassTypeId(),KeyboardEventCB,g_pOivSceneRoot);
g_pOivSceneRoot->addChild(pEventCallback);
///////////////////////////////////////////////////////////////////////////////////
SoRotation *pFixRot = new SoRotation;
pFixRot->rotation.setValue(SbVec3f(1,0,0),-75.0 / 180.0 * 3.1415);
g_pOivSceneRoot->addChild(pFixRot);
g_pZRotation = new SoRotation;
g_pOivSceneRoot->addChild(g_pZRotation);
g_pOivSceneRoot->addChild(BuildSurface());
g_pOivSceneRoot->addChild(BuildCtrlPt());
}
剩下的代碼和以前的課程類似,我們就不在詳細介紹了。
現在編譯運行我們程序,屏幕會顯示一個表面帶有貼圖的貝塞爾曲面。按左右箭頭可以旋轉曲面。按下空格鍵,可以顯示/隱藏貝塞爾曲面的控制點數據。效果和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 >