数值模拟实时三维可视化的C#与OpenGL实现
2009-02-26 08:18:46 来源:WEB开发网 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梺璇查叄濞佳勭珶婵犲伣锝夘敊閸撗咃紲闂佺粯鍔﹂崜娆撳礉閵堝洨纾界€广儱鎷戦煬顒傗偓娈垮枛椤兘骞冮姀銈呯閻忓繑鐗楃€氫粙姊虹拠鏌ュ弰婵炰匠鍕彾濠电姴浼i敐澶樻晩闁告挆鍜冪床闂備浇顕栭崹搴ㄥ礃閿濆棗鐦遍梻鍌欒兌椤㈠﹤鈻嶉弴銏犵闁搞儺鍓欓悘鎶芥煛閸愩劎澧曠紒鈧崘鈹夸簻闊洤娴烽ˇ锕€霉濠婂牏鐣洪柡灞诲妼閳规垿宕卞▎蹇撴瘓缂傚倷闄嶉崝搴e垝椤栫偛桅闁告洦鍨扮粻鎶芥倵閿濆簼绨藉ù鐘荤畺濮婃椽妫冨☉娆愭倷闁诲孩鐭崡鎶芥偘椤曗偓瀹曞爼顢楁径瀣珫婵犳鍣徊鍓р偓绗涘洤绠查柛銉墮閽冪喖鏌i弬鎸庢喐闁荤喎缍婇弻娑⑩€﹂幋婵囩亪濡炪値鍓欓悧鍡涒€旈崘顔嘉ч幖绮光偓鑼嚬缂傚倷绶¢崰妤呭箰閹间焦鍋╅柣鎴f绾偓闂佺粯鍔曠粔闈浳涢崘顔兼槬闁逞屽墯閵囧嫰骞掗幋婵愪紑閻庤鎸风粈渚€鍩為幋锔藉亹闁圭粯甯╂导鈧紓浣瑰劤瑜扮偟鍒掑▎鎾宠摕婵炴垶鐭▽顏堟煙鐟欏嫬濮囨い銉︾箞濮婃椽鏌呴悙鑼跺濠⒀傚嵆閺岀喖鎼归锝呯3闂佹寧绻勯崑娑㈠煘閹寸姭鍋撻敐搴樺亾椤撴稒娅婇柡灞界У濞碱亪骞忕仦钘夊腐闂備焦鐪归崐鏇㈠箠閹邦喗顫曢柟鎯х摠婵挳鏌涢幘鏉戠祷闁告挸宕—鍐Χ閸℃浠搁梺鑽ゅ暱閺呮盯鎮鹃悜钘壩ㄧ憸澶愬磻閹剧粯鏅查幖绮瑰墲閻忓秹姊虹紒妯诲鞍婵炲弶锕㈡俊鐢稿礋椤栨氨鐤€闂傚倸鐗婄粙鎰姳閼测晝纾藉ù锝堟閻撴劖鎱ㄥΟ绋垮婵″弶鍔欓獮妯兼嫚閼碱剦妲伴梻浣稿暱閹碱偊宕愭繝姣稿洭寮舵惔鎾存杸濡炪倖姊婚妴瀣啅閵夛负浜滄い鎾跺仜濡插鏌i敐鍥у幋妤犵偞甯¢獮瀣籍閳ь剟鎮楁繝姘拺閻熸瑥瀚崕妤呮煕濡 鍋撻悢鎻掑緧婵犵數濮烽弫鍛婃叏閻戣棄鏋侀柛娑橈攻閸欏繑銇勯幘鍗炵仼缁炬儳顭烽弻鐔煎礈瑜忕敮娑㈡煃闁垮鐏﹂柕鍥у楠炴帡宕卞鎯ь棜缂傚倸鍊风粈渚€藝闁秴鏋佸┑鐘虫皑瀹撲線鏌涢埄鍐姇闁稿﹦鍏橀弻娑樷攽閸℃浼€濡炪倖姊归崝鏇㈠煘閹达附鍊婚柛銉㈡櫇鏍¢梻浣告啞閹稿鎮烽敂鐣屸攳濠电姴娲﹂崵鍐煃閸濆嫬鏆熼柨娑欑矒濮婇缚銇愰幒鎴滃枈闂佸憡鐟ユ鎼佸煝閹炬枼鍫柛顐ゅ枔閸樻悂鏌h箛鏇炰户缁绢厼鐖煎畷鎴﹀箻鐠囪尙鐤€婵炶揪绲介幉锟犲磹椤栫偞鈷戠痪顓炴噹娴滃綊鎮跺☉鏍у姦闁糕斁鍋撳銈嗗笒閸燁偊鎯冨ú顏呯厸濞达絽婀辨晶顏堟煃鐟欏嫬鐏撮柟顔界懇瀵爼骞嬮悩杈敇闂傚倷绀佸﹢杈ㄧ仚闂佺濮ょ划搴ㄥ礆閹烘绫嶉柛顐ゅ枎娴犺櫣绱撴担鍓插創妞ゆ洘濞婇弫鍐磼濞戞艾骞堥梻浣告惈濞层垽宕濆畝鍕€堕柣妯肩帛閻撴洟鏌熼懜顒€濡煎ù婊勫劤閳规垿鏁嶉崟顐℃澀闂佺ǹ锕ラ悧鐘茬暦濠靛鏅濋柍褜鍓熼垾锕傚锤濡も偓閻掑灚銇勯幒宥堝厡缂佺姴澧介埀顒€鍘滈崑鎾斥攽閻樿京绐旈柛瀣殔閳规垿顢欑涵鐑界反濠电偛鎷戠徊鍨i幇鏉跨闁瑰啿纾崰鎾诲箯閻樼粯鍤戦柤绋跨仛濮f劙姊婚崒姘偓鐑芥嚄閼哥數浠氭繝鐢靛仜椤曨參宕楀Ο渚殨妞ゆ劑鍊栫€氭氨鈧懓澹婇崰鏍р枔閵婏妇绡€闁汇垽娼ф牎缂佺偓婢樼粔鐟邦嚕閺屻儱绠甸柟鐑樼箘閸炵敻鏌i悩鐑橆仩閻忓繈鍔岄蹇涘Ψ瑜夐崑鎾舵喆閸曨剙纰嶅┑鈽嗗亝缁诲倿锝炶箛娑欐優闁革富鍘鹃敍婊冣攽閳藉棗鐏犻柟纰卞亰閿濈偛顓奸崶鈺冿紳婵炶揪缍侀ˉ鎾诲礉瀹ュ鐓欑紒瀣仢閺嗛亶鏌i敐鍥у幋妤犵偛顑夐弫鍐焵椤掑倻涓嶅┑鐘崇閸嬶綁鏌涢妷鎴濆暟妤犲洭鎮楃憴鍕碍缂佸鎸抽垾鏃堝礃椤斿槈褔鏌涢埄鍏狀亪妫勫鍥╃=濞达絽澹婇崕鎰版煕閵娿儱顣崇紒顔碱儏椤撳吋寰勭€n亖鍋撻柨瀣ㄤ簻闁瑰搫绉堕ˇ锔锯偓娈垮枛閻忔繈鍩為幋锕€鐓¢柛鈩冾殘娴狀垶姊洪崨濠庣劶闁告洦鍙庡ú鍛婁繆閵堝繒鍒伴柛鐕佸灦瀹曟劙宕归锝呭伎濠碘槅鍨抽崢褎绂嶆ィ鍐╁€垫慨妯煎亾鐎氾拷

