Three.js开发秘籍:FlyControls的拖拽视角问题解决方案

简介: Three.js开发秘籍:FlyControls的拖拽视角问题解决方案

需求背景

工作中需要使用 threejs 制作一个第一人称的 viewer,在使用 threejsflyControls 时发现一些和需求不一样的情景。

主要的问题就是拖拽查看时相机在拖拽后会导致上方向的变化从而导致视角变化很奇怪,所以需要改造一下原本的 FlyControl

既然要改造那就肯定要先解析 FlyControls 的源码了

FlyControls的功能

FlyControls 实现了一个类似第一人称视角通过 WASD 来调整相机前进的基本控制器。

例子threejs.org/examples/#m…

文档threejs.org/docs/index.…

可以看到上图 WASD 控制移动,RF 控制上下移动,QE 旋转相机,方向键上下左右可以控制视角。

也可以用鼠标偏移位置自动旋转视角

源码分析属性声明

地址

github.com/mrdoob/thre…

首先 FlyControls 继承自 EventDispatcherEventDispatcher 是事件调度器。

主要是用于 FlyControls 的事件信息传递用。

构造函数中一个是 object 也就是控制的摄像机对象从 TS 定位文件中可以看出是一个Camera或者继承自Camera的对象。

domElement 则是当前 threejs renderer 绘制的 dom 元素

接下来就是一系列变量的定义

其中 movmentSpeedrollSpeed 是控制相机移动和旋转的速度的

dragToLook 则是我们需求中需要的拖拽使相机视角发生变化,可以看到这里默认是 false

autoForward 是自动向前

EPS 应该是最小误差修正用的

可以看到这里还用 lastQuaternionlastPosition 记录了最后相机的四元组和位置信息

tmpQuaternion 就是临时保存用的一个四元组

剩下就是一些状态值

源码分析事件监听

在代码最底部可以看到 FlyControls 监听了7个事件分别对应一系列操作。

先从第一个keydown分析

1、一开始判断是否按下了 alt 键和是否启用了控制器

2、然后根据按键的键码分别设置 moveState 的状态,其中 shift 对移动速度进行了修改

3、然后就是最关键的 updateMovementVectorupdateRotationVector,这两个之后进行分析。

这里 keyupkeydown 类似就不过多做分析

然后是鼠标操作三兄弟

pointerdown 可以看出来是根据 dragToLook 来进行不同的操作。

如果是拖拽调整视角就修改 status 的值

如果不是则根据按下的鼠标左键还是又键修改 moveState 的状态。

紧接着pointermove事件中

依旧如果不是使用拖拽查看或者 status大于0 (这里的 status>0 是由向前的 pointerdown 修改的,也就是可以看做是否按下了鼠标)

然后就是这个 getContainerDimensions ,其实就是查看这个当前的 viewer 是不是在 docment 对象,返回相应的大小和偏移值

halfWidthhalfHeight 就是当前 viewer 可视区域一半的宽高。

