【问题标题】:three.js set and read camera look vectorthree.js 设置和读取相机外观矢量
【发布时间】:2013-03-19 18:48:39
【问题描述】:

而不是使用 camera.rotation 或使用 lookAt() 函数旋转相机 我想直接给相机传一个look vector... 是否可以直接设置一个camera look vector,是否可以从camera读取look vector?

【问题讨论】:

    标签: vector camera three.js


    【解决方案1】:

    相机没有“look vector”,所以不能设置。

    但是,您可以构造一个 point 来查看,方法是将您的查看向量添加到相机的位置,然后调用

    camera.lookAt( point );
    

    这里是如何确定相机正在看的方向,假设相机没有父级(除了场景)。

    相机正在向下看它的内部负 z 轴,所以创建一个指向负 z 轴的向量:

    var vector = new THREE.Vector3( 0, 0, - 1 );
    

    现在,对应用于相机的矢量应用相同的旋转:

    vector.applyQuaternion( camera.quaternion );
    

    生成的矢量将指向相机正在看的方向。

    或者,您可以使用以下方法,即使相机是另一个对象的子对象,该方法也可以:

    camera.getWorldDirection( dirVector );
    

    three.js r.73

    【讨论】:

    • 这是很好的信息,谢谢 West。我仍然认为内部某处必须有一个外观矢量,它应该是 3d 相机的基础......啊,好吧,我想我理解这背后的原因,相机永远不会移动,整个场景都围绕它进行变换,远眺 - z,因此外观向量始终为 0 0 -1,其他一切都旋转
    • 没有。相机在世界空间中移动,但从相机的参考系看,它正向下看它的负 z 轴。
    • 确定西,另一种方法(如果您使用观察点)是规范化(相机 - 观察)..这种方式应该能够避免父母时的额外计算
    【解决方案2】:

    上面的答案包装成一个实用程序,这就是我用我的三个实用程序所做的:

    THREE.Utils = {
        cameraLookDir: function(camera) {
            var vector = new THREE.Vector3(0, 0, -1);
            vector.applyEuler(camera.rotation, camera.eulerOrder);
            return vector;
        }
    };
    

    THREE.Utils.cameraLookDir(camera);打电话

    【讨论】:

    • 非常漂亮的马特风格,我可以期待另一个实用程序会以相同格式跟随 cameraLookDir 的大括号吗?
    • 是的,你只需要用逗号分隔它们。这是文字 javascript 对象表示法,您应该注意,您需要确保在此脚本之前加载了 THREE 以使其全部正常工作。
    • 对于我假设的大写:package = THREE,class= Utils,method = cameraLookDir。以防这看起来有点时髦。
    • 看起来不错@mattdlockyer,有没有办法使用它——在环绕 3d 模型时——保持文本标签朝向相机?
    • 使用精灵作为文本标签,它们将始终正确地指向和定向到相机
    【解决方案3】:

    这些其他答案非常有见地,但并不完全正确。该代码返回一个向量,该向量指向与相机指向的方向相同的方向。这是一个很好的开始!

    但除非相机位于原点 (0, 0, 0)(或正好位于将原点连接到旋转矢量点的线段上,但不超过该点,因此该点位于相机后面)相机不会看那个点。显然——只是常识——相机的位置也会影响正在观察的点。好好想想!!

    无论相机在哪里,相机方法lookAt() 都会查看 3D 空间中的一个点。因此,要获得相机正在注视的点,您需要通过调用来调整相机位置:

    vec.add( camera.position );

    还值得一提的是,相机不是在看一个点,而是在向下看一条由无数个点组成的线,每个点与相机的距离不同。其他答案中的代码返回一个长度正好为一个单位的向量,因为将四元数应用于归一化 z 轴向量 (0, 0, -1) 会返回另一个归一化向量(在不同方向上)。要计算距相机任意距离x 的观察点,请使用:

    THREE.Vector3( 0, 0, -x ).applyQuaternion( camera.quaternion ).add( camera.position );

    这会在距离原点x 的 z 轴上取一个点,将其旋转到相机的方向,然后通过添加相机的位置来创建一个“世界点”。我们想要一个“世界点”(而不仅仅是一个“相对于相机点”),因为camera.lookAt() 也需要一个“世界点”作为参数。

    【讨论】:

    • 在three.js中,Vector3类可用于表示点、向量或方向向量。在这种情况下,问题是关于方向向量。接受的答案解释了如何从方向向量设置相机方向。它还解释了如何从相机方向推断方向向量。接受的答案没有什么不正确的。你在回答别人的问题。
    • 是的。你是对的。我对此进行了更多思考,并看到您甚至提到将矢量添加到相机位置。你做得很好。对我来说,考虑如何使用 nlerp() 而不是 slerp() 很有趣,因为它的计算成本要低得多,并且如果选择距离 x 处的相机lookAt 点并插值到所需的值,则可以使其工作几乎相同lookAt 点也在距离 x 处。但你是对的。这是另一个话题。对于任何误解,我深表歉意。对不起。
    • 接受的答案解释了如何从方向向量设置相机方向。不,你没有。
    【解决方案4】:

    我所做的是在渲染场景之前使用方法lookAt(Vector),如下面的代码,只需在新的html文件上尝试使用它:)

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <title></title>
        <style >
          *{
            margin: 0 ;
          }
          #WebGlElement {
            height: 500px;
            width:  500px;
            background-color: red
          }
        </style>
      </head>
      <body>
        <script src="js/three.min.js"></script>
    
        <div id="WebGlElement"></div>
    
        <script>
          var contianer = document.getElementById("WebGlElement");
          var origin = new THREE.Vector3(0,0,0);
          // CREATE THREE BASIC ELEMENTS
          var scene = new THREE.Scene();
          var camera = new THREE.PerspectiveCamera( 40, 300/300, 1, 1000 );
    
          var renderer = new THREE.WebGLRenderer();
          // SET RENDERER AND ATTACH IT TO BODY
          renderer.setSize( 500, 500 );
          //document.body.appendChild( renderer.domElement );
          contianer.appendChild( renderer.domElement);
          // CREATE A GEOMETRY AND ADD IT TO SCENE
    
          /*var geometry = new THREE.BoxGeometry( 1, 1, 5 );
          var material = new THREE.MeshBasicMaterial( { color: 0x1abc9c } );
          material.wireframe = true ;
          material.wireframeLinewidth = 0.1 ;
          var cube = new THREE.Mesh( geometry, material );
          scene.add( cube );*/
          var geometry = new THREE.Geometry();
          geometry.elementsNeedUpdate=true;
    
          geometry.vertices.push(
    	      new THREE.Vector3( -0,  1, 0 ),
    	      new THREE.Vector3( -1, -1, 0 ),
    	      new THREE.Vector3(  1, -1, 0 )
          );
          geometry.faces.push(
            new THREE.Face3( 0, 1, 2 ),
            new THREE.Face3( 2, 1, 0 )
         );
    
          var material = new THREE.MeshBasicMaterial( { color: 0x1abc9c } );
          //material.wireframe = true ;
          //material.wireframeLinewidth = 0.1 ;
          var cube = new THREE.Mesh( geometry, material );
          scene.add( cube );
    
    
          var axisHelper = new THREE.AxisHelper( 1 );
          scene.add( axisHelper );
    
    
          // POSITION OF CAMER ON Z
          camera.position.z = 5;
          camera.position.y = 5;
          camera.up = new THREE.Vector3(0,0,1);
          
          var dir = 1;
          var number = 0.115
    
          // CREATE FUNCTION FOR RENDER
          var render = function () {
    
      				requestAnimationFrame( render );
      				//circle.rotation.x += 0.01;
              if ( camera.position.x> 5) {
                dir = -1;
              }
              if ( camera.position.x< -5) {
                 dir = 1;
              }
              camera.lookAt(cube.position);
    
              //camera.rotation.y += 0.015 * dir;
              camera.position.x += number * dir;
              renderer.render(scene, camera);
    
      	  };
    
    
          // EXECUTE FIRST RENDER
          render();
    
        </script>
    
    
    
      </body>
    </html>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-20
      • 1970-01-01
      • 2016-05-13
      • 2012-07-23
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      相关资源
      最近更新 更多