BS Contact VRML 各个版本特性

德国 Bitmanagement,致力开发Web3D/VRML/X3D和交互MPEG-4市场。

现在 Bitmanagement 正式推出的 BS Contact 浏览器,在场景版权保护、场景视觉效果、大场景浏览速度都取得了很大的发展。从 BS Contact VRML 6.1 开始提供对 ISO 标准 X3D (X3D/XML编码)的支持。BS Contact VRML/X3D 6.2 开始支持硬件的 Direct3D 9 的高级特效,Bitmanagement 正在参与 X3D 工作组的程序化着色标准的开发。Bitmanagement 还积极的参与多用户 MPEG-4 浏览器的开发。最新 物理系统的支持也在开发中。

Contact 7.108 特性

PhysX 物理引擎☆☆☆☆
多用户支持☆☆☆☆
脚本和界面中支持UTF-8 和 Unicode☆☆☆☆
支持中文文字显示为纹理☆☆☆☆
base64 编码图片加密 ☆☆☆☆
cookie 读取与设置☆
Flash 动态纹理和 Flash 交互链接支持☆
64 位版支持超过 2G 的内存读写 ☆☆☆☆
COLLADA 格式支持
物体级别的自动 LOD

Contact 7.04 特性

组渲染节点,可用于后期特效处理的 ☆☆☆☆☆☆☆
实时渲染到纹理节点更新,并可支持 HDR 格式和多渲染目标 ☆☆☆
粒子系统支持自定义发射器形状 ☆
支持 DirectX 合声和变声特效

Contact 7.0 特性

JPEG2000 小波压缩纹理格式支持
几何对象阻隔优化
自定义透视/轴侧视角 ☆
高分辨率静像渲染 ☆
视频渲染输出 ☆☆
实时视频输入支持 ☆☆☆☆☆☆☆
立体纹理支持
元数据节点 ☆
数据类型扩展
CAD 组件扩展

Contact 6.2 特性

Mozilla FireFox 支持
DirectX 9 支持,支持 DirectX 9 FX 特效文件和 HLSL(高级着色语言)☆☆☆☆☆☆☆
DirectX 9 图形驱动下支持 TGA、HDR 图像格式
支持高级程序化着色引擎(Shader)节点,支持提议中的 X3D 程序化着色标准 ☆☆☆☆☆☆
支持 OpenGL 图形驱动下的红蓝立体显示,另外还提供支持 OpenGL 四方立体显示加速的特别版本的 BS Contact Stereo。☆☆☆
支持专门的组节点调节 Z-buffer 顺序
支持 X3D 事件工具节点
支持由场景来指定浏览器的设置
截图工具 ☆

Contact 6.1 特性

场景内容加密 ☆☆☆☆☆
X3D支持 X3D/XML编码支持,支持XML DOM 整合 ☆☆☆
BSP树、四叉树、八叉树等大场景优化节点 ☆☆
Composite textures 合成纹理支持透明度
兼容 Mozilla、Opera、Netscape
Internet Explorer 下的CAB包自动安装 ☆
Internet Explorer 安全补丁兼容性修正

Contact 6 特性

增强了多纹理的支持,支持凹凸贴图
整合 H-Anim 2001角色动画系统支持、顶点变形优化
过程化纹理用于支持自动生成水等动态纹理
DSS压缩纹理格式支持
多显示支持
支持Quake类的操控方式
支持游戏杆和3D眼镜
透明网页镶入模式及在三维场景镶入浏览器模式

Contact 5.1 特性

实时阴影投射

Contact 5.0 特性

底层图形管线控制节点,支持直接Z缓存、模板缓存的读写和多遍绘制 ☆☆☆☆☆☆☆
环境反射和金属效果
多纹理支持
动态3D视点纹理支持
MPEG-4 层
MPEG-4 二维图形扩展
大场景内存优化
自由变形
真实雾化
纹理化文本
拖放事件支持
键盘鼠标支持
EAI 及 EAI 扩展

VRML的基础教程

VRML创作工具很多是“所见即所得”式的,通过图形界面可以方便地创作虚拟境界,但VRML不仅仅是普通的三维设计,尽管这些工具很容易上手,却往往屏蔽掉了VRML标准的具体细节,因为如果想深入掌握VRML,还需要全面了解节点、域、检测器等技术细节,而达成此目的的最好方法就是用编写文本文件的方式创作VRML境界。本教程提供了六个典型例子,这些例子并不复杂,也不精彩,但涵盖了VRML的关键内容。

在开始创作之前,应作好下面的准备。

文本编辑器 随便你喜欢的文本编辑器,如Win95下的NotePad,Dos下的Edit等等。

VRML浏览器 若用的Web浏览器是Netscape4.0一下版本,可下载CosmoPlayer(http://cosmo.sgi.com);若用的是Netscape4.0或更高版本,则已内置CosmoPlayer2.0,只是安装Netscape时请注意是否选中了相应选项;若用的是Internet Explore4.0,则有可能已经内置了VRML2.0浏览器,判断是否内置的方法很简单,就是看它能否打开VRML文件(*.wrl,*.wrz),如果不行,可以从http://www.microsoft.com/vrml/下载VRML浏览器插件,对于IE3.x,还需要下载一些辅助插件。当然在开始之前应基本熟悉VRML浏览器的操作方法。

硬件 VRML和硬件平台无关,只要能提供VRML浏览器。在下面的教程中,我们假定硬件平台是微机,输出设备是图形窗口,输入设备为鼠标器和键盘。当然,如果有更先进的虚拟现实设备和支持它的VRML浏览软件效果会更好。对于我们将要创作的境界,微机就足够了。

资料 本站就是最全面的资料,遇到新概念时可查阅本站相关资料。

第一节 “Hello,World!”

按照惯例,我们以”Hello,World!”作为我们的第一个虚拟境界,它由立方体、圆锥和球体组成,你可能已经注意到,VRML的标志正是由这三个几何形状构成的。输入的第一行文字是:

#VRML V2.0 utf8

这是VRML文件的标志,所有2.0版本的VRML文件都以这行文字打头,VRML97是由VRML2.0版修订而成的,符合VRML97规范的VRML文件也以这行文字打头。其中“#”表示这是一个注释。而utf8表示此文件采用的是utf8编码方案,这在标准中有详细说明。

先加入一个Group节点(组节点):

Group {

组节点的花括号之内的所有内容视为一个整体,利用组节点可以把虚拟场景组织成条理清晰的树形分支结构。下面定义组节点的children域(孩子域):

children [

在children后的方括号内定义Group节点的所有孩子对象,第一个孩子是一个Shape节点(形态节点),它描述一个几何形状及其颜色等特征:

Shape {

在Shape 节点内定义一个几何体Box(方盒节点):

geometry Box {}

注意我们没有为Box定义任何域,这意味着它的尺寸和坐标位置等特性取缺省值(单位立方体)。随后补齐各右括号:

}

]

}

至此,我们已经成功地制作了第一个虚拟境界,把它保存为Hello World.wrl,下面是完整的文件:

#VRML V2.0 utf8

Group {

children [

Shape {

geometry Box {}

}

]

}

用浏览器打开这个文件,你会看到一个灰色的立方体,尽管不太好看,但你还是可以通过改变视点位置从不同方位观察它,初步体验“三维交互”的感觉。

下面定义立方体的外观,这只需改变Shape节点的appearance域(外观),appearance 域是一个Appearance 节点,此Appearance节点的material域(材质)定义为一个Material 节点:

appearance Appearance {

material Material {}

}

这样,上面的Shape节点变成了:

Shape {

appearance Appearance {

material Material {}

}

geometry Box {}

}

这是定义几何造型的基本格式。现在立方体还是灰色的,这是因为其中的Material节点采用的还是缺省值,下面修改它的diffuseColor域(漫射色),VRML的颜色说明采用的是RGB颜色模型,所以要定义红色的立方体,漫射色应该是{1 0 0},三个数字依次表示红色、绿色和蓝色,取值范围都是0到1:

material Material {diffuseColor 1 0 0 }

现在我们生成了第二个场景,完整的代码是:

#VRML V2.0 utf8

Group {

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

]

}

在这个场景中,红色的立方体位于屏幕的中心,它的中心坐标为{0 0 0 }。若想把它移动一个位置,可以通过为它外套一个Transform(变换节点)来实现:

Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material {}

}

geometry Box {}

}

]

}

在VRML中,Transform节点除了可以引进平移、旋转和缩放变换以外,其作用和Group节点的作用一样。把Transform 节点的translation域(平移)设置为5 0 0,意味着Transform节点所在的坐标系相对于其上层坐标系向右平移(即x轴方向)5个单位,在其它两个方向不移动,VRML的距离单位是米,5个单位相当于5米。我们第三个场景的完整代码是:

#VRML V2.0 utf8

Group {

children [

Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

]

}

]

}

接下来我们把方块所在的Transform节点复制三份,并把各自包含的几何形状依次定义为方块、球体和圆锥:

Group {

children [

Transform {

translation 5 0 0

children [

Shape { …. geometry Box {} }

]

}

Transform {

translation 0 0 0

children [

Shape { … geometry Sphere {} }

]

}

Transform {

translation -5 0 0

children [

Shape { … geometry Cone {} }

]

}

]#end of Group children

}

你可能已经感觉到,VRML文件中有许多括号(花括号“{}”和方括号“[]”),所以务请注意括号的配对,建议采用本教程的缩进风格。注意上面的VRML文件中三个Transform节点的平移量是不同的,因而三个几何体的位置也就不同。另外,还可以修改三个几何体的颜色:球面Sphere为绿色(0 1 0),圆锥为蓝色( 0 1 0 )。最后,为了以后引用方便,分别给这三个Transform 节点指定一个名称:

DEF box Transform {…}

DEF sphere Transform {…}

DEF cone Transform {…}

这个VRML场景的完整代码是:

#VRML V2.0 utf8

Group {

children [

DEF box Tranform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

]

}

DEF sphere Transform {

translation 0 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 1 0 }

}

geometry Sphere {}

}

]

}

DEF cone Transform {

translation -5 0 0

children [

Shape {

appearnance Appearance {

material Material { diffuseColor 0 0 1 }

}

geometry Cone { }

}

]

}

]# end of Group children

}

把此文件保存为helloworld.wrl,用VRML浏览器打开这个文件,通过调整视点从多个方位浏览自己的作品。

小结:在这一节,我们创建了第一个虚拟境界,涉及到如何用几何体构建境界,以及如何设定几何体的颜色与材质。尽管这个由方块、圆锥和球体组成的场景图比较简单,但已经反映了VRML的基本功能。当然,除了可用鼠标改变视点外,这还只是一个静态世界,在下一节,我们将引进VRML的动态特征。

第二节 增加交互能力

上一节我们学习了用几何体建立虚拟境界以及为几何体赋予色彩和材质的方法,这样建立的虚拟境界是静态的。这一节我们将使一个几何体(为了更具一般性,下面我们称之为对象)能够根据用户动作做出反应,即交互能力,这是VRML2.0最突出的特征。

1。检测器

在VRML中,检测器(Sensor)节点是交互能力的基础。检测器节点共九种。在场景图中,检测器节点一般是以其它节点的子节点的身份而存在的,它的父节点称为可触发节点,触发条件和时机由检测器节点类型确定。

接触检测器( TouchSensor)是最常用的检测器之一,最典型的应用例子是开关。其它检测器将在后续教程中陆续介绍。这里我们定义一个开关节点lightSwitch(这是一个组节点),并定义一个接触检测器作为它的子节点:

DEF lightSwitch Group {

children [

各几何造型子节点…

DEF touchSensor TouchSensor {}

]

}

这样开关节点lightSwitch就是一个可触发节点。当然,检测器存在的理由是它被触发时能够引起某种变化,所以在更深入讨论开关节点之前,我们先讨论一下场景变化。 2.视点

最常见的变化是视点的变化,在我们的第一个境界中你可能已经体验到视点变化:当你拖动鼠标或按动箭头键时(按照VRML术语,称为航行),虚拟境界就会旋转或缩放,这实际上是在调整你的视点位置或视角。在虚拟场景的重要位置可以定义视点节点(ViewPoint),它们是境界作者给用户推荐的上佳观赏方位,在CosmoPlayer浏览器中,用户就可以通过鼠标右键选择作者推荐的各个视点。这里我们定义两个视点节点:

DEF view1 Viewpoint {

position 0 0 20

description “View1”

}

DEF view2 Viewpoint {

position 5 0 20

description “view2”

}

我们的潜在目的是使用户可以通过触发开关节点来切换视点。现在先研究一下这两个视点节点,其中的坐标表示视点在场景中的位置,坐标的单位是米,这在前面已经提到过,视点的名称将会在浏览器菜单中提示出来供用户选择。把上述视点说明加入helloworld.wrl中(放在Group节点之前),并把其中的方块节点修改成可触发节点:

DEF box Tranform {

children [

Shape { …. Box …}

DEF touchBox TouchSensor {}

]

}

把修改过的文件另存为“touchme.wrl”。

3。事件传递

下面我们把触发(用鼠标箭头按动方块)和场景变化(视点切换)这两件事情联系起来,在场景图中,除节点构成的层次体系外,还有一个“事件体系”,事件体系由相互通讯的节点组成。能够接收事件的节点都应具有事件入口(eventIn),如果它要接收多种类型的事件(称为入事件),它就应该具有多个事件入口,也就是说,事件入口象节点的域一样是有类型的。同样,发送事件的节点应有事件出口(eventOut),事件出口也是有类型的。例如ViewPoint节点就有一个事件入口set_bind,当向此事件送入一个值“TRUE”(即所谓的入事件)时,该viewpoint节点成为当前视点。又如,接触检测器TouchSensor有一个事件出口isActive,当受到用户触发后它就从此出口送出一个“TRUE”(即所谓的出事件),补充一句,在下一个事件发送之前,此事件一直保存在事件出口中(作为记录)。

