如何围绕另一个旋转点?
How to rotate point around another one?
我在围绕另一个点旋转时遇到问题。
我不擅长三角学,所以请帮助我并纠正我的解决方案。
要围绕另一个点旋转一个点,我将点移动到坐标系的原点,这样我要旋转的点将位于坐标系 (0,0,0) 的原点,旋转点Z、Y、Z轴再往回移
示例:我需要围绕点 y(3,2,1) 旋转点 x(1,1,1),所以我从点 x 减去点 y 的坐标 - x(1 - 3,1 - 2,1 - 1), rotate point x
围绕 x , y 和 z 轴,然后 return x`` 通过添加 y 坐标到正确的位置。它会工作吗?
对不起英语不好。
你的做法是正确的。它可以应用于不同的操作,如旋转和缩放。如果你仅限于一个几何函数的编程开发环境,其中心点仅以 (0,0,0) 为中心,那么你的步骤可以应用于执行相对于中心点的操作:
1) Apply a vector to the point to rotate that would move the center point to the origin by:
a) Determine the vector offset that would move the center point (for example point 3,2,1) to the origin.
In this case, it is vector <-3,-2,-1>.
b) Then apply it to the point (in this case 1,1,1 => [1 - 3,1 - 2,1 - 1];
2) Apply the operation (in this case a rotation), and probably a transformation matrix;
3) Apply the reverse of the vector in "1a" to the point determined in step "b" above.
第一个答案的类似解决方案:
Rotation of Point in 3D Space
理解旋转。
从二维开始。
二维坐标通过 2 个值 x 和 y 定义位置。 x 是沿 x 轴的距离,y 是沿 y 轴的距离。按照惯例,计算机图形通常具有从左到右定义的 x 轴和从上到下的 y 轴。
注意此答案中的代码是伪代码,不代表任何特定语言。
轴
我们可以将一个轴表示为一个向量,比如x轴是x方向1个单位,向下0个单位,y轴是x方向0个单位,向下1个单位。
对于代码,我们将向量定义为(例如 x 轴 xAxis.x = 1
、yAxis.y = 0
)
轴有一个重要的特性,即它们总是 1 个单位长。见下文单位向量
因此,在定义了轴和一个点后,我们可以通过先沿 x 轴然后沿 y 轴移动来找到它的位置。
xAxis = { x : 1, y : 0 }; // define the x axis
yAxis = { x : 0, y : 1 }; // define the y axis
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
旋转
这似乎是定位点的漫长方法。但是,当您旋转坐标系时,您实际上是在旋转 x 轴和 y 轴。因此,要获得旋转坐标系中的坐标,您需要 2 个旋转轴。见下文来自角度的单位向量
x轴旋转旋转量,y轴与x轴成90度。
rotation = PI / 4; // using radians rotate clockwise 45 deg
// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get the y axis at 90 deg (PI / 2) from the x axis
yAxis.x = cos(rotation + (PI / 2));
yAxis.y = sin(rotation + (PI / 2));
我们现在可以在旋转坐标系中移动点
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
有一些捷径。 y 轴与 x 轴成 90 度(除非倾斜)以将向量旋转 90 度,我们交换取反 y
的分量
// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get y at 90 deg from x
yAxis.x = -xAxis.y;
yAxis.y = xAxis.x;
同样沿轴移动,每个分量相互独立,因此可以在一行中完成计算。
pos.x = point.x * xAxis.x + point.y * yAxis.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y;
起源。
坐标系由原点和描述轴的单位向量定义。要围绕特定点旋转一个点,我们需要将旋转点作为原点。我们再移动坐标相对于新原点旋转
point = { x : 10, y : 10 };
origin = { x : 5 , y : 4 };
// move point relative to the origin
pos.x = point.x - origin.x;
pos.y = point.y - origin.y;
现在我们可以应用旋转
rotatedPos.x = pos.x * xAxis.x + pos.y * yAxis.x;
rotatedPos.y = pos.x * xAxis.y + pos.y * yAxis.y;
但是旋转后的点仍然是相对于原点的,我们需要将它相对于原点移回原点。
rotatedPos.x = rotatedPos.x + origin.x;
rotatedPos.y = rotatedPos.y + origin.y;
在计算机图形学中,我们通常会保留相对于其本地原点的相关坐标。它有一个我们称之为局部坐标系的坐标系,以[0,0]或3d中的[0,0,0]为旋转点。这意味着我们可以跳过相对于旋转点移动点的计算部分。
然后我们可以为每个轴在一行中进行旋转和定位
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
规模
我们想要缩放坐标也是很常见的,这可以通过改变代表每个轴的单位向量的长度来实现。例如,如果我们想沿 x 轴缩放坐标 2 倍,我们将 x 轴的长度设为 2 倍
point = {x : 5, y : 6}; // point in local coordinates.
xAxis = {x : 1, y : 0}; // normalised x axis
xAxis.x = xAxis.x * 2; // scale x axis
xAxis.y = xAxis.y * 2;
// apply transformation.
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
3D
对于 3D,一切都大同小异,但多了一个轴和组件
xAxis = {x : 1, y : 0, z : 0}; // direction and scale of x axis
yAxis = {x : 0, y : 1, z : 0}; // direction and scale of y axis
zAxis = {x : 0, y : 0, z : 1}; // direction and scale of z axis
origin = {x : 0, y : 0, z : 0}; // position of origin.
因此要将点移动到上述 3D 坐标系中
point = {x : 5, y : 6, z : 4}; // point in local coordinates.
// move point.x distances along x axis
pos.x = point.x * xAxis.x
pos.y = point.x * xAxis.y
pos.z = point.x * xAxis.z
// move point.y distances along y axis
pos.x += point.y * yAxis.x
pos.y += point.y * yAxis.y
pos.z += point.y * yAxis.z
// move point.y distances along y axis
pos.x += point.z * zAxis.x
pos.y += point.z * zAxis.y
pos.z += point.z * zAxis.z
// then relative to the origin
pos.x += origin.x
pos.y += origin.y
pos.z += origin.z
或更紧凑
pos.x = point.x * xAxis.x + point.y * yAxis.x + point.z * zAxis.x + origin.x
pos.y = point.x * xAxis.y + point.y * yAxis.y + point.z * zAxis.y + origin.y
pos.z = point.x * xAxis.z + point.y * yAxis.z + point.z * zAxis.z + origin.z
矩阵
上面开始变得有点笨拙所以为了简化它我们可以转换上面的对象point
, xAxis
, yAxis
, zAxis
, origin
到一组数组(称为矩阵)
point = [5,6,4]; // vector as array [x,y,z]
origin = [0,0,0]; // origin as array [x,y,z]
rotation = [1,0,0,0,1,0,0,0,1]; // 3 axis [x.x,x.y,x.z, y.x,y.y,y.z, z.x,z.y,z.z]
// rotation /*
[x.x,x.y,x.z, // x axis
y.x,y.y,y.z, // y axis
z.x,z.y,z.z] // z axis
*/
符号可以简化,在许多语言中,重载允许您直接以 shorthand 形式进行数学计算。
pos = point * rotation + origin;
3D 旋转
在 2D 中,我们通常只围绕一个虚轴(屏幕内外的 z 轴)旋转,在 3D 中,我们围绕 3 个轴(x、y 或 z 轴)之一旋转。
我们旋转的顺序也会影响最终旋转的位置。围绕 z 旋转 5 度然后围绕 y 旋转 10 度不同于围绕 y 旋转 10 度然后围绕 z 旋转 5 度。
由于每个轴本身就是一个可以旋转的向量,我们可以通过一个旋转矩阵来旋转每个轴。结果是一个组合了许多旋转的矩阵。
假设我们想绕 z 轴旋转 10 度,我们创建了 3 个旋转轴
ang = 10; // in deg
xAxisA = [cos(ang) ,sin(ang),0]; // 1 unit long
yAxisA = [-sin(ang),cos(ang),0]; // 1 unit long
zAxisA = [0 ,0 ,1]; // 1 unit long
或者作为旋转矩阵
A = rotationZ = [cos(ang), sin(ang), 0, -sin(ang), cos(ang), 0, 0, 0, 1];
然后我们想绕 y
旋转
xAxisB = [cos(ang) ,0 , sin(ang)]; // 1 unit long
yAxisB = [0, 1 , 0 ]; // 1 unit long
zAxisB = [-sin(ang),0, cos(ang)]; // 1 unit long
或者作为旋转矩阵
B = rotationY = [cos(ang), 0, sin(ang), 0, 1, 0, -sin(ang), 0, cos(ang)];
然后我们可以通过 y 旋转旋转 z 旋转中的每个轴。
// rotate each rotation axis by the second rotation axis.
xAxisAB.x = xAxisA.x * xAxisB.x + xAxisA.y * yAxisB.x + xAxisA.z * zAxisB.x;
xAxisAB.y = xAxisA.x * xAxisB.y + xAxisA.y * yAxisB.y + xAxisA.z * zAxisB.y;
xAxisAB.z = xAxisA.x * xAxisB.z + xAxisA.y * yAxisB.z + xAxisA.z * zAxisB.z;
yAxisAB.x = yAxisA.x * xAxisB.x + yAxisA.y * yAxisB.x + yAxisA.z * zAxisB.x;
yAxisAB.y = yAxisA.x * xAxisB.y + yAxisA.y * yAxisB.y + yAxisA.z * zAxisB.y;
yAxisAB.z = yAxisA.x * xAxisB.z + yAxisA.y * yAxisB.z + yAxisA.z * zAxisB.z;
zAxisAB.x = zAxisA.x * xAxisB.x + zAxisA.y * yAxisB.x + zAxisA.z * zAxisB.x;
zAxisAB.y = zAxisA.x * xAxisB.y + zAxisA.y * yAxisB.y + zAxisA.z * zAxisB.y;
zAxisAB.z = zAxisA.x * xAxisB.z + zAxisA.y * yAxisB.z + zAxisA.z * zAxisB.z;
或空手
rotationAB = rotationZ * rotationY;
或
AB = A * B;
生成的矩阵 AB
是 z 旋转和 y 旋转的组合旋转。你可以继续前进,围绕 x
旋转
// rotate about the x Axis
xAxisC = [1, 0 , 0 ]; // 1 unit long
yAxisC = [0, cos(ang) , sin(ang)]; // 1 unit long
zAxisC = [0, -sin(ang), cos(ang)]; // 1 unit long
C = rotationX =[1, 0, 0, 0, cos(ang), sin(ang), 0, -sin(ang), cos(ang)];
最终轮换为
ABC = A * B * C
但请记住顺序很重要。
A * B * C != C * B * A; // order of multiplication is important.
使用矩阵、向量库。
以上是大学一年级计算机科学课程几周内将涵盖的内容,但假设您对矢量数学有很好的理解。编写代码可能会变得非常重复,并且由于问题的性质,很难阅读和发现错误。
我一直认为最好的学习方法是编写自己的库,但在这种情况下,库是一个很好的起点,因为这个主题比旋转、缩放和平移更深入。
那里有数百个 matrix/vector 数学库,一个好的起点是 github
数学符号
在数学中,x 轴称为 î
(发音为 i hat),y 轴称为 ĵ
(发音为 j hat)。每个轴由一个单位向量 î = [1,0]
和 ĵ = [0,1]
定义(对于 3D,我们使用三个 3D 向量 î = [1,0,0]
、ĵ = [0,1,0]
和 k hat = [0,0,1]
对不起,我找不到k 帽子在字符集中)
矢量基础知识。
一个向量
向量是一组表示方向和距离的数字。在数学中,向量是矩阵。例如 v = [1,0]
在代码中为 structure/object/class v = { x : 1, y : 0}
矢量也可以描述为距离和方向,例如 10 公里东南。从一种类型转换为另一种类型很容易(见下文)
单位向量。
单位向量是长度为 1 个单位的向量。 (1,0) 是一个单位向量,它的长度是 1 个单位长。您可以乘以单位向量以找到原点 n 个单位。
n = 5;
axis = { x : 1, y : 0 };
point.x = axis.x * n; // 5 * 1 = 5
point.y = axis.y * n; // 5 * 0 = 0
矢量长度
您可以使用毕达哥拉斯来获取向量的长度。例如,向量 {x : 3, y : 4}
的长度等于 sqrt( 3 * 3 + 4 * 4 ) = sqrt( 9 + 16 ) = sqrt( 25 ) = 5
五个单位长,显然不是单位向量
标准化向量(标准化美式拼写)
向量归一化过程会将向量转换为单位向量。它是通过将向量的分量除以向量长度来完成的。
vec = { x : 3, y : 4 };
length = sqrt( vec.x * vec.x + vec.y * vec.y ); // length = 5
// nVec is the normalised vector vec
nVec.x = vec.x / length; // 3/5 = 0.6;
nVec.y = vec.y / length; // 4/5 = 0.8;
来自角度的单位向量
为了在特定方向创建单位向量,我们使用了一点三角函数
angle = 90; // in deg (normally this is radians)
v90.x = cos(angle);
v90.y = sin(angle);
我在围绕另一个点旋转时遇到问题。 我不擅长三角学,所以请帮助我并纠正我的解决方案。
要围绕另一个点旋转一个点,我将点移动到坐标系的原点,这样我要旋转的点将位于坐标系 (0,0,0) 的原点,旋转点Z、Y、Z轴再往回移
示例:我需要围绕点 y(3,2,1) 旋转点 x(1,1,1),所以我从点 x 减去点 y 的坐标 - x(1 - 3,1 - 2,1 - 1), rotate point x
围绕 x , y 和 z 轴,然后 return x`` 通过添加 y 坐标到正确的位置。它会工作吗?
对不起英语不好。
你的做法是正确的。它可以应用于不同的操作,如旋转和缩放。如果你仅限于一个几何函数的编程开发环境,其中心点仅以 (0,0,0) 为中心,那么你的步骤可以应用于执行相对于中心点的操作:
1) Apply a vector to the point to rotate that would move the center point to the origin by:
a) Determine the vector offset that would move the center point (for example point 3,2,1) to the origin.
In this case, it is vector <-3,-2,-1>.
b) Then apply it to the point (in this case 1,1,1 => [1 - 3,1 - 2,1 - 1];
2) Apply the operation (in this case a rotation), and probably a transformation matrix;
3) Apply the reverse of the vector in "1a" to the point determined in step "b" above.
第一个答案的类似解决方案: Rotation of Point in 3D Space
理解旋转。
从二维开始。
二维坐标通过 2 个值 x 和 y 定义位置。 x 是沿 x 轴的距离,y 是沿 y 轴的距离。按照惯例,计算机图形通常具有从左到右定义的 x 轴和从上到下的 y 轴。
注意此答案中的代码是伪代码,不代表任何特定语言。
轴
我们可以将一个轴表示为一个向量,比如x轴是x方向1个单位,向下0个单位,y轴是x方向0个单位,向下1个单位。
对于代码,我们将向量定义为(例如 x 轴 xAxis.x = 1
、yAxis.y = 0
)
轴有一个重要的特性,即它们总是 1 个单位长。见下文单位向量
因此,在定义了轴和一个点后,我们可以通过先沿 x 轴然后沿 y 轴移动来找到它的位置。
xAxis = { x : 1, y : 0 }; // define the x axis
yAxis = { x : 0, y : 1 }; // define the y axis
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
旋转
这似乎是定位点的漫长方法。但是,当您旋转坐标系时,您实际上是在旋转 x 轴和 y 轴。因此,要获得旋转坐标系中的坐标,您需要 2 个旋转轴。见下文来自角度的单位向量
x轴旋转旋转量,y轴与x轴成90度。
rotation = PI / 4; // using radians rotate clockwise 45 deg
// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get the y axis at 90 deg (PI / 2) from the x axis
yAxis.x = cos(rotation + (PI / 2));
yAxis.y = sin(rotation + (PI / 2));
我们现在可以在旋转坐标系中移动点
point = { x : 10, y : 10 };
// position the point first move along the x axis by distance x
pos.x = point.x * xAxis.x;
pos.y = point.x * xAxis.y;
// then move along the y axis by distance y
pos.x = pos.x + point.y * yAxis.x;
pos.y = pos.y + point.y * yAxis.y;
有一些捷径。 y 轴与 x 轴成 90 度(除非倾斜)以将向量旋转 90 度,我们交换取反 y
的分量// get the x axis at 45 deg
xAxis.x = cos(rotation);
xAxis.y = sin(rotation);
// get y at 90 deg from x
yAxis.x = -xAxis.y;
yAxis.y = xAxis.x;
同样沿轴移动,每个分量相互独立,因此可以在一行中完成计算。
pos.x = point.x * xAxis.x + point.y * yAxis.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y;
起源。
坐标系由原点和描述轴的单位向量定义。要围绕特定点旋转一个点,我们需要将旋转点作为原点。我们再移动坐标相对于新原点旋转
point = { x : 10, y : 10 };
origin = { x : 5 , y : 4 };
// move point relative to the origin
pos.x = point.x - origin.x;
pos.y = point.y - origin.y;
现在我们可以应用旋转
rotatedPos.x = pos.x * xAxis.x + pos.y * yAxis.x;
rotatedPos.y = pos.x * xAxis.y + pos.y * yAxis.y;
但是旋转后的点仍然是相对于原点的,我们需要将它相对于原点移回原点。
rotatedPos.x = rotatedPos.x + origin.x;
rotatedPos.y = rotatedPos.y + origin.y;
在计算机图形学中,我们通常会保留相对于其本地原点的相关坐标。它有一个我们称之为局部坐标系的坐标系,以[0,0]或3d中的[0,0,0]为旋转点。这意味着我们可以跳过相对于旋转点移动点的计算部分。
然后我们可以为每个轴在一行中进行旋转和定位
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
规模
我们想要缩放坐标也是很常见的,这可以通过改变代表每个轴的单位向量的长度来实现。例如,如果我们想沿 x 轴缩放坐标 2 倍,我们将 x 轴的长度设为 2 倍
point = {x : 5, y : 6}; // point in local coordinates.
xAxis = {x : 1, y : 0}; // normalised x axis
xAxis.x = xAxis.x * 2; // scale x axis
xAxis.y = xAxis.y * 2;
// apply transformation.
pos.x = point.x * xAxis.x + point.y * yAxis.x + origin.x;
pos.y = point.x * xAxis.y + point.y * yAxis.y + origin.y;
3D
对于 3D,一切都大同小异,但多了一个轴和组件
xAxis = {x : 1, y : 0, z : 0}; // direction and scale of x axis
yAxis = {x : 0, y : 1, z : 0}; // direction and scale of y axis
zAxis = {x : 0, y : 0, z : 1}; // direction and scale of z axis
origin = {x : 0, y : 0, z : 0}; // position of origin.
因此要将点移动到上述 3D 坐标系中
point = {x : 5, y : 6, z : 4}; // point in local coordinates.
// move point.x distances along x axis
pos.x = point.x * xAxis.x
pos.y = point.x * xAxis.y
pos.z = point.x * xAxis.z
// move point.y distances along y axis
pos.x += point.y * yAxis.x
pos.y += point.y * yAxis.y
pos.z += point.y * yAxis.z
// move point.y distances along y axis
pos.x += point.z * zAxis.x
pos.y += point.z * zAxis.y
pos.z += point.z * zAxis.z
// then relative to the origin
pos.x += origin.x
pos.y += origin.y
pos.z += origin.z
或更紧凑
pos.x = point.x * xAxis.x + point.y * yAxis.x + point.z * zAxis.x + origin.x
pos.y = point.x * xAxis.y + point.y * yAxis.y + point.z * zAxis.y + origin.y
pos.z = point.x * xAxis.z + point.y * yAxis.z + point.z * zAxis.z + origin.z
矩阵
上面开始变得有点笨拙所以为了简化它我们可以转换上面的对象point
, xAxis
, yAxis
, zAxis
, origin
到一组数组(称为矩阵)
point = [5,6,4]; // vector as array [x,y,z]
origin = [0,0,0]; // origin as array [x,y,z]
rotation = [1,0,0,0,1,0,0,0,1]; // 3 axis [x.x,x.y,x.z, y.x,y.y,y.z, z.x,z.y,z.z]
// rotation /*
[x.x,x.y,x.z, // x axis
y.x,y.y,y.z, // y axis
z.x,z.y,z.z] // z axis
*/
符号可以简化,在许多语言中,重载允许您直接以 shorthand 形式进行数学计算。
pos = point * rotation + origin;
3D 旋转
在 2D 中,我们通常只围绕一个虚轴(屏幕内外的 z 轴)旋转,在 3D 中,我们围绕 3 个轴(x、y 或 z 轴)之一旋转。
我们旋转的顺序也会影响最终旋转的位置。围绕 z 旋转 5 度然后围绕 y 旋转 10 度不同于围绕 y 旋转 10 度然后围绕 z 旋转 5 度。
由于每个轴本身就是一个可以旋转的向量,我们可以通过一个旋转矩阵来旋转每个轴。结果是一个组合了许多旋转的矩阵。
假设我们想绕 z 轴旋转 10 度,我们创建了 3 个旋转轴
ang = 10; // in deg
xAxisA = [cos(ang) ,sin(ang),0]; // 1 unit long
yAxisA = [-sin(ang),cos(ang),0]; // 1 unit long
zAxisA = [0 ,0 ,1]; // 1 unit long
或者作为旋转矩阵
A = rotationZ = [cos(ang), sin(ang), 0, -sin(ang), cos(ang), 0, 0, 0, 1];
然后我们想绕 y
旋转xAxisB = [cos(ang) ,0 , sin(ang)]; // 1 unit long
yAxisB = [0, 1 , 0 ]; // 1 unit long
zAxisB = [-sin(ang),0, cos(ang)]; // 1 unit long
或者作为旋转矩阵
B = rotationY = [cos(ang), 0, sin(ang), 0, 1, 0, -sin(ang), 0, cos(ang)];
然后我们可以通过 y 旋转旋转 z 旋转中的每个轴。
// rotate each rotation axis by the second rotation axis.
xAxisAB.x = xAxisA.x * xAxisB.x + xAxisA.y * yAxisB.x + xAxisA.z * zAxisB.x;
xAxisAB.y = xAxisA.x * xAxisB.y + xAxisA.y * yAxisB.y + xAxisA.z * zAxisB.y;
xAxisAB.z = xAxisA.x * xAxisB.z + xAxisA.y * yAxisB.z + xAxisA.z * zAxisB.z;
yAxisAB.x = yAxisA.x * xAxisB.x + yAxisA.y * yAxisB.x + yAxisA.z * zAxisB.x;
yAxisAB.y = yAxisA.x * xAxisB.y + yAxisA.y * yAxisB.y + yAxisA.z * zAxisB.y;
yAxisAB.z = yAxisA.x * xAxisB.z + yAxisA.y * yAxisB.z + yAxisA.z * zAxisB.z;
zAxisAB.x = zAxisA.x * xAxisB.x + zAxisA.y * yAxisB.x + zAxisA.z * zAxisB.x;
zAxisAB.y = zAxisA.x * xAxisB.y + zAxisA.y * yAxisB.y + zAxisA.z * zAxisB.y;
zAxisAB.z = zAxisA.x * xAxisB.z + zAxisA.y * yAxisB.z + zAxisA.z * zAxisB.z;
或空手
rotationAB = rotationZ * rotationY;
或
AB = A * B;
生成的矩阵 AB
是 z 旋转和 y 旋转的组合旋转。你可以继续前进,围绕 x
// rotate about the x Axis
xAxisC = [1, 0 , 0 ]; // 1 unit long
yAxisC = [0, cos(ang) , sin(ang)]; // 1 unit long
zAxisC = [0, -sin(ang), cos(ang)]; // 1 unit long
C = rotationX =[1, 0, 0, 0, cos(ang), sin(ang), 0, -sin(ang), cos(ang)];
最终轮换为
ABC = A * B * C
但请记住顺序很重要。
A * B * C != C * B * A; // order of multiplication is important.
使用矩阵、向量库。
以上是大学一年级计算机科学课程几周内将涵盖的内容,但假设您对矢量数学有很好的理解。编写代码可能会变得非常重复,并且由于问题的性质,很难阅读和发现错误。
我一直认为最好的学习方法是编写自己的库,但在这种情况下,库是一个很好的起点,因为这个主题比旋转、缩放和平移更深入。
那里有数百个 matrix/vector 数学库,一个好的起点是 github
数学符号
在数学中,x 轴称为 î
(发音为 i hat),y 轴称为 ĵ
(发音为 j hat)。每个轴由一个单位向量 î = [1,0]
和 ĵ = [0,1]
定义(对于 3D,我们使用三个 3D 向量 î = [1,0,0]
、ĵ = [0,1,0]
和 k hat = [0,0,1]
对不起,我找不到k 帽子在字符集中)
矢量基础知识。
一个向量
向量是一组表示方向和距离的数字。在数学中,向量是矩阵。例如 v = [1,0]
在代码中为 structure/object/class v = { x : 1, y : 0}
矢量也可以描述为距离和方向,例如 10 公里东南。从一种类型转换为另一种类型很容易(见下文)
单位向量。
单位向量是长度为 1 个单位的向量。 (1,0) 是一个单位向量,它的长度是 1 个单位长。您可以乘以单位向量以找到原点 n 个单位。
n = 5;
axis = { x : 1, y : 0 };
point.x = axis.x * n; // 5 * 1 = 5
point.y = axis.y * n; // 5 * 0 = 0
矢量长度
您可以使用毕达哥拉斯来获取向量的长度。例如,向量 {x : 3, y : 4}
的长度等于 sqrt( 3 * 3 + 4 * 4 ) = sqrt( 9 + 16 ) = sqrt( 25 ) = 5
五个单位长,显然不是单位向量
标准化向量(标准化美式拼写)
向量归一化过程会将向量转换为单位向量。它是通过将向量的分量除以向量长度来完成的。
vec = { x : 3, y : 4 };
length = sqrt( vec.x * vec.x + vec.y * vec.y ); // length = 5
// nVec is the normalised vector vec
nVec.x = vec.x / length; // 3/5 = 0.6;
nVec.y = vec.y / length; // 4/5 = 0.8;
来自角度的单位向量
为了在特定方向创建单位向量,我们使用了一点三角函数
angle = 90; // in deg (normally this is radians)
v90.x = cos(angle);
v90.y = sin(angle);