Open Inventor 簡介

Open Inventor 簡介

 

簡介

Open Inventor(以下簡稱OIV)是SGI公司開發的基於OpenGL的面向對象三維圖形軟件開發包。使用OIV開發包,程序員可以快速、簡潔地開發出各種類型的交互式三維圖形軟件。OIV具有平臺無關性,它可以在Microsoft WindowsUnixLinux等多種操作系統中使用。OIV允許使用CC++JavaDotNet多種編程語言進行程序開發。經過多年的發展,OIV已經基本上成爲面向對象的3D圖形開發“事實上”的工業標準。廣泛地應用於機械工程設計與仿真、醫學和科學圖像、地理科學、石油鑽探、虛擬現實、科學數據可視化等領域。

 

       學習過OpenGL的人應該有一種感覺,就是OpenGL入門容易,提高很難。OpenGL提供的函數並不多,不過區區一百多個核心函數。OpenGL的編程思想比較簡單,就是一個有限狀態機的思想。因此學習OpenGL往往入門很快。但是在入門之後,要想進一步提高編程功力,很多人就會感覺無從下手。這種情況一部分歸咎於編寫三維圖形軟件需要了解的知識比較多,另一部分的原因恐怕就是OpenGL提供的功能過於基本和底層了。而且OpenGL使用的是“面向過程”的編程方法,對於我們目前廣泛使用的“面向對象”的編程思想沒有提供支持。當然這裏我們不是說OpenGL的功能不強大,看看無數多個使用OpenGL編寫的應用程序,我們不得不驚歎OpenGL的表現能力。但關鍵是我們不能指望每個程序員都成爲“約翰.卡馬克”(ID 公司的3D天才程序員,是DoomQuake的主要設計師)。

 

       正是看到了OpenGL在應用上的不便,SGI公司在OpenGL庫的基礎上開發了面向對象三維圖形軟件開發工具包-Open InventorOIV是面向對象的,因爲它本身就是使用C++編寫的,它允許用戶從已存在的類中派生出自己的類,通過派生的方式可以很容易地擴展OIV庫。OIV支持“場景”,“觀察器”和“動作”等高級功能,用戶可以把3D物體保存在“場景”中,通過“觀察器”來顯示3D物體。利用“動作”可以對3D物體進行特殊的操作(例如,拾取操作,選中操作等)。正是因爲有了這些高級功能,才使得普通程序員也能編寫出功能強大的三維交互式應用軟件。

 

OIV 是由一系列的對象模塊組成的,通過利用這些對象模塊,開發人員有可能以花費最小的編程代價,開發出能充分利用強大的圖形硬件特性的程序。OIV是一個建立在OpenGL基礎上的對象庫,開發人員可以任意使用、修改和擴展對象庫。Inventor 對象包括:數據庫圖元、形體、屬性、組、和引擎等對象;還有例如像手柄盒和軌跡球等操作器、材質編輯器、方向燈編輯器、examiner觀察器等組件。    Inventor提供了一個完整且經濟高效的面向對象系統。

 

 

Open InventorOpenGL之間的差別

       OIV的主要參考書《 The Inventor Mentor 》中(將在後面做介紹),有一段文字生動形象地介紹了OIVOpenGL之間的差別。在書中,作者假設要建造一棟房子,她把使用磚頭、水泥、沙子來建造房屋的原始方式比作使用OpenGL來開發程序,而將利用預製水泥構件、成套室內設備來建造房屋比作使用OIV來開發程序。這種比喻形象地說出了OIV開發程序具有簡單、高效的特點。值得注意的一點是,OIVOpenGL是相容的。在OIV中提供了多種方法允許直接調用OpenGL的命令,這使得OIV的功能變得更加強大。

 

