Vega扩展模块的设计与研究

来源:岁月联盟 作者:毛学刚 李明泽 时间:2010-08-30
摘  要 本文基于对Vega 和Vega扩展模块体系结构的深入研究,采用了C++、OpenGL三维图形库Vega API开发了一个波浪仿真的Vega扩展模块,该扩展模块与Vega中的其它模块完全兼容,从而扩展Vega的功能,并利用该模块实现了波浪的交互式仿真效果。实践证明该开发Vega扩展模块的方法对于其它领域的用户开发Vega扩展模块也是完全适用的。    关键词  Vega;扩展模块;交互式仿真 

1  引言

    Vega 是在 SGI Performer 基础上起来的仿真软件平台[1],主要用于虚拟现实技术中的实时场景生成、声音仿真及可视化等领域。由于Vega大幅度地减少了源代码,从而大大地提高了工作效率,可以迅速创建各种实时交互的三维环境,以满足各种用户的需要[2]。Vega 软件环境是目前实时视景仿真领域主流的高层开发平台,其结构和功能是模块化的,用户可针对自己的仿真需求选用特定的模块组合[3]。但是Vega不可能包罗万象,对于某些特殊场景的仿真,如波浪仿真等,Vega没有对应的模块,使得相应的设计开发工作十分困难。因此,有必要对Vega进行扩展研究,研制出能够满足各种开发需求的专用仿真模块。

2  扩展模块结构分析

    Vega扩展模块由5部分构成,分别为:模块关键字配置文件,LynX界面配置文件,LynX 图标菜单项插件 DLL,编程接口DLL 和LIB[3]。模块关键字配置文件是扩展名为 KEY 的ASCII文本文件,包含抽象出的自定义类的特征关键字及其参数、参数类型和参数缺省值等。LynX界面配置文件是根据模块关键字配置文件包含的关键词定义的,界面配置文件也是扩展名为GUI的ASCII文本文件,表示 LynX中的自定义类参数的图形调整接口,每个窗口元素对应自定义类的一种属性参数。LynX 图标菜单项插件把代表自定义类的大图标和工具栏小图标以及新增菜单项读入到LynX 界面。三者共同完成LynX界面的扩展。扩展模块的核心 DLL,提供自定义类的编程接口,自定义类同其他 Vega 类一样,是一个完整的控制结构,提供给外界管理自身和完成特定功能的 API。因此在定义类的同时安装各种回调函数,包括公共Vega API的回调、仿真循环前配置系统的回调和读取自定义 ADF 文件的回调。自定义类具备读取 ADF 文件的功能后,就同LynX图形界面联系起来。自定义类最终提供给用户的是 C 编程接口,这是在动态链接库中用 EXTERN 语句导出的。静态库是上述动态链接库的副产品,在将自定义类用于仿真程序时要在程序中连接静态库。

3  波浪扩展模块的具体实现

    由扩展模块结构分析可知,波浪模块的实现主要有两部分工作,LynX界面的扩展和开发自定义波浪类。LynX界面的扩展主要包括开发出扩展模块的关键字配置文件、GUI 配置文件以及 LynX插件动态链接库。最后将这些文件放到系统默认的路径下,当 LynX启动时,系统会自动调用这些文件,显示出扩展模块的 LynX图形界面。自定义波浪类开发主要分为:初始化波浪类、安装公共Vega API的回调、创建C编程接口等,其流程如图1所示。

3.1  扩展LynX界面

3.1.1  创建LynX关键字文件    在波浪类的关键字配置文件中定义了3个关键字:波形(wavefrom),尺寸(dimensions)和观察者(observer)。以其中一个关键字波形(wavefrom)为例,定义语句和格式如下所示:    keyword "waveform" {    param amplitude {        type  FLOAT;        default      1;        min          0;        max         10;    }    param period {        type  FLOAT;        default      5;        min          0.01;        max         30;    }    }3.1.2  创建LynXGUI配置文件    在波浪模块的LynXGUI配置文件定义了一个图框部件和三个窗口部件,其中三个窗口部件分别用来设置波形,尺寸和观察者三个关键字,而图框部件用来设置波浪类。以其中一个设置波形(wavefrom)关键字部件为例,定义语句和格式如下所示:    frame w_waveform {      topWidget       CLASSNAMES;labelstr    "Waveform";scale w_amp {        labelstr    "Amplitude";        param            c_wave.amplitude;        decimalpts       2;}scale {        labelstr    "Period";        topWidget       w_amp;        param            c_wave.period;        decimalpts       1;}    }    创建关键字配置文件、GUI 配置文件要放到Vega 的安装目录…/Vega/Dada/LynxData/Config里面。Lynx自动地在该文件夹中读取所有的GUI和KEY文件。图1波浪扩展模块实现的流程图
3.1.3  创建LynX插件    此时运行LynX将会看到标识波浪仿真模块的图标还是一个问号,要想改变图标就要创建图标插件 DLL,该动态链接库是用MFC的Appwizard DLL实现的。创建完的波浪模块图标插件 DLL名为LynxPIMyWave.dll,最后要把该动态链接库放到…/Vega/Bin/LynxPlugins文件夹中,以便启动LynX时,读取该文件。这样界面扩展的工作完成了,其效果见图2所示。


图2 Lynx扩展界面

3.2  自定义波浪类的开发

