82 Three.js 使用第一视角控制器FirstPersonControls控制相机
程序员文章站
2022-03-26 18:13:40
...
简介
顾名思义,通过第一视角控制器你可以像第一视角射击游戏那样控制摄像机。鼠标用于控制视角,键盘用于控制移动角色。本人感觉最类似的效果就是cs
游戏死亡后,能够随意漂浮的感觉。
案例实现
案例查看地址:http://www.wjceo.com/blog/threejs/2018-03-29/142.html
- 首先,引入相关库文件,其中,我们额外引入了一个处理颜色的库叫
chroma.js
库。在这里,就不详细介绍这个库了,如果需要相关内容,请查看其官方文档:http://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>
下一篇: 手把手教你如何微信公众号开发