可以再舉一個我們程序員比較熟悉的例子。我們知道,使用C++語言編寫Windows程序的時候,基本上可以有兩種方法:第一種方法是直接使用Windows API開發程序;第二種方法是使用Microsoft Visual C++中的MFC類庫開發。使用API開發程序就和使用OpenGL來開發3D應用程序一樣。而使用MFC就像是使用OIV。我們知道,如果使用API來開發程序的話,程序員需要做程序初始化,創建窗口,消息分發,程序框架等大量的代碼。這點和使用OpenGL來開發3D程序幾乎是一樣的,程序員必須對程序中的所有部分負責。而使用MFC開發程序就輕鬆很多了,因爲MFC內部已經爲程序提供了儘可能的方便,包括像初始化,創建窗口,消息分發,程序框架等等這些都已經是內建的了,程序員只需要實現自己的功能就可以了。同時MFC也允許用戶直接調用Windows API,並且MFC運行效率和Windows API的效率不相上下。

 

       其實對我們程序員來說,再詳細的說明也比不上程序代碼來得直接。下面將使用OpenGLOIV同時編寫一個顯示紅色立方體的簡單程序,通過這兩個例子的比較,就可以很比較容易地瞭解OIVOpenGL之間的差別了。

 

//使用OpenGL 顯示一個紅色立方體

#include "stdafx.h"

#include <glut.h>

 

GLfloat mat_diffuse[] = {1.0,0.0,0.0,0.0};

GLfloat mat_specular[] = {1.0,1.0,1.0,1.0};

GLfloat high_shininess[] = {100.0};

 

void myInit(void)

{

     GLfloat light_position[] = {0.0,3.0,6.0,0.0};

     glLightfv(GL_LIGHT2,GL_POSITION,light_position);//設置光源

     glEnable(GL_DEPTH_TEST);

     glDepthFunc(GL_LESS);

     glEnable(GL_LIGHTING);

     glEnable(GL_LIGHT0);

     glShadeModel(GL_SMOOTH);

}

 

void display(void)

{

     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

     glPushMatrix();

         //爲光照模型指定材質參數

         glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);

         glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);

         glMaterialfv(GL_FRONT,GL_SHININESS,high_shininess);

         glColorMaterial(GL_FRONT,GL_AMBIENT);//使材質色跟蹤當前顏色

         glEnable(GL_COLOR_MATERIAL);

         glPushMatrix();

              glRotatef(40,1.0,1.0,1.0);

              glutSolidCube(2);

         glPopMatrix();

         glDisable(GL_COLOR_MATERIAL);

     glPopMatrix();

     glFlush();

}

 

void myReshape(int w,int h)

{

    glViewport(0,0,(GLsizei)w,(GLsizei)h);

    glMatrixMode(GL_PROJECTION);

    glLoadIdentity();

    if(w <= h)

         glOrtho(-5.5,5.5,-5.5*(GLfloat)h/(GLfloat)w,5.5*(GLfloat)h/(GLfloat)w,-5.5,5.5);

    else

        glOrtho(-5.5*(GLfloat)w/(GLfloat)h,5.5*(GLfloat)w/(GLfloat)h,-5.5,5.5,-5.5,5.5);

    glMatrixMode(GL_MODELVIEW);

    glLoadIdentity();

}

 

int main(int argc,char ** argv)

{

    //初始化

    glutInit(&argc,argv);

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    glutInitWindowSize(400,400);

    glutInitWindowPosition(100,100);

    //創建窗口

    glutCreateWindow("Cube");

    //繪製

    myInit();

    glutReshapeFunc(myReshape);

    glutDisplayFunc(display);

 

    glutMainLoop();

    return 0;

}

程序運行的結果:

 

       注意,爲了簡單起見,我們使用了OpenGLglut庫。

 

       在main函數中,首先做了初始化OpenGL的工作,然後又創建了一個窗口。在myInit函數中主要是設置光源,啓動深度檢測等工作。最主要的函數是display函數。在這個函數中,首先設置材質,然後在設置旋轉矩陣,最後顯示立方體。我們假設閱讀本文的讀者應該熟悉OpenGL的開發,因此我們將不再詳細說明這個程序。

 

       從上面OpenGL的例子可以看到,僅僅爲了顯示一個立方體,使用OpenGL來開發就需要如此多的代碼,要是開發一個大型的3D程序,其難度可想而知了。

 

 

//使用Open Inventor 顯示一個紅色立方體

#include <Inventor/Win/viewers/SoWinExaminerViewer.h> 

#include <Inventor/nodes/SoSeparator.h>

#include <Inventor/nodes/SoCube.h>

#include <Inventor/nodes/SoMaterial.h>

 

int main(intchar **argv)

{

     //初始化Inventor

     HWND myWindow = SoWin::init(argv[0]);

     //創建觀察器

     SoWinExaminerViewer *myViewer = new SoWinExaminerViewer(myWindow);

     //創建場景

     SoSeparator *root = new SoSeparator;

     SoMaterial *myMaterial = new SoMaterial;

     myMaterial->diffuseColor.setValue(1.0, 0.0, 0.0);//紅色

     root->addChild(myMaterial);

     root->addChild(new SoCube);//增加上一個立方體

     //觀察器和場景相關聯

     myViewer->setSceneGraph(root);

//顯示主窗口

myViewer->show();

     SoWin::show(myWindow);

    // 主循環

     SoWin::mainLoop();

     return 0;

}

程序運行的結果:

 

       這兩個程序很明顯的差別就是使用OIV開發程序的代碼要遠小於使用OpenGL開發的程序。當然這不是使用OIV唯一的一點好處。上面OIV例子代碼中,一開始也是先初始化OIV,然後創建一個觀察器窗口,接着創建場景,向場景增加上材質對象(材質對象設置爲紅色),再向場景增加上立方體對象。最後顯示場景,進入程序主循環。我們可以看到,OIV的程序邏輯性比較好,不像OpenGL那樣帶有太多的回調函數,導致我們的思路跳來跳去的。

 

       OIVOpenGL程序之間一個最大的差別就是OIV不需要程序員“畫”3D模型。在上面的OIV例子中,我們只是向場景中增加上一個立方體對象,至於在那裏顯示,以及何時顯示立方體都是OIV自己來決定的,不需要程序員來考慮。作爲對比,在OpenGL程序中,我們需要在display回調函數中一條一條地調用OpenGL命令,只有這樣才能將立方體顯示出來。

 

       使用OIV的另外一個好處是,OIV的程序是“活”的。我們可以使用鼠標來操作場景中的物體。例如,我們可以在觀察器窗口上按住鼠標左鍵,移動鼠標來任意旋轉立方體,也可以上下移動鼠標來放大或縮小立方體。也就是說上面的OIV例子代碼其實是一個交互式的3D程序,而我們沒有做任何的工作就自動獲得了這種交互功能。相對來說,使用OpenGL就沒有這麼幸運了,我們的OpenGL例子只是顯示了一個立方體,無論用鼠標怎樣操作,立方體都不會動。當然,我們也可以使OpenGL程序具有交互的功能,但要開發一個操作非常順手的交互式軟件不是一件容易的事情。

 

       讀者或許認爲上面的OIV例子中有一些錯誤,在例子中,我們使用C++new 操作符創建了多個對象,但在整個程序中沒有調用一次delete操作符來刪除對象。這樣做不會產生內存泄漏嗎? 這點請不要擔心,OIV有自己的內存管理方式,它使用引用計數的技術來管理內存。每個對象都有一個引用計數的變量,只要它被使用過一次,引用計數就加1,不再使用時,引用計數就減1,如果引用計數變成0,那麼這個對象就自動被刪除。這種內存管理的方式有些類似於微軟的COM接口引用方式。正是因爲OIV具有自動管理內存的功能,才使得利用OIV開發大型3D應用程序相對變得相對輕鬆。我們都知道,內存泄漏始終是C++程序員心中抹不去的一塊陰霾。

 

 