3.2.1  初始化类    Vega的所有模块必须有一个初始化函数和一个配置函数,自定义扩展的波浪类也不例外,初始化函数完成的工作是分配内存、申请初始值和安装类定义回调,其初始化波浪类的步骤如下:    (1)InitModule():在这里安装用户的类定义回调    (2)vgDefineSys():读ADF文件,在这里调用用户的ADF扫描器回调。    (3)ConfigModule():由函数vgConfigSys()调用。 3.2.2  安装公共API回调    为使波浪模块支持Vega的公用 API 函数,分别为各函数注册相应的回调函数,并编写代码,实现各函数。首先为Vega函数ConfigSys()注册回调函数,在其实现中获取指向图像通道类的实例的指针,再为该通道的后台帧缓存绘制函数注册回调函数[4],设为draw ( ),其代码如下:void vgWave::draw(){pfBasicState();glEnable( GL_LIGHTING );glDisable( GL_COLOR_MATERIAL );float aandd[4] = {.17f,0.3f,0.4f,1.0f };float nothing[4] = { 0.0f,0.0f,0.0f,0.0f };glMaterialf ( GL_FRONT_AND_BACK,GL_SHININESS,128.0f );glMaterialfv( GL_FRONT_AND_BACK,GL_AMBIENT_ AND_ DIFFUSE,aandd);glMaterialfv( GL_FRONT_AND_BACK,GL_SPECULAR,nothing );glMaterialfv( GL_FRONT_AND_BACK,GL_EMISSION,nothing ); glShadeModel(GL_SMOOTH); for ( int j = 0;j < m_ny - 1;j++ ) {        glBegin( GL_TRIANGLE_STRIP );        for ( int i = 0;i < m_nx;i++ ) {               glNormal3fv( m_norms[i][j+1] );               glVertex3fv( m_verts[i][j+1] );               glNormal3fv( m_norms[i][j] );               glVertex3fv( m_verts[i][j] );        }        glEnd();    }glEnable( GL_COLOR_MATERIAL );pfPopState();pfBasicState();}    每帧刷新前,系统都调用该函数绘制图形,在前后台缓存交换时输出显示,实现波浪模块的仿真功能。3.2.3  创建C编程接口    自定义类的内部逻辑是通过在动态链接库中安装自定义回调实现的,回调函数供系统调用,但自定义类最终要提交给外界可供编程的函数库,因此,在DLL中用类似下列语句导出能为仿真应用程序所用的C接口:WAVEMOD_DLLEXPORT ERR           InitWaves        ( void );WAVEMOD_DLLEXPORT int              GetNumWaves ( void );WAVEMOD_DLLEXPORT vgWave*      NewWave              ( void );WAVEMOD_DLLEXPORT void     SetWaveObserv     ( vgWave *wave,vgObserver *obs );WAVEMOD_DLLEXPORT vgObserver* GetWaveObserv ( vgWave *wave );WAVEMOD_DLLEXPORT vgWave*      GetWave                ( int wavenum );WAVEMOD_DLLEXPORT vgWave*             FindWave        ( const char *wname );WAVEMOD_DLLEXPORT float            GetWavePeriod       ( void *wave );WAVEMOD_DLLEXPORT float     GetWaveAmplitude ( void *wave );WAVEMOD_DLLEXPORT float            GetWaveElev    (vgObserver *obs,float x,float y,float time );WAVEMOD_DLLEXPORT void     GetWaveNorm  ( vgObserver *obs,float x,float y,   float time,pfVec3 norm );    静态库是编译连接动态链接库的副产品,编译psVgWave.dll 的同时配置生成 psVgWave.lib,在仿真程序中连接该库,可以使用其中的API。经过上述步骤,一个完整的自定义波浪类建立起来了,在使用上等同于Vega内置类,在LynX界面中具备参数调整接口。

4  波浪仿真系统的实现

    应用自定义的Vega波浪扩展模块和Visual C++6.0开发了一个简单的波浪仿真系统。该系统实现了波浪的交互式仿真,其系统运行界面如图3所示。该系统的成功开发说明了用C++、OpenGL与Vega API开发的波浪扩展模块和Vega的其它模块能够完全的兼容,该模块能够被成功应用到其它波浪仿真的应用程序中。


图3 波浪交互式仿真系统界面

5  结论

    Vega提供了仿真应用的平台,而Vega扩展模块的接口,从某种意义上提供了新算法、新技术试验和应用的平台,使我们能够把优秀的算法、改进的算法和技术及时有效地应用到仿真程序中去。本文用C++、OpenGL与Vega API开发了一个波浪仿真的Vega扩展模块,既检验了算法,又丰富了平台,并且应用了软件复用的原则,使以后的工作在此基础上更易于开展下去,取得更佳的效果。波浪的模拟是一个很具挑战性的课题,本文介绍的波浪仿真仅是一个初步的结果,下一步研究是增加反射、耗散、海底摩擦以及风力对波浪生成的影响,为利用海洋资源、预防海洋灾难做一些基础工作。

[1] Simon Premoze,Michael Ashikhmin M. Rendering Natural Waters [J]. Computer Graphics Forum,2001,20(4):189-200
[2] 龚卓荣. Vega 程序设计[M]. 北京:国防出版社,2002[3] 段春梅,张艳,战守义. Vega特效模块扩展的研究与设计[J]. 机工程,2006,32(05):271-273[4] 宋志明,康凤举. Vega开发环境的扩展研究[J].系统仿真学报,2004,16(01):178-179

图片内容