事件出口和事件入口通过路径相连,这就是VRML文件中除节点以外的另一基本组成部分:ROUTE 语句。ROUTE语句把事件出口和事件入口联系在一起,从而构成事件体系。在这里,我们是把接触检测器touchBox的事件出口isActive连接到视点节点view2的事件入口set_bind:

ROTUE touchBox.isActive TO view2.set_bind

好了!现在我们得到的VRML文件是:

#VRML V2.0 utf8

DEF view1 Viewpoint {

position 0 0 20

description “view1”

}

DEF view2 Viewpoint {

position 5 0 20

description “view2”

}

Group {

children [

DEF box Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0}

}

geometry Box {}

}

DEF touchBox TouchSensor {}

]

}

DEF sphere Transform {

translation 0 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 1 0}

}

geometry Sphere {}

}

]

}

DEF cone Transform {

translation -5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 0 1 }

}

geometry Cone {}

}

]

}

] #end of Group children

}

ROUTE touchBox.isActive TO view2.set_bind

把这个文件调入浏览器,然后把鼠标指向方块并按下左钮(先别松开!),可以看到视点已经变为view2,内部的机制我们已经很清楚:左钮按下时方块节点的接触检测器被触发,接着接触检测器从事件出口isActive送出一个事件“TRUE”,这个事件通过路由进入视点节点view2的事件入口set_bind,view2收到“TRUE”后成为当前视点,所以在我们眼前场景发生了变化。

现在松开左钮,可以看到场景恢复到原来方位,这种功能称为视点回跳,其原因是松开左钮后接触检测器向view2发送了一个“FASLE”事件,这样view2当前的地位被解除,原来的视点成为系统视点栈的栈顶节点(即当前视点),详细说明可参见标准中对视点节点的专门论述。如果我们不想视点回跳,就想停留在view2视点,那该怎么办呢?这种非系统缺省功能要自己来定义。

4。 利用脚本编写自定义行为 在VRML中,利用Script节点(脚本节点)定义用户自定义行为,所谓定义即用脚本描述语言(Scripting Language)编写脚本的过程。VRML97支持的脚本描述语言目前有两种:Java和EMCAScript(这是JavaScript标准化后的名称),关于这两种语言本身,请参考相应参考书,VRML97标准中定义了它们和VRML的接口方法。应提请注意的是:VRML是基于节点的语言,所以脚本也是封装在Script这个特殊节点中的。这里我们不过多讨论脚本描述语言的细节,主要讨论把脚本集成到VRML文件中的方法。

上面我们曾把接触检测器touchBox 和视点view2直接通过路径连接起来,现在要定义我们指定的行为,就需要在二者之间插入一个脚本节点,也就是让路径绕个弯: ROUTE touchBox.isActive TO touchScript.touchBoxIsActive

ROUTE touchScript.bindView2 TO view2.set_bind

其中的脚本节点touchScript有一个事件人口touchBoxIsActive和一个事件出口bind_View2,前者接收来自接触检测器touchBox的事件,然后经自己的脚本处理后,把结果发送给视点节点view2:

DEF touchScript Script {

eventIn SFBool touchBoxIsActive

eventOut SFBool bindView2

url”javescript:

function touchBoxIsActive(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仍然保持为当前视点。

本节的完整代码是:

#VRML V2.0 utf8

DEF view1 Viewpoint {

position 0 0 20

description “view1”

}

DEF view2 Viewpoint {

position 5 0 20

description “view2”

}

Group {

children [

DEF box Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

DEF touchBox TouchSensor {}

]

}

DEF sphere Transform {

translation 0 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 1 0}

}

geometry Sphere {}

}

]

}

DEF cone Tranform {

transltion -5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 0 1 }

}

geometry Cone {}

}

]

}

] #end of Group children

}

DEF touchScript Script {

eventIn SFBool touchBoxIsActive

eventOut SFBool bindView2

url “javascript :

function touchBoxIsActive (active) {

bindView2 = TRUE;

}”

}

ROUTE touchBox.isActive TO touchScript.touchBoxIsActive

ROUTE touchScript.bindView2 TO view2.set_bind

小结:本节建立的虚拟境界并不复杂,但涉及到了VRML2.0最基础性的功能和概念:利用检测器产生事件、利用路由传递事件以及利用脚本编写自定义行为,掌握了这些内容也就掌握了VRML2.0的核心。在后面的几节中,我们将探索一些专题性的有趣功能,而本节是基础,因而必须透彻理解。

第三节 邻近检测器

本节讨论邻近检测器(proximitySensor),当用户进入或离开邻近检测器所划定的区域时就会触发它。正如你在标准中可以查到的那样,ProximitySensor节点定义为:

ProximitySensor {

exposedField SFVec3f center 0 0 0

exposedField SFVec3f size 0 0 0

exposedField SFBool enabled TRUE

eventOut SFBool isActive

eventOut SFVec3f position_changed

eventOut SFRotation orientation_changed

eventOut SFTime enterTime

eventOut SFTime exitTime

}

这里稍作介绍。ProximitySensor节点共有三个外露域(exposedField)和五个出事件(eventOut).出事件我们已经熟悉,是节点状态发生改变时用来通知其它节点的,这里的出事件isActive 用于ProximitySensor通报自己已被激活。enterTime和exitTime通报用户(代表用户的用户化身或指示器)进入和退出ProximitySensor检测区的时刻。若用户已在检测器之内,则当用户的位置或方位发生变化时,送出position_changed和orientation_changed出事件这五个出事件联合起来,就定义了邻近检测器的功能。外露域则集域(Field)、入事件(eventIn)和出事件(eventOut)三者的功能于一身,也就是说,它既象域一样描述了节点的当前状态,又可以作为入事件由其它节点修改这种状态,并作为出事件把这种改变通知其它节点。这里的enabled外露域是布尔型的,用于ProximitySensor的启用和停用,center和size定义形为长方体的邻近检测区。

我们的出发点是第一节中建造的境界helloworld,它是由方块、球体和圆柱这三个物体构成的静态世界,现在在球体周围增加一个邻近检测区:

DEF sphere Transform {

translation 0 0 0

children [

Shape {….}

DEF comeClose ProximitySensor {

center 0 0 0

size 4 4 4

}

]

}

ProximitySensor的名字为comeCloser,邻近区的中心和球体的球心重合,形状为正方体,边长为4米,是球体直径的两倍。当用户走进球体时就会触发这个邻近检测器,检测器发出isActive事件,我们把这个事件出口通过路由指向Script节点(用来绑定视点2):

DEF comeCloserScript Script {

eventIn SFBool enterProximitySensorIsActive

eventOut SFBool bindView2

url ” javascript :

function enterProximitySensorIsActive (active) {

bindView2=TRUE;

} “

}

随后,我们在邻近检测器的出事件isActive和脚本节点comeCloserScript的入事件enterProximitySensorIsActive之间建立路由,后者收到事件后执行函数enterProximitySensroIsActive,函数发出bindView2出事件,这个出事件通过路由连接到视点节点View2:

ROUTE comeCloser.isActive TO comeCloserScript.enterProximitySensorIsActive

