Open Inventor 简介

深入学习资料:http://blog.csdn.net/robinhao

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

openinventor@gmail.com

openinventor@126.com

发布了420 篇原创文章 · 获赞 760 · 访问量 129万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览