美文网首页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)

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