美文网首页
3.第一章3小节 场景动画

3.第一章3小节 场景动画

作者: 我的名字好长好长灬 | 来源:发表于2021-05-31 21:10 被阅读0次

    以下文章即Learn Threejs 第三版英文翻译学习记录,可以到正版书店购买对应书籍。

    如果你想在场景种功能使用动画,那第一件要做的事情就是先找到绘制场景的时间间隔(就是已特定的周期渲染场景)。在HTML5 和JavaScript Api 出来之前,使用setInterval方法去处理这件事情,这个方法定义了,我们可以100 毫秒去执行一个方法(就是周期函数,约定某个周期调用某个函数一次),但是这个方法没有考虑到浏览器的一些问题,如果你浏览其他的页面,这个函数依然会按照时间周期执行。而且,setInterval方法不是异步刷新屏幕,它需要更高的CPU使用率、频率、获得较差的性能。

    介绍 RequestAnimationFrame

    幸运的是,我们可以通过requestAnimationFrame这个函数来解决问题,通过这个函数,你可以按照时间间隔调用,而且不用定义这个时间。这个时间间隔有浏览器定义。你可以在将你的函数传入到这个方法中去处理你的绘制任务,浏览器会尽可能平滑、高效的处理这个绘制任务。

    function renderScene() { 

    requestAnimationFrame(renderScene); 

    renderer.render(scene, camera);

    }

    (就是一个while循环 / 也类似递归调用)

    在这个renderScene 函数中,我们调用了requestAnimationFrame函数,来保证动画的正常运行。你仅需要在创建场景完成后调用一次rendererScene函数来启动函数。

    ...

    document.getElementById("webgl-output").appendChild(renderer.domElement);

    renderScene();

    如果你运行这个示例,你会发现,和我们之前提供的示例,没有任何区别,因为我们还没有开始设置任何动画。在我们添加动画之前,我们需要添加一个小的插件,它会为我们提供有关动画帧率的相关信息。这个库是Threejs同一个作者开发的,渲染一个小的界面,为我们提供相关信息。

    添加这个静态库,我们需要在head里引入,例如:

    <script type="text/javascript" src="../../libs/util/Stats.js"></script>

    (我在demo中只发现了一个stats.min.js)

    唯一需要做的事情就是将这个库初始化,并添加到页面中;

    function initStats(type) {

           var stats = new Stats();

           stats.showPanel(type);// 0: fps, 1: ms, 2: mb, 3+: custom

           document.body.appendChild(stats.dom);

          return stats;

      }

    (这个我试过,有一个小窗口,能显示fps ms mb,3+什么都没有,setMode和showPanel都可以)

    通过函数初始化统计试图信息,并根据传入类型变量显示对应的视图,可以显示每秒渲染帧数(FPS)、渲染需要的时间(MS)、内存分配相关信息(MB), 在我们的初始化函数之前调用initStats函数,例如:

    function init(){

    var stats = initStats(); ...

    }

    Tip:说的意思是他将这些工具类的函数放到了util.js中,说你要用的话,就直接引入util.js

    <script type="text/javascript" src="../js/util.js"></script>

    我们现在唯一要做的事情就是在循环执行的方法中调用stats的update方法,在renderScene 函数中,例如:

    function renderScene() {

    stats.update();

    ......

    equestAnimationFrame(renderScene);

    renderer.render(scene, camera);

    }

    如果你运行了添加的代码,你将会看到在左上角有一个统计图,如截图所示(略,自己试吧);

    开始 立方体 动画

    我们写好了requestAnimationFrame和状态提示插件,我们现在找到一个地方写我们的动画代码。在这部分,我们将扩展renderScene方法,通过旋转各个坐标轴来执行立方体旋转动画,我们开始,下边是代码:

    function renderScene() { ...

    cube.rotation.x += 0.02;

    cube.rotation.y += 0.02;

    cube.rotation.z += 0.02;

    ... requestAnimationFrame(renderScene);

    renderer.render(scene, camera);

    }

    看起来很简单,是吧?我们要做的是,在每次renderScene函数调用刷新的时候,将每个坐标轴属性增加0.02,它显示是一个围绕所有轴平滑旋转的立方体。将蓝色的球执行弹性动画也不难。

    (https://www.cnblogs.com/jaycethanks/p/12032947.html 这篇文章详细介绍了,球的切面什么的,会解决你做出来的球不圆的问题)

    开始 球 动画

    弹球动画,我们再次向rebderScene函数中添加了几行代码,例如:

    var step=0;

    function renderScene() {

    ...

    step+=0.04;

    sphere.position.x = 20 + 10*(Math.cos(step));

    sphere.position.y = 2 + 10*Math.abs(Math.sin(step)); ...

    requestAnimationFrame(renderScene);

    renderer.render(scene, camera);

    }

    在场景中,立方体,我们不断设置了它的rotation属性,球体我们设置了position属性。我们希望球体从一个点完美的运动到场景的另一个点,而且是一个平滑的曲线,下面是我的算法介绍:(图略)

    运动轨迹图

    可以看到,我们需要修改x轴和y轴的值,数学函数Math.cos,Math.sin 函数可以帮助我们创建一个生成平滑的轨迹可供使用的一个值(就是通过函数的计算能够得到平滑曲线上的点的值),在这里我们不需要知道详细的工作流程。现在,你只需知道 step+=0.4 定义了球体运动的速度,在第8节中,Creating and Loading Advanced Meshes and Geometries (应该是一节内容,就是高级使用技巧),我们可以通过章节了解如何使用这些动画函数,而且会解释这些。下班就是球在空中弹跳的样子:(略 自己做就好了 没什么);

    在结束本章之前,我们需要在场景中再添加一些物体,在使用3D场景、动画、颜色和属性的时候,它通常需要一些实验来验证颜色或者是速度这些。如果你能有一个简单的GUI,允许你动态地改变这些属性,那做实验就更容易了。

    使用GUI 体验更加

    谷歌的几位员工开发了一个dat.GUI库(你可以通过http://code.google.com/p/dat-gui/查看文档),你可以在代码中很容易的使用用户界面组件,在本章的队后一部分,在示例中添加一个用户界面,允许我们执行以下操作:控制弹跳球的速度、控制立方体旋转。

    就像我们做统计一样,第一步将开源库添加html的<head>标签中,如:

    <script type="text/javascript" src="../../libs/util/dat.gui.js"></script>

    接下来需要配置JavaScript对象,使用dat.GUI来保存属性。在JavaScript主方法中,我们添加以下JavaScript对象,例如:

    var controls = new function() {

     this.rotationSpeed = 0.02; 

    this.bouncingSpeed = 0.03;

    }

    在这个JavaScript对象中,我们定义了两个属性:this.rotationSpeed 和 this.bouncingSpeed,而且给他们赋值,下一步,我们将这个对象传递到dat.GUI 对象中,并定义这两个属性的范围,如下所示:

    var gui = new dat.GUI();

    gui.add(controls, 'rotationSpeed', 0, 0.5);

    gui.add(controls, 'bouncingSpeed', 0, 0.5);

    rotationSpeed 和 bouncingSpeed 属性都是设置了0-0.5区间,现在我们只需要将操作放入到renderScene 渲染循环中。(后边说的比较复杂,意思就是将你之前加入GUI的两个属性,立刻就会生效了)

    function renderScene() {

    ...

    cube.rotation.x += controls.rotationSpeed;

     cube.rotation.y += controls.rotationSpeed; 

    cube.rotation.z += controls.rotationSpeed;

    step += controls.bouncingSpeed;

    sphere.position.x = 20 +(10 * (Math.cos(step)));

     sphere.position.y = 2 +(10 * Math.abs(Math.sin(step)));

    ...

    }

    现在,我们运行示例 05-control-gui.html,你可以看到一个简单的用户界面,用来控制弹性系数和旋转速度

    GUI 控制

    (其实咋说呢就是提供了一个GUI用户操作界面,操作控制项,还是比较好用的,新版的需要导入dat.gui.min.js)

    我们之前几章写的HTML代码,我们导入TrackballControls.js JavaScriypt文件。在这个文件中,我们可以控制camera 影响渲染结果,我们会在第9章详细介绍Camera的动画和移动。我们只需要添加几行JavaScript代码就可以添加这个组件,初始化球运动的轨迹...(接下来说的意思就是一定要记住将randerer添加到document中)。

    document.getElementById("webgl-output").appendChild(renderer.domElement); // add the two lines below

    var trackballControls = initTrackballControls(camera, renderer);

    var clock = new THREE.Clock();

    initTrackballControls 方法在utils.js中已经被定义了,这个我们之前提到过。在接下来的章节种功能,我们会介绍更多细节来说明它是怎么工作的,现在我们只需要更新render方法,例如:

    function render() {

    trackballControls.update(clock.getDelta());

    ...

    }

    现在已经做完了,如果你再次打开05-control-gui.html 示例,你可以移动你的鼠标,或者左击鼠标来移动视角camera,如果你在移动的时候点击 ‘s’键,你可以放大和缩小;如果按下‘d’,你可以拖拽那个场景。(我没找见这个文件)

    以后的demo将默认使用这些动画控制组件,一边您能够更容易的查看渲染结果。

    如果你在你的浏览器上查看,你可能注意到当你缩放浏览器的大小时,渲染界面不会跟着缩放,在下一个章节中,我们将会添加这个(就是想说下几节中,解决上述问题)。

    当浏览器尺寸改变时,渲染结果跟着改变

    当浏览器尺寸发生改变的时候,更改camera的操作是很简单的。第一件事情就是注册添加时间监听,如下:

    window.addEventListener('resize', onResize, false);

    现在,当浏览器i尺寸发生变化时,就会调用onResize方法,下一步我们需要做的是,当onResize方法调用时,我们需要更新camera和渲染,例如:

    function onResize() {

    camera.aspect = window.innerWidth / window.innerHeight; 

    camera.updateProjectionMatrix(); 

    renderer.setSize(window.innerWidth, window.innerHeight);

    }

    对于camera来说,我们需要改变aspect属性,让他始终保持浏览器横纵比;对于renderer,我们需要改变它的渲染尺寸;(接下来说的意思就是:把这些代码封装到一个init方法中,以便我们更好的使用它);

    var camera;

      var scene;

      var renderer;

    function init() { ...

    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(45, window.innerWidth /

    window.innerHeight, 0.1, 1000); renderer = new THREE.WebGLRenderer(); ...

    }

    总结

    第一章到此结束,在这一节中,我们为您展示了如何设置你的开发环境、如何获取程序代码、如何从提供的示例中开始。您进一步了解到Three.js是如何渲染的,第一步创建THREE.Scene 对象,添加camera、光线light、你想渲染的模型。我们也向您介绍了如何在基础的场景里显示阴影(我就没加出来,估计日后能加出来吧)、显示动画等,最后,我们添加了一些小组件。我们使用dat.GUI 它可以很快速的为我们创建用户界面来控制渲染属性,添加了stats.js(用来观察渲染情况,如内存、刷新频率等)

    在下一章节中,进一步了解Three.js的其他功能。

    相关文章

      网友评论

          本文标题:3.第一章3小节 场景动画

          本文链接:https://www.haomeiwen.com/subject/zxhfsltx.html