Three.js使用第一视角控制器FirstPersonControls控制相机(代码教程)
程序员文章站
2022-04-25 17:29:16
简介
顾名思义,通过第一视角控制器你可以像第一视角射击游戏那样控制摄像机。鼠标用于控制视角,键盘用于控制移动角色。本人感觉最类似的效果就是cs游戏死亡后,能够随意漂浮的感觉。...
简介
顾名思义,通过第一视角控制器你可以像第一视角射击游戏那样控制摄像机。鼠标用于控制视角,键盘用于控制移动角色。本人感觉最类似的效果就是cs游戏死亡后,能够随意漂浮的感觉。
案例实现
首先,引入相关库文件,其中,我们额外引入了一个处理颜色的库叫chroma.js库。在这里,就不详细介绍这个库了,如果需要相关内容,请查看其官方文档:https://gka.github.io/chroma.js/#color-rgba
<script src="/lib/libs/chroma.js"></script> <script src="/lib/js/controls/firstpersoncontrols.js"></script>
其次,就是在实例化相机以后,通过camera实例化相关对象,然后进行相关配置:
controls = new three.firstpersoncontrols(camera); controls.lookspeed = 0.2; //鼠标移动查看的速度 controls.movementspeed = 20; //相机移动速度 controls.nofly = true; controls.constrainvertical = true; //约束垂直 controls.verticalmin = 1.0; controls.verticalmax = 2.0; controls.lon = -100; //进入初始视角x轴的角度 controls.lat = 0; //初始视角进入后y轴的角度
最后,需要在每次渲染里面更新控制器:
var clock = new three.clock(); function animate() { render(); //更新性能插件 stats.update(); //更新控制器 controls.update(clock.getdelta()); requestanimationframe(animate); }
该控件的相关控制方法:
操控 | 效果 |
---|---|
移动鼠标 | 向四周看 |
上、下、左、右方向键 | 向上、下、左、右移动 |
w | 向前移动 |
a | 向左移动 |
s | 向后移动 |
d | 向右移动 |
r | 向上移动 |
f | 向下移动 |
q | 停止移动 |
案例代码
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>title</title> <style type="text/css"> html, body { margin: 0; height: 100%; } canvas { display: block; } </style> </head> <body onload="draw();"> </body> <script src="/lib/three.js"></script> <script src="/lib/js/loaders/objloader.js"></script> <script src="/lib/js/loaders/mtlloader.js"></script> <script src="/lib/libs/chroma.js"></script> <!--处理颜色的库--> <script src="/lib/js/controls/firstpersoncontrols.js"></script> <script src="/lib/js/libs/stats.min.js"></script> <script src="/lib/js/libs/dat.gui.min.js"></script> <script src="/lib/js/detector.js"></script> <script> var renderer; function initrender() { renderer = new three.webglrenderer({antialias:true}); renderer.setsize(window.innerwidth, window.innerheight); renderer.sortobjects = false; //告诉渲染器需要阴影效果 document.body.appendchild(renderer.domelement); } var camera; function initcamera() { camera = new three.perspectivecamera(45, window.innerwidth/window.innerheight, 0.1, 10000); camera.position.set(0, 10, 50); camera.lookat(new three.vector3(0,0,0)); } var scene; function initscene() { scene = new three.scene(); } //初始化dat.gui简化试验流程 var gui; function initgui() { //声明一个保存需求修改的相关数据的对象 gui = { }; var datgui = new dat.gui(); //将设置属性添加到gui当中,gui.add(对象,属性,最小值,最大值) } var light; function initlight() { scene.add(new three.ambientlight(0x444444)); light = new three.pointlight(0xffffff); light.position.set(0,50,0); //告诉平行光需要开启阴影投射 light.castshadow = true; scene.add(light); } function initmodel() { //辅助工具 var helper = new three.axeshelper(50); scene.add(helper); var mtlloader = new three.mtlloader(); mtlloader.setpath('/lib/assets/models/'); //加载mtl文件 mtlloader.load('city.mtl', function (material) { var objloader = new three.objloader(); //设置当前加载的纹理 objloader.setmaterials(material); objloader.setpath('/lib/assets/models/'); objloader.load('city.obj', function (object) { //设置颜色的取值范围 var scale = chroma.scale(['yellow', '008ae5']); console.log(object); //重新设置纹理颜色 setrandomcolors(object, scale); //将模型缩放并添加到场景当中 scene.add(object); }) }); } //添加纹理的方法 function setrandomcolors(object, scale) { //获取children数组 var children = object.children; //如果当前模型有子元素,则遍历子元素 if (children && children.length > 0) { children.foreach(function (e) { setrandomcolors(e, scale) }); } else { if (object instanceof three.mesh) { //如果当前的模型是楼层,则设置固定的颜色,并且透明化 if(array.isarray(object.material)){ for(var i = 0; i<object.material.length; i++){ var material = object.material[i]; var color = scale(math.random()).hex(); if (material.name.indexof("building") === 0) { material.color = new three.color(color); material.transparent = true; material.opacity = 0.7; material.depthwrite = false; } } } // 如果不是场景组,则给当前mesh添加纹理 else{ //随机当前模型的颜色 object.material.color = new three.color(scale(math.random()).hex()); } } } } //初始化性能插件 var stats; function initstats() { stats = new stats(); document.body.appendchild(stats.dom); } var controls; function initcontrols() { controls = new three.firstpersoncontrols(camera); controls.lookspeed = 0.2; //鼠标移动查看的速度 controls.movementspeed = 20; //相机移动速度 controls.nofly = true; controls.constrainvertical = true; //约束垂直 controls.verticalmin = 1.0; controls.verticalmax = 2.0; controls.lon = -100; //进入初始视角x轴的角度 controls.lat = 0; //初始视角进入后y轴的角度 } function render() { renderer.clear(); renderer.render( scene, camera ); } //窗口变动触发的函数 function onwindowresize() { camera.aspect = window.innerwidth / window.innerheight; camera.updateprojectionmatrix(); render(); renderer.setsize( window.innerwidth, window.innerheight ); } var clock = new three.clock(); function animate() { //更新控制器 render(); //更新性能插件 stats.update(); controls.update(clock.getdelta()); requestanimationframe(animate); } function draw() { //兼容性判断 if ( ! detector.webgl ) detector.addgetwebglmessage(); initgui(); initrender(); initscene(); initcamera(); initlight(); initmodel(); initcontrols(); initstats(); animate(); window.onresize = onwindowresize; } </script> </html>
下一篇: Docker镜像上传到阿里云的步骤详解