您当前的位置:首页 > 计算机论文>软件开发论文

基于Java和VRML虚拟场景通信方式的研究

2016-03-31 17:18 来源:学术参考网 作者:未知

  引言

  VRML(VirtualRealityModelingLanguage),即虚拟现实建模语言,是HTML的3D模拟,是一种三维造型和渲染的图形描述性语言,通过创建一个虚拟场景以达到现实中的效果。VRML凭借其强大的三维功能,真正将Internet变成了一个广阔的三维空间。VRML是虚拟现实的软件实现方法之一,是建立和体验一个新世界的通信媒介。

  VRML把“虚拟世界”看作成一个“场景”,而场景中的一切都看作“对象”(也就是“节点”),它使用场景图数据结构来建立3D实境。VRML的一个显著的优点就是交互性,可以实现互动的场景。虚拟世界中动画节点具有广泛性和多样性,可以将虚拟世界各个部分的传感器和内插器串起来,从而使三维造型运动起来。但对于一些复杂的动画动作,由VRML提供的内插器和感应器,显得比较局限,在这个时候,将VRML和java有效的结合在一起将增强VRML的动画效果、交互能力,本文就VRML中使用java的两种方式进行讨论和比较,并应用java的浏览器类实现了用VRML构建的校园导游图(3D)中的小地图(2D),并且实现了两者之间的相互控制。

  1Java程序和VRML场景的通信

  前面己经提过,VRML场景和用户的交互性的实现需要两个基本因素:行为和执行模式。行为描述了将要发生的事件,而执行模式则实现来回传送场景实体的方法,行为通过执行模式改变场景中的VRML对象的状态。在VRML场景中有两种行为决定事件的产生,即静态行为和动态行为。静态行为是说场景中运动的模式是和定义的新节点相结合达到的,并没有需要使用程序,只是两个节点通过一个语句来结合,它也就决定了只有一种运动可能,这种可预制的运动形式远远不能满足用户对动画和交互性的需求。动态行为则用一段程序逻辑去决定事件的产生。在VRML中不能显示场景行为改变的逻辑,因为它没有节点支持这种逻辑,场景也就被限制在预先定义的路线上,沿预定的路线来传递先前的事件。所以控制场景事件的程序,也就只能在场景的外部。

  VRML有支持它自己的API(ApplicationProgrammingInterface),这样就提供给Java程序一个可以访问VRML浏览器的界面和可执行的环境。Java对VRML的所有支持都是通过附加的封装类实现(VRML浏览器插件的安装程序自动将这些类安装到指定目录下)。通过这些类,Java程序就能够访问VRML场景、接受和发送事件、从页面上得到VRML对象,实现对VRML场景的完全控制。VRML中使用Java有两大类方式,即通过内部Script节点和外部编程接口(EAI)。一般VRML浏览器都支持Java语言。