ROUTE comeCloserScript.bindView2 TO view2.set_bind

也就是说,一旦用户进入邻近区,境界的当前视点将转换成View2.这个由两个视点、三个物体、一个邻近检测器和一个脚本节点组成的境界的完整代码如下:

#VRML V2.0 utf8

DEF view1 Viewpoint {

position 0 0 20

description “view1”

}

DEF view2 Viewpoint {

position 0 0 20

description “view2”

}

Group {

children [

DEF box Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

]

}

DEF sphere Transform {

translation 0 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 1 0 }

}

geometry Sphere {}

}

DEF comeCloser ProximitrySensor {

center 0 0 0

size 4 4 4

}

]

}

DEF cone Transform {

translation -5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 0 1}

}

geometry Cone {}

}

]

}

]#end of Group children

}

DEF comeCloserScript Script {

eventIn SFBool enterProximitySensorIsActive

eventOut SFBool bindView2

url “javascript :

function enterProximitySensorIsActive(active) {

bindView2=TRUE;

}”

}

ROUTE comeCloser.isActive TO comeCloserScript.enterProximitySensorIsActive

ROUTE comeCloserScript.bindView2 TO view2.set_bind

启动VRML浏览器进入境界,面向球体一直走过去,当你刚刚感到靠近球体时,会突然感到自己后退了一大步(或者说物体跳到前方更远的地方),这表明邻近检测器已经检测到你的靠近,它把这件事通知脚本节点,脚本节点把视点View2绑定成当前视点,从而使你感到视点突然改变。

再稍稍修改一下邻近检测器,把它的中心位置向右移了2米:

DEF comeCloser ProximitySensor {

center 2 0 0

size 4 4 4

}

这样你就可以从左边(方块那一边)走进球体(视点不跳),但不能从右边(圆锥那一边)走近它(视点跳转)。

总之,ProximitySensor能够检测用户是否进入或离开检测器指定的空间区域,典型用法是当用户走进房间时开启灯光,当用户离开时关闭灯光,从而建立功能丰富的“智能”空间。

第四节 连续动画

在第二节中我们已经使用过接触检测器,当我们把鼠标指针放到方块(这个几何节点包含接触检测器)上面时,指针形状发生变化,这意味着我们已经进入检测区,如果按下鼠标左钮,则按照我们的定义,当前视点会发生变化。

这一节仍然制作这样一个对接触有反应的方块,只是接触后它会连续不断地转动,动画行为可以用时间检测器(TimeSensor)驱动,而不断变化的旋转值可用脚本节点或朝向插补器(orientationInterpolator)给出。

1。接触检测器

作为开始的基本代码是:

#VRML V2.0 utf8

DEF cube Transform {

rotation 1 1 1 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

DEF TouchS TouchSensor {}

]

}

DEF revolver Script {

eventIn SFBool startRevolving

eventOut SFRotation revolve

field SFFloat angle 0

url “javascript :

function startRevolving () {

revolve[0]=1;

revolve[1]=1;

revolve[2]=1;

revolve[3]=angle;

angle+=0.1;

}”

}

ROUTE TouchS.isOver TO revolver.startRevolving

ROUTE revolver.revolve TO cube.set_rotation

其中,方块cube包含两个子节点,前者定义了它的形态(红色的单位立方体),后者把它定义成接触检测器。注意,cube的类型是Transform节点,它的rotation 域是外露域,指定本组相对于上层坐标系的旋转值,这里指定的初始值是“1 1 1 0 ”,其中前三个数值定义旋转轴,最后一个值定义旋转角。由于它是外露域,因而可以通过入事件(名为set_rotation)进行修改,下面定义的动态行为就是这样实现的。

Script节点revolver的核心是内联的ECMAScript脚本函数。它给定一个不断变化的旋转值。当鼠标指针移动到方块之上时,接触检测器发出isOver,和第一节中采用的isActive事件不同,isOver只有在鼠标左钮按下时才会发出。isOver事件通过路由传递给脚本节点的事件入口startRevolving,从而启动函数startRevolving,函数将一个新的旋转值发往事件出口revolve,这个旋转值通过路由进入cube的外露域rotation,修改了方块的旋转角,引起它的朝向变化。鼠标指针在cube上面的每次方位变化都引起isOver事件发送一次,从而导致方块旋转一次。

2。时间检测器

为了使方块能够连续旋转,需要引进等间隔连续发送的时间序列,这正是时间检测器的用武之地。时间检测器随着时间推移不断产生事件,可用于多种目的,包括: a. 驱动连续性的仿真和动画

b. 控制周期性的活动(如每分钟一次)

c. 初始化单独事件,如报警钟

下面是我们要用的时间检测器和修改后的路由关系:

DEF ticker TimeSensor {

cleInterval 0.1

loop TRUE

enabled FALSE

}

ROUTE TouchS.isOver TO ticker.set_enabled

ROUTE ticker.cycleTime TO revolver.startRevolving

ROUTE revolver.revolve TO cube.set_rotation

enabled用于启用和停用时间检测器,开始时它处于停用状态,以后由接触检测器的isOver事件修改这一状态。启用的时间检测器每隔0.1秒送出一个cycleTime事件,并用它来触发revolver的startRevolving事件,注意,cycleTime事件的类型为SFTime,而路由两端事件的类型必须匹配,所以尽管这里我们不关心这个事件表示的具体时刻,还是把revolver的startRevolving事件类型也改为SFTime.这样,revolver的函数startRevolving()就会每0.1秒调用一次,从而驱动方块连续旋转。完整的代码是:

#VRML V2.0 utf8

DEF cube Transform {

rotation 1 1 1 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geoemtry Box {}

}

DEF TouchS TouchSensor {}

]

}

DEF revolver Script {

eventIn SFTime startRevolving

eventOut SFRotation revolve

field SFFloat angle 0

url “vrmlscript :

function startRevolving () {

revolve[0]=1;

revolve[1]=1;

revolve[2]=1;

revolve[3]=angle;

angle+=0.1;

}”

}

DEF ticker TimeSensor {

cycleInterval 0.1

loop TRUE

enabled FALSE

}

ROUTE TouchS.isOver TO ticker.set_enabled

ROUTE ticker.cycleTime TO revolver.startRevolving

ROUTE revolver.revolve TO cube.set_rotation

上述脚本节点的功能比较简单,只是不断送出调整的旋转值,它是关键帧动画的一种。由于关键帧动画十分常用,故VRML专门定义了插补器节点来实现它。

3。 朝向插补器

插补器节点可认为是VRML内置的脚本节点,它们执行简单的动态计算,通常和时间检测器或者能够使对象产生动作的节点结合在一起使用,生成线性关键帧动画。插补器节点实际上是一个由关键点和对应关键值定义的分段线形函数。根据插值类型的不同,VRML共定义六个插补器节点:ColorInterpolator(颜色插补器)、CoordinateInterpolator(坐标插补器)、NormalInterpolator(法线插补器)、OrientationInterpolator(朝向插补器)、positionInterpolator(位置插补器)、ScalarInterpolator(标量插补器)。

所有插补器的域和事件都是类似的:

