没有合适的资源?快使用搜索试试~ 我知道了~
VB.NET三维程序设计
5星 · 超过95%的资源 需积分: 49 44 下载量 160 浏览量
2015-02-22
18:29:59
上传
评论 3
收藏 454KB PDF 举报
温馨提示
试读
26页
VB.NET的三维程序设计,网上资源很少,尤其是像这样的入门教程!因此我将我找到的教程给大家!
资源推荐
资源详情
资源评论
VB.NET三维程序设计
目前流行的各种大型网络游戏,以及各种高端的图形图像应用设计,大部分都使用了 3D 技术。流行的三维设
计编程接口(API)有两大类,一类是 OpenGL,主要用于 Java 编程;另一类是 DirectX,主要用于 Windows 环境下
的各类三维软件编程。
DirectX 其实是一个组件套件,是由微软公司开发的应用程序编程接口,包含有 Direct Graphics、Direct Input、
Direct Play(针对游戏/网络)、Direct Sound(针对 3D 声音功能)、Direct Show 等多个组件,它提供了一整套的
多媒体接口方案。而今已发展成为对整个多媒体系统的各个方面都有决定性影响的接口。
DirectX 是 1995 年诞生的,1996 年在 DirectX 中加入了 Direct3D,用于访问 3D 硬件加速的高级图形功能,通
过提供通用的 COM(Component Object Model,组件对象模型)编程接口使硬件和设计分离,随后很快发展到
DirectX8.0,并从 DirectX9.0 开始支持托管代码。自 2002 年.NET 和 C#诞生以后,DirectX 的应用也迅速得到提升,
很多优秀的性能也逐步加入到托管 DirectX 中。由于 DirectX 的使用非常普遍,所以目前所有的显卡无一例外的都
支持 DirectX 编程接口,给各类三维应用设计带来了很大方便。
注意,本章的所有例子全部是在安装 DirectX9.0c SDK December 2005 后调试通过的。要调试本章的所有例子,
必须先安装 VS2005,然后再安装 DirectX9.0 SDK December 2005(几百 MB),如果仅仅为了直接运行已经编译后的.exe
文件,而不进行调试,也可以只安装 DirectX9.0c(几十 MB)。例子中调试使用的具体版本为:
Microsoft.DirectX.dll 版本 1.0.2902.0
Microsoft.DirectX.Direct3D.dll 版本 1.0.2902.0
Microsoft.DirectX.Direct3DX.dll 版本 1.0.2908.0
使用 DirectX 编写程序,首先必须在资源管理器中添加对它的引用。步骤为:【项目】Æ【添加引用】,然后在
弹出窗口的.NET 选项中选择上面列出的版本,单击【确定】。选择时要仔细观察引用的是哪个版本,不要选错。一
定要注意,本章的例子必须在引用上面列出的版本下才能正常调试,在低版本下或者高版本下,由于 SDK 提供的属
性及方法不一定相同,所以不保证能正常运行。
由于三维设计涉及面很广,而且包含很多复杂的模型计算以及数学处理等方面的内容,因此这里不准备在短短
一章中把 Direct3D 的内容全部介绍,而是只关心简单的、最基本的三维设计思路,并通过介绍 DirectX 提供的
Primitive 和 Mesh 对象的基本用法,为复杂的三维设计入门起到一个抛砖引玉的作用。
1 简单的 3D 设计入门
与一般 Windows 应用程序不同,为了提高显示速率和展现真实的三维效果,三维设计有一个特定的基本编程模
式。为了让读者首先有一个感性认识,这一节先不介绍 DirectX 提供的各种功能,而是通过一个简单例子介绍利用
DirectX 编程接口进行三维设计的一般方法,然后再介绍涉及到的相关概念和技术。
【例 1】使用 DirectX 设计一个能够旋转的三角形,并将本机显卡和显示器的相关参数显示出来。
(1) 新建一个名为 SimpleDirect3DExample 的 Windows 应用程序,使用默认的窗体名称。
(2) 在【项目】Æ【添加引用】Æ在【.net】选项下同时选中 Microsoft.DirectX、Microsoft.DirectX.Direct3D
和 Microsoft.DirectX.Direct3DX,注意选择的版本要和本章开头列出的版本一致,单击【确定】。
(3) 在命名空间的上方,添加引用代码:
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
(4) 在构造函数上方添加字段声明:
Dim device As Device 'Device指显卡适配器,一个显卡至少有一个适配器
Dim VertexBuffer As VertexBuffer
Dim d3dfont As Microsoft.DirectX.Direct3D.Font
Dim adapterInformationString As String
Dim showAdapterString As Boolean = True
Dim angle As Single = 0.0F
Dim incrementAngle As Single = 0.1F
Dim enableRotator As Boolean = True
这段代码中,Device 对象代表一个显卡适配器,如果显卡驱动程序正确并支持 3D,就不会出现异常。然后就
利用这个 Device 对象和显存交换信息,也可以通过这个对象获取或设置显卡适配器的相关配置信息。
顺便提一下,由于目前很多显卡都支持多显示器,即一块显卡可以连接一个以上的显示器,这就相当于一块显
卡有多个适配器。在编写 3D 程序时,要支持多显示器,就必须为同一块显卡的每一个适配器各创建一个 Device。
在本章的所有例子中,均假定只有一个显卡适配器,所以只创建了一个 Device。
(6) 在窗体的 Load 事件中添加代码:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim presentParams As PresentParameters = New PresentParameters
presentParams.Windowed = True '窗口模式
presentParams.SwapEffect = SwapEffect.Discard '交换
device = New Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, presentParams)
'设置窗体显示方式
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)
'为了能响应键盘事件,该属性必须设为true
Me.KeyPreview = True
adapterInformationString = "F1:显示/隐藏提示信息" + vbLf + _
"<F2>:旋转/不旋转" + vbLf + _
"上箭头:提高转速" + vbLf + _
"下箭头:降低转速" + vbLf + _
"<Esc>:退出"
Dim AdapterDetails As AdapterDetails = Manager.Adapters.Default.Information
adapterInformationString += String.Format("显卡驱动程序:{0}" & vbLf, AdapterDetails.DriverName)
adapterInformationString += String.Format("显卡驱动程序版本:{0}" & vbLf, AdapterDetails.DriverVersion)
Dim DisplayMode As DisplayMode = Manager.Adapters.Default.CurrentDisplayMode
adapterInformationString += String.Format("显示器当前分辨率:{0} X {1}" & vbLf, DisplayMode.Width,
DisplayMode.Height)
adapterInformationString += String.Format("显示器当前颜色质量:{0}" & vbLf, DisplayMode.Format)
adapterInformationString += String.Format("显示器当前刷新频率(Hz):{0}" & vbLf, DisplayMode.RefreshRate)
'创建D字体对象,显示字符用,这两句不能放在场景中,否则会很慢
Dim winFont As New System.Drawing.Font("Arial", 9, FontStyle.Regular)
d3dfont = New Microsoft.DirectX.Direct3D.Font(device, winFont)
d3dfont.PreloadText(adapterInformationString)
'创建顶点缓冲
VertexBuffer = New VertexBuffer(GetType(CustomVertex.PositionColored), _
3, device, Usage.Dynamic Or Usage.WriteOnly, _
CustomVertex.PositionColored.Format, Pool.Default)
AddHandler VertexBuffer.Created, AddressOf OnVertexBufferCreate
OnVertexBufferCreate(VertexBuffer, Nothing)
End Sub
代码中首先设置窗体样式,目的是为了重绘窗体时能得到连续变化的窗体图像;然后利用 Manager 命名空间下
提供的类判断显卡和显示器相关的配置参数;第三步是定义一个三维字体对象,以便显示配置信息;最后在显存中
创建了可以容纳 3 个顶点的顶点缓冲,并添加了 OnVertexBufferCreate 事件,该事件在每次重建顶点缓冲时都会
自动触发,但是第一次需要直接调用。
为什么必须通过事件实现呢?这是因为在运行时,如果改变窗口的大小,设备就会自动重置。当创建的资源位
于默认的内存池时(比如顶点缓冲),重置设备会释放缓冲。所以当改变窗口大小的时候,重置了 device,释放了
顶点缓冲。虽然 Managed DirectX 在重置 device 之后会自动的重建顶点缓冲。但是,由于原来的顶点缓冲已经被
释放,所以重建的顶点缓冲中已经没有了数据,也就无法将原来的内容重新绘制出来。
在重建顶点缓冲并准备好填充数据时,会自动触发顶点缓冲的 Created 事件,所以可以利用这个事件,让其重
建缓冲时自动调用 OnVertexBufferCreate 重建顶点数据。这样就能看到连续的图像了。
(7) 直接添加代码:
Private Sub OnVertexBufferCreate(ByVal sender As Object, ByVal e As EventArgs)
'锁定顶点缓冲-->定义顶点-->解除锁定。
Dim buffer As VertexBuffer = CType(sender, VertexBuffer)
Dim verts As CustomVertex.PositionColored() = CType(buffer.Lock(0, 0), CustomVertex.PositionColored())
verts(0).Position = New Vector3(0.0F, 1.0F, 1.0F)
verts(0).Color = Color.BlueViolet.ToArgb()
verts(1).Position = New Vector3(-1.0F, -1.0F, 1.0F)
verts(1).Color = Color.GreenYellow.ToArgb()
verts(2).Position = New Vector3(1.0F, -1.0F, 1.0F)
verts(2).Color = Color.Red.ToArgb()
buffer.Unlock()
End Sub
在这个事件中,首先通过 VertexBuffer 对象的 Lock 方法锁定顶点缓冲,然后在顶点缓冲中构造一个三角形,
三角形的三个顶点分别定义了不同的颜色,构造完成后再调用 Unlock 方法解除顶点缓冲。
每次顶点缓冲需要重新构造其数据时,系统都会自动触发这个事件。
(8) 添加设置矩阵参数的代码:
Private Sub SetupCamera()
'--------设置世界矩阵
Dim world As New Vector3(angle, angle / 2.0F, angle / 4.0F)
device.Transform.World = Matrix.RotationAxis(world, angle)
If enableRotator Then
angle += incrementAngle / (Math.PI)
End If
'--------设置投影矩阵
'纵横比
Dim aspectRatio As Single = 1
'只能显示nearPlane到farPlane之间的场景
Dim nearPlane As Single = 1
Dim farPlane As Single = 100
'视界
Dim fieldOfView As Single = Math.PI / 4.0F
device.Transform.Projection = Matrix.PerspectiveFovLH(fieldOfView, aspectRatio, nearPlane, farPlane)
'--------设置视图矩阵
Dim cameraPosition As New Vector3(0, 0, -5)
Dim cameraTarget As New Vector3(0, 0, 0)
Dim upDirection As New Vector3(0, 1, 0)
device.Transform.View = Matrix.LookAtLH(cameraPosition, cameraTarget, upDirection)
'--------不进行背面剔除
device.RenderState.CullMode = Cull.None
'--------不要灯光
device.RenderState.Lighting = False
End Sub
这段代码中用到了世界矩阵、投影矩阵和视图矩阵,不进行背面剔除,不使用灯光。
(9) 在窗体的 Paint 事件中添加代码:
Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
device.Clear(ClearFlags.Target, System.Drawing.Color.AliceBlue, 1.0F, 0)
SetupCamera()
'--------------场景处理
device.BeginScene()
device.VertexFormat = CustomVertex.PositionColored.Format
device.SetStreamSource(0, VertexBuffer, 0)
device.DrawPrimitives(PrimitiveType.TriangleList, 0, 1)
If showAdapterString Then
d3dfont.DrawText(Nothing, adapterInformationString, 25, 30, Color.Green)
End If
device.EndScene()
'---------------发送场景
device.Present()
'---------------强制重新调用Form1_Paint事件
If WindowState <> FormWindowState.Minimized Then
Me.Invalidate()
End If
End Sub
在介绍 GDI+时,我们已经知道很多图形图像操作都是在窗体的 Paint 事件中处理的,在三维设计中,一样
可以让所有操作都在 Paint 事件中处理。和 GDI+编程不同,三维编程不是直接在屏幕坐标上绘制,而是和录像相似,
首先要确定拍摄对象,设置好摄像机位置,选择拍摄的场景视界,然后才可以录制场景信息,此时在显示器上观察
到的内容就相当于拍摄场景时在摄像机中观察到的内容。与实际拍摄不同的是显示的场景是我们自己设计的。实际
上,在摄像机中看到的场景就是向顶点缓冲发送的内容。
在 Paint 事件中,使用 Clear 方法清除窗口的所有内容,并将其填充为实心的颜色。该方法的第一个参数指定
了要填充的对象,第二个参数是要填充的颜色。
例子中使用了 DrawPrimitives 方法绘制场景,DrawPrimitives 方法有三个参数,第一个参数是要绘制的基本
图形的类型,以便知道每个基本图形需要几个顶点,例子中指定绘制的类型为三角形列,这样它就知道每个三角形
需要三个顶点来绘制;第二个参数是从哪个顶点开始绘制,这个例子指定从第一个顶点开始(索引号为 0);第三个
参数是要绘制的基本图形的数量,由于本例中只画一个三角形,所以设为 1。
设置场景后,必须使用 Present 方法更新显示。
调用 EndSence 方法的目的是通知 Direct3D 不再绘图了。每次调用 BeginSence 之后,在结束绘图前都必须调
用这个方法。
这个事件的最后一句调用了 Invalidate 方法,这是三角形旋转后更新显示的关键。每个场景发送后,通过
Invalidate 方法使其不停地触发 Paint 事件,从而可以周而复始的重绘窗体。再利用不断变换角度,完成连续旋转
的目的。
还有一个关键的地方,在默认模式下,Invalidate 方法只会重新绘制代码中指定的部分,例子中使用的是 this,
即告诉系统只需要重新绘制当前窗体部分就行了。为了提高绘制效率,它不会重新处理其他的绘制过程。因此在默
认模式下,看到的效果是闪烁的、不连续的。为了解决这个问题,必须修改默认模式,即在 Form1 的 Load 事件中
添加:
Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.Opaque, True)
这样就得到希望的效果了。
(10) 添加窗体的 KeyDown 事件代码:
Private Sub Form1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
Select Case (e.KeyCode)
Case Keys.Escape
Me.Close()
Case Keys.F1
showAdapterString = Not showAdapterString
Case Keys.F2
enableRotator = Not enableRotator
Case Keys.Up
If enableRotator Then
incrementAngle += 0.01F
End If
Case Keys.Down
If enableRotator And incrementAngle > 0.02F Then
incrementAngle -= 0.01F
End If
End Select
End Sub
(11) 按<F5>键编译并运行,一个漂亮的不停旋转的三角形就展现出来了。运行效果如图 7-1 所示。鼠标拖动
右下角改变一下窗体的大小,观察三角形有什么变化。
观察运行的程序界面,可以看到显示器颜色位数显示的是一个字符串,字符串的字母和数字交替出现。字母表
示了数据的类型,数字表示这种类型的数据所占的位数。常见字母有:
A―alpha、B―blue、X―unused、L―luminance、R―red、P―palette、G―green
每种类型所占的位数加起来,就是这种格式的总大小。比如 X8R8G8B8,就是 32 位的格式,红、绿、蓝各占 8
位,还有 8 位没有使用。
我们可能已经从这个例子中感觉到了,三维设计涉及到的新概念比较多,学习 3D 技术的关键是要先搞清楚这
些常用的概念及其用法,否则的话,就很难看懂代码,或者说很难入门,自然也就不知道编写 3D 程序时应该如何
下手了。
2 DirectX 基础知识
从例 7-1 中可以看出,理解三维设计中涉及的概念是非常重要的。如果对这些概念似懂非懂,即使花费再多的
时间,也很难真正掌握实际的设计方法,进一步提高编写三维程序的能力也就成了一句空话。
本节从数学和 Direct3D 相结合的角度,介绍需要掌握的基本知识。
2.1 左手坐标系与右手坐标系
3D 系统中的每一个点都由 x,y,z 三个值组成。一般情况下,x 轴的正方向向右,y 轴的正方向向上。然后根
据 z 轴的正方向划分为两种坐标系,如果 z 轴正方向为远离观察者而去的方向,即朝着屏幕里面的方向,这种坐标
系叫左手坐标系,反之叫做右手坐标系。
Direct3D 默认使用左手坐标系。
在 Direct3D 中,用 Vector3 表示一个三维向量,例如:
Vector3 a As new Vector3(1, 2, 2)
图7-1 例7-1的运行效果
剩余25页未读,继续阅读
资源评论
- monkeylzx2016-05-07很好的学习三维绘图资料,感谢分享!学习了。
车万伏特
- 粉丝: 1
- 资源: 14
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功