Javascript 找到旋转点的角度,使其面向三维空间中的另一点
假设我有两个向量: V1={x:3.296372727813439,y:-14.497928014719344,z:12.004105246875968} V2={x:2.3652551657790695,y:-16.73208508053185,z:8.945905454164146} 我如何计算v1需要旋转什么角度才能直接看v2 换成英语:假设我确切地知道我在太空中的什么地方,以及另一个人在太空中的什么地方。。。。从数学上讲,我如何计算出手指指向它们的角度 我当前(不正确)的公式Javascript 找到旋转点的角度,使其面向三维空间中的另一点,javascript,3d,three.js,rotation,Javascript,3d,Three.js,Rotation,假设我有两个向量: V1={x:3.296372727813439,y:-14.497928014719344,z:12.004105246875968} V2={x:2.3652551657790695,y:-16.73208508053185,z:8.945905454164146} 我如何计算v1需要旋转什么角度才能直接看v2 换成英语:假设我确切地知道我在太空中的什么地方,以及另一个人在太空中的什么地方。。。。从数学上讲,我如何计算出手指指向它们的角度 我当前(不正确)的公式 v2.x
v2.x -= v1.x; // move v2 (vector 2) relative to the new origin
v2.y -= v1.y;
v2.z -= v1.z;
v1.x = 0; // set v1 (vector 1) as the origin
v1.y = 0;
v1.z = 0;
var r = Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.y,2) + Math.pow(v2.z,2));
var θ = Math.acos((Math.pow(v2.x,2) + Math.pow(v2.z,2))/(r*Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.z,2))));
var ϕ = Math.acos(v2.x/Math.sqrt(Math.pow(v2.x,2) + Math.pow(v2.z,2)));
然后我用θ和φ旋转v1
v1.rotation.y = θ;
v2.rotation.x = ϕ;
但这给了我错误的旋转
θ=0.6099683401012933
ν=1.8663452274936656
但是如果我使用THREE.js并使用lookAt函数,它会产生这些旋转,这非常好:
y/θ:-0.24106818240525682
x/ñ:2.5106584861123644
提前谢谢你的帮助!我无法在最终结果中使用THREE.js,我尝试使用纯香草js,以便将其移植到另一种语言。正确的公式是:
var dx = v2.x-v1.x; //-0.93
var dy = v2.y-v1.y; //-31.22
var dz = v2.z-v1.z;
var rxy = Math.sqrt( Math.pow(dx,2) + Math.pow(dy,2) );
var lambda = Math.atan(dy/dx);
var phi = Math.atan(dz/rxy)
需要根据向量所处的四分之一,调整上述的phi
和lambda
公式。我让你很容易:
//if you do the calculations in degrees, you need to add 180 instead of PI
if (dx < 0) phi = phi + Math.PI;
if (dz < 0) lambda = -1 * lambda;
//如果以度为单位进行计算,则需要添加180而不是PI
如果(dx<0)phi=phi+Math.PI;
如果(dz<0)λ=-1*lambda;
使用矩阵怎么样?我认为v1是您的观点,并展望v2。矩阵是显示方向的好方法。欧拉角是方位的另一种解释
我的想法是建立一个从对象空间到世界空间的转换矩阵,你想做的事情可以分为三个步骤:
(0,0,0)
世界空间与对象空间相同<代码>v1'(0,0,0)v1(3.296372727813439,-14.497928014719344,12.004105246875968)
,对象空间与世界空间有偏移,但对象空间轴与世界空间轴平行,摄影机旋转仍为(0,0,0)v2
,正如您所看到的,摄影机旋转会发生变化(0,1,0)
。在对象空间中,可以通过v1-v2
计算基础z轴
z=(v1.x-v2.x,v1.y-v2.y,v1.z-v2.z)。normalize()
基x向量:我们知道基向量是垂直于z-up平面的向量,我们通过向上和z的叉积得到x向量
x=up.crossproduct(z)
基y向量,y在z-x平面前
y=z.产品(x)
我们可以将旋转矩阵构建为3 x 3矩阵:
然后,我们最终得到变换矩阵:
我们可以用矩阵表示摄像机的方位。如果你需要欧拉角或四元数。他们之间有一些相互转换的方式。您可以在本书中找到:
Three.js实现了与my way相同的LookAt()
功能
下面是three.js源代码,我添加了一些注释:
function lookAt( eye, target, up ) //eye : your camera position; target : which point you want to look at; up : camera up vector
{
if ( x === undefined ) {
x = new Vector3();
y = new Vector3();
z = new Vector3();
}
var te = this.elements; //this.elements is a 4 x 4 matrix stored in a list.
z.subVectors( eye, target ).normalize(); // set z vector with the direction from your camera to target point.
if ( z.lengthSq() === 0 ) {
z.z = 1;
}
x.crossVectors( up, z ).normalize(); // set the x vector by cross product up and z vector, you know cross product would get a //vector which perpendicular with these two vectors.
if ( x.lengthSq() === 0 ) {
z.z += 0.0001; // if z is ZERO vector, then, make a little addition to z.z
x.crossVectors( up, z ).normalize();
}
y.crossVectors( z, x ); // set y by cross product z and x.
// using basic axises to set the matrix.
te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x;
te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y;
te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z;
return this;
};
// now you get the transformation matrix, you can set the rotation or orientation with this matrix.
希望它能帮助你。x/ñ是绕x轴旋转的,因此它等于y,z之间的角度,对于y/θ,我们必须找到x,z之间的角度
V1={x:3.296372727813439,y:-14.497928014719344,z:12.004105246875968}
V2={x:2.3652551657790695,y:-16.73208508053185,z:8.945905454164146}
var v={dx:V2.x-V1.x,dy:V2.y-V1.y,dz:V2.z-V1.z}
测试向量(v);
函数测试向量(vec){
console.log();
可变角度=角(vec);
控制台日志(“φ:+角度。φ+”θ:+角度。θ);
}
函数角(vec){
返回{
θ:(Math.PI/2)+Math.atan2(vec.dz,vec.dx),
phi:(3*Math.PI/2)+Math.atan2(vec.dz,vec.dy)
};
}
我从THREE.js(r84)的最新版本中提取了相关代码。
我认为这是获得你想要的结果的最好方法
//除非注释中另有说明,否则所有函数都源自最新版本的THREE.js(r84)
// https://github.com/mrdoob/three.js/tree/master
//THREE.js根据麻省理工学院授权(版权所有©2010-2017 THREE.js作者)
//
//K Scandrett已将某些功能更改为在此设置下工作,
//但不是计算。
//任何错误都被认为是我的,而不是THREE.js的作者。
//我不保证在修改原始代码时没有产生任何bug
//因此,使用风险自负。享受比萨饼吧。
var v1={x:3.296372727813439,y:-14.497928014719344,z:12.004105246875968};
var v2={x:2.3652551657790695,y:-16.732085
//convert v1 and v2 Cartesian coordinates to Spherical coordinates;
var radiusV1 = Math.sqrt( Math.pow(v1.x) + Math.pow(v1.y) + Math.pow(v1.z));
var headingV1 = Math.atan2(v1.x , v1.z);
var pitchV1 = Math.asin(-(v1.y) / radiusV1);
var radiusV2 = Math.sqrt( Math.pow(v2.x) + Math.pow(v2.y) + Math.pow(v2.z));
var headingV2 = Math.atan2(v2.x , v2.z);
var pitchV2 = Math.asin(-(v2.y) / radiusV2);
//calculate angular displacement.
var displacementHeading = headingV2 - headingV1;
var displacementPitch = pitchV2 - pitchV1;
//make this displacement as an addition to camera rotation.
camera.rotation.x += displacementPitch;
camera.rotation.y += displacementHeading;