eventIn SFFloat set_fruction

exposedField MFFloat key […]

exposedField MF<type> keyValue […..]

eventOut [S|M]F<type> value_changed

关键值域keyValue的类型决定了插补器的类型(例如,OrientationInterpolator的keyValue域的类型是MFFloat).入事件set_fraction接收SFFloat型的事件,插补器随即根据它进行插值,并通过出事件value_changed送出插值结果。

这里我们把时间检测器的fraction_changed事件作为插补器的输入,这个事件是一个[0,1]区间的值,每个时间步都送出一次,表示当前周期内已过去的时间相对于整个周期的比例,是插补器常用的输入源之一。与此对应,我们把插补器关键帧的取值也定义在[0,1]范围内。与0和1这两个关键帧对应的关键值的旋转轴是相同的,只是旋转角度不同(0,3.14159),这样方位插补器输出的旋转值的旋转轴固定不变,旋转角从0递增到3.14159,然后不断重复。

#VRML V2.0 utf8

DEF cube Transform {

rotation 1 1 1 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

DEF TouchS TouchSensor {}

]

}

DEF revolver orientationInterpolator {

key [0,1]

keyValue [ 0.5 0.5 0.5 0,0.5 0.5 0.5 3.14149]

}

DEF ticker TimeSensor {

cycleInterval 2

loop TRUE

enabled FALSE

}

ROUTE TouchS.isOver TO ticker.set_enabled

ROUTE ticker.fraction_changed TO revolver.set_fraction

ROUTE revolver.value_changed TO cube.set_rotation

小结:本节实现连续动画,动画由接触检测器启动,由时间检测器驱动,动画本身比较简单,就是不断地旋转。产生不断变化的旋转值的方法有两种:自己编写脚本,或者利用插补器节点。

第五节 动态修改场景图

场景图是描述境界结构的基本概念,节点是构成场景图的基本单元。组节点是能够包含字节点的节点,组节点本身还可作为其它组节点的子节点,从而形成层次性体系结构。VRML中的组节点包含Anchor(锚)、 Billboard(布告牌)、 Collision(碰撞)、Group (组)、Inline (内联)、LOD(细节层次)、 Switch(开关)、Transform(变换)共八种,除Inline、LOD、Switch这几个具有特殊功能外,它们都定义了入事件addChildren 和removeChildren ,前者用于向组节点的子节点域children 中增加新的子节点,后者用于从中删除子节点,这样就可以动态修改场景图的结构。

下面是我们这一节要建立的境界,开始的时候球体位于左边红色方块的内部,在按动底部的绿色方块后,球体进入右边蓝色方块之内。

首先定义三个方块:

#VRML V2.0 utf8

Viewpoint { position 0 0 15 }

DEF leftBox Transform {

translation -5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

]

}

DEF rightBox Transform {

translation 5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 0 1 }

}

geometry Box {}

}

]

}

DEF onoff Transform {

translation 0 -5 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 0 1 0 }

}

geometry Box {}

}

]

}

其中左边的方块为红色,右边的方块为蓝色,下边的方块为绿色,都是Transform类型,三者都位于场景图的最高层,都是场景图的根节点,都包含一个Box几何体作为子节点。下面为红方块增加一个球体子节点:

DEF leftBox Transform {

translation -5 0 0

children [

Shape {

appearance Appearance {

material Material { diffuseColor 1 0 0 }

}

geometry Box {}

}

DEF SphereChild Shape {

appearance Appearance {

material Material { diffuseColor 1 0 1 }

}

geometry Sphere { radius 1.2 }

}

]

}

为了以后引用方便,这里还为球体子节点起了名字:SphereChild .为了让用户能够增删这个儿子,把绿方块定义成接触检测器:

DEF onoff Transform {

translation 0 -5 0

children [

Shape {

appearance Appearance {

material Material {diffuseColor 0 1 0 }

}

geometry Box {}

}

DEF TS TouchSensor {}

]

}

子节点增删的具体任务由Script节点来完成:

DEF S Script {

eventIn SFBool isActive

eventOut MFNode child

field MFNode testNode USE SphereChild

 

url”javascript :

function isActive (value) {

if (value)child = testNode;

}”

}

注意它的出事件child的类型是MFNode,也就是说通过这个事件送出的是节点。节点S的testNode域是对球体SphereChild引用(USE语句),引用不复制该节点,而是把同一节点再次插入场景图,从而导致SphereChild拥有多个父亲,所以场景图仅仅是层次结构,而不是树形结构。加上下面的路由语句,建立事件联系:

ROUTE TS.isActive TO S.isActive

ROUTE S.child TO leftBox.removeChildren

ROUTE S.child TO rightBox.addChildren

接触检测器TS的激活事件isActive连接到脚本节点S的isActive,这样用户一旦按动绿方块,就会启动脚本节点的事件处理函数isActive(),此函数把testNode节点(即球体节点SphereChild )送至出事件S.child.根据路由,左边红方块的事件入口leftBox.removeChildren 收到此事件,按照removeChildren的语义,球体节点SphereChild从leftBox的子节点列表中删除。与此同时,右边蓝方块的事件入口rightBox.addChildren也收到S.child出事件,根据addChildren的语义,球体节点SphereChild加入 rightBox的子节点列表。通过这个过程,球体节点SphereChild的父节点从leftBox更换成rightBox.

第六节 扩充节点类型

VRML提供了54种节点类型,称为内部节点类型。然而实际应用种可能要求新的节点类型,原型(prototype)是VRML实现节点类型扩充的基本机制。新节点类型是根据已定义的(内部的或原型的)节点类型定义的,一旦定义,原型节点类型就可以象内部节点类型一样在场景图中实例化。原型可以在当前文件中定义并使用,也可以在其它文件中定义,即外部原型,外部原型提供了一种使节点类型能够跨越网络的机制。本节的原型例子取自VRML97标准,它定义的是一个桌子类型,这个原型为:

#VRML V2.0 utf8

PROTO TwoColor Table [ field SFColor legColor 0.8 0.4 0.7

field SFColor topColor 0.6 0.6 0.1 ]

}

Transform {

children [

Transform {

translation 0.0 0.6 0.0

children [

Transform {

appearance Appearance {

material Material { diffuseColor IS topColor }

}

geometry Box { size 1.2 0.2 1.2 }

}

}

Transform {

translation -0.5 0 -0.5

children [

DEF Leg Shape {

appearance Appearance { diffuseColor IS legColor }

}

geometry Cylinder { height 1 radius 0.1 }

}

]

}

Transform { #另一条桌腿

translation 0.5 0 -0.5

children USE Leg

}

Transform { #另一条桌腿

translation -0.5 0 0.5

children USE Leg

}

Transform { #另一条桌腿

translation 0.5 0 0.5

children USE Leg

}

]#根节点Transform的儿子结束

}#根Transform 结束

}#原型结束

原型语句PROTO分为原型接口声明和原型定义两部分、接口声明包括原型的入事件和出事件的类型和名称,以及原型的域的类型、名称和缺省值。这里的接口声明为:

PROTO TwoColorTable [ field SFColor legColor 0.8 0.4 0.7

field SFColor topColor 0.6 0.6 0.1 ]

这个原型的类型名称为“TwoColorTable”(双色桌),它有两个域:legColor(桌腿色)和topColor(桌面色)。作为节点类型,TwoColorTable的用法和其它内部节点类型一样,例如下面的语句定义一个TwoColorTable类型的节点,它的桌腿为红色,桌面为绿色:

TwoColor Table {

legColor 1 0 0 topColor 0 1 0

}

接口声明之后是原型的主体,称为原型定义。原型定义实际上是一个场景图,由一个或多个根节点、嵌入的PROTO语句和ROUTE语句构成,其中的第一个节点类型确定原型实例在VRML文件中的使用方法。例如,如果原型定义中的第一个节点是Material节点,则只要可以使用Material节点的地方,原型实例都可以使用。原型定义中定义的其它节点及其附带的场景图都不进入原型实例所在的变换层系,但可以被原型定义中的ROUTE语句或Script节点引用。TwoColorTable原型中的第一个节点是Transform组节点,它决定了TwoColorTable型节点在场景图中的方法,在场景图中添加一个TwoColorTable型节点,相当于增加Transform.

原型定义中节点的域、入事件、出事件可以通过IS语句和接口声明中的域、入事件、出事件建立关联,关联实际上相当于把原型定义中的这些域和事件公开作为原型的域和事件。关联的基本规则是域和域、入事件和入事件、出事件和出事件对应关联,原型定义中的外露域可以和接口声明中的域、入事件、出事件或外露域关联。本例中的关联有两个:桌面diffuseColor 域和接口声明中的topColor域,桌腿的diffuseColor域和接口声明中的legColor域之间。也就是说,TwoColorTable型节点中的topColor和legColor值实际上分别确定了桌面和桌腿的漫反射色diffuseColor.

第七节 结束语

本教程创建了六个典型VRML境界,介绍了VRML的主要功能。这些例子的侧重点在于VRML的交互式特征,而不是营造境界的造型特征,后者可参见一般的三维图形工具,把这二者结合起来,可以创建更加精彩的交互式3D境界。本章根据需要介绍了部分VRML节点的基本用法,以后将对VRML节点进行分类和较为全面的评论。

当然,VRML功能十分丰富,要成为VRML专家,一方面需要研读VRML97标准,以求全面深入的掌握和应用,另一方面,要经常研读成功的作品,获取创作灵感。

百度Hi竟然捆绑安装Cnnic无忧上网条?

昨天正在Ps图片,突然Ps就非法操作,挂掉了.好郁闷.接着我就重启机器,就无法进入到桌面了,实在在登陆界面,硬盘灯狂闪,用Win PE查看文件,找不到硬盘,只好启动到Mac系统下,把桌面等地方的文件备份出来.然后重装系统.

前好多天我就想重做系统,因为被损坏的C++搞乱了系统,但因为一些繁杂琐碎的事,一直没有腾出空闲重装系统,桌面上的图标有满了.

MSDN版的Xp SP3早就下载好并且刻录好了.Nero真是有点变态了,一个刻录软件,现在竟然干到一二百兆,弄了一堆没有用的东西,什么视频编辑,光盘复制,音频转压,CD封面设计,自己做好自己的刻录本职工作好了,就算我要去设计封面,我干嘛不用Ps?只选择了刻录组件,其他都没选择,没想到启动后竟然提示要安装完整的以获得什么优势,下面自吹自擂的广告词也很恶心:”Nero-真的很好用”,想关掉这个Nero源获取都没办法,无法保存设置.晕啊.下次我用Once做刻录试试.要扔掉Nero了.越来越烂了.

昨晚装系统,装完后因为更新了声卡驱动,导致录音机蓝屏,只能换回原来没有问题的版本,安装百度HI后,在奇虎360中竟然发现了Cnnic无忧上网条,文件路径是空的,很疑惑,但是没有去怀疑百度Hi,心想它即使要绑定插件也要绑定自己的工具条吧.因为驱动不完美,也做完了Ghost,所以今天又重新安装了系统,然后装BaiduHi,又发现了上网条,把上网条清理之后再次安装了一遍百度HI,又发现了上网条,果然是百度Hi搞的,真无语了.经过网友测试,的确有这个存在,是在官方首页下载的beta2版本,不知道什么原因.不排除误杀的可能.唉垃圾插件,流氓插件,何时能了!!!!

雨下了一天了,稀里哗啦的.挺好.绿萝被我放在外面了,把每个叶子都擦了一遍,有半年多的灰了.对面二楼的房子传出当愣愣的声响,特意观察了一下,一分钟响一次,一次两声,貌似手机的短信和弦声,从从昨晚发现一直到现在还没有停止.够烦人的了.很佩服这个设备.我也很好奇,是什么东西的声响,不应该是手机短信啊,理论上不像,但声音很像.奇怪.奇怪.真奇怪.

NSIS V2.37 汉化版下载

  NSIS 是“Nullsoft 脚本安装系统”(Nullsoft Scriptable Installation System) 的缩写,它是一个免费的 Win32 安装、卸载系统,采用了简洁高效的脚本方式。它本来是一个由 Nullsoft 创建并用于作为 Winamp 及其插件发布的系统,但现已被上百个应用程序所应用,作为它们进行程序发布的工具。

  NSIS 创建的安装程序可以进行安装、卸载、设置系统设置、解压文件等等。几乎可以做所有事情。因为它基于脚本文件,所以您可以完全控制您的安装程序的每个部分。它的脚本语言支持变量、函数、字串处理,就像是一个普通的程序语言 – 但其仅设计用来创建安装程序。

  简体中文增强版除了主程序的翻译之外还把主要的文档作了翻译并修正了官方版本里简体中文语言习惯用语不合适之处。单纯的使用脚本来编写安装程序对于大多数人来说不仅困难而且容易出错,为此,简体中文增强版里集成了一个相当好用的脚本编辑器 – VNISEdit 增强版 (Build 060712 By Restools)。只需要根据向导就能轻松的做出很酷的安装程序,甚至,您还可以在向导里给您的安装程序添加启动画面、让您的安装程序在安装过程中播放音乐,而这,只需要点几下鼠标即可。除此之外,VNISEdit 附带的注册表转换插件还可以把 .reg 文件一次性的转换为 NSIS 脚本,补丁制作向导可以一次性地为您生成体积超小的补丁升级程序。简体中文增强版还在官方版本的基础上集成了一些有用的插件,比如 FindProc 可以根据可执行文件名查找进程是否在运行,这在制作补丁程序或者汉化包时非常有用。由于各个组件在使用时各自独立,所以强烈推荐安装全部组件。(注:部分插件不支持 9X 系统)

安装版下载地址:
http://nchc.dl.sourceforge.net/sourceforge/nsis/nsis-2.37-setup.exe

免安装版下载地址:
http://jaist.dl.sourceforge.net/sourceforge/nsis/nsis-2.37.zip

开启安装log版下载地址:
http://jaist.dl.sourceforge.net/sourceforge/nsis/nsis-2.37-log.zip

