美文网首页Three.js学习笔记
Three.js笔记(八)相机(2)

Three.js笔记(八)相机(2)

作者: BIM科学家小张 | 来源:发表于2022-03-14 16:45 被阅读0次

自定义控件

回到PerspectiveCamera透视相机上来。注释OrthographicCamera正交相机,取消注释PerspectiveCamera透视相机,移动相机,使其面向立方体,删掉tick中的对网格体旋转的部分。

// 相机

const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 1, 1000)

// const aspectRatio = sizes.width / sizes.height

// const camera = new THREE.OrthographicCamera(- 1 * aspectRatio, 1 * aspectRatio, 1, - 1, 0.1, 100)

// camera.position.x = 2

// camera.position.y = 2

camera.position.z = 3

camera.lookAt(mesh.position)

scene.add(camera)

以用鼠标控制相机为例,首先需要知道鼠标坐标。可以使用原生JavaScript的侦听事件addEventListener,来侦听mousemove事件。

坐标将通过回调函数返回,比如event.clientX和event.clientY

// 鼠标

window.addEventListener('mousemove', (event) =>

{

    console.log(event.clientX, event.clientY)

})

此处的返回值可以直接使用,但是调整下值的范围会更好,比如调整为区间为1的值。

比如,对于x:

    当光标位于画布左侧,输出-0.5

    当光标位于画布中间,输出0

    当光标位于画布右侧,输出0.5

当然也可以采用其它值。

仿照size变量,这里创建个cursor变量,变量默认属性包含x和y,当触发mousemove回调时,更新属性的值

// 鼠标

const cursor = {

    x: 0,

    y: 0

}

window.addEventListener('mousemove', (event) =>

{

    cursor.x = event.clientX / sizes.width - 0.5

    cursor.y = event.clientY / sizes.height - 0.5

    console.log(cursor.x, cursor.y)

})

event.clientX除以sizes.width会返回一个介于0~1之间的值,通过减去一个0.5,让值分布在0.5~-0.5

这样,就完成了鼠标位置的存储,并且可以通过tick更新位置。

const tick = () =>

{

    // ...

    // 更新相机

    camera.position.x = cursor.x

    camera.position.y = cursor.y

    // ...

}

运行后,会发现沿y轴运动方向不对,这是因为Three.js中positon.y向上运动时为正,在网页中clientY向下运动时为正。

通过在cursor.y上添加负号,来纠正。

window.addEventListener('mousemove', (event) =>

{

    cursor.x = event.clientX / sizes.width - 0.5

    cursor.y = - (event.clientY / sizes.height - 0.5)

})

可以通过cursor.x和cursor.y乘上一个数字,来调整幅度大小。此时仍可通过lookAt()方法调整相机朝向。

const tick = () =>

{

    // ...

    // 更新相机

    camera.position.x = cursor.x * 5

    camera.position.y = cursor.y * 5

    camera.lookAt(mesh.position)

    // ...

}

更进一步,还可以通过使用Math.sin()和Math.cos()实现相机绕网格体旋转。

同时使用cos和sin时,可以让运动变成圆周运动。要运动成完成的圆,角度的大小必须是Π的2倍。可以通过使用Math.PI,使用Π的值。

要增加圆的半径,可以简单的将Math.sin()和Math.cos()结果乘上一个数。

const tick = () =>

{

    // ...

    // 更新相机

    camera.position.x = Math.sin(cursor.x * Math.PI * 2) * 2

    camera.position.z = Math.cos(cursor.x * Math.PI * 2) * 2

    camera.position.y = cursor.y * 3

    camera.lookAt(mesh.position)

    // ...

}

tick()

这只是一个自定义控制的例子,Three.js内置了许多控件类,用来进行许多的相似操作。

内建控件

如果在Three.js文档中搜索控件,会看到很多现成的控件。

DeviceOrientationControls设备陀螺仪控件

DeviceOrientationControls设备陀螺仪控件,就是根据权限许可,依照设备方向相应的旋转相机。如果设备合适,可以用来创建全景图或者VR效果。

FlyControls飞行控件

FlyControls飞行控件允许像飞船一样控制相机,此时可在三个轴上任意旋转、并可前后移动。

FirstPersonControls第一人称控件

FirstPersonControls第一人称控件类似上一个,但具有一个固定向上的轴,即不能向前后左右翻转,虽然名字里有第一人称,但是相机本身不含人。

PointerLockControls指针锁定控件

PointerLockControls指针锁定控件使用了JavaScript的pointer lock API。通过这个,隐藏了鼠标指针,并使其居中,但仍在事件回调中继续发送移动。使用这个API,可以创建FPS游戏,但是,这个API只提供了相机的旋转,相机的移动和游戏中的物理效果仍旧需要自行处理。

OrbitControls环绕控件

OrbitControls环绕控件类似于上面的自定义控件的例子。可以通过左键绕某个点旋转,使用鼠标右键横向平移,使用滚轮放大缩小。

TrackballControls轨迹球控件

TrackballControls轨迹球控件类似OrbitControls环绕控件,但是可以在竖直方向上翻转。

TransformControls变换控件

TransformControls变换控件和相机无关。可以用它给对象添加一个控件,用来移动对象。

这里只讲OrbitControls环绕控件

OrbitControls环绕控件

注释掉tick中更新相机的部分。

实例化

首先,使用OrbitControls类实例化变量。

由于使用了Webpack,将会以以下形式引入

import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

之后就可以直接实例化OrbitControls 类,但要在创建相机后执行。

要使其正常工作,需要向其传入相机和画布,然后实例会自己处理鼠标事件。

// 控件

const controls = new OrbitControls(camera, canvas)

这样就可以使用鼠标左键或者右键来移动相机,使用滚轮进行缩放。

比自定义控件方便得多,且带有许多控件。然后再往更深层次研究。

target目标

默认情况下,相机看向场景中心。可以通过target目标属性修改它。

这个属性是个Vector3,意思就是通过x、y、z三个属性定义的。

如果希望OrbitControls环绕控件默认查看立方体上方,只需要增加y值。

controls.target.y = 2

这个用处不是很大,先注释掉它。

Damping阻尼

Damping阻尼通过加速度和摩擦力公式来平滑动画。

要启用阻尼,请将controls的enableDamping属性设置为true。

为了正常运行,还需要通过在每帧调用controls.update()。可以通过tick()实现。

// 控件

const controls = new OrbitControls(camera, canvas)

controls.enableDamping = true

// ...

const tick = () =>

{

    // ...

    // Update controls

    controls.update()

    // ...

}

这样控件看起来更加流畅。

阻尼可以用在各种旋转、移动、缩放、角度控制上,甚至按键绑定上。

何时使用内建控件

虽然这些控件很方便,但是都有局限性。如果过于依赖它们,可能需要以意想不到的方式改变类的工作方式。

首先请确保所需的功能,然后检查内建控件的功能是否完全覆盖所需的。

否则,需要自己建立控件。

相关文章

  • Three.js笔记(八)相机(2)

    自定义控件 回到PerspectiveCamera透视相机上来。注释OrthographicCamera正交相机,...

  • [读]three.js 相机camera位置属性设置详解

    three.js 相机camera位置属性设置详解

  • 场景起步

    引入three.js 新建场景 新建相机 添加renderer 渲染到html 执行渲染

  • Three.js笔记(七)相机(1)

    简述 在前面的章节中,已经使用PerspectiveCamera创建过相机,但是文档中还有其他类型的相机。 Cam...

  • three.js的两种相机

    THREE.js支持两种相机类型,透视相机(PerspectiveCamera,Css3的3d渲染也存在persp...

  • three.js笔记

    three.js 专业名词 场景(Scene)、相机(camera)和渲染器(WebGLRenderer)rend...

  • three.js 相机camera属性解析

    在使用three.js初始化相机的时候经常看到如下代码: function initCamera() { ...

  • three.js

    three.js 使用ES6标准 三大组建 场景(scene)、相机(camera)和渲染器(renderer)。...

  • three.js浅谈@相机

    相机的种类 上一节我们了解了threejs绘制一个场景的过程,这一节我们来认识以下什么是相机相机分为4种 透视相机...

  • 35three.js鼠标控制物体旋转缩放

    three.js包含了很多相机控制器,通过旋转相机可以达到同样的旋转效果。但是当我们需要固定场景背景,固定固定摄像...

网友评论

    本文标题:Three.js笔记(八)相机(2)

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