我正在编写星际争霸2自定义地图,并在3D中获得了一些数学方法。目前我正在尝试创建和旋转任意轴周围的点,由x,y和z给出(xyz向量被标准化)。
我一直在尝试很多并在互联网上阅读了很多东西,但我不知道它是如何正常工作的。我当前的脚本(你可能不知道语言,但没什么特别的)是几个小时打破所有内容的结果(无法正常工作):
point CP;
fixed AXY;
point D;
point DnoZ;
point DXY_Z;
fixed AZ;
fixed LXY;
missile[Missile].Angle = (missile[Missile].Angle + missile[Missile].Acceleration) % 360.0;
missile[Missile].Acceleration += missile[Missile].AirResistance;
if (missile[Missile].Parent > -1) {
D = missile[missile[Missile].Parent].Direction;
DnoZ = Point(PointGetX(D),0.0);
DXY_Z = Normalize(Point(SquareRoot(PointDot(DnoZ,DnoZ)),PointGetHeight(D)));
AZ = MaxF(ACos(PointGetX(DXY_Z)),ASin(PointGetY(DXY_Z)))+missile[Missile].Angle;
DnoZ = Normalize(DnoZ);
AXY = MaxF(ACos(PointGetX(DnoZ)),ASin(PointGetY(DnoZ)));
CP = Point(Cos(AXY+90),Sin(AXY+90));
LXY = SquareRoot(PointDot(CP,CP));
if (LXY > 0) {
CP = PointMult(CP,Cos(AZ)/LXY);
PointSetHeight(CP,Sin(AZ));
} else {
CP = Point3(0.0,0.0,1.0);
}
} else {
CP = Point(Cos(missile[Missile].Angle),Sin(missile[Missile].Angle));
}
missile[Missile].Direction = Normalize(CP);
missile[Missile].Position = PointAdd(missile[Missile].Position,PointMult(missile[Missile].Direction,missile[Missile].Distance));
我无法理解数学。如果你能用简单的术语解释它是最好的解决方案,那么剪切的代码也会很好(但不太有帮助,因为我计划将来做更多的3D东西)。
答案 0 :(得分:22)
http://en.wikipedia.org/wiki/Rotation_matrix。请查看Rotation matrix from axis and angle部分。为方便起见,这里有您需要的矩阵。它有点毛茸茸。 theta是角度,ux,uy和uz是规范化轴向量的x,y和z分量
如果您不了解矩阵和载体,请回复,我会帮助您。
答案 1 :(得分:11)
执行此类轮换的有用方法是使用quaternions执行此操作。在实践中,我发现它们更容易使用并且具有避免Gimbal lock的额外好处。
Here是一个很好的演练,解释了它们如何以及为什么用于围绕任意轴的旋转(它是对用户问题的响应)。它的级别更高,对于那个不熟悉这个想法的人来说会很好,所以我建议从那里开始。
更新以避免链接腐蚀
来自链接网站的文字:
毫无疑问,你已经得出结论,围绕轴旋转
穿过原点和单位球上的点(a,b,c)
三维是线性变换,因此可以
由矩阵乘法表示。我们会给你一个非常光滑的
确定该矩阵的方法,但要理解紧凑性
这个公式最好从一些评论开始。
三维旋转是相当特殊的线性 变形,尤其是因为它们保留了长度 矢量和(当两个矢量旋转时)之间的角度 向量。这种转换被称为"正交"他们是 由正交矩阵表示:
M M' = I
我们通过'方便地表示转置。换句话说 正交矩阵的转置是它的逆。
考虑定义转换所需的数据。
您已经为旋转轴ai + bj + ck
指定了符号,
方便地假设是单位矢量。唯一的其他数据是
旋转角度,我将缺乏更自然的性格
用r表示(用于旋转?),我们将假设给出
弧度。
现在旋转实际上甚至在正交之间有点特殊 转换,实际上它们也被称为特殊正交 变换(或矩阵)凭借其存在的性质 "取向保留"。将它们与反射相比较 也保持长度和角度,你会发现几何 保持方向的特征(或者#3;手性"如果你 prefer)在矩阵的行列式中具有数字对应物。 旋转矩阵具有行列式1,而反射矩阵具有行列式1 决定因素-1。事实证明,产品(或组成)两个 轮换再次轮换,这与事实是一致的 产品的决定因素是决定因素的产物(或1 in 轮换的情况)。
现在我们可以描述一个人可能遵循的循序渐进的方法 构建所需的矩阵(在我们简化整个过程和之前) 跳到答案!)。首先考虑我们旋转的步骤 单位矢量:
u = ai + bj + ck
这样它就符合"标准"也许是单位向量 k(正位z轴)。现在我们知道如何围绕z轴旋转; 这是在x,y上进行通常的2x2转换的问题 单独坐标:
cos(r) sin(r) 0
M = -sin(r) cos(r) 0
0 0 1
最后我们需要"撤消"把你带到k的初始轮换, 这很简单,因为这种转变的反转是(我们 召回)由矩阵转置表示。换句话说,如果 矩阵R表示将u转换为k,然后R'拿k到你, 我们可以写出这样的转换组成:
R' M R
很容易证实这种矩阵乘积成倍增加 时间你,再次回来:
R' M R u = R' M k = R' k = u
因此,这确实围绕由u。
定义的轴旋转这个表达的一个优点是它干净地分离出来 M与Q和Q的相关性对角度r的依赖性。在...上 "轴"矢量你。但是,如果我们必须进行计算 细节,我们显然会有很多矩阵乘法。
所以,到了快捷方式。事实证明,当所有尘埃落定时 旋转之间的乘法与单位的乘法同构 四元。如果你之前没有见过它们,那么四元数就是一个 一种复数的四维推广。他们是 "发明"威廉·汉密尔顿于1843年发表:
[威廉罗恩汉密尔顿爵士] http://www-gap.dcs.st-and.ac.uk/~history/Mathematicians/Hamilton.html
今天的3D图形程序员负债累累。
每个单位四元数q = q0 + q1*i + q2*j + q3*k
然后定义一个旋转矩阵:
(q0² + q1² - q2² - q3²) 2(q1q2 - q0q3) 2(q1q3 + q0q2)
Q = 2(q2q1 + q0q3) (q0² - q1² + q2² - q3²) 2(q2q3 - q0q1)
2(q3q1 - q0q2) 2(q3q2 + q0q1) (q0² - q1² - q2² + q3²)
验证Q是正交矩阵,即。那Q Q' = I
,意思是
Q的行形成一个标准正交基础的本质。因此对于
例如,第一行的长度应为1:
(q0² + q1² - q2² - q3²)² + 4(q1q2 - q0q3)² + 4(q1q3 + q0q2)²
= (q0² + q1² - q2² - q3²)² + 4(q1q2)² + 4(q0q3)² + 4(q1q3)² + 4(q0q2)²
= (q0² + q1² + q2² + q3²)²
= 1
并且前两行的点积为零:
[ (q0² + q1² - q2² - q3²), 2(q1q2 - q0q3), 2(q1q3 + q0q2) ]
* [ 2(q2q1 + q0q3), (q0² - q1² + q2² - q3²), 2(q2q3 - q0q1) ]
= 2(q0² + q1² - q2² - q3²)(q2q1 + q0q3)
+ 2(q1q2 - q0q3)(q0² - q1² + q2² - q3²)
+ 4(q1q3 + q0q2)(q2q3 - q0q1)
= 4(q0²q1q2 + q1²q0q3 - q2²q0q3 - q3²q2q1)
+ 4(q3²q1q2 - q1²q0q3 + q2²q0q3 - q0²q2q1)
= 0
通常也可以显示det(Q) = 1
,因此Q是
真的是轮换。
但围绕Q轴旋转的是什么?从什么角度来看?好, 给定角度r和单位矢量:
u = ai + bj + ck
和以前一样,相应的四元数是:
q = cos(r/2) + sin(r/2) * u
= cos(r/2) + sin(r/2) ai + sin(r/2) bj + sin(r/2) ck
因此:
q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c,
我们能够获得所需的属性乘以Q"修复" U:
Q u = u
让我们做一个简单的例子,而不是通过冗长的代数。
让u = 0i + 0.6j + 0.8k
成为我们的单位向量,r = pi是我们的旋转角度。
然后四元数是:
q = cos(pi/2) + sin(pi/2) * u
= 0 + 0i + 0.6j + 0.8k
和旋转矩阵:
-1 0 0
Q = 0 -0.28 0.96
0 0.96 0.28
在这个具体案例中,很容易验证Q Q' = I和det(Q)= 1。
我们还计算:
Q u = [ 0, -0.28*0.6 + 0.96*0.8, 0.96*0.6 + 0.28*0.8 ]'
= [ 0, 0.6, 0.8 ]'
= u
即。单位矢量u定义旋转轴,因为它是固定的"由Q。
最后,我们说明旋转角度为pi(或180°) 通过考虑Q如何作用于方向上的单位向量 正x轴的垂直于u:
i + 0j + 0k, or as a vector, [ 1, 0, 0 ]'
然后是Q [ 1, 0, 0 ]' = [-1, 0, 0 ]'
,它是[1,0,0的旋转
]'通过角度pi关于你。
作为四元数和四元组旋转表示的参考 一些额外的表示方法(以及它们的优点 for),请看这里的详细信息:
[代表3D旋转] http://gandalf-library.sourceforge.net/tutorial/report/node125.html
给定角度r以弧度和单位向量u = ai + bj + ck或[a,b,c]',定义:
q0 = cos(r/2), q1 = sin(r/2) a, q2 = sin(r/2) b, q3 = sin(r/2) c
并从这些值构造旋转矩阵:
(q0² + q1² - q2² - q3²) 2(q1q2 - q0q3) 2(q1q3 + q0q2)
Q = 2(q2q1 + q0q3) (q0² - q1² + q2² - q3²) 2(q2q3 - q0q1)
2(q3q1 - q0q2) 2(q3q2 + q0q1) (q0² - q1² - q2² + q3²)
乘以Q然后影响所需的旋转,特别是:
Q u = u
答案 2 :(得分:5)
要执行3D旋转,您只需将旋转点偏移到原点并围绕每个轴顺序旋转,将结果存储在每个轴旋转之间,以便与下一个旋转操作一起使用。该算法如下所示:
将点偏移到原点。
Point of Rotation = (X1, Y1, Z1)
Point Location = (X1+A, Y1+B, Z1+C)
(Point Location - Point of Rotation) = (A, B, C).
围绕Z轴执行旋转。
A' = A*cos ZAngle - B*sin ZAngle
B' = A*sin ZAngle + B*cos ZAngle
C' = C.
接下来,围绕Y轴执行旋转。
C'' = C'*cos YAngle - A'*sin YAngle
A'' = C'*sin YAngle + A'*cos YAngle
B'' = B'
现在执行关于X轴的最后一次旋转。
B''' = B''*cos XAngle - C''*sin XAngle
C''' = B''*sin XAngle + C''*cos XAngle
A''' = A''
最后,将这些值添加回原始旋转点。
Rotated Point = (X1+A''', Y1+B''', Z1+C''');
我发现这个link非常有帮助。它定义了如何围绕X,Y和Z轴执行单独旋转。
在数学上,您可以像这样定义一组操作:
答案 3 :(得分:2)
以下是您可以用来围绕任何轴旋转的内容,无论是x,y还是z。 Rx,Ry和Rz分别表示围绕a,x,y和z的旋转。
答案 4 :(得分:0)
对于使用矩阵的三维任意轴的旋转,我有一个页面here。矩阵(here)的链接解释和推导包括以下旋转/平移矩阵。这是一个矩阵,它产生的结果是通过(a,b,c)旋转点(x,y,z)的方向,方向矢量⟨u,v,w⟩为角度θ。
结果是这三点:
该页面包含源代码下载的链接。如果您想以交互方式进行旋转,可以在this site处进行。尝试使用示例旋转链接来了解正在发生的事情。
答案 5 :(得分:0)
进行编程的一种非常简洁的方法,尤其是如果您能够使用矩阵进行操作(例如在Matlab中)的是Rodrigues' Rotation Formula。
该公式使用一个非常简单的公式绕着由单位矢量定义的轴以角度绕轴创建旋转矩阵:
您可以检查欧氏轴的公式是否与Wikipedia上的公式完全相同,并由Aakash Anuj在此处发布。
自从我发现它以来,我仅将其用于旋转。希望对任何人有帮助。
答案 6 :(得分:0)
axis-angle 直接转换为四元数;假设轴是单位向量,角度是围绕该轴的自旋。轴被赋予规则的 (x,y,z)
方向坐标。四元数是 (cos(theta),sin(theta)*x, sin(theta)*y, sin(theta)*z)
然后适当相乘。
可以通过使用 Rodrigues Rotation Formula 围绕轴角旋转 (1,0,0)
,(0,1,0)
,(0,0,1)
来形成基础,结果如下...然后{ {1}}、forward
和 right
向量可用于将点缩放到正确位置。 (这只是一个矩阵,但本质上是转置的,这样 axii 就可以立即提取出来,在任何特定点为您提供相对的“向上”)
up