VRML的基础教程分析.docx
- 文档编号:7980809
- 上传时间:2023-01-27
- 格式:DOCX
- 页数:28
- 大小:29.06KB
VRML的基础教程分析.docx
《VRML的基础教程分析.docx》由会员分享,可在线阅读,更多相关《VRML的基础教程分析.docx(28页珍藏版)》请在冰豆网上搜索。
VRML的基础教程分析
VRML的基础教程 [转]
VRML创作工具很多是“所见即所得”式的,通过图形界面可以方便地创作虚拟境界,但VRML不仅仅是普通的三维设计,尽管这些工具很容易上手,却往往屏蔽掉了VRML标准的具体细节,因为如果想深入掌握VRML,还需要全面了解节点、域、检测器等技术细节,而达成此目的的最好方法就是用编写文本文件的方式创作VRML境界。
本教程提供了六个典型例子,这些例子并不复杂,也不精彩,但涵盖了VRML的关键内容。
在开始创作之前,应作好下面的准备。
文本编辑器随便你喜欢的文本编辑器,如Notepad,Vpad,Cosmo World等等,当然有可视化的编辑器如3ds则更好。
VRML浏览器强烈推荐BS Contact6.2,可以到www.Bitmanagement.de上下载
硬件VRML和硬件平台无关,只要能提供VRML浏览器。
在下面的教程中,我们假定硬件平台是微机,输出设备是图形窗口,输入设备为鼠标器和键盘。
当然,如果有更先进的虚拟现实设备和支持它的VRML浏览软件效果会更好。
对于我们将要创作的境界,微机就足够了。
第一节"Hello,World!
"
按照惯例,我们以"Hello,World!
"作为我们的第一个虚拟境界,它由立方体、圆锥和球体组成,你可能已经注意到,VRML的标志正是由这三个几何形状构成的。
输入的第一行文字是:
#VRMLV2.0utf8
这是VRML文件的标志,所有2.0版本的VRML文件都以这行文字打头,VRML97是由VRML2.0版修订而成的,符合VRML97规范的VRML文件也以这行文字打头。
其中“#”表示这是一个注释。
而utf8表示此文件采用的是utf8编码方案,这在标准中有详细说明。
先加入一个Group节点(组节点):
Group{
组节点的花括号之内的所有内容视为一个整体,利用组节点可以把虚拟场景组织成条理清晰的树形分支结构。
下面定义组节点的children域(孩子域):
children[
在children后的方括号内定义Group节点的所有孩子对象,第一个孩子是一个Shape节点(形态节点),它描述一个几何形状及其颜色等特征:
Shape{
在Shape节点内定义一个几何体Box(方盒节点):
geometryBox{}
注意我们没有为Box定义任何域,这意味着它的尺寸和坐标位置等特性取缺省值(单位立方体)。
随后补齐各右括号:
}
]
}
至此,我们已经成功地制作了第一个虚拟境界,把它保存为HelloWorld.wrl,下面是完整的文件:
#VRMLV2.0utf8
Group{
children[
Shape{
geometryBox{}
}
]
}
用浏览器打开这个文件,你会看到一个灰色的立方体,尽管不太好看,但你还是可以通过改变视点位置从不同方位观察它,初步体验“三维交互”的感觉。
下面定义立方体的外观,这只需改变Shape节点的appearance域(外观),appearance域是一个Appearance节点,此Appearance节点的material域(材质)定义为一个Material节点:
appearanceAppearance{
materialMaterial{}
}
这样,上面的Shape节点变成了:
Shape{
appearanceAppearance{
materialMaterial{}
}
geometryBox{}
}
这是定义几何造型的基本格式。
现在立方体还是灰色的,这是因为其中的Material节点采用的还是缺省值,下面修改它的diffuseColor域(漫射色),VRML的颜色说明采用的是RGB颜色模型,所以要定义红色的立方体,漫射色应该是{100},三个数字依次表示红色、绿色和蓝色,取值范围都是0到1:
materialMaterial{diffuseColor100}
现在我们生成了第二个场景,完整的代码是:
#VRMLV2.0utf8
Group{
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor100}
}
geometryBox{}
}
]
}
在这个场景中,红色的立方体位于屏幕的中心,它的中心坐标为{000}。
若想把它移动一个位置,可以通过为它外套一个Transform(变换节点)来实现:
Transform{
translation500
children[
Shape{
appearanceAppearance{
materialMaterial{}
}
geometryBox{}
}
]
}
在VRML中,Transform节点除了可以引进平移、旋转和缩放变换以外,其作用和Group节点的作用一样。
把Transform节点的translation域(平移)设置为500,意味着Transform节点所在的坐标系相对于其上层坐标系向右平移(即x轴方向)5个单位,在其它两个方向不移动,VRML的距离单位是米,5个单位相当于5米。
我们第三个场景的完整代码是:
#VRMLV2.0utf8
Group{
children[
Transform{
translation500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor100}
}
geometryBox{}
}
]
}
]
}
接下来我们把方块所在的Transform节点复制三份,并把各自包含的几何形状依次定义为方块、球体和圆锥:
Group{
children[
Transform{
translation500
children[
Shape{....geometryBox{}}
]
}
Transform{
translation000
children[
Shape{...geometrySphere{}}
]
}
Transform{
translation-500
children[
Shape{...geometryCone{}}
]
}
]#endofGroupchildren
}
你可能已经感觉到,VRML文件中有许多括号(花括号“{}”和方括号“[]”),所以务请注意括号的配对,建议采用本教程的缩进风格。
注意上面的VRML文件中三个Transform节点的平移量是不同的,因而三个几何体的位置也就不同。
另外,还可以修改三个几何体的颜色:
球面Sphere为绿色(010),圆锥为蓝色(010)。
最后,为了以后引用方便,分别给这三个Transform节点指定一个名称:
DEFboxTransform{...}
DEFsphereTransform{...}
DEFconeTransform{...}
这个VRML场景的完整代码是:
#VRMLV2.0utf8
Group{
children[
DEFboxTranform{
translation500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor100}
}
geometryBox{}
}
]
}
DEFsphereTransform{
translation000
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor010}
}
geometrySphere{}
}
]
}
DEFconeTransform{
translation-500
children[
Shape{
appearnanceAppearance{
materialMaterial{diffuseColor001}
}
geometryCone{}
}
]
}
]#endofGroupchildren
}
把此文件保存为helloworld.wrl,用VRML浏览器打开这个文件,通过调整视点从多个方位浏览自己的作品。
小结:
在这一节,我们创建了第一个虚拟境界,涉及到如何用几何体构建境界,以及如何设定几何体的颜色与材质。
尽管这个由方块、圆锥和球体组成的场景图比较简单,但已经反映了VRML的基本功能。
当然,除了可用鼠标改变视点外,这还只是一个静态世界,在下一节,我们将引进VRML的动态特征。
第二节增加交互能力
上一节我们学习了用几何体建立虚拟境界以及为几何体赋予色彩和材质的方法,这样建立的虚拟境界是静态的。
这一节我们将使一个几何体(为了更具一般性,下面我们称之为对象)能够根据用户动作做出反应,即交互能力,这是VRML2.0最突出的特征。
1。
检测器
在VRML中,检测器(Sensor)节点是交互能力的基础。
检测器节点共九种。
在场景图中,检测器节点一般是以其它节点的子节点的身份而存在的,它的父节点称为可触发节点,触发条件和时机由检测器节点类型确定。
接触检测器(TouchSensor)是最常用的检测器之一,最典型的应用例子是开关。
其它检测器将在后续教程中陆续介绍。
这里我们定义一个开关节点lightch(这是一个组节点),并定义一个接触检测器作为它的子节点:
DEFlightchGroup{
children[
各几何造型子节点...
DEFtouchSensorTouchSensor{}
]
}
这样开关节点lightch就是一个可触发节点。
当然,检测器存在的理由是它被触发时能够引起某种变化,所以在更深入讨论开关节点之前,我们先讨论一下场景变化。
2.视点
最常见的变化是视点的变化,在我们的第一个境界中你可能已经体验到视点变化:
当你拖动鼠标或按动箭头键时(按照VRML术语,称为航行),虚拟境界就会旋转或缩放,这实际上是在调整你的视点位置或视角。
在虚拟场景的重要位置可以定义视点节点(ViewPoint),它们是境界作者给用户推荐的上佳观赏方位,在CosmoPlayer浏览器中,用户就可以通过鼠标右键选择作者推荐的各个视点。
这里我们定义两个视点节点:
DEFview1Viewpoint{
position0020
description"View1"
}
DEFview2Viewpoint{
position5020
description"view2"
}
我们的潜在目的是使用户可以通过触发开关节点来切换视点。
现在先研究一下这两个视点节点,其中的坐标表示视点在场景中的位置,坐标的单位是米,这在前面已经提到过,视点的名称将会在浏览器菜单中提示出来供用户选择。
把上述视点说明加入helloworld.wrl中(放在Group节点之前),并把其中的方块节点修改成可触发节点:
DEFboxTranform{
children[
Shape{....Box...}
DEFtouchBoxTouchSensor{}
]
}
把修改过的文件另存为“touchme.wrl”。
3。
事件传递
下面我们把触发(用鼠标箭头按动方块)和场景变化(视点切换)这两件事情联系起来,在场景图中,除节点构成的层次体系外,还有一个“事件体系”,事件体系由相互通讯的节点组成。
能够接收事件的节点都应具有事件入口(eventIn),如果它要接收多种类型的事件(称为入事件),它就应该具有多个事件入口,也就是说,事件入口象节点的域一样是有类型的。
同样,发送事件的节点应有事件出口(eventOut),事件出口也是有类型的。
例如ViewPoint节点就有一个事件入口set_bind,当向此事件送入一个值“TRUE”(即所谓的入事件)时,该viewpoint节点成为当前视点。
又如,接触检测器TouchSensor有一个事件出口isActive,当受到用户触发后它就从此出口送出一个“TRUE”(即所谓的出事件),补充一句,在下一个事件发送之前,此事件一直保存在事件出口中(作为记录)。
事件出口和事件入口通过路径相连,这就是VRML文件中除节点以外的另一基本组成部分:
ROUTE语句。
ROUTE语句把事件出口和事件入口联系在一起,从而构成事件体系。
在这里,我们是把接触检测器touchBox的事件出口isActive连接到视点节点view2的事件入口set_bind:
ROTUEtouchBox.isActiveTOview2.set_bind
好了!
现在我们得到的VRML文件是:
#VRMLV2.0utf8
DEFview1Viewpoint{
position0020
description"view1"
}
DEFview2Viewpoint{
position5020
description"view2"
}
Group{
children[
DEFboxTransform{
translation500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor100}
}
geometryBox{}
}
DEFtouchBoxTouchSensor{}
]
}
DEFsphereTransform{
translation000
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor010}
}
geometrySphere{}
}
]
}
DEFconeTransform{
translation-500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor001}
}
geometryCone{}
}
]
}
]#endofGroupchildren
}
ROUTEtouchBox.isActiveTOview2.set_bind
把这个文件调入浏览器,然后把鼠标指向方块并按下左钮(先别松开!
),可以看到视点已经变为view2,内部的机制我们已经很清楚:
左钮按下时方块节点的接触检测器被触发,接着接触检测器从事件出口isActive送出一个事件“TRUE”,这个事件通过路由进入视点节点view2的事件入口set_bind,view2收到“TRUE”后成为当前视点,所以在我们眼前场景发生了变化。
现在松开左钮,可以看到场景恢复到原来方位,这止δ艹莆拥慊靥湓蚴撬煽笈ズ蠼哟ゼ觳馄飨騰iew2发送了一个“FASLE”事件,这样view2当前的地位被解除,原来的视点成为系统视点栈的栈顶节点(即当前视点),详细说明可参见标准中对视点节点的专门论述。
如果我们不想视点回跳,就想停留在view2视点,那该怎么办呢?
这种非系统缺省功能要自己来定义。
4。
利用脚本编写自定义行为在VRML中,利用Script节点(脚本节点)定义用户自定义行为,所谓定义即用脚本描述语言(ScriptingLanguage)编写脚本的过程。
VRML97支持的脚本描述语言目前有两种:
Java和EMCAScript(这是JavaScript标准化后的名称),关于这两种语言本身,请参考相应参考书,VRML97标准中定义了它们和VRML的接口方法。
应提请注意的是:
VRML是基于节点的语言,所以脚本也是封装在Script这个特殊节点中的。
这里我们不过多讨论脚本描述语言的细节,主要讨论把脚本集成到VRML文件中的方法。
上面我们曾把接触检测器touchBox和视点view2直接通过路径连接起来,现在要定义我们指定的行为,就需要在二者之间插入一个脚本节点,也就是让路径绕个弯:
ROUTEtouchBox.isActiveTOtouchScript.touchBoxIsActive
ROUTEtouchScript.bindView2TOview2.set_bind
其中的脚本节点touchScript有一个事件人口touchBoxIsActive和一个事件出口bind_View2,前者接收来自接触检测器touchBox的事件,然后经自己的脚本处理后,把结果发送给视点节点view2:
DEFtouchScriptScript{
eventInSFBooltouchBoxIsActive
eventOutSFBoolbindView2
url"javescript:
functiontouchBoxIsActive(active){
bindView2=TRUE;
}"
}
关于这个Script节点,请注意一下几点:
(1)它的事件入口touchBoxIsActive和事件出口bindView2是自定义的,其它VRML节点的域和事件都是固定的。
(2)事件入口touchBoxIsActive(即入事件)和事件出口bindView2(即出事件)的类型都是SFBool(单值布尔型),touchBox的事件出口isActive和view2的事件入口set_bind的类型也是相同的。
(3)“url”是脚本节点的一个域,可以直接包含脚本,也可以包含一个或多个用URL地址指示的脚本,若有多个地址,则按照先后次序获取第一个可得到的脚本。
(4)脚本是以函数(function)的形式给出的,函数名touchBoxIsActive与事件入口的名称相同,这是和ECMAScript语言的接口约定,表示相应事件入口收到事件后调用此函数进行处理。
5.事件流程与小结
下面我们整理一下事件流程:
(1)用户在方块上按下鼠标左键。
(2)接触检测器发出一个“TRUE”事件。
(3)此事件进入脚本节点touchScript的事件入口touchBoxIsActive.
(4)调用脚本函数touchBoxIsActive(注意函数并没有判断入事件的值)。
(5)函数向touchScript的事件出口bindView2发送一个“TRUE”事件(还可以进行其它判断或执行其它事件)。
(6)view2节点收到“TRUE”事件,成为当前视点。
按照VRML约定,“认为”上述事件是同时发生的,也就是这些事件的时间戳相同。
(7)若用户松开鼠标左键,则接触检测器发出一个“FALSE”事件,此事件同样引起脚本函数调用并发送“TRUE”事件,所以view2仍然保持为当前视点。
本节的完整代码是:
#VRMLV2.0utf8
DEFview1Viewpoint{
position0020
description"view1"
}
DEFview2Viewpoint{
position5020
description"view2"
}
Group{
children[
DEFboxTransform{
translation500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor100}
}
geometryBox{}
}
DEFtouchBoxTouchSensor{}
]
}
DEFsphereTransform{
translation000
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor010}
}
geometrySphere{}
}
]
}
DEFconeTranform{
transltion-500
children[
Shape{
appearanceAppearance{
materialMaterial{diffuseColor001}
}
geometryCone{}
}
]
}
]#endofGroupchildren
}
DEFtouchScriptScript{
eventInSFBooltouchBoxIsActive
eventOutSFBoolbindView2
url"javascript:
functiontouchBoxIsActive(active){
bindView2=TRUE;
}"
}
ROUTEtouchBox.isActiveTOtouchScript.touchBoxIsActive
ROUTEtouchScript.bindView2TOview2.set_bind
小结:
本节建立的虚拟境界并不复杂,但涉及到了VRML2.0最⌒缘墓δ芎透拍睿豪眉觳馄鞑录⒗寐酚纱菔录约袄媒疟颈嘈醋远ㄒ逍形莆樟苏庑┠谌菀簿驼莆樟薞RML2.0的核心。
在后面的几节中,我们将探索一些专题性的有趣功能,而本节是基础,因而必须透彻理解。
第三节邻近检测器
本节讨论邻近检测器(proximitySensor),当用户进入或离开邻近检测器所划定的区域时就会触发它。
正如你在标准中可以查到的那样,ProximitySensor节点定义为:
ProximitySensor{
exposedFieldSFVec3fcenter000
exposedFieldSFVec3fsize000
exposedFieldSFBoolenabledTRUE
eventOutSFBoolisActive
eventOutSFVec3fposition_changed
eventOutSFRotationorientation_changed
eventOutSFTimeenterTime
eventOutSFTimeexitTime
}
这里稍作介绍。
ProximitySensor节点共有三个外露域(exposedField)和五个出事件(eventOut).出事件我们已经熟悉,是节点状态发生改变时用来通知其它节点的,这里的出事件isActive用于ProximitySensor通报自己已被激活。
enterTime和exitTime通报用户(代表用户的用户化身或指示器)进入和退出ProximitySensor检测区的时刻。
若用户已在检测器之内,则当用户的位置或方位发生变化时,送出position_changed和orientation_changed出事件这五个出事件联合起来,就定义了邻近检测器的功能。
外露域则集域(Field)、入事件(eventIn)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VRML 基础教程 分析