2.4 综合实例

Sim.js框架简化了开发工作,面向对象和模块化的特点使得网页代码更加易于管理和维护,但同时也要求程序员要有清晰的设计思路,尤其是在3D对象类的定义上。本节我们介绍两个实例,以便让读者能够更好地理解并掌握Sim.js框架的编程方法。

2.4.1 地月系模拟动画

本节介绍了一个地月系模拟动画,最终的效果如图2-6所示,月亮自转的同时围绕地球公转,地球自转的同时围绕太阳公转,月亮作为地球的子类跟随地球运动,在运动过程中,还可以观察到光线变化、月偏食、月全食等现象。

图2-6 地月系模拟动画

同时,一并介绍一些前面没有提及的概念及其使用方法,包括:

(1)第一人称漫游;

(2)图片纹理;

(3)子类与层级关系;

(4)线段处理;

(5)粒子系统。

对于这些内容的解释和说明,我们在脚本文件中穿插进行。

(1)第一人称漫游。它允许用户通过键盘或鼠标对场景进行巡游控制,详见本书3.5.1节。

(2)图片纹理。在真实的3D场景中,模型是有纹理的,而不仅仅是只有颜色值,Three.js通过ImageUtils.loadTexture方法使用图片纹理对3D模型进行贴图,使得模型更接近真实。MeshLambertMaterial(朗勃面)是一种很常用的材质,它将使用漫反射的方式引用前面的纹理图片,最终效果还与光线有关;另外一种常用的材质是MeshPhongMaterial,它可以产生镜面效果。

(3)子类与层级关系。在本例中,月亮属于地球的子类,将跟随地球一起绕太阳公转,通过创建子类,不管地球如何运动,月亮将自动跟随地球,程序不需要再单独处理这部分内容。层级关系是计算机动画的重要概念之一。比如骨骼动画,对于人体动画,小腿骨骼将跟随大腿骨骼一起运动。

(4)线段处理。在真实的太阳系中并没有轨道线,但在程序中加入轨道线将使场景更加美观。我们使用圆形轨道来模拟真实轨道(真实轨道是椭圆的),THREE.LineBasicMaterial材质可将geometry中的顶点逐个相连,只要分段足够多,最终的效果将趋于平滑的圆形,本例中,轨道线被分成了120段。

(5)粒子系统。为使整个地月系看起来更加生动,我们为其添加了背景星空,随机地添加了1000颗星星,它们的大小和亮度不等,类似的情形包括烟雾效果、火焰效果、波纹效果等,在Three.js中,这类效果可以使用粒子系统来实现,即THREE.ParticleSystem。

请注意ParticleSystemMaterial材质的sizeAttenuation属性,它用于通知Three.js在摄像机移动时是否重新缩放每个粒子。此处设置为false的意义在于:这些星星粒子距离我们非常遥远,摄像机的移动对其而言产生不了视觉上的明显差异。

图2-7将场景扩展到了整个太阳系,包含水星、金星、地球、火星、木星、土星六大近地行星,所有星球均按真实大小比例和距太阳的距离构造,通过第一人称视角漫游,用户可以自由选择在任意位置、任意角度来观察太阳系。

图2-7 太阳系模拟动画

在这个模拟动画的制作过程中,还会用到一些更高级的编程知识,比如自定义几何体、着色器编程等。其中关于着色器编程方面的内容涉及一门新的语言GLSL(OpenGL Shading Language),本书不打算深入讨论,因为其涉及过多的GPU渲染管线方面的知识,这部分内容并非本书的主要写作目的。

2.4.2 雪花飘飘

2.4.1节中,背景星空部分我们使用了粒子系统(THREE.ParticleSystem)。粒子系统是一种特殊的几何体,它只有点(vertices),没有面(faces),实践中我们经常用它实现烟雾、火焰、尾气等效果。粒子系统的应用面很广,本节以“雪花飘飘”为例进行介绍,网页的最终效果如图2-8所示,主要的代码如下:

图2-8 雪花飘飘网页效果

这段代码随机地生成了10000个点,为每一个点贴上了雪花的图片纹理,并在update事件中不断更新每个顶点的y坐标,最终形成了“雪花飘飘”的动画效果。

本例共使用了10000个顶点来构成雪花效果,顶点越多,越消耗资源,对于烟雾效果来说,经常会有几十万甚至更多的顶点数。为提高效率,Three.js提供了BufferGeometry这种几何体它可以大大提高渲染效率。利用BufferGeometry构建粒子系统的一般方法如下: