`
huozheleisi
  • 浏览: 1234412 次
文章分类
社区版块
存档分类
最新评论

利用VC++6.0初始化Direct3D

 
阅读更多

利用VC++6.0初始化Direct3D

玩过游戏的人对DirectX一定不会陌生,因为在Windows平台下的游戏多数需要DirectX的支持。微软公司开发DirectX最主要的目的之一就是促进在Windows操作系统上的游戏和多媒体应用程序的发展。在MS-DOS下,游戏开发者们为了使他们的程序能够适应各种各样的硬件设备而绞尽脑汁。而DirectX在硬件设备和应用程序之间提供了一套完整接口,大大降低了软件安装和配置的复杂程度,并最大限度的利用硬件的优秀特性。另外通过使用这些接口,软件开发者在尽情利用硬件高性能的同时,而不用烦恼复杂而又多变的硬件执行细节。因此,DirectX作为Windows平台下游戏设计解决方案,一经推出立即被游戏开发商广泛接受,也使广大游戏爱好者编制自己的游戏成为现时。

微软的DirectX软件开发工具包(SDK)为Windows平台下的应用程序提供了以下组件:DirectDraw、DirectSound、DirectPlay、Direct3D 、DirectInput 、DirectSetup、AutoPlay等 。Direct3D是最重要、最复杂的组件之一,它提供实时、交互的3D技术,完成三维场景的的建立和显示。

DirectX SDK提供了许多例子程序,熟悉这些例子程序是掌握DirectX编程最简捷的途径。但这些程序是基于SDK的,熟悉了VC++6.0的MFC类库及文档/视结构的编程人员会感到陌生。本文主要介绍在VC++6.0环境中利用MFC实现Direct3D的编程。

一、创建程序框架

程序框架的创建很简单,直接利用VC++6.0提供的MFC AppWizard建立工程,选择单文档,MyView的基类选择CFormView,其它选项按需要选择。

这样建立的框架,是在主框架(CFrameWnd类)上覆盖了一个视窗(CFormView类)。下一步就是在这个视窗上创建新视并把它初始化成一个三维场景。

二、建立Direct3D初始化类CD3dView

这是最重要的一个步骤。CD3dView由CView类继承而来,和其它视如: CListView、CTreeView一样是视Cview的扩展,完成Direct3D对象的创建、初始化、以及对硬件设备的列举。下面介绍它的几个主要函数(由于篇幅所限,重点介绍几个重要的函数,详见程序实例)。

1.OnCreate()函数

在窗口生成过程中调用OnCreate()函数,主要完成对象创建和初始化。

Direct3DRMCreate(&d3drm1)函数对指针d3drm1进行初始化。

d3drm1->QueryInterface(IID_IDirect3DRM3,(void**)&d3drm)来查询Direct3DRM3接口。

2.CreateDevice()函数

该函数是一个专用成员函数,产生标准的Direct3D接口。它在OnPaint()函数中调用。

DirectDrawCreateClipper(0, &clipper, 0 )用来检索指向DirectDrawClipper接口的指针clipper,clipper是一个DirectDraw的结构,对窗口更新进行管理,使应用程序在窗口环境下正确运行。

clipper->SetHWnd( 0, m_hWnd )将clipper与窗口相连。

d3drm->CreateDeviceFromClipper( clipper,GetGUID(),rect.right, rect.bottom,&device )产生指向Direct3DRMDevice接口的指针device,它是最重要的一个接口。第一个参数裁剪器,第二个参数为寻找到的GUID,第三、四个参数是客户区的宽度和高度,确保device设备合适地出现在窗口中。

d3drm->CreateFrame(0, &scene )创建整个场景的帧。

CreateScene为一虚函数,可在继承类中重载,生成希望得到的场景。

3.GetGUID函数

要显示三维场景,需要给Direct3D设备确定一个GUID。但Direct3DRM接口并没有提供这样的成员函数。因此这个函数的内部实际上是采用立即模式运行的。

Searchdata结构指明色彩模型,resultdata存储搜寻结果。

DirectDrawCreate( 0, &ddraw, 0 )检索指向DirectDraw接口的指针。

ddraw->QueryInterface(IID_IDirect3D, (void**)&d3d )通过查询对象找到Direct3D接口d3d。

d3d->FindDevice( &searchdata, &resultdata )将d3d指针指向两结构,如果返回DD_OK,则找到一个GUID。

4.OnPaint(),OnActive()函数

当第一次调用OnPaint()函数时,调用CreateDevice()创建Direct3D接口。GetUpdateRect( 0, FALSE )用来确定是否需要重新绘制图形。OnPaint()剩余部分与OnActive()函数基本相同,都需要利用QueryInterface()函数检索Direct3DRMWinDevice接口指针,从而激活Direct3DRMDevice。

三、动态产生新视

为了在CMyView上放置新视。再建一个新类CSceneView,从CD3dView继承。

CMyView类中的CreateD3DView()产生一个CSceneView的对象,并把他显示在CMyView的适当位置。如果有兴趣,除这个视外,根据需要还可创建其它视,一起放在CMyView上。三维场景就是在这个视中建立起来的。

四、程序的驱动

程序的驱动是利用MFC的OnIdle()函数,当程序空闲时,OnIdle()函数将被调用。Direct3DRM提供了Tick()函数通知Direct3D更新场景中的所有对象并在此基础上显示一幅新的图像。如果机器运行速度较慢,可以将该函数的参数设置大一些,相反可设置小一些。

OnIdle()函数在CMyApp中调用。

五、新视中三维环境的建立

前面介绍了CD3dView中的虚函数CreateScene()在CSceneView中进行了重载,它用来产生三维场景并显示三维实体。

首先,设置场景的背景颜色为白色,scene->SetSceneBackgroundRGB(D3DVAL(1), D3DVAL(1),D3DVAL(1))完成这一功能。然后,设置场景中的灯光,在程序中d3drm->CreateLightRGB(D3DRMLIGHT_POINT, D3DVAL(0.9), D3DVAL(0.8),

D3DVAL(0.9),shadow_light)创建了一个点光源,d3drm->CreateLightRGB(D3DRMLIGHT_AMBIENT, D3DVAL(0.1),D3DVAL(0.1), D3DVAL(0.1), &l2)创建了一个平光源。将这两个光源放置在场景中来照亮三维实体和整个场景。

接下来d3drm->CreateFrame( scene,&camera )建立视点,camera-SetPosition(scene,D3DVALUE(0),D3DVALUE(0),-D3DVALUE(10))设置视点的位置。camera->SetOrientation( scene, D3DVAL(0), D3DVAL(0),D3DVAL(1),D3DVAL(0),D3DVAL(1),D3DVAL(0))设置视点的方向。

最后,d3drm->CreateViewport( device, camera, 0,0,device->GetWidth(), device->GetHeight(), &viewport)建立一个视窗。到此为止,一个三维的立体空间已经在前面创建的视初始化完毕。但什么也看不见,因为在这个三维空间里没有加载任何三维实体。

d3drm->CreateMeshBuilder( &teapot_builder)创建网格,teapot_builder->Load("teapot.x", NULL,D3DRMLOAD_FROMFILE, NULL, NULL) 从文件读取网格。

最后,将创建的网格放到三维空间适当的位置并创建阴影,执行程序显示出带有阴影的茶壶在旋转。

注:本文主要的目的是将SDK程序移植成MFC程序,整个初始化过程虽然比较复杂,但本文提供CD3dView类完成了全部初始化,大大简化了Direct3D的编程工作。用户只要在这个类的派生类中重载CreateScene(),即可建立所需场景。附带程序在VC++6.0中编译通过,需Directx6.1版本支持。

作者单位:河北廊坊陆军导弹学院101室 张焕明 杜建伟 张 波

邮编:065000 电话:0316-2115923转79251

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics