文档库 最新最全的文档下载
当前位置:文档库 › VRML中二维地图的一种制作方法

VRML中二维地图的一种制作方法

VRML中二维地图的一种制作方法
转载于https://www.wendangku.net/doc/1016565259.html,


VRML中二维地图的一种制作方法

首先我们来讲解一下二维导航地图的原理:

在VRML世界当中,世界坐标系的定义为右手系。如下图所示:

即X轴水平指向屏幕左侧,Y轴垂直向上,而Z轴则指向我们用户。



在我们所制作的场景当中,虚拟替身的行走是在X-Z平面上的。而我们现在所要制作的二维地图,是要在平行于我们的显示器平面上,也就是说X-Y平面上。

从这里可以看出,实际上二维地图的制作原理很简单,只需要把X-Z平面上的坐标值简单的变换到X-Y平面上即可。也就是说,将三维世界的Z坐标值变换为二维世界当中的Y坐标值。

当然,这里还需要两个参数来对这个二维地图进行调整,第一个是比例系数,另外一个是偏移量。
所谓比例系数,就是你的场景的真实尺寸(场景在X轴和Z轴上的长度)与二维地图尺寸的比值。
而偏移量是你的场景中心点与世界坐标系原点之间的距离(当然也分为X轴偏移量和Z轴偏移量)。

我们的视点在场景当中的坐标值可以通过VRML97标准当中给我们提供的ProximitySensor节点的position_changed事件出口来获得。
这样我们可以在脚本节点当中定义相同类型的EventIn来接收这个值,并进行相应的处理。如下:

DEF script Script {
EventIn SFVec3f getposition
EventOut SFVec3f positiontomap
url “javascript:
function getposition (value)
{
positiontomap.x=(value.x+offset_x)/proportion_x;
positiontomap.y=-(value.z+offset_z)/proportion_z;
positiontomap.z=0;
}

}

在这里,我们所用的公式为:二维地图坐标值=(三维场景坐标值+偏移量)/比例系数。
需要注意的是,由于你的二维地图贴图不一定是很规则的,所以offset和proportion有可能需要一些微调。
当然,上面我们已经说过,要进行Z轴到Y轴的变换,只需要简单的把计算Z值所得的结果直接传递给二维地图的Y值就可以了。但是不要忘记,VRML当中的空间坐标系规则为右手系,如果把Y轴转换为Z轴朝向我们用户本身的话,此时的Z轴的方向却不是如正常的Y轴一样垂直向上,而是正好相反垂直向下(如下图)。所以我们在赋值给地图Y坐标的时候需要将计算结果取负。



接下来,我们只需要将这个计算结果传递给我们所制作的二维地图当中的一个用来标志当前视点位置的标志物就可以了。如果不考虑方向问题,这里的标志物可以直接用无方向性的小球来代替。

那么下面我们来说一下可以表示方向性的二维地图:
原理是相同的,只不过我们现在不仅仅需要上面的坐标运算,除此之外还需要一个空间朝向运算。当前视点的空间朝向可以同样从ProximitySensor当

中得到,相应的事件出口为orientation_changed 。
同样,我们可以在脚本节点当中定义类型相同的EventIn来接收并处理这个空间朝向值:
如:
DEF script Script {
EventIn SFVec3f getorientation
EventOut SFVec3f orientationtomap
url “javascript:
function getorientation(value)
{
orientationtomap.x=value.x;
orientationtomap.y=value.z;
orientationtomap.z=value.y;
orientationtomap.angle=value.angle;
}

}

最后将这个处理过后的空间朝向值再传递给我们的二维地图标志物就可以了
值得一提的是,这里面不再需要什么计算公式,只需要将Y值和Z值互换就可以了。但是为何没有进行为了保证右手系规则而取负值的操作呢?呵呵,其实是因为这个方向性是可以在你的标志物上进行调解的,你只需要制作一个方向性与变换之后的坐标系Z轴方向相反的标志物就可以了,在VRML当中,最简单的能够做成这样的标志物就是圆锥体,尖部朝上,正好与变换后的Z轴方向向反。

我想说到这里,大家对二维地图的原理已经清楚了,那么接下来我将以上的原理整理一下,写成一个完整的程序,以便大家能够更清楚地了解二维地图的制作方法:

#首先:定义一个二维地图
#注意,这里面我以BS和Blaxxun浏览器为例,将二维地图放置在一个Layer
#中,如果你使用cortona或者其他浏览器的话,你也可以采用别的方法来承载
#二维地图,比如说HUD,总之,就是要保证它与显示器平面平行。

Layer2D {
children [
#这个Transform的作用是让你可以整体的移动二维地图,调整他的位置或进行整体的缩放
DEF maptrans Transform {
translation 0 0 0
scale 1 1 1
children [
#二维地图的形体表现,一个没有深度的Box,当然,你也可以用一个面
Transform {
children [
Shape {
appearance Appearance {
material Material {
emissiveColor 1 1 1
}
texture ImageTexture {
url "yourmap.jpg"
#贴上你制作好的二维地图图片,可以在VRML或3Dmax中截图,进行简单的处理
}
}
geometry Box {
size 1 1 0
}
}
]
}

#用来做标志物的圆锥体
DEF sign Transform {
children [
Shape {
appearance Appearance {
material Material {

emissiveColor 1 0 0
}
}
geometry Cone {
bottomRadius 0.025
height 0.1
}
}
]
}
]
}
]
}
#用来获得当前视点位置的代理节点
DEF proxy ProximitySensor {
size 100000 100000 100000
center 0 0 0
enabled TRUE
}

#脚本,这里将两种作用的方法写在同一个脚本当中
DEF script Script {
eventIn SFVec3f getposition
eventIn SFRotation getorientation
eventOut SFVec3f positiontomap
eventOut SFRotation orientationtomap
#这里就需要你自己来设置了
field SFFloat offset_x 0
field SFFloat offset_z 0
field SFFloat proportion_x 1000
field SFFloat proportion_z 1000
url "javascript:
function getposition (value)
{
positiontomap.x=(value.x+offset_x)/proportion_x;
positiontomap.y=-(value.z+offset_z)/proportion_z;
positiontomap.z=0;
}
function getorientation (value)
{
orientationtomap.x=value.x;
orientationtomap.y=value.z;
orientationtomap.z=value.y;
orientationtomap.angle=value.angle;
}
"
}

ROUTE proxy.position_changed TO script.getposition
ROUTE proxy.orientation_changed TO script.getorientation
ROUTE script.positiontomap TO sign.translation
ROUTE script.orientationtomap TO sign.rotation

可以直接将以上代码复制到vrmlpad当中,用BS或者blaxxun来观察结果。
到此为止,我们的二维地图制作方法就讲解完了。

为了方便,我将这些代码中的大部分制作成了一个外部扩展节点,大家可以方便的调用,设置好参数就可以了。

l功能简介:
将二维地图的一些简单功能写成了一个节点,将参数设置好,就可以很简单的制作二维地图了。
l扩展节点定义:
EXTERNPROTO map2D [
exposedField SFVec2f translation
exposedField SFVec2f size
exposedField MFString mapimg
exposedField SFVec2f button_close_translation
exposedField SFVec2f button_close_size
exposedField MFString button_close_img
exposedField SFVec2f buttonsize
exposedField MFNode buttons
exposedField SFVec3f signsize
field SFFloat proportion_x
field SFFloat proportion_z
field SFFloat offset_x
field SFFloat offset_z
field SFBool isopened
field SFBool enablemove
eventIn SFVec3f getposition
eventIn SFRotation getorientation
eventIn SFBool openit
eventIn SFBool closeit
eventIn SFBool openorcloseit
exposedField SFFloat transparency
]
[“map2D.wrl#map2D”]
l域与事件功能简介:域与事件
功能及作用

exposedField SFVec2f translation
设置整个二维地图在屏幕上的位置,值0 0表示地图中心点与屏幕中心点重合。

exposedField SFVec2f size
设置二维地图的尺寸大小

exposedField MFString mapimg
设置二维地图的图片

exposedField SFVec2f button_close_t

ranslation
设置关闭按钮的位置

exposedField SFVec2f button_close_size
设置关闭按钮的尺寸大小

exposedField MFString button_close_img
设置关闭按钮的图片

exposedField SFVec2f buttonsize
设置地图上其他按钮的整体缩放

exposedField MFNode buttons
用来承载地图上其他按钮的数组,可以在这里定义你自己的系统按钮,比如说在地图上设置一些关键点。

exposedField SFVec3f signsize
二维地图上用来标志人物位置的标志尺寸

field SFFloat proportion_x
X轴方向上的比例系数

field SFFloat proportion_z
Z轴方向上的比例系数

field SFFloat offset_x
X轴方向上的偏移量

field SFFloat offset_z
Z轴方向上的偏移量

field SFBool isopened
设置地图初始状态是否为打开状态,默认值为FALSE,关闭状态。

field SFBool enablemove
设置是否允许用鼠标拖拽移动地图,默认值为FALSE,不允许移动。

eventIn SFVec3f getposition
用来接收ProximitySensor节点所传递来的当前视点位置的事件入口

eventIn SFRotation getorientation
用来接收ProximitySensor节点所传递来的当前视点的空间朝向的事件入口。

eventIn SFBool openit
该事件入口如果接收值为TRUE,则显示二维地图。接收值为FALSE不进行任何操作。

eventIn SFBool closeit
该事件入口如果接收值为TRUE,则关闭二维地图的显示。接收值为FALSE不进行任何操作。

eventIn SFBool openorcloseit
当二维地图状态为打开显示状态时,该事件入口如果接收值为TRUE,则关闭二维地图的显示。接收值为FALSE则不进行任何操作。

当二维地图状态为关闭状态时,该事件入口如果接收值为TRUE,则显示二维地图,接收值为FALSE则不进行任何操作。

exposedField SFFloat transparency
设置二维地图背景的透明度。



l使用方法:
将该附件下载放在同你的VRML主文件相同的文件夹下(当然你也可以放置在其他文件夹下,自己修改节点定义当中的url),然后将扩展节点定义复制粘贴到你的主文件顶部,文件头之下。接下来你就可以在主文件当中定义你的二维地图了。

#在此之前,你还需要一个用来获取当前视点做标的ProxitimySensor节点:
DEF prox ProximitySensor {
size 1000 1000 1000
center 0 0 0
}
#然后定义你的二维地图
DEF map map2D {
mapimg "maps/map.jpg"
button_close_translation 0.475 0.475
button_close_size 0.05 0.05
isopened TRUE
enablemove TRUE
}
连接两个必要的路由
ROUTE prox.position_changed TO map.getposition
ROUTE prox.orientation_changed TO map.getorientation

大功告成,试试看吧!

二维地图的截图:

相关文档