获取向量之间的xyz角度?

时间:2017-03-02 12:00:33

标签: vector rotation glsl

如何获得两个单位矢量之间的x,y和z旋转值?我不能使用点积,因为这只给我一个值。我想使用旋转矩阵在每个轴上旋转,对于那些我需要每个轴上的角度差异。 我尝试过只有两个组件的点积,但我有点困惑。 这样做有一个快速简便的方法吗?也许我对这两件事做错了,但我不知道。 如果有人知道一个glsl方法来做这个确切的事情,那将是最好的!

1 个答案:

答案 0 :(得分:4)

如果要获得两个矢量之间的x,y和z角度,请将两个矢量投影的点积乘以所需轴的正交平面。

也就是说,如果您想要两个矢量之间的z角,请创建原始的xy平面矢量。为此,请创建一个忽略向量的z分量的向量。

vec3 u = vec3( ... ); // your input vector
vec3 v = vec3( ... ); // your other input vector
float x_angle = acos( dot( u.yz, v.yz ) );
float y_angle = acos( dot( u.xz, v.xz ) );
float z_angle = acos( dot( u.xy, v.xy ) );

请注意,如果您使用u.xzu.zx,则无关紧要,因为您将使用点积。只需确保对点积中的两个向量使用相同的顺序。此外,代码的第3 - 5行假设单位向量,因为表达式中没有提及向量长度。

还应该注意,使用acos可能会导致参数的小值出错。为避免这种情况,可以采用2D投影向量之间的差异,并与atan2函数一起使用。

修改

建议最终目标是构造旋转矩阵以重新定向具有相同变换的其他矢量,我建议使用轴角方法(也称为任意轴旋转)。该方法包括找到两个矢量(点积)和一个适当的旋转轴之间的角度,该角度与该角度相对应(叉积)。

首先,您要使用点积找到两个矢量之间的角度。

float angle = acos( dot( u, v ) ); // for unit vectors

接下来,要查找旋转轴,请使用叉积。知道交叉乘积将产生垂直于uv的向量,以任意顺序交叉它们将给出一个合适的轴。

vec3 axis = cross( u, v ); // again, for unit vectors
// normalize this if need be

您想要使用的矩阵的形式可以在此Wikipedia article从轴和角度旋转矩阵的标题下找到。我建议存储一些临时值,以使计算运行得更快。

float c = cos(angle);
float s = sin(angle);
float t = 1 - c;

一旦构造了这个矩阵,只需将其乘以任何向量即可重新应用原始变换。