8192字节版下载地址:
http://nchc.dl.sourceforge.net/sourceforge/nsis/nsis-2.37-strlen_8192.zip

汉化补丁下载(0602版):
点击下载此文件

远程引用网易相册图片(xmlhttp+缓存)

163的相册有防盗链的功能,在其他域名下引用图片时候会得不到数据.
体现在浏览器上,就是一个红X.
我们利用httprequest和application缓存技术,可以破解这种防盗链.

保存成一个asp文件在你网站目录,就可以用如下的方式调用网易的图片了.除了网易,我想其他加了防盗链的图片都可以用这个方法,比如百度,比如QQ相册.等等

http://你的网站/aspname.asp?url=图片地址

<%
'代码作者:siyizhu 日期:2006-05-22
Dim url, body, myCache

url = Request.QueryString("url")

Set myCache = new cache
myCache.name = "picindex"&url
If myCache.valid Then
body = myCache.value
Else
body = GetWebData(url)
myCache.add body,dateadd("d",1,now)
End If

If Err.Number = 0 Then
Response.CharSet = "UTF-8"
Response.ContentType = "application/octet-stream"
Response.BinaryWrite body
Response.Flush
Else
Wscript.Echo Err.Description
End if

'取得数据
Public Function GetWebData(ByVal strUrl)
Dim curlpath
curlpath = Mid(strUrl,1,Instr(8,strUrl,"/"))
Dim Retrieval
Set Retrieval = Server.CreateObject("Microsoft.XMLHTTP")
With Retrieval
.Open "Get", strUrl, False,"",""
.setRequestHeader "Referer", curlpath
.Send
GetWebData =.ResponseBody
End With
Set Retrieval = Nothing
End Function

'cache类

class Cache
private obj 'cache内容
private expireTime '过期时间
private expireTimeName '过期时间application名
private cacheName 'cache内容application名
private path 'url

private sub class_initialize()
path=request.servervariables("url")
path=left(path,instrRev(path,"/"))
end sub

private sub class_terminate()
end sub

public property get blEmpty
'是否为空
if isempty(obj) then
blEmpty=true
else
blEmpty=false
end if
end property

public property get valid
'是否可用(过期)
if isempty(obj) or not isDate(expireTime) then
valid=false
elseif CDate(expireTime)<now then
valid=false
else
valid=true
end if
end property

public property let name(str)
'设置cache名
cacheName=str & path
obj=application(cacheName)
expireTimeName=str & "expires" & path
expireTime=application(expireTimeName)
end property

public property let expires(tm)
'重设置过期时间
expireTime=tm
application.lock
application(expireTimeName)=expireTime
application.unlock
end property

public sub add(var,expire)
'赋值
if isempty(var) or not isDate(expire) then
exit sub
end if
obj=var
expireTime=expire
application.lock
application(cacheName)=obj
application(expireTimeName)=expireTime
application.unlock
end sub

public property get value
'取值
if isempty(obj) or not isDate(expireTime) then
value=null
elseif CDate(expireTime)<now then
value=null
else
value=obj
end if
end property

public sub makeEmpty()
'释放application
application.lock
application(cacheName)=empty
application(expireTimeName)=empty
application.unlock
obj=empty
expireTime=empty
end sub

public function equal(var2)
'比较
if typename(obj)<>typename(var2) then
equal=false
elseif typename(obj)="Object" then
if obj is var2 then
equal=true
else
equal=false
end if
elseif typename(obj)="Variant()" then
if join(obj,"^")=join(var2,"^") then
equal=true
else
equal=false
end if
else
if obj=var2 then
equal=true
else
equal=false
end if
end if
end function
end class
%>

Php版本:

<?php
/**********************************************************************
突破防盗链的显示图片标签[simg],PHP程序部分
作者:t1000
开发论坛:水客坊论坛
*********************************************************************/
ob_start();
$img=$_GET['url'];

$host=$path=str_replace('http://','',$img);
$host=explode('/',$host);
$host=$host[0];
$path=strstr($path,'/');
$fp = fsockopen($host, 80, $errno, $errstr, 30);
if ($fp)
{
@fputs($fp, "GET $path HTTP/1.1
");
@fputs($fp, "Host: $host
");
@fputs($fp, "Accept: */*
");
@fputs($fp, "Referer: http://$host/
");
@fputs($fp, "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
");
@fputs($fp, "Connection: Close

");
}

$Content = '';
while ($str = fread($fp, 4096))
$Content .= $str;
@fclose($fp);
$pos=strpos($Content,"

");
$head=substr($Content,0,$pos);
$text=substr($Content,$pos+4);
header($head);
echo $text;
?>

日子叠着日子

日子叠着日子,像纸一样,叠着,如果去暴力的撕开,就碎了.

一个偶然,发现了Bs Contact控件的授权的C#算法,于是操刀写算法注册机.

N次陷入死巷后终成正果.可惜VB.Net,该死的微软DotNet框架.写个几百K的程序都没办法,无法脱离这个.Net圈子.一个注册机要几兆之大?可笑.

于是,开始了VB6的翻写.为什么用VB6,因为它比较容易!

孰知,变态的Bs授权算法,算式的运算竟然超过了VB中的Long允许长度.换成Double进行位运算,还是溢出,左溢出,右溢出.陷入了死结,网上找答案,得到要想进行大数运算可能要自己写算法了,我数学可没那么高深,要放弃了.

VC++6中没问题,不用担心有溢出,而且也不用去在意那个该死的.Net框架.可C不熟悉,上手慢,装了个鸟文版看着不舒服,就又下了一个残次品的中文版,残次品的定义是我装了出错之后给定义的.又找了一个健全的版本装,依旧报错.这系统算是被糟蹋了.重装!装Xp SP3,虽然想起装系统我就犯愁,但是没办法.

下载Xp系统盘的空闲上网闲逛,也不知道从哪得的灵感,想起用别的语言写个Dll去处理Vb中会溢出的算式,然后Vb去调用它取最终的结果就行了.然后就动手操作.果然可以.用E写了个简单的Dll,然后用Vb调用.哦耶.搞定.兴奋.非常的兴奋.

整理,虚拟机上编译(本机的操作系统已经接近混乱崩溃,没法正常编译.),然后分发给Vrml群里的一些人测试,当作端午节的礼物.呵呵,一共只有不到500K.结束了.战斗的前奏刚刚结束,该冲锋了.

欲编写一套虚拟公路系统,含冥思苦想出来的可视化建模功能,来作为我的Vrml收关之作,不知道结果,我只求过程中的喜悦.

夜深了,该睡去….安,端午快乐.

实现C#和VB.net之间的相互转换

也许你需要把你以前的VB.net项目迁移到C#,或者与此相反,不是每个.net程序员都同时精通C#和VB.net。也许你需要读懂用VB.net写的示例代码或者共享的源码,但是你又恰好只熟悉C#,这时候你就需要一种转换软件来帮助你快速、准确地完成你的工作。

  以下分别对目前流行的几种转换软件列出了安装、使用的方法,以及它们各自的优点和缺点,希望能帮助读者更快地找到自己需要的软件,并尽快部署、使用,解决工作中的问题。

  VB.net转换为C#

  1. VB.net to C# Converter(下载地址:http://www.vbconversions.com/

  VB.net to C# Converter是一款离线转换软件,安装简单,提供试用版,而且试用版永不过期,但是试用版只能翻译不超过600行源码的工程。VB.net to C# Converter将用户的VB.net项目用C#语言重新编写,同时变量名、注释行都被保留下来。它具有完备的功能,提供专业的报告生成工具,而且能够对转换过程中的错误生成错误记录,并且在此基础上提供错误分析和提供修改建议。总之,它是一款充分为使用者考虑的,功能完备的转换工具。

  它提供多种类型工程的转换,包括Windows Forms 工程、Console 工程、Windows Control 库、Web Control 库、Web Services工程、Windows Service 工程。提供多种形式的转换,包括单一工程、多个工程、交互式代码转换、命令行形式转换。大多数的VB 函数都能转换为相应的 C# 功能,而且注解等也能得到很好的转换。可以使用向导,并提供在线帮助。转换准确率高达99%。

  但是,它不支持中文,中文注解会生成乱码。完整版需要购买。

  2.在线VB.net程序转换为C#

  在线转换的网址是http://www.developerfusion.co.uk/utilities/convertvbtocsharp.aspx。使用方便,而且免费。只是目前正在试用阶段,转换后程序错误较多,并且在转换后的代码里不包含注释,这是因为转换后的代码在返回之前,首先被翻译为抽象树,而目前的这种树状结构把注释都忽略了。

  C#转换为VB.net

  1. C# to VB.NET Translator实现单个文件的转换

  这是一个使用Web Services的在线解决方案,转换界面已经简单的不能再简单了。你要做的只是把你的 C#代码拷贝、粘贴到输入框中然后点击翻译(Translate)按钮。它可以免费使用,但必须在线转换(网址是http://authors.aspalliance.com/aldotnet/examples/translate.aspx)。现在,它还不能处理标签(tags)或者任何HTML,所以你的C#代码必须是纯的C#。并且,它只能转换一个文件,不能转换整个目录。

  2.使用Web Services代理实现整个目录中文件的转换

  基于以上的Web Services,XML for ASP.NET Developers提供了可以实现整个目录转换的解决方案,你可以在下面网址看到它的示例代码和解决方案:http://www.xmlforasp.net/codeSection.aspx?csID=44。这种转换方式可以免费使用,并能转换整个目录。XML for ASP.NET Developers 上的解决方案实际还是调用C# to VB.net Translator的Web Services,只是扩展了C# to VB.net Translator的功能,但是部署要麻烦许多,需要自己建立工程,并添加引用。

  为了方便大家更好地理解XML for ASP.NET Developers的解决方案,在这里对解决方案的实现步骤做进一步阐述。其具体步骤如下:

  ● 新建一个asp.net Web 服务的C#工程ConvertC。

  ● 在工程中添加Web引用http://authors.aspalliance.com/aldotnet/examples/csharptovbtranslator.asmx?WSDL。该引用自动命名为com.aspalliance.authors.

  ●在该工程根目录下添加CsharpFiles文件夹,将需要转换的C#文件另存为.txt文本文件放到文件夹下。

  ●添加新的Web窗体ConvertCtoVb.aspx,在该窗体中添加id为CSharptoVBCon-verterFrm的form。

  ● 双击ConvertCtoVb.aspx生成ConvertCtoVb.aspx.cs 文件。该文件首先要实例化Web引用com.aspalliance.authors中的CSharpToVBTranslator类,并取得id为CSharptoVBCon-verterFrm的 form作为代码容器,然后对CSharpFiles文件夹中的每个文件分别读取需要转换的代码,调用该Web Service中的TranslateCSharpToVB( )方法进行转换,最后输出转换后的代码到页面的form代码容器。

  ● 设置ConvertCtoVb.aspx为初始文件,运行该工程,CsharpFiles文件夹下的所有文件就可以从c#转换到vb.net了。

  3.使用C# to VB.net Converter

  该软件下载地址是http://csharpconverter.claritycon.com/。该软件提供在线和离线两种方式实现C# to VB.net的转换,而且离线版安装简单,使用方便。但在某些情况下转换不太准确,其实这些情况在其他一些转换工具中也普遍存在。这就需要我们了解一些C#和VB.net之间的差别,下面就列出了几种需要手动修改的情况。需要注意的是,这些情况也是我们在使用别的转换软件实现自动转换后,应该重点检查的部分。

  ● C#中引用比较和值的比较都使用“==” 关键字,而VB.net 使用“is”关键字做引用比较,使用“=”来做值的比较,所以当C#程序中使用“==”来做引用比较时会出现转换错误。修改方法是:转换后,所有的引用比较中都用 “is”替换 “=”。

  ● C#中字符连接符和加法运算符都使用“+”,所以当C#中使用“+”作为字符连接符时将引起C#中的字符连接符“+”不能正确的转换为VB.net中的字符连接符“&”。修改方法是:转换后,手动修改字符连接符“+”为“&”。

  ● 因为VB.net是大小写不敏感的,C#转换后可能出现重名。修改方法是:手动修改成恰当的惟一名字。

  ● 注释有时不能加载到正确位置。修改方法是:手动把注释调整到正确位置。

  手工转换

  以上提到的是使用工具实现C#和VB.net之间的转换,但是在时间和工作量允许的情况下,你也可以完全通过手动修改实现C#和VB.net之间的相互转换。当然这样做的好处是明显的,首先你可以全面了解两种语言的语法和构造的差别,并可以通过一门语言学习另外一门语言。其次,也可以有效地避免上面提到的转换软件在特定情况下可能产生的错误。因为,虽然我们可以使用自动化工具实现转换,提高我们的工作效率,但至今却还没有一种工具能够实现100%的无差错转换。因为,大多数的转换软件都是基于字面和语法的转换,而不是基于程序逻辑的转换,所以程序转换过程中就可能因为程序逻辑不被理解而发生如前面提到过的错误,因此使用自动化工具转换后我们还是要进行测试和少量修改的,同时了解一定的C#和VB.net的语法和它们之间的差别对我们还是很有好处的。如果采用手工转换,那么C#和VB.net之间的语法对照表可能对你有用,可以参考以下网址:http://www.harding.edu/USER/fmccown/WWW/vbnet_csharp_comparison.html

另一则:

1.http://www.kamalpatel.net/(最常用的,不过对于16进制的Int不能正常转换)
在线版:VB.Net => C#   C#=>VB.Net
离线版:C#=>VB.Net
2.http://csharpconverter.claritycon.com/(推荐!非常好用的一个,几乎没出过太大的问题。)
在线版:C#=>VB.Net
离线版:C#=>VB.Net
3.http://www.ragingsmurf.com/
在线版:C#=>VB.Net
4.http://aspalliance.com/
在线版:C#=>VB.Net
5.http://developerfusion.com/
在线版:VB.Net => C#   C#=>VB.Net