three.js 设置和读取相机外观矢量

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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>

【讨论】:

以上是关于three.js 设置和读取相机外观矢量的主要内容,如果未能解决你的问题,请参考以下文章

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

three.js pov 相机环顾四周的错误

Three.js 中的“THREE.OrbitControls”中的相机位置变化

three.js 围绕 Y 轴的相机旋转似乎关闭

three.js - 相机变化的非常奇怪的行为

Three.js - 广告牌效果,相机平移后保持方向