blob.png

  1.1通过Script节点和路由(Route)实现Java程序与VRML的通信

  Script节点是连接VRML和Java的桥梁,其中url字段是它与外部程序联系的关键,url是WWW上一个对象的完全地址,指出了外部程序所处的位置,不管是本地的或者是在网络远端的合法程序都能被使用。甚至该字段的值能直接被赋为合法的源程序。Script不仅支持java语言,还支持javascript脚本语言和vrmlscript脚本语言(javascript的一个子集)。

  Java程序之所以能够访问Script节点,是因为在Java的vrml.node包中含有一个Script类,它是一个抽象类,通过对Script类的继承,Java程序便可以与Script结点建立联系,从而达到控制VRML其它结点的目的。

  有了Script节点和Script类,VRML和java就可以通信了。首先定义Script节点中的各域域值,接着便设置路由(Route)使VRML中的其它节点与Script节点联系起来,当与Script节点有联系的节点发生事件时,事件通过路由传给Script节点的eventIn域,Script节点则通过url域中指定的地址找到java类,该类必须继承自Script类。Java类开始工作,最先执行的是initialize()方法------进行初始化工作,在initialize()方法中必须获得Script节点中eventIn或field域的值,或者把java中的值返回给Script中的eventOut域。getField、getEventIn、getEventOut都是Script类提供的方法:

  getField(”fieldName”);

  getEventIn(”eventInName”);

  getEventOut(”eventOutName”);

  作为参数的fieldName、eventInName、eventOutName要与Script节点中定义的名称相符合,对应的Field类的子类也要与Script节点中定义的各种Type类型一致。Field类的子类存在于vrml.filed包中,它提供getValue()和setValue()方法。

  初始化完成后,通过Script类提供的processEven(Eventp0)或processEvents(intp0,Event[]p1)方法来捕获Script节点传递的事件。processEvent和processEvents方法是所有外部事件公共的输入点。Java程序通过替代这两个方法对事件做出相应的处理。Vrml包中Event类的getName()方法返回事件名称(该名称与Script节点中发生该事件的eventInName相同),确定发生的事件,从而做出相应的处理;Event类的getValue()方法则返回一个ConstField类的实例(它是Script节点中发生该事件的eventIn域),ConstField类是Field类的子类,它没有setValue()方法,因而只能取出Script节点中eventIn域的值,而不能修改。

  所有事件处理完后,程序就调用Script类中的eventsProcessed()方法,在这儿可以加入用户想要实现的动画、交互等各种效果。

  离开虚拟世界的时候同样可以实现各种动画效果。删除Script节点或者整个VRML世界消失的时候(打开了其它页面),通过替代Script类中的shutdown()方法实现离开VRML世界的方式。

  进一步通过Script节点,能java程序处理过的数据返回给VRML世界。通过初始化时getEventOut()得到的变量的setValue()方法将值传递给Script节点的eventOut±或,再通过路由传递给VRML中的各类节点,完成整个通信过程。

  图1给出了Script节点和Java程序进行通信的图示:

  1.1.1通过Script节点和Node类直接修改VRML节点

  上面的讨论中和java程序发生联系的只有Script节点,java程序改变VRML世界中节点值,只有通过Script节点和路由,同时必须在Script节点的eventOut域设置控制点。当有大量数据需要传送时,这种给每个数据设置一个eventOut域加一个路由的方法显然是相当麻烦的。因此就改进出用java程序直接修改节点的方法。

  Java程序直接修改场景中的节点,仍然要用到Script节点。首先在定义Script节点时,将eventOut域改为field域,fieldType定义为SFNode,具体格式如下:

  fieldSFNodefieldnameUSEnodeNamenodeName为所要修改的节点名称(在VRML中由DEF语句命名),产生一个指向名为nodeName节点的指针。执行初始化时通过getField()方法得到相应的SFNode类的一个实例,通过getValue()方法得到该类的值,这里它的值恰好是名称为nodeName的Node类的实例,然后通过Node类提供的方法直接修改节点。Node类存在于vrml.node包中,包含getExposedField(Stringp0)、getEventIn(Stringp0)方法,分别得到节点的field和eventIn域,并把结果作为Field类;再通过各Field类的子类提供的方法读取和设置值,将设置结果直接返回节点,不用再设置路由,从而达到了直接修改节点的目的。Node类还提供了getEventOut(Stringp0)方法,用它可以得到节点的eventOut域,与前两个方法不同,它得到的结果是一个不能修改的Field类,即Field类的子类ConstField类。

  使用改进后的方法,可以有效的缩减代码长度,节省VRML世界的计算时间,提高VRML场景的生成速度。1.1.2通过Script节点和Browser类直接创建VRML场景

  虽然有了上面改进的方法,但是上述方法一般只能修改节点的各个域的值,尽管通过设置Group节点的addChindren和removeChindren的值来添加和删除具体节点,但是使用起来相当不便,并且无法操作路由。当有大量不同的并相互关联的节点要通过java程序在VRML中创建时,工作量是难以想象的。为了满足这一要求,必须作进一步的改进。

  Script类继承自BaseNode类,而BaseNode类中定义了两个方法:getBrowser()和getType()。getBrowser()方法将会返回BaseNode类所处的浏览器。Browser类存在于vrml包中,它提供了一系列方法来对整个VRML世界进行控制。

  通过addRoute(SFNodefromNode,SFStringfromEventOut,SFNodetoNode,SFStringtoEventIn)方法和deleteRoute(SFNodefromNode,SFStringfromEventOut,SFNodetoNode,SFStringtoEventIn)方法可以添加和删除路由。

  createVrmlFromString(SFStringvrmlSyntax)直接仓键整个世界,把要创建的节点语法以字符串的方式作为参数写入,在VRML世界中建立相应节点;createVrmlFromURL(MFStringurl,SFNodenode,SFStringevent)方法能达到同样效果,所不同的是该方法的提供节点语法的参数是放在url地址所指出的VRML文件中,浏览器通过url找到要加入的节点,把它加入到node参数指定的节点中event参数指定的eventIn域中。而且,用replaceWorld(MFNodenodes)方法可以用指定的节点来替换整个VRML世界;而用loadURL(MFStringurl,MFStringparameter)方法则可以实现用ml指定的另一个VRML世界来替换当前的世界。

  Script类执行initialize()方法时,得到浏览器实例,然后processEvent(Evente)方法执行时使用上述方法建立、修改VRML场景。

  通过改进,不仅VRML语言的代码长度缩减,java程序代码也大大减少,进一步提高了VRML场景的生成速度。

  1.2通过外部编程接口(EAI)来直接操控VRML世界

  上面所讨论的,都离不开Script节点和Script类。正因为如此,所有为了实现通信功能编写的java类都必须继承自Script类。由于java不支持多继承,所以继承了Script类后的java程序类就不能再继承其它类了。如果通过编写一个小应用程序(Applet)来操控VRML场景,使用的java程序类便要继承自Applet类了,这时用上述通过Script类的方法相当复杂。特别是要把VRML世界与Applet集成在同一个HTML页面时,用Script类来实现颇为困难,而且程序代码冗长、可扩展性差。

  VRML97标准提供的外部编程接口(ExternalAuthoringInterface)实现了java小应用程序类与VRML场景的通信。EAI定义了外部环境怎样通过VRML现存的事件驱动模式来访问VRML内部的节点的一系列方法。

  Java程序主要使用Browser和Node两个类,以及其它一些如处理eventIn域和eventOut域的各个属性类(EventIn*、EventOut*)和处理例外的各种*Exception类完成对EAI的描述。这里的Browser类与上面方法一所说的Browser是不同的,此处Browser类被封装在vrml.external包中,它包含有方法一中Browser类的大部分方法,用这些方法通过EAI实现方法一中的各项功能。

  不仅如此,此处Browser类还提供了如下三个方法:getBrowser(AppletpApplet)、getBrowser(AppletpApplet,StringframeName,intindex)和getNode(Stringname)方法。前两个方法是静态方法,直接在Applet类中使用这两个方法得到Applet类和VRML世界所在的浏览器类的实例。getNode()方法可以直接得到VRML世界的具体节点(Node类)的实例,用InLine语句嵌入在VRML世界中的各个节点用getNode()方法是无法得到的。这里的Node类与方法一的Node类是完全不同的,它用自己的getEventIn()和getEventOut()方法来得到VRML节点的各个域(注:这里没有getexposedField()方法,是因为VRML节点中的exposedField域有隐含的set_fieldname和fieldname_changed事件来控制field域的具体值,其中set_fieldname正是eventIn事件,而fieldname_changed正是eventOut事件),然后使用返回的Event*的实例的getValue()和setValue()方法来控制具体的值。EventIn*类仅提供了设置值的setValue()方法;EventOut*类相对复杂,不仅提供了getValue()方法来获得当前值,还提供了监听EventOut域的接口-----EventOutObserver,随时监听VRML节点中是否有新的EventOut事件发生,一旦有新事件发生,通过替代该接口提供的callback(EventOutvalue,doubletimeStamp,Objectdata)方法响应事件。

  正因为有了vrml.external包提供的Browser和Node类,完全可以抛弃Script节点和Script类甚至路由而对VRML

  世界的各种节点即Node类的各个实例直接操控。但此方法也有它的局限性,因为getBrowser()方法的参数必须是Applet的实例,因而该方法只能通过java小应用程序来控制VRML世界。

  2应用实例

  用EAI实现在同一HTML页面中三维虚拟世界的浏览(由VRML语言实现)和二维平面图的显示(由Applet实现),其中二维平面图实时显示浏览者在三维世界中所处的位置。当VRML虚拟场景中引入Java的控制之后,VRML原本存在的一些不足就能得到巨大的改进,人们一直所追求的交互性的三维场景将不再难以实现。以下给出了部分简单易于理解的Java代码和用这段代码即可实现的效果图(图2所示):

blob.png

  

/********Applet程序App.java********/

publicclassAppextendsAppletimplementsRunnable{privateBrowserbrowser;

  Nodepro;

  EventOutSFVec3fpos;floatpp[]=newfloat[3];

  Intppp[]=newint[3];

  Imageimage;

  Threadt;publicvoidinit()

  {image=getImage(getDocumentBase(),Mmap.jpgM);browser=Browser.getBrowser(this);pro=browser.getNode("new_pos");

  pos=(EventOutSFVec3f)pro.getEventOut(Mposition_changedM);

  }

  publicvoidpaint(Graphicsg)

  {g.drawImage(image,1,0,160,330,this);g.setColor(Color.red);pp=pos.getValue();ppp[0]=(int)pp[0]+79;ppp[2]=(int)pp[2]+300;g.fillArc(ppp[0],ppp[2],4,4,0,360);

  }

  publicvoidstart()

  {t=newThread(this);t.start();

  }

  publicvoidrun()

  {while(true)

  {try{Thread.currentThread().sleep(1000);}catch(InterruptedExceptione){}repaint();

  }

  }

  }

  上面只是对用java控制VRML场景增强VRML世界中交互性在构造校园导游图中的一个初步运用,运用这两者之间的交互编程,最终实现的校园导游图具备了以下功能:

  1)让游览者找到自己在虚拟校园中所处的位置。由于在整个游览过程中,四周的场景都是三维建筑物,小地图指示用户所处的平面位置。

  2)在小地图上能直观的实现视点切换的功能。在小地图上标明了学校各地点的名称,直接点击就可以瞬间在虚拟世界里到达该地点。

  3)在小地图上有路标向导功能。即当你在虚拟校园里走动时,恰好触碰到一定的场景。这时在小地图上会有文字提示:要么是各类建筑物的说明,要么是学校的简介,抑或是向你推荐一条可行的游览道路,也有可能是阻止你进入没开发的和正在施工的区域。

  4)小地图的放缩功能。在小地图上你可以实现对局部选定区域或整个区域的放大和缩小。这使得你即能注意细节,又能总领全局。

  5)建筑物上锚点的设置时用户可以在虚拟现实世界和传统的二维网页之间进行切换,满足用户浏览网页的不同需求。

  在实现用户计算机和服务器时,我们采用client/server的方式,客户端为用户提供一个易于操作和控制的界面,让用户在浏览校园的时候能发表自己的观点:在校园的Billboard栏里提出对实事、教学的观点;让用户选择喜欢的建筑结构和图片来完成虚拟校园的开发,搭建出完美的校园构造后提交给服务器。服务器端程序主要有两部分:网络部分负责处理来自客户端的请求,包括保存用户的登录名和密码、实现和客户端的通讯,上传和下载相关文件,修改和保存数据库和新文件。数据库部分负责查询用户信息,通过JDBC和用户数据库连接,验证用户身份,确保安全。图3说明了系统各部分调用关系:

blob.png

  

JAI(JavaAuthenticInterface)是一种基于语言的外部访问接口EAI,它为和VRML文件集成在一起的JavaScrpit和Java类提供了访问VRML场景的接口。当用户浏览校园导游图时有一种身临其境的真实感。随着网络技术和硬件设备的急速发展,在人们对网络图像的追求不再是死板简单的一张画,用户更希望在网络上能看到一个完美独立的虚拟世界。我们用VRML和Java相结合开发出来的校园导游图系统正是这样一个具有完美3D效果、互动性和多媒体性的虚拟世界。

  3两种通信方式的比较

  上述两种方法都能实现java语言与VRML世界的通信,但是使用的条件和效果是不同的。一般来讲方法二是针对java的Applet的,而方法一用途就比较广泛,几乎没有什么限制。现将这两个方法做个具体的比较,见表1:

blob.png

  4结论

  图4总结了VRML程序和Java,以及其它程序之间进行交互性控制的示意。

blob.png

  本文讨论了VRML世界与java语言的两个方法,大大改善了VRML虚拟世界的真实性和交互性。有了java程序的介入,就能在VRML世界中生成复杂的动画,多种逻辑(分支和循环等)的场景变化,还能使得虚拟世界响应键盘、鼠标、窗口等各类java语言支持的事件。所以要建设一个好的虚拟环境实现VRML世界与java程序间的,必不可少的。

 


相关文章
学术参考网 · 手机版
https://m.lw881.com/
首页