
用这一句试下吧:
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
不过我也不敢肯定,因为NEHE的源码我用这几句话都没消掉锯齿
最近在研究ES,可以加下QQ一起讨论下,因为很多东西我也不懂
一、实验题目
五子棋游戏。
二、问题分析
五子棋是双人博弈棋类益智游戏,由围棋演变而来,属纯策略型。棋盘通常15*15,即15行,15列,共225个交叉点,即棋子落点;棋子由黑白两色组成,黑棋123颗,白棋122颗。游戏规则为黑先白后,谁先五子连成一条直线谁赢,其中直线可以是横的、纵的、45度、135度。
本次Java编程我的目的是现实人机对战,即游戏者一方是人,另一方计算机。这就要求程序不仅要具备五子棋的基本界面,还要编程指导计算机与人进行对弈。为了使程序尽可能智能,我采用了贪心策略、传统搜索算法、极大极小博弈树算法,对应游戏玩家的3个等级:简单、中等、困难。
三、功能设计
我的程序基本功能是实现人机对弈五子棋。人和电脑交替下棋,谁先五子连成一条直线谁就赢。下面是我程序的功能模块:
1.等级设置
核心功能是实现不同策略与算法的对比运用,纯贪心策略实现简单等级对手,直接搜索算法实现中等等级对手,极大极小博弈树算法实现困难等级对手。对应程序中的3选1单选按钮。
2.悔棋功能
模拟栈机制实现人悔棋,不限步长的悔棋。对应程序中的悔棋按钮。
3.棋面绘制
根据不同机计算机的屏幕分辨率,绘制逼真的棋盘。
4.图片引入
两张古典的人物图片,生动模拟对弈双方。人物图片旁的黑白棋钵图片显示黑白棋归属。
5.背景设置
支持用户选择背景,包括棋盘、棋盘边框、窗口边框,彰显个性。
6.音乐播放
下棋时有棋子落地的声音,一方胜利时有五子连成一片的声音。同时在设置背景时相应的改变整个对弈过程中的背景音乐。
7.时间显示
在棋盘正上方有一模拟文本框显示当前棋局用时。
8.其他小功能
支持和棋、认输、开启新游戏、退出游戏等 *** 作。
四、数据结构与算法设计
数据结构部分
1.当前棋局的存储结构
我的五子棋程序选择通常用到的15行*15列棋盘,可以开二维数组PositionFlag = new int[15][15],PositionFlag[i][j]为0表示(i,j)点尚无棋,为1表示(i,j)点是人的棋子,为2表示(i,j)点是机器的棋子。之所以选择二维数组,主要原因有两点:
1.本程序需要频繁随机访问15*15的交叉点,对应查询该点状态以及改变该点状态,随机访问是数组的特点。
2.15*15=225开二维数组的内存需求相对现在内存为2G及以上的计算机完全可以接受,且数组实现简单、 *** 作方便。
基于以上两点,尽管创建动态的顺序表—链表可能可以节省少量内存(可以只存当前有棋的点,原数组对应位置为0的点可以不存),但选择数组的优势完全在上述两点体现了出来。
2.实现悔棋 *** 作的数据结构
由于每次悔棋只需回退当前几步,后进先出原则,这正是栈这种典型数据结构的设计思想,于是我选择栈。我自己先写了用自定义数组模拟的栈,但由于是学Java语言且由于悔棋的存储空间需要随当前步数增大而增大(由于每局最多下225步,即最多要悔225步,所以自己开个225的数组完全可以避免存储空间自增长的问题且内存完全可以接受,之所以不用自定义数组而用ArrayList类主要是为了尝试Java中STL的用法),所有我最终改为用Java类库中的ArrayList类。
确定用ArrayList类实现栈机制后就必须考虑每个ArrayList单元具体存储什么。刚开始我存储的是当前的棋局,即整个局面,而每个局面对应一个二维数组,这样是很占用内存的。试想一下,在最坏情况下,225个ArrayList单元,每个单元存放一个15*15的二维数组,尽管225*15*15在Java的内存管理机制下不会爆栈,但也是极不划算的。之所以说不划算,是因为有更好的解决方案。由于每次悔棋只是在回退倒数一步,多步悔棋只需循环回退,所以可以只存储当前棋局最后一步的下法,对应一个二维点,完全可以自定义一个二维坐标类chessOneStep。
算法设计部分
Java语言是面向对象的语言。我在进行五子棋游戏编程是总共传创建了11个自定义的类。在编写程序的过程中,我有一个明显的体验就是面向对象编程就是一项有关对象设计和对象接口技术,很多关键的技术就是如何设计自定义的对象。
下面我先概括给出我的所有类的作用:
1.mainFrame类:主框架类,我应用程序的入口;
2.chessPositon类:主控类,这个类是我程序的核心类,负责控制双方的下棋,以及调用其他的类完成当前棋局的显示绘制;
3.chessPanel类:面板类,调用其他底层类完成当前棋局的显示绘制;
4.chessBoard类:棋盘绘制类,负责棋盘的绘制;
5.chessImage类:文件类,包含各种资源(背景图片、背景音乐)以及静态全局变量(public static Type);
6.chessButton类:组件类,定义各种组件,包括按钮、单选按钮、文本框等;
7.chessMusic类:音乐类,负责调用Java库类完成背景音乐、下棋音乐、取胜音乐等的播放;
8.chessPiece类:棋局类,定义棋局二维数组数据结构并完成相关 *** 作;
9.chessList类:栈类,完成悔棋等 *** 作;
10. chessOneStep类:棋子类,定义每步坐标以及下在该处获得的估价值;
11.myCompare类:排序类,完成chessOneStep类的自定义排序
详细设计
1.mainFrame类
作为我的五子棋程序的主类,mainFrame类主要实例化相关的对象,如chessbutton,chessborad等,从而完成框架的创建。更重要的是实例化chessposition,这是本程序的核心类,控制游戏双方行棋过程完成人机互动下棋,然后将MyChessPosition与鼠标响应addMouseListener()关联起来。
2.chessMusic类
一个好的游戏必须给人一种身临其境的感觉,而声音是营造这种氛围的重要因素。参照网上各游戏运行商的音乐配置,我选择相关逼真的声音。包括背景音乐、下棋棋子落到棋盘发出的声音以及一方胜出的配乐。所有这些功能的实现,依赖于自定义的chessMusic类,采用AudioInputStream配合Clip的方式完成音乐播放的软硬件工作,然后定义两个接口chessmusic(String Name)和Stop(),前者完成播放功能,后者完成关闭当前音乐功能。因为音频文件相对较大,而我的程序提供在不同背景乐之间切换的功能,所以在打开另一个音频文件之前必须关闭前一个正在播放的音频文件,防止出现溢出。
3.chessImage类
适当的动画或图片能给游戏玩家带来美的体验。所以我的五子棋程序界面在不失和谐的前提下引入了尽可能多的图片,包括对弈双方、棋钵等。图片引入的具体工作通过语句import javax.imageio.ImageIO完成。同时,由于图片要在用到它的类中被访问,为了避免频繁调用函数,我直接将图片相关联的对象定义为public static,表明是公用的、静态的。进一步引申开去,我将程序中用到的静态全局变量都定义在chessImage类中。具体如下:
public static Date begin//每局开始时间
public static Date cur//每局结束时间
public static chessOneStep LineLeft//结束端点1
public static chessOneStep LineRight//结束端点2
public static boolean IsGameOver//是否只有一方获胜
public static int ColorOfBackGround[][]= {{255, 227, 132},{0,255,127},{218,165,32}}//背景颜色
public static int ColorOfWindows[][]= {{ 60,179,113},{245,245,245},{122,122,122}}//背景颜色
public static int WitchMatch//背景搭配
public static String MusicOfBackGround//背景音乐
public static int CurrentStep//记录当前步数
public static int Rank//设置难度等级
public static boolean IsSurrender//判断是否认输
public static boolean IsTie//判断是否认输
public static String Message//输出提示信息
public static Image IconImage// 图标
public static Image blackBoard//白棋盘
public static Image whiteBoard//黑棋盘
public static Image blackChess// 白棋棋子图片
public static Image whiteChess// 白棋棋子图片
public static Image RightPlayer//白棋棋罐图片
public static Image LeftPlayer//白棋玩家头像图片
public static String path = "src/"// 图片的保存路径
4.chessButton类
这个是程序的组件类。定义了各种功能键,完善程序功能,营造逼真的人机对战游戏效果。分为3类:效果。。
(1)、按钮组件
本程序有5个按钮,支持和棋、认输、新游戏、退出、悔棋等。认输和和棋按钮终止当前的棋局,给出相应的提示信息;退出按钮调用系统System.exit(0)的函数正常返回;悔棋按钮调用后面要介绍的chessList类实现悔棋;新游戏按钮则刷新当前棋局准备下一轮,要将记录当前棋局的二维数组全部置0,刷新当前棋局开始时间等。
(2)、单选按钮组件
游戏界面支持设置个性化界面,包括背景颜色与背景音乐,跟重要的一点是设置难度(简单、中等、困难)。单选按钮只能多选一。背景颜色主要是存储相关颜色搭配方案的RGB颜色,开2维数组,即对应RGB3原色数组的一维数组,然后通过改变WitchMatch全局变量的值来有用户自己选择颜色搭配,不同的颜色搭配对应不同的背景音乐表达一致的主题。难度设置主要是改变计算机的下棋算法,不同难度通过Rank判断进入不同的程序分支,实现不同智能等级的计算机下棋水平。
(3)、文本框
在不同的单选按钮前添加相应的文本框,提示用户可以实现的功能。同时我用颜色模拟出显示当前棋局耗用时间的文本框。
不论按钮还是单选按钮都要关联相应的消息,把相应功能的实现放在消息响应处理函数理。这些主要是实现Java库提供的消息响应接口里的方法。
5.chessPiece类
主要完成当前棋面的存储,存储棋面的数据结构为二维数组int[][] PositionFlag;然后定义获取、设置某点以及整个棋面的状态的方法。
(1)、SetPositionFlag(int x, int y, int flag)//设置(x,y)处的状态为flag
(2)、GetPositionFlag(int x, int y)//获取(x,y)处的状态
(3)、SetAllFlag(int [][]NewFlag)//设置当前整个棋面的状态为NewFlag
(4)、GetAllFlag()//获取当前整个棋面的状态
(5)、DrawChessPiece(Graphics g)//绘制当前局面的棋子
由于本类比较重要,所以附上了代码,见源代码1。
6.chessBoard类
功能为绘制棋盘线。由于围棋的棋盘比较复杂,横线、竖线较多,且为了使棋盘美观,还要自定义窗口边框、棋盘边框、对弈双方边框等,对线宽、线型也有一定要求。有时要单像素线条,有时要多像素线条。对于多像素线条,我主要用了2种方法。
方法一:
在需要绘制多像素线条处首先绘制一条单像素线,然后根据线宽要求上下平移适当像素达到绘制多像素的目的。这样的方法适合绘制水平线或竖直线,绘制其他斜率的线条容易造成走样。在没有想到比较好的反走样编程思想后我选择了调用Java库中已经封装好的函数。
方法二:
为了克服方法一绘制非水平或竖直线时造成的走样,同时也为了更进一步学习Java语言,我猜想肯定会有类似OpenGL中设置线宽的画刷,于是上网百度找到了相应的画刷Stroke类。通过Java库实现绘制不同线宽的直线,达到了反走样效果。
7.chessOneStep类
这个类是为了配合chessList类实现悔棋以及在计算机下棋算法实现返回有效状态点而设计的。主要数据成员为
private int x,y,weight;//其中x,y表示点坐标,weight表示将棋下到该点获得的估价值。
主要方法如下:
(1)、GetX()//获得当前对象的x坐标
(2)、GetY()//获得当前对象的y坐标
(3)、GetWeight()//获得当前对象的(x,y)处的估价值
8.chessList类
程序支持悔棋功能,为了实现悔棋,自定义了chessList类。这个类主要通过引入java.util.ArrayList和java.util.List实现集合的数据类型。然后自定义一些方法,如下:
(1)、AddStep(chessOneStep OneStep)//添加一步棋到List中
(2)、GetSize()//获得当前List的大小
(3)、ClearList()//清空List
(4)、RemoveLast()//删去List中的最后元素
由于每次删除当前List中的最后一个元素,实现后进先出,所以可以模拟栈的功能实现悔棋。
9.myCompare类
由于在计算机下棋的极大极小博弈树算法中需要对自定义对象chessOneStep按weight进行排序,所以引入了myCompare类,通过实现Comparator接口中的compare方法完成自定义对象排序。
10.chessPanel类
程序的自定义面板类,主要负责完成当前框架内容的显示。这是一个重要的与框架和图形显示密切相关的类。主要数据成员为
private chessboard MyChessBoard//当前显示棋盘
private chesspiece MyChessPiece//当前显示整个棋面的状态
主要方法如下:
(1)、chesspanel(chessboard MyChessBoard1, chesspiece MyChessPiece1)//构造函数,分别用MyChessBoard1和MyChessPiece1初始化MyChessBoard和MyChessPiece
(2)display(chessboard MyChessBoard1, chesspiece MyChessPiece1)//自定义显示回调函数,调用repaint()完成重新绘制游戏界面
(3)、paintComponent(Graphics g)//核心方法,调用各种函数完成具体的绘制工作
11.chessPositon类
程序算法核心类,总的功能是控制人和计算机轮流下棋,以及调用chessPanel类中的display(chessboard , chesspiece )方法完成界面的实时刷新。关于chessPositon类,我在此将重点介绍。chessPosition类的主要数据成员如下:
private static chessboard MyChessBoard//当前显示棋盘
public static chesspiece MyChessPiece//当前显示整个棋面的状态
private static chesspanel Mychesspanel////当前显示面板
public static chesslist MyChessList=new chesslist()//当前下棋集合,用于悔棋
final private static int INF = (1 << 30) // 表示正无穷大的常量,用于极大极小博弈数搜索算法
public static boolean CanGo//控制当前下棋一方
类的设计集中体现在成员方法的设计上。实现人机对战,只有语言是远远不够的,还要加入算法,用算法引导计算机下棋。下面介绍该类的方法成员:
(1)、chessposition(chesspanel , chessboard ,chesspiece ) //带有参数的构造函数
(2)、chessposition()
不带参数的构造函数
(3)、mouseClicked(MouseEvent event)
鼠标响应函数,负责人的下棋,根据鼠标点击的位置转换得到所在棋盘的相对位置。如果该位置不合法,即超出棋盘有效范围,点击无响应;如果该位置上已有棋,d出消息框给出提示。这二者都要求重新给出下棋位置,即当前鼠标响应无效…直到点击到棋盘有效区域。
(4)、IsOver(int[][] Array,int x,int y)
判断当前int[][]Array对应的棋局是否结束,即一方五子连成一条直线。此处有两种思路,一种对当前棋面上的所有棋子都进行一次判断,具体为水平方向、竖直方向、与水平线成45度方向、与水平线成135度方向,只要有一个方向五子连成一条直线就说明有一方获胜,游戏结束;另一种思路为只在当前下棋的4个方向进行判断,我的程序采用的是第二种,所以IsOver方法除了int[][]Array参数外,还有x,y参数,(x,y)表示当前下棋的坐标点。
(5)display()
通过调用自定义面板类的显示回调函数用于重新显示游戏界面,达到每下一步棋及时更新游戏界面的目的。
(6)、GetValue(int flag, int num)
估值函数,根据经验把棋局分成只有1颗棋相连,2颗棋相连且两端被封死,2颗棋相连且一端封死另一端活的,2颗棋相连且两端都是活的,同理3颗棋、4颗棋也各自可分3种情况。不同的情况对应不同的估价值。估价值的设定是决定计算机一方是否智能的一个关键因素。
(7)、GetPredictValue(int flag, int num)
对未连成一片但通过再下一颗子就能连成一片的局面进行估值,这在双方下棋的有限步骤内是能产生重要影响的。如果每局棋仅考虑当前一步,是不可取的。
(8)、Evaluate(int[][] Array, int x, int y)
根据棋面具体情况以及预先设定的估值函数,对某个点对应的局面进行评估。由于每次双方只能下一颗棋,所以可以每次取当前局面的所有点中对应估值最大值点的估值作为整个局面的估值。
(9)、GetGreedNext()
计算机下棋方法1,对应难度等级为简单,采用贪心思想。每次下棋前在求得最有利点下棋,而是否最有利只是通过一步评估。算法伪码描述为:
Max取负无穷大
for(行i从0到15)
{
For(列j从0到15)
{
If((i,j)对应的位置无棋)
{
a.假设放上一颗由人控制的棋,求估价值;
b.假设放上一颗由计算机控制的棋,求估价值;
c.取二者中较大值作为(i,j)处的估价值tmp;
d.取tmp与Max较大值赋值给Max.
}
}
}
最终Max对应的点就是当前整个局面中最大的估值点。至于上述为什么要考虑双方都在该点下棋的情况呢?主要原因为下五子棋是个攻防兼备的过程,不仅要考虑自己对自己最有利,还要考虑对对手最不利,通俗来讲就是在自己赢的时候不能让对手先赢。
(10)、GetSearchNext(int LookLength)
derectSearch(int [][]Array,boolean who,int deepth)
计算机下棋方法2:直接搜索法,对应难度等级为中等。
每步棋最多有225个不同下法,若采用直接搜索法则对应的孩子节点有225个(在下棋过程中会逐渐减少),即每层有最多225个节点待扩展,这就决定了直接搜索进行不超过2次—主要原因有两点:
a.采用深度优先搜索需要递归,递归中状态过多可能会爆栈,我们知道递归是用栈机制来实现的;采用宽度优先搜索又需要存储为扩展的节点,这对内存容量要求很高。
b.不管深搜还是广搜,在时间复杂度为O(N^m)的情况下都是不能接受的。其中N为当前棋局的待扩展节点,最大225m为搜索的深度。
综上所述,在采用直接搜索法时搜索深度不能太深,严格来说是应该控制在2层以内,在计算机运算速度在10^7次每秒的情况下,理论和实验都表明超过2层就会变得很慢且这种趋势成指数级增长。
直接搜索算法伪代码为
GetSearch(boolean flag,int deep)
{
如果deep等于0,返回当前棋局估值;
for(行i从0到15)
{
For(列j从0到15)
{
If((i,j)对应的位置无棋)
{
如果轮到计算机下棋,置标志位为2
GetSearch(!flag,deep-1);
如果轮到人下棋,置标志位为1;
GetSearch(!flag,deep-1);
}
}
}
}
(11)、GetMinMaxsearchNext(int LookLength)
MinMaxsearch(int [][]Array,boolean who, int deepth)
计算机下棋算法3:极大极小博弈树法,对应难度等级为困难。五子棋是个博弈游戏,当前在寻找对自己最有利的下棋点时要尽可能保证对对手最不利,这种思想可以用极大极小博弈树
(一)OpenGL
OpenGL(Open Graphics Libaray)由SGI公司为其图形工作站开发的可以独立于窗口 *** 作和硬件环境的图形开发系统。其目的是将用户从具体的硬件和 *** 作系统中解放出来。用此系统可以不去理解这些系统的结构和指令系统,只要按规定的格式书写应用程序就可以在任何支持该语言的硬件平台上执行。由于OpenGL的高度可重用性,已经有几十家大公司表示接受OpenGL作为标准软件接口,目前加入OpenGL ARB(OpenGL体系结构审查委员会)的成员有SGI公司、HP公司、MicroSoft公司、Intel公司、IBM公司、SUN公司、DEC公司、AT&T公司的Unix软件实验室等。在该组织的努力下,OpenGL已经成为高性能图形和交互式视景处理的工业标准,能够在Windows95/98、Windows NT、Windows 2K、Macos、Beos、OS/2以及Unix上应用。OpenGL的实质是作为图形硬件的软件接口,是一组三维的API函数。
1.OpenGL的主要功能
(1)建模。不但有简单的点线面还提供了复杂的三维物体(球、锥等)以及复杂的曲线曲面(Bezier、Nurbs等)绘制函数。
(2)变换。主要包括基本变换(平移、旋转等)和投影变换(平行、透视投影等)。
(3)颜色模式设置。RGBA模式、ColorIndex颜色索引。
(4)光照和材质设置。OpenGL光有辐射光、环境光、漫反射光、镜面光;材质是用光反射率来表示的。场景中物体最终反映到人眼的颜色是光的RGB分量和材质的RGB分量叠加形成的。
(5)纹理映射。主要表达物体表面的细节。
(6)位图显示和图像增强。图像功能除了基本的复制和图像像素读写外,还提供融合(Blending)、反走样(Antialiasing)、雾化(Fog)等特殊的图像处理效果。
(7)双缓冲(Double Buffering)动画。双缓冲即前台缓冲和后台缓冲。后台计算场景、产生画面,前台显示后台已经计算好的画面。
(8)交互技术。主要是提供三种工作模式:绘图模式、选择模式和反馈模式。绘图模式完成场景的绘制,可以借助物体的几何参数及运动控制参数、场景的观察参数、光照参数和材质参数、纹理参数、OpenGL函数的众多常量控制参数、时间参数等和Windows对话框、菜单、外部设备等构成实时交互的程序系统。在选择模式下,则可以对物体进行命名,选择命名的物体,控制对命名的物体的绘制。而反馈模式则给程序设计提供了程序运行的信息,这些信息也可反馈给用户,告诉用户程序的运行状况和监视程序的运行进程。
(9)其他。利用OpenGL还能实现深度暗示(Depth Cue)、运动模糊(Motion Blur)等特殊效果。
2.OpenGL的基本原理
OpenGL是一个硬件发生器的软件接口,其主要目的是将二维、三维物体绘制到一个帧缓冲里,它包括几百个图形函数。开发者主要利用这些函数来建立三维模型和进行三维实时交互。
(1)图元 *** 作和指令。OpenGL能够从多种可选择的模式画图元,而且一种模式的设置一般不会影响其他模式的设置,无论发生深墨情况,指令总是被顺序处理,也就是说,一个图元必须完全画完之后,后继图元才能影响帧存。
(2)图形控制。OpenGL提供诸如变换矩阵、光照、反走样方法、像素 *** 作等参数来控制二维和三维图形的绘制。它并不提供一个描述或建立复杂几何物体的手段。OpenGL提供的是怎样画复杂物体的机制而非描绘复杂物体本身的面面俱到的工具。即OpenGL是过程性的而非描述性的。
(3)执行模式。OpenGL命令的解释模式是客户/服务器模式的,即由客户发布命令,命令由OpenGL服务器(解释器)来处理,服务器可以运行在相同的或不同的计算机上,基于这一点,OpenGL是网络透明的。
地下水三维可视化系统开发与应用
3.OpenGL的命令语法与状态
基于OpenGL标准开发的微机应用程序必须在32位Windows平台下,如Windows98/NT环境,运行时所需的动态连接库为OpenGL32.DLL、Glu32.DLL。OpenGL包含100多个库函数,这些函数按一定的格式来命名。
(1)核心函数115个,每个函数以gl开头,这些函数是最基本的,可以运行在任何工作平台上。这些函数创建二维和三维几何形体,设置视点,建立视觉体,设置颜色及材质,建立灯光,进行纹理映射,反走样,处理融合,雾化场景等,它们可以接受不同的参数,因而可派生300多个函数。
(2)OpenGL实用库函数以glu开头,共43个。这些函数基于OpenGL核心函数,主要提供对辅助函数的支持,并且执行了核心OpenGL函数的交互,因而是比核心函数更高一层的函数,也更有通用性。可以运行在任何OpenGL工作平台上。
(3)辅助库函数,共31个。以aux开头,它们是一类特殊的OpenGL函数,是帮助初学者尽快进入OpenGL编程而做简单练习用的。因此并不能在所有平台上运行。但Windows98/NT支持它们。
(4)Windows专用库函数,以wgl开头。主要是连接OpenGL和Windows窗口系统的,用它们可以管理着色描述表及显示列表,扩展功能,管理字体位图等。
(5)Win32 API函数,共6个,用于处理像素格式及缓冲。
(6)OpenGL结构,共4个。
4.OpenGL图形 *** 作步骤
步骤1:设置像素格式:主要包括建立OpenGL绘制风格、颜色模式、颜色位数、深度位数等;
步骤2:建立模型:建立三维模型;
步骤3:舞台布景:如何把景物放置在三维空间的适当位置,设置三维透视视觉体以观察场景;
步骤4:效果处理:设置物体的材质(颜色、光学性能及纹理映射等)加入光照及光照条件;
步骤5:光栅化:把景物及其颜色信息转化为可在计算机上显示的像素信息。
(二)VRML
1.VRML简介
VRML是英文Virtual Reality Modeling Language——虚拟现实造型语言的缩写。其最初的名字叫Virtual Reality Makeup Language。名字是由第一届WWW(1994,日内瓦)大会上,由Tim Berners Lee和Dave Raggett所组织的一个名为Bird-of-a-Feather(BOF)小组提出的。后来Makeup改为Modeling。VRML和HTML是紧密相连的,是HTML在3D领域的模拟和扩展。由于VRML在Internet具有良好的模拟性和交互性,因而显示出强大的生命力。
VRML是一种3D交换格式,它定义了当今3D应用中的绝大多数常见概念,诸如变换层级、光源、视点、几何、动画、雾、材质属性和纹理映射等。VRML的基本目标是确保能够成为一种有效的3D文件交换格式。
VRML是HTML的3D模型。它把交互式三维能力带入了万维网,即VRML是一种可以发布3D网页的跨平台语言。事实上,三维提供了一种更自然的体验方式,例如游戏、工程和科学可视化、教育和建筑。诸如此类的典型项目仅靠基于网页的文本和图像是不够的,而需要增强交互性、动态效果连续感以及用户的参与探索,这正是VRML的目标。
VRML提供的技术能够把三维、二维、文本和多媒体集成为统一的整体。当把这些媒体类型和脚本描述语言(scripting language)以及因特网的功能结合在一起时,就可能产生一种全新的交互式应用。VRML在支持经典二维桌面模型的同时,把它扩展到更广阔的时空背景中。
VRML是赛博空间(cyber space)的基础。赛博空间的概念是由科幻作家William Gibson提出的。虽然VRML没有为真正的用户仿真定义必要的网络和数据库协议,但是应该看到VRML迅速发展的步伐。作为标准,它必须保持简单性和可实现性,并在此前提下鼓励前沿性的试验和扩展。
2.VRML的基本工作原理及其特性
(1)用文本信息描述三维场景。在Internet网上传输,在本地机上由VRML的浏览器解释生成三维场景,解释生成的标准规范即是VRML规范。正是基于VRML的这种工作机制,才使其可能在网络应用中有很快的发展。当初VRML的设计者们考虑的也正是文本描述的信息在网络上的传输比图形文件迅速,所以他们避开在网络上直接传输图形文件而改用传输图形文件的文本描述信息,把复杂的处理任务交给本地机从而减轻了网路的负荷。
(2)统分结合模式。VRML的访问方式基于C/S模式,其中服务器提供VRML文件,客户通过网络下载希望访问的文件,并通过本地平台的浏览器(Viewer)对该文件描述的VR世界进行访问,即VRML文件包含了VR世界的逻辑结构信息,浏览器根据这些信息实现许多VR功能。这种由服务器提供统一的描述信息,客户机各自建立VR世界的访问方式被称为统分结合模式,也是VRML的基本概念。由于浏览器是本地平台提供的,从而实现了VR的平台无关性。
(3)基于ASCII码的低带宽可行性。VRML像HTML一样,用ASCII文本格式来描述世界和链接,保证在各种平台上通用,同时也降低了数据量,从而在低带宽的网络上也可以实现。
(4)实时3D着色引擎。传统的VR中使用的实时3D着色引擎在VRML中得到了更好的体现。这一特性把VR的建模与实时访问更明确地隔离开来,也是VR不同于三维建模和动画的地方。后者预先着色,因而不能提供交互性。VRML提供了6+1个自由度,即三个方向的移动和旋转,以及和其他3D空间的超链接(Anchor)。
(5)可扩充性。VRML作为一种标准,不可能满足所有应用的需要。有的应用希望交互性更强,有的希望画面质量更高,有的希望VR世界更复杂。这些要求往往是相互制约的,同时又受到用户平台硬件性能的制约,因而VRML是可扩充的,即可以根据需要定义自己的对象及其属性,并通过Java语言等方式使浏览器可以解释这种对象及其行为。
(三)X3D
X3D(Extensible 3D——可扩展3D)是一个软件标准,定义了如何在多媒体中整合基于网络传播的交互三维内容。X3D将可以在不同的硬件设备中使用,并可用于不同的应用领域中。比如工程设计、科学可视化、多媒体再现、娱乐、教育、网页、共享虚拟世界等方面。X3D也致力于建立一个3D图形与多媒体的统一的交换格式。X3D是VRML的继承。VRML(Virtual Reality Modeling Language-虚拟现实建模语言)是原来的网络3D图形的ISO标准(ISO/IEC 14772)。X3D相对VRML有了改进,提供了以下的新特性:更先进的应用程序界面,新添的数据编码格式,严格的一致性,组件化结构(用来允许模块化的支持标准的各部分)。
1.X3D设计目标
X3D确立了以下的设计目标:
(1)分离数据编码和运行时间结构;
(2)支持大量的数据编码格式,包括XML(Extensible Markup Language);
(3)增加新的绘图对象、行为对象、交互对象;
(4)给3D场景提供可选的应用程序界面(APIs);
(5)定义规格的子集“概貌(Profiles)”以适合不同的市场需要;
(6)允许在不同层次(1evels)的服务上都能实现X3D规格;
(7)尽可能添加完善规格中行为的定义或描述。
2.X3D特性
为了满足工程设计、科学可视化、多媒体再现、娱乐、教育、网页、共享虚拟世界等方面使用的需要,X3D添加了以下的新特性:
(1)3D图形:多边形化几何体、参数化几何体、变换层级、光照、材质、多通道/多进程纹理帖图;
(2)2D图形:在3D变换层级中显示文本、2D矢量、平面图形;
(3)动画:计时器和插值器驱动的连续动画;人性化动画和变形;
(4)空间化的音频和视频:在场景几何体上映射视听源;
(5)用户交互:基于鼠标的选取和拖曳;键盘输入;
(6)导航:摄像机;用户在3D场景中的移动;碰撞、接近和可见性检测;
(7)用户定义对象:通过创建用户定义的数据类型,可以扩展浏览器的功能;
(8)脚本:通过程序或脚本语言,可以动态地改变场景;
(9)网络:可以用网络上的资源组成一个单一的X3D场景;可以通过超链接对象连接到其他场景或网络上的其他资源;
(10)物理模拟:人性化动画;地理化数据集;分布交互模拟(Distributed Interactive Simulation-DIS)协议整合。
(四)Java 3D
Java 3D用其自己定义的场景图和观察模式等技术构造了3D的上层结构,实现了在Java平台使用三维技术。Java 3D API是Sun定义的用于实现3D显示的接口。3D技术是底层的显示技术,Java 3D提供了基于Java的上层接口。Java 3D把OpenGL和DirectX这些底层技术包装在Java接口中。这种全新的设计使3D技术变得不再繁琐并且可以加入到J2SE、J2EE的整套架构,这些特性保证了Java 3D技术强大的扩展性。Java 3D建立在Java2(Java1.2)基础之上,Java语言的简单性使Java 3D的推广有了可能。Java 3D是在OpenGL的基础上发展起来的,可以说是Java语言在三维图形领域的扩展,其实质是一组API即应用程序接口。利用Java 3D所提供的API就可以编写出一些诸如三维动画、远程三维教学软件、三维辅助设计分析和模拟软件,以及三维游戏等。它实现了以下三维功能:
(1)生成简单或复杂的形体(也可以调用现有的三维形体);
(2)使形体具有颜色、透明效果、贴图;
(3)在三维环境中生成灯光、移动灯光;
(4)具有行为的处理判断能力(键盘、鼠标、定时等);
(5)生成雾、背景、声音;
(6)使形体变形、移动、生成三维动画;
(7)编写非常复杂的应用程序,用于各种领域如VR(虚拟现实)。
1.Java 3D的数据结构
Java 3D的数据结构和OpenGL的数据结构一样,采用的是场景图的数据结构,但Java 3D根据Java语言的特点。Java 3D的场景图是DAG(Directed-acyclic Graph),其特点是具有方向的不对称性。Java 3D的场景图由Java 3D的运行环境直接转变成具有三维显示效果的显示内存数据,从而在计算机上显示出三维效果,显示内存中不断接收Java 3D的运行最新结果,从而产生三维动画。
2.、Java 3D(API)中的类
Java 3D是根据OpenGL的三维图形库及VRML的基础上开发出来的一个API,里面包含了几乎所有编写Java交互式三维应用程序所需的最基本的类(类方法)、接口。主要存放在程序包Javax.media.j3d中,这些是Java 3D的核心类。另外,还有提供一个有助于快速编程的应用类型的包(Utility包)com.sun.j3d.utils(可或缺,主要是能大大地提高程序的编写效率)。除了核心类和Utility包之外,还有:
(1)Java.awt(主要是定义一个显示用的窗口);
(2)Javax.vecmath(主要是处理定义的矢量计算所用的类,今后核心类);
(3)Java 3D的类根据作用可分为Node、NodeComponent,其中Node又分为Group及Leaf两个子类。
(五)IDL
1.IDL简介
IDL(Interactive Data Language)是美国RSI公司(Research System Inc)的产品,它集可视、交互分析、大型商业开发为一体,为用户提供了完善、灵活、有效的开发环境。IDL的主要特性包括:
(1)高级图像处理、交互式二维和三维图形技术、面向对象的编程方式、OpenGL图形加速、跨平台图形用户界面工具包、可连接ODBC兼容数据库及多种程序连接工具等。
(2)IDL是完全面向矩阵的,因此具有处理较大规模数据的能力。IDL可以读取或输出有格式或无格式的数据类型,支持通用文本及图像数据,并且支持在NASA,TPT,NOAA等机构中大量使用的HDF,CDF及netCDF等科学数据格式及医学扫描设备的标准格式DICOM格式。IDL还支持字符、字节、16位整型、长整型、浮点、双精度、复数等多种数据类型。能够处理大于2Gb的数据文件。IDL采用OpenGL技术,支持OpenGL软件或硬件加速,可加速交互式的2D及3D数据分析、图像处理及可视化。可以实现曲面的旋转和飞行;用多光源进行阴影或照明处理;可观察体(Volume)内部复杂的细节;一旦创建对象后,可从各个不同的视角对对象进行可视分析。
(3)IDL具有图像处理软件包,例如感兴趣区(ROI)分析及一整套图像分析工具、地图投影及转换软件包,宜于GIS的开发。
(4)IDL带有数学分析和统计软件包,提供科学计算模型。可进行曲线和曲面拟合分析、多维网格化和插值、线性和非线性系统等分析。
(5)用IDL DataMiner可快速访问、查询并管理与ODBC兼容的数据库,支持Oracle,Informix,Sybase,MS SQL等数据库。可以创建、删除、查询表格,执行任意的SQL命令。
(6)IDL可以通过ActiveX控件将IDL应用开发集成到与COM兼容的环境中。用Vi-sual Basic,Visual C++等访问IDL,还可以通过动态连接库方式从IDL调用C,Fortran程序或从其他语言调用IDL。
(7)用IDL GUIBuilder可以开发跨平台的用户图形界面(GUI),用户可以拖放式建立图形用户界面GUI,灵活、快速地产生应用程序的界面。
(8)IDL为用户提供了一些可视数据分析的解决方案,早在1982年NASA的火星飞越航空器的开发就使用了IDL软件。
2.IDL的编程方式
IDL有两种编程方式,一是利用IDL平台的GUIBuilder进行编程,这种方式的特点是所见即所得,使用IDL自身所具有的控件进行编程和界面设置,但使用灵活性不够;另一种是利用IDL平台的集成开发环境的组件编程技术,这种方式的特点是较为灵活,而且功能较强,可以随着编程者的意愿进行设置。另外在IDL中有批处理文件语句,即在命令行中直接输入命令语句来进行数据的读入和输出,以及进行属性设置和处理。此外,IDL提供IDLDRAW WIDGET控件,可进行基于COM技术的开发。
3.IDL的应用领域
由于其强大的功能和独特的特点,IDL语言可以应用地球科学(包括气象、水文、海洋、土壤、地质、地下水等)、医学影像、图像处理、GIS系统、软件开发、大学教学、实验室、测试技术、天文、航空航天、信号处理、防御工程、数学统计及分析、环境工程等很多领域,IDL语言都可以得到广泛的应用。目前应用IDL语言,已经开发出了ENVI,IMAGIS,RiverTools,医学等成熟产品。具体的应用实例也非常多,如在2000年澳大利亚悉尼奥运会综合预报系统、美国国家环境卫星数据和信息服务中心的厄尔尼诺现象分析等工作中得到了成功的应用。
北京市勘察设计研究院应用IDL语言,已开发了真三维地质分析系统AutoDig,能够直接对简单的地质数据,或其他带层次性的数据实现科学的、完整的三维建模;同时也提供真三维显示功能,不仅能对三维体实现任意的旋转、放大、缩小,而且也能实现交互式的真三维切割功能。
(六)小结
三维图形技术是随着计算机软硬件技术的发展而发展变化的,其鼻祖是SGI公司推出的OpenGL三维图形库。OpenGL是业界最为流行也是支持最广泛的一个底层3D技术,几乎所有的显卡厂商都在底层实现了对OpenGL的支持和优化。OpenGL同时也定义了一系列接口用于编程实现三维应用程序,但是这些接口使用C(C++)语言实现并且很复杂。掌握针对OpenGL的编程技术需要花费大量时间精力。
Java 3D是在OpenGL的基础上发展起来的,可以说是Java语言在三维图形领域的扩展,其实质是一组API即应用程序接口。
Direct3D是Microsoft公司推出的三维图形编程API,它主要应用于三维游戏的编程。众多优秀的三维游戏都是由这个接口实现的。与OpenGL一样,Direct3D的实现主要使用C++语言。
VRML2.0(VRML97)自1997年12月正式成为国际标准之后,在网络上得到了广泛的应用,这是一种比BASIC,JAVASCRIPT等还要简单的语言。现已发展为X3D。脚本化的语句可以编写三维动画片、三维游戏、计算机三维辅助教学。它最大的优势在于可以嵌在网页中显示。
美国RSI公司(Research System Inc)研制和开发的最新可视软件IDL(Interactive Data Language)交互式数据语言,是进行数据分析、可视化和跨平台应用开发的较佳选择,它集可视、交互分析、大型商业开发为一体,为用户提供了完善、灵活、有效的开发环境。三维技术的比较见表1-2。
表1-2 三维技术对比
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)