Open Inventor的開發環境

       目前世界上比較成熟的OIV開發包有三個,它們分別由SGITGSSIM公司開發的,它們在遵循OIV接口規範的基礎上各有特點。

 

       OIV最早是由SGI提出並開發的。SGIOIV主要用在UNIX操作系統下,在SGI公司的操作系統中已經集成了OIV開發環境,所以只要使用SGIUNIX操作系統就可以直接在上面開發OIV程序。但對於其它的UNIX系統或Linux操作系統,必須手工安裝。2000年左右,SGI開放了OIV的源碼。讀者如果感興趣,可以到http://oss.sgi.com/projects/inventor/ 免費下載源碼。它的使用協議是LGPL

 

       TGS公司是最早將OIVUnix系統移植到Microsoft Windows下的公司。TGSOIV是目前世界上使用最多的OIV版本。它具有功能強大,性能優異等優點。而且TGS爲了滿足不同應用領域的要求,對OIV做了大量的擴展,這也大大促進了OIV的應用。TGS是一家商業公司,它們開發的OIV是一個商業軟件開發包,其購買開發版權的費用非常昂貴,不適合普通用戶學習和使用。不過,如果讀者的項目費用比較充裕的話,我們還是建議採用TGSOIV版本。它們的網站:http://www.tgs.com/

 

       SIM公司開發的Coin3D OIV可以同時在UNIXMicrosoft Windows下使用。雖然Coin3D OIV的功能和性能沒有TGS的強大,但開發一般的3D應用程序還是綽綽有餘的。而且它是一個開放源碼的OIV開發包,可以讓我們瞭解OIV內部運行的機理。所以Coin3D OIV比較適合普通用戶。但請注意,Coin3D OIV免費版本的使用協議採用的是GPL協議,GPL協議要求使用Coin3D OIV開發的軟件必須也是一個免費,開源的軟件。因此如果讀者要開發一個商業軟件,一定要注意避免版權的問題。SIM公司爲商業軟件使用Coin3D提供了另外的一種使用協議,商業用戶需要每年支付一筆很少的開發費用(相對我們獲得的功能,以及和其它OIV的費用),就可以在商業軟件中使用Coin3D OIV了。它們的網站:http://www.coin3d.org/

 

 

Open Inventor的開發資料

       目前OIV的開發資料不多,而且都是英文資料。主要的開發書籍有三本:

 

       1Open Inventor C++ Reference PagesOpen Inventor C++參考手冊。這類似於微軟的MSDN,裏面介紹了Open Inventor中的所有C++類和方法。

 

       2The Inventor Mentor 這本書是OIV的主要入門書籍。所有學習使用OIV的用戶都應該首先閱讀此書。通過閱讀此書,用戶可以循序漸進地掌握OIV的基本開發過程。(目前我們正在翻譯此書)

 

       3The Inventor ToolMaker。這是一本適合OIV高級用戶的書籍,書中主要講述如何擴展、定製OIV

 

       這三本書都可以在亞馬遜網上書店( http://www.amazon.com )中買到。

 

 

題外話

也許很多人對OIV不是很瞭解。但可能很多人都聽說過VRML文件格式。VRML文件是瀏覽器用於在網頁中顯示3D物體的一種通用文件格式。其實VRML文件格式就是OIViv文件格式的一個子集。當年VRML格式的創建者參考了OIViv文件格式。所以OIV自動支持VRML文件的導入。而Java 3D借鑑了很多VRML的思想。因此Java 3DOIV在設計思想上也是很相近的。

 

近些年來,國內外流行起“設計模式”的編程概念,在“設計模式”裏有一種叫做MVC(模型-視圖-控制器)的設計模式。其實我們細想一下,MVC和“場景”,“觀察器”、“動作”這些概念是相通的。不過在SGI設計OIV的時候,“設計模式”的思想恐怕還沒有流行起來。從這點可以看出,在那些面向對象編程方面的大師們的骨髓中早已藏有“設計模式”的思想,只不過他們沒有表達出來而已。這也說明了,我們不應該刻意地去套用“設計模式”,而應該像“春夢了無痕”那樣將“設計模式”的思想融會在自己的程序中。^_^

 

www.openinventor.cn

[email protected]

[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章