-( event.pageX - container.offset[ 0 ] ) ( ( event.pageY - container.offset[ 1 ] )是鼠标在当前可视区域的相对坐标,

其值减去一半的宽度后,其实就可以视作鼠标相对于可视区域中心点的相对位置了。

x轴来举例可以看出来 ( event.pageX - container.offset[ 0 ] ) - halfWidth 则是红线部分则是鼠标到中心点的距离。

然后除以 halfWidth 则是一个归一化处理,相当于把鼠标距离中心点位置的值域控制在0到1之间了,最后在修改 moveState

最后pointerup事件则是将状态还原

在此之后 可以看到 updateMovementVectorupdateRotationVector  实质上是修改了 moveVector 和  rotationVector

最后

再根据之前设置的速度和旋转值以及 rotationVectormoveVector 来控制相机的位置以及旋转。

最后的判断则是看移动和旋转的值是否太小了。

太小就进行忽略。

分析

那么这个控制器为什么会造成拖拽后上方向发生变化呢,其实从上面代码的分析不难看出。

先将鼠标向上旋转一个角度

再将鼠标朝右旋转

最后再朝下拖动鼠标时

此时的相机左方向轴已经不在x轴与y轴构成的平面上了。

所以相机上方向发生了变化。

其根本原因是相机左右旋转时旋转轴是以自身上方向为旋转轴造成的。

如果要保持相机上方向一致的情况下旋转视角应该以z轴作为相机旋转的旋转轴。

这样相机怎么旋转都能保持上方向一致了。



相关文章
|
5天前
|
JavaScript 前端开发
JS浮点数精度问题及高精度小数运算:BigNumber解决方案
JS浮点数精度问题及高精度小数运算:BigNumber解决方案
31 0
|
1月前
|
Web App开发 缓存 JavaScript
深入浅出Node.js后端开发
【9月更文挑战第26天】本文将引导你了解Node.js的基本原理,并通过实际案例展示如何在后端开发中应用它。我们将从Node.js的核心概念讲起,逐步深入到构建一个完整的后端服务,最后探讨如何优化你的Node.js应用。准备好让你的开发技能更上一层楼了吗?让我们一起潜入Node.js的世界!
|
5天前
|
小程序 JavaScript 前端开发
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
uni-app开发微信小程序:四大解决方案,轻松应对主包与vendor.js过大打包难题
58 1
|
17天前
|
JavaScript 前端开发 NoSQL
深入浅出Node.js后端开发
本文将引导你了解Node.js的基础知识,包括安装、运行环境搭建以及简单的代码示例。通过阅读本文,你将学会如何利用Node.js进行后端开发,并理解异步编程和事件驱动模型的核心概念。文章还将介绍一些实用的库和框架,帮助你快速开始Node.js项目。
45 4
|
19天前
|
JavaScript 前端开发 开发者
VUE 开发——Node.js学习(一)
VUE 开发——Node.js学习(一)
47 3
|
21天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js后端开发
【9月更文挑战第35天】本文将带你走进Node.js的世界,从基础概念到实战应用,一步步揭示Node.js在后端开发中的魅力。我们将通过实际代码示例,让你轻松掌握Node.js的开发技巧,开启你的后端开发之旅。
|
9天前
|
JavaScript 前端开发 安全
TypeScript的优势与实践:提升JavaScript开发效率
【10月更文挑战第8天】TypeScript的优势与实践:提升JavaScript开发效率
|
9天前
|
JavaScript 前端开发 IDE
深入理解TypeScript:提升JavaScript开发的利器
【10月更文挑战第8天】 深入理解TypeScript:提升JavaScript开发的利器
20 0
|
17天前
|
前端开发 JavaScript 关系型数据库
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
这篇文章介绍了一个名为Vue3Admin的全栈后台应用,前端基于SoybeanAdmin二次开发,后端基于Nest.js。主要使用了Vue3.5、AntDesignVue、UnoCSS、Pinia等前端技术栈,以及Nest.js、PostgreSQL、Prisma等后端技术栈。文章详细描述了系统的功能设计,包括动态国际化语言配置、登录用户操作日志、用户和角色权限映射、动态路由菜单、消息公告发布及前端业务功能等。同时,也提供了项目运行所需的环境和依赖,以及如何拉取代码、安装依赖和启动项目的方法。最后,文章展示了项目的演示图,并对项目进行了总结,指出项目未经严格测试,仅供学习交流使用。
前端的全栈之路:基于 Vue3 + Nest.js 全栈开发的后台应用
|
8天前
|
前端开发 JavaScript 开发者
JS 异步解决方案的发展历程以及优缺点
本文介绍了JS异步解决方案的发展历程,从回调函数到Promise,再到Async/Await,每种方案的优缺点及应用场景,帮助开发者更好地理解和选择合适的异步处理方式。