👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
- 1.1 ☘️第一视角控制器FirstPersonControls控制相机
- 二、🍀利用THREE.FirstPersonControls实现第一视角控制
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中使用第一视角控制器FirstPersonControls控制相机,实现游戏第一人称效果,亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️第一视角控制器FirstPersonControls控制相机
THREE.FirstPersonControls 是 Three.js 的第一视角控制器,允许用户以第一人称视角进行三维场景的浏览、漫游。使用这个控制器时,用户可以通过鼠标或键盘来控制视角。
相关操控方法:
移动鼠标 向四周看
上、下、左、右方向键 向上、下、左、右移动
W 向前移动
A 向左移动
S 向后移动
D 向右移动
R 向上移动
F 向下移动
Q 停止移动
创建方法:
new THREE.FirstPersonControls(camera)
参数camera 为Threejs的相机对象
属性:
方法:
handleResize () : undefined 若应用程序窗口大小发生改变,则应当调用此函数。
lookAt ( vector : Vector3 ) : FirstPersonControls vector - 一个表示目标位置的向量。 或者,世界空间位置的x、y、z分量。 确保控制器将相机方向朝向到所传入的目标的位置。
lookAt ( x : Float, y : Float, z : Float ) : FirstPersonControls vector - 一个表示目标位置的向量。 或者,世界空间位置的x、y、z分量。 确保控制器将相机方向朝向到所传入的目标的位置。
二、🍀利用THREE.FirstPersonControls实现第一视角控制
1. ☘️实现思路
- 1、初始化renderer渲染器
- 2、初始化Scene三维场景
- 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
- 4、初始化THREE.AmbientLight环境光源,scene场景加入环境光源,初始化THREE.PointLight点光源,设置点光源位置,设置点光源投影,scene添加点光源。
- 5、加载几何模型:创建THREE.AxesHelper坐标辅助工具,创建THREE.MTLLoader加载器,调用load方法获取模型材质信息,在MTLLoader的load方法中创建THREE.OBJLoader obj模型加载器,OBJLoader 加载器设置材质为从MTLLoader获取的材质,调用OBJLoader的load方法,加载模型, 生成mesh物体,scene场景加入mesh和THREE.AxesHelper坐标辅助工具。
- 6、创建第一视角控制器FirstPersonControls,设置控制器相关参数。加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>learn44(使用第一视角控制器FIRSTPERSONCONTROLS控制相机)</title>
<script src="lib/threejs/127/three.js-master/build/three.js"></script>
<script src="lib/js/Detector.js"></script>
<script src="lib/js/chroma.js"></script>
<script src="lib/threejs/127/three.js-master/examples/js/loaders/OBJLoader.js"></script>
<script src="lib/threejs/127/three.js-master/examples/js/loaders/MTLLoader.js"></script>
<script src="lib/threejs/127/three.js-master/examples/js/controls/FirstPersonControls.js"></script>
<script src="lib/threejs/127/three.js-master/examples/js/libs/stats.min.js"></script>
<script src="lib/threejs/127/three.js-master/examples/js/libs/dat.gui.min.js"></script>
</head>
<style>
html, body {
margin: 0;
height: 100%;
}
canvas {
display: block;
}
</style>
<body onload="draw()">
</body>
<script>
var renderer
var initRender = () => {
renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.sortObjects = false
document.body.appendChild(renderer.domElement)
}
var camera
var 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
var initScene = () => {
scene = new THREE.Scene()
}
var light
var initLight = () => {
scene.add(new THREE.AmbientLight)
light = new THREE.PointLight(0xffffff)
light.position.set(0, 50, 0)
light.castShadow = true
scene.add(light)
}
var initModel = () => {
var helper = new THREE.AxesHelper(50)
scene.add(helper)
var mtlLoader = new THREE.MTLLoader()
mtlLoader.setPath('data/model/city/')
mtlLoader.load('city.mtl', material => {
var objLoader = new THREE.OBJLoader()
objLoader.setMaterials(material)
objLoader.setPath('data/model/city/')
objLoader.load('city.obj', object => {
var scale = chroma.scale(['yellow', '008ae5'])
setRandomColors(object, scale)
scene.add(object)
})
})
}
var 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
var initStats = () => {
stats = new Stats()
document.body.appendChild(stats.dom)
}
var controls
var 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轴的角度
}
var render = () => {
renderer.render(scene, camera)
}
var onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
render()
renderer.setSize(window.innerWidth, window.innerHeight)
}
var clock = new THREE.Clock()
var animate = () => {
render()
stats.update()
controls.update(clock.getDelta())
requestAnimationFrame(animate)
}
var draw = () => {
initRender()
initScene()
initCamera()
initLight()
initModel()
initStats()
initControls()
animate()
window.onresize = onWindowResize
}
</script>
</html>
效果如下: