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 设置和读取相机外观矢量的主要内容,如果未能解决你的问题,请参考以下文章