1. 引言
当代CFD/NHT等大型数值模拟软件的开发工作在全球范围内进行得如火如荼,但主要的成果集中在国外大型相关专业软件开发商,如ANSYS公司的FLUENT和CFX等。国内,尤其是高校内同类软件的开发应该在计算性能和个性化上寻求创新和突破,如果一味地依赖商用软件,我国与国外先进水平的差距将会越拉越大。
哈尔滨工业大学推进理论与技术研究所开发的HITurbine主要是针对航空以及地面燃气涡轮内部流场的数值模拟而设计开发的,图1为HITurbine的主界面。
图1 HITurbine主界面
由于现有大多已有成熟的数值程序是由Fortran编写的,所以HITurbine考虑并采用了如图2所示系统结构:
C# |
Main Program & Interface |
Fortran |
OpenGL |
Real-time 3D Result Visualization |
Computation Program(DLL) |
Other API |
HPC,etc |
图2 HITurbine系统的结构
2. 实时三维可视化实现
目前,微软公司已推出的DirectX 9.0c中已经包含了一个Managed DirectX程序集,这个程序集为.NET框架下的托管代码提供了访问Direct3D的接口,这使得C#能够方便地编写Direct3D代码[1]。OpenGL目前的进展有些落后,虽然运用C/C++、VB以及Fortran等开发OpenGL程序的技术已经相对成熟(参见文献[2][3]),然而.NET仍没有提供OpenGL API的接口,所以也不存在C#开发OpenGL的标准和规范,这对于擅长界面编写的C#来说,亦可称为一种挑战。
Direct3D的参考书籍和网络资源相当丰富,其中在.NET环境下的开发框架在文献[1][4]中有详细的叙述,而OpenGL的资源则相对少得很多。实质上OpenGL具有平台无关性,利用C#与其实现实时的三维可视化与其它语言没有实质性的差异,关键是要在开发环境下做好相应的配置,下文将对.NET 下三种OpenGL具体配置方式加以讨论。
2.1 C# 直接调用 OpenGL
用C#和OpenGL实现计算实时可视化,最直接的方式就是利用C#调用OpenGL所提供的开发库。但是如前所述,OpenGL所提供的函数均为C接口的API形式,用C#实现要进行类似混合语言编程过程的DLL调用,即调用OPENGL32.DLL、GLU32.DLL以及GLUT32.DLL等。另外,为了体现OOP思想,可新建一个OpenGL调用类,如下clsGL类和clsGLU类分别调用OpenGL和GLU:
using System.Runtime.InteropServices;
public class clsGL {
//OpenGL常量声明
public const uint GL_COLOR_ BUFFER_ BIT = 0x00004000;
public const uint GL_MODELVIEW = 0x1700;
public const uint GL_PROJECTION =0x1701;
…… ……
//函数入口声明
[DllImport("opengl32.dll")]
public static extern void glClear(uint mask);
[DllImport("opengl32.dll")]
public static extern void glBegin(uint mode);
…… ……
}
public class clsGLU {
//OpenGL常量与函数入口声明
…… ……
}
然而OpenGL提供约有250个左右不同的函数,还不包括GLUT等常用的工具库和大量如上所述的OpenGL常量,所以若要在C#中进行DLL调用,可想而知其工作量将是非常大的。所以这种方式虽然直接,但相对以下所述的两种方式较为繁琐,所以在实际运用中少见。
2.2 利用CSOpenGL实现
若利用CSOpenGL实现,则需先将CSOpenGL.dll、CSOpenGLC.dll、mfc70.dll和msvcr70.dll四个文件拷贝到可执行文件目录,当然也可以放到系统文件夹system32下公用。然后进行引用“using CSOpenGL;”即可在.NET环境下进行OpenGL代码编写了。
将绘图的功能模块单独写为一个单独的继承自GLViewPainter类的绘图类,如zPainter,该类中的工作仅仅是对Paint()方法的重构和具体绘图方法的建模。代码框架如下:
public class zPainter : GLViewPainter {
public zPainter() { }
public override void Paint(GLView view)
{
……/* OpenGL初始化, 如glViewport(0, 0, view.Width, view.Height); glMatrixMode(GL_PROJECTION);等 */
drawYourImg (); // Draw Images
glFlush();
}
public void drawYourImg() {
……/* OpenGL初始化,如glEnable(GL_BLEND);等 */
……//Draw Your Images Here
}
通过参数传递和drawYourImg()建模,即可实现绘图类的绘图功能。在图1的主界面中,右侧黑色部分为一个pictureBox控
件,此即为图形绘制表面,可以通过如下代码进行指定:
zPainter nZp = new zPainter();
GLView View = new GLView();
View.Parent = this.pictureBox1;
View.CreateControl();
View.Dock = DockStyle.Fill;
View._OnPaint = new zPainter();
以上代码实现了利用CSOpenGL接口进行C#的三维可视化编程,OpenGL初始化及如纹理及场景绘制等具体绘图方法可以参考[5][6]等。
2.3 利用CsGL实现
CsGL的应用方法在文献[5]中有过叙述。本文将在利用CsGL方面做一些补充,以使得更好地运用其开发程序界面。
利用CsGL时csgl.dll与csgl.native.dll是必须的。将其拷贝到可执行文件运行目录或系统目system32下后,新建一个继承于OpenGLControl的新类,并加以引用“using CsGL.OpenGL;”,然后至少作如下三个重构:
class csglP : OpenGLControl {
public override void glDraw() {
base.glDraw();
……/* OpenGL初始化,如glEnable(GL_BLEND);等 */
GL.glBegin(GLenum mode);
……//Draw Your Images Here
GL.glEnd();
}
protected override void InitGLContext() {
base.InitGLContext();
……/*绘制环境初始化,如GL.glShadeModel(GL.GL_SMOOTH);等 */
}
protected override void OnSizeChanged (EventArgs e) {
base.OnSizeChanged(e);
……/* 窗口大小变化时调用,如GL.glViewport(0, 0, this.Width, this.Height);等 */
}
}
为了实现在指定绘制平面内绘图,可以类似CSOpenGL加入以下代码:
csglP zView = new csglP();
Controls.Add(zView);
zView.Parent = this.pictureBox1;
zView.Dock = DockStyle.Fill;
这样就实现了在.NET环境下的CsGL配置,进而可以在.NET 下编写OpenGL的C#代码。与CSOpenGL相比,CsGL的运用方法更接近OpenGL的C接口方式,但大体上十分相似,只是由于封装得不同,所以对用户来说只是需重构的方法不一样而已,关键的核心绘图代码则是一致的,并且与其它语言也很相似,毕竟OpenGL是平台无关的。用户可以自己通过Object Browser查看和比较这两个接口。
3. 具体实例
为了更加清晰地说明,下面以一个实例的实现过程进行较为具体地解释。
3.1 绘制椭球体
在OpenGL中绘制三维图形,椭球体的绘制相对来说较为简单。本例将以CSOpenGL实现过程为例详细说明其具体绘制过程。
做好2.2中所述的配置后,然后再将drawYourImg()方法改写如下:
public void drawYourImg() {
float[] ambient = { 1.0f, 1.0f, 0.0f, 1.0f };
float[] diffuse = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] specular = { 1.0f, 1.0f, 1.0f, 1.0f };
float[] position = { 1.0f, 1.0f,1.0f, 0.0f };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
gluLookAt(6.0, 6.0, 6.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
IntPtr hdc = gluNewQuadric();
gluSphere(hdc, 2.0, 38, 38);
gluDeleteQuadric(hdc); }
接下来如2.2中进行绘制表面制定后,即可在主程序中调用该方法,绘制出如图3所示的椭球体:
图3 利用CSOpenGL实现椭球体绘制
3.2 其它
实际上,利用上述各种方式实现都是大同小异的,不同点仅仅在环境的配置上。3.1是一个最简单的例子,如果建立更加复杂的几何模型(即drawYourImg方法),再通过更多的OpenGL参数控制,可以绘制更加复杂的三维图形,如图4和图5为某型航空涡轮叶片,图中表面曲线为插值结果。本文目的在于C#实现框架的建立,OpenGL具体绘制不是本文的重点,在此不加赘述。其中,图3为线框模型渲染的效果,图4添加了光照效果并以平滑着色。实际应用中可以根据需要还可以应用OpenGL提供的阴影和纹理等效果,渲染出更加令人满意的场景。
图4 某型航空涡轮叶片线框模型渲染效果图
图5使用光照并以平滑着色的渲染效果
通过上文的分析可以发现,利用C#编写OpenGL代码更具吸引力,原因在于其更加简单直观,而且省去了C/C++下的很多如前后台缓存交换问题等等的一系列工作。本文说明了常用的三种实现模式,具体 OpenGL的编程技术在文中没有展开,具体可参见[6]等讲述OpenGL的书籍。利用C#和OpenGL实现计算结果实时三维可视化的关键在于OpenGL绘图方法的建模,本文进行的工作是框架的搭建。具体在应用CSOpenGL或 CsGL两个接口进行三维建模时,只要做好上述的环境配置,就可以在.NET环境下应用C#编写OpenGL代码来实现实时三维可视化了,接下来的工作就是通过参数传递,运用计算所得数据实现实时三维可视化。同时可见,一般的数值模拟软件均可以利用此框架进行快速开发,已使其具有计算结果实时可视化功能。用户还可以根据需要扩展和发展这个框架,例如建立多个监视窗口等,这在.NET下利用C#是很容易实现的。
更多精彩
赞助商链接