美文网首页
threejs 自学 关于摄像机的使用

threejs 自学 关于摄像机的使用

作者: squidbrother | 来源:发表于2023-03-29 18:03 被阅读0次

    摄像机运动的理解

    观察一个模型的方式

    1. 保持摄像机不变情况下,通过修改被观察模型的旋转角度、位置、大小,来实现;
    2. 旋转摄像机的情况下,通过轨道控制器Orbit controls,实现摄像机的变化
    3. 不借助于轨道控制器,通过脚本来旋转摄像机 - (更加灵活,最重要一点,不需要人为操作)

    基本使用

    1. 三维图查看角度
    • x轴方向观察
    // 通过UI按钮改变相机观察角度
    document.getElementById('x').addEventListener('click', function () {
        camera.position.set(500, 0, 0); //x轴方向观察
        camera.lookAt(0, 0, 0); //重新计算相机视线方向
    })
    
    • y轴方向观察
    // 通过UI按钮改变相机观察角度
    document.getElementById('y').addEventListener('click', function () {
        camera.position.set(0, 500, 0); //y轴方向观察
        camera.lookAt(0, 0, 0); //重新计算相机视线方向
    })
    
    • z轴方向观察
    // 通过UI按钮改变相机观察角度
    document.getElementById('z').addEventListener('click', function () {
        camera.position.set(0, 0, 500); //z轴方向观察
        camera.lookAt(0, 0, 0); //重新计算相机视线方向
    })
    
    1. lookAt()的作用
      改变.position属性后,如果不执行.lookAt()方法,相机的观察方向默认不变
      如果你希望相机圆周运动的同时,改变相机视线方向,保持相机镜头始终指向坐标原点或其它位置,需要每次改变.position属性后,重新执行一遍.lookAt()方法
    function render() {
        angle += 0.01;
        camera.position.x = R * Math.cos(angle);
        camera.position.z = R * Math.sin(angle);
        // .position改变,重新执行lookAt(0,0,0)计算相机视线方向
        camera.lookAt(0,0,0);
        requestAnimationFrame(render);
    }
    render();
    
    1. 镜头的基本运动
      模拟 贯穿 整个街道的镜头效果
      模拟 望远镜放大缩小( 最好使用目标与摄像机的距离,作为边界显示 )
    // 渲染循环
    function render() {
        camera.position.z -= 0.3; //-- 相机逐步向canvas画布内移动(如果目标的z值 比摄像机的z值 小的话)
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    }
    render();
    
    // 渲染循环
    function render() {
        camera.position.z += 0.3; //-- 相机逐步向canvas画布外移动(如果目标的z值 比摄像机的z值 大的话)
        renderer.render(scene, camera);
        requestAnimationFrame(render);
    }
    render();
    

    实际使用

    1. 操控摄像机围绕模型旋转
    • 参考案例链接: https://threejs.org/examples/webgl_interactive_cubes.html
    let theta = 0;
    init();
    animate();
    function init(){
      let camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
    }
    function animate(){
      requestAnimationFrame( animate );
      render();
    }
    function render(){
      theta += 0.1;
      camera.position.x = radius * Math.sin( THREE.MathUtils.degToRad( theta ) );
      camera.position.y = radius * Math.sin( THREE.MathUtils.degToRad( theta ) );
      camera.position.z = radius * Math.cos( THREE.MathUtils.degToRad( theta ) );
      camera.lookAt( scene.position );
      camera.updateMatrixWorld();
    }
    
    1. 将移动镜头封装为一个函数,并且增加缓动效果
    • 参考案例链接: https://dragonir.github.io/3d/#/shadow - 光、模型与摄像机
    import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
    ...
    function animateCamera(position, rotation) {
      //相机 - 位置动画
      new TWEEN.Tween(camera.position)
        .to(position, 1800)
        .easing(TWEEN.Easing.Quadratic.InOut)
        .start()
        .onComplete(function () {
          TWEEN.remove(this)
        })
      //相机 - 旋转动画
      new TWEEN.Tween(camera.rotation)
        .to(rotation, 1800)
        .easing(TWEEN.Easing.Quadratic.InOut)
        .start()
        .onComplete(function () {
          TWEEN.remove(this)
        })
    }
    
    // 点击第一Tab菜单
    document.getElementById('one').addEventListener('click', () => {
      document.getElementById('one').classList.add('active');
      document.getElementById('two').classList.remove('active')
      document.getElementById('content').innerHTML = 一段文字'
      animateCamera({ x: 3.2, y: 2.8, z: 3.2 }, { y: 1 });
    });
    
    1. 摄像机沿着指定轨迹漫游
      示例地址 - http://www.webgl3d.cn/pages/188907/

    2. 操作摄像机与模型互动,如 开门进入车内动画

    • 操作摄像机移动到指定位置
      示例地址 - https://juejin.cn/post/7028780379649605646
      代码片段
    1. 当小人模型移动到某个指定区域范围时候,修改摄像机的位置以及朝向
    //-- 检测修改摄像机位置函数
    function checkChangeCameraFn(roleObject){
        //-- 当前摄像机的位置
        var camPos = new THREE.Vector3(
          camera.position.x,
          camera.position.y,
          camera.position.z
        );
    
        //-- 目标摄像机的位置
        var targetPos;
        
        //-- 角色进入指定范围
        if ( rolePosition.position.x > -3 && rolePosition.position.x < 22 && rolePosition.position.z > 31 && roleObject.position.z < 58 ) {
          targetPos = new THREE.Vector3(
            roleObject.position.x,
            roleObject.position.y + 50,
            roleObject.position.z + 40
          );
        }else{
            //-- 角色不在指定范围内,摄像机位置回到之前与角色关系位置
            targetPos = new THREE.Vector3(
              roleObject.position.x,
              roleObject.position.y + 30,
              roleObject.position.z + 60
            );
        }
        
        //-- 通过Vector3的lerp方法,实现当前位置与目标位置的缓动动画
        camPos.lerp(targetPos, 0.033);
        //-- 修改摄像机的位置以及朝向
        camera.position.copy(camPos);
        camera.lookAt(ballPosition.position);
    }
    animate();
    function animate(){
        requestAnimationFrame( animate );
        ...
        //-- 摄像机位置朝向改变
        checkChangeCameraFn(小人模型对象);
        renderer.render( scene, camera );
    }
    
    1. 模型沿着指定轨迹行驶,渲染时候切换三个摄像机镜头 -- (既有轨迹运动也有镜头切换,推荐!)
    • 添加若干相机,如全局相机,模型相机,被模型盯住模型上的相机,切换相机来显示
    • 沿着指定轨迹行驶
      原贴地址 - https://juejin.cn/post/7061203887536996360
      效果图

    OrbitControls轨道控制器 与 摄像机的关系

    • 说明:
      OrbitControls轨道控制器,是一个threejs的非核心库,无需安装,只要显示引入js文件即可

    执行构造函数THREE.OrbitControls()浏览器会同时干两件事,
    给浏览器定义了一个鼠标、键盘事件,自动检测鼠标键盘的变化,如果变化了就会自动更新相机的数据, 执行该构造函数同时会返回一个对象
    给该对象添加一个监听事件,只要鼠标或键盘发生了变化,就会触发渲染函数

    作者:3D建模学习
    链接:https://juejin.cn/post/7221777883160510525
    来源:稀土掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    • 轨道控制器与摄像机的关系
      ※ OrbitControls.target属性对应目标 等同于 camera.lookAt()的观察目标
      ※ OrbitControls.update(); 等同于 相机控件内部会执行 camera.lookAt(controls.target);
      ※ 对于透视投影相机而言,OrbitControls缩放,本质上就是改变camera.position
    轨道控制器与摄像机的关系 轨道控制器与摄像机的关系2
    • 轨道控制器常用属性和方法
    controls.enablePan = false; //禁止右键拖拽
    controls.enableRotate = false; //禁止旋转
    controls.enableZoom = false;//禁止缩放
    controls.minDistance = 200; //相机位置与观察目标点最小值
    controls.maxDistance = 500; //相机位置与观察目标点最大值
    controls.getDistance(); //计算出camera.position和controls.target的距离
    
    • 限制摄像机的旋转范围
      默认上下旋转范围:
    // 上下旋转范围
    controls.minPolarAngle = 0; //-- 默认值0
    controls.maxPolarAngle = Math.PI; //-- 默认值Math.PI
    

    限制不能看到模型底部

    controls.maxPolarAngle = Math.PI/2;
    

    限制左右范围 - 如: 前方180度内

    controls.minAzimuthAngle = -Math.PI/2;
    controls.maxAzimuthAngle = Math.PI/2;
    
    • 借助轨道控制器查看摄像机的位置变化
    orbitControl.addEventListener( 'change', function () {
    
        //相机位置与目标观察点距离
        // const pos = camera.position;
        // console.log( 'pos', pos );
        // const dis = orbitControl.getDistance();
        // console.log( 'dis', dis );
    
    } );
    

    未完待续.....

    相关文章

      网友评论

          本文标题:threejs 自学 关于摄像机的使用

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