如何在C#中一次旋转,缩放和转换矩阵?

好的,这应该是一个简单的矩阵问题,但我对矩阵的理解有些局限。 这是场景:我有一个1px乘1px精灵,我希望按比例缩放x和y(每边不同的数量),然后我想将该精灵旋转一定角度,然后我希望能够精确定位整个事物(从左上角或中心,对我没有任何影响)。

到目前为止,我的代码模糊地接近,但是根据我传入的角度,它往往会被一些随机的数量所取消。

我认为这样做会:

Point center = new Point( 50, 50 ); float width = 60; float height = 100; float angle = 0.5; Vector3 axis = new Vector3( center.X, center.Y, 0 ); axis.Normalize(); Matrix m = Matrix.Scaling( width, height, 0 ) * Matrix.RotationAxis( axis, angle ) * Matrix.Translation( center.X, center.Y, 0 ); 

但它倾向于缩小旋转线的缩小范围,尽管我认为它的定位是正确的。

我也试过这个:

  Matrix m = Matrix.Transformation2D( new Vector2( center.X, center.Y ), 0f, new Vector2( width, height ), new Vector2( center.X, center.Y ), angle, Vector2.Zero ); 

线条看起来完全正确,尺寸和形状完全正确,但我根本无法正确定位。 如果我在上面的调用结束时使用翻译向量,或者如果我使用Sprite.Draw设置位置,则无法正常工作。

这一切都在SlimDX中。 我究竟做错了什么?

我刚刚经历了学习矩阵变换的痛苦,但是使用了XNA。

我发现这些 文章 对于理解会发生什么非常有帮助。 XNA中的方法调用非常相似,其背后的理论都应该适用于您,即使使用SlimDX也是如此。

从浏览你的代码开始,我认为你应该在开始时转换到原点,然后在结尾处再次翻译到最终位置,尽管我在这方面仍然是一个新手。

我会这样做的顺序是:

  • 翻译成原点
  • 规模
  • 旋转
  • 转换到所需的位置

首先转换为原点的原因是旋转基于原点 。 因此,要围绕某个点旋转某些东西,请在旋转之前将该点放在原点上。

好的,现在正在运作。 这是我的工作代码,以防其他人需要它:

  Point sourceLoc = new Point ( 50, 50 ); float length = 60; float thickness = 2; float angle = 0.5; Matrix m = Matrix.Scaling( length, thickness, 0 ) * Matrix.RotationZ( angle ) * Matrix.Translation( sourceLoc.X, sourceLoc.Y, 0 ); sprite.Transform = m; sprite.Draw( this.tx, Vector3.Zero, Vector3.Zero, Color.Red ); 

这将绘制您所选长度的倾斜线,其厚度等于您选择的厚度(假设您的纹理是1×1像素的白色图像)。 源位置是线将从您指定的任何角度(以弧度表示)发射的位置。 因此,如果你从0开始并以0.1之类的值递增,直到你达到2PI,然后重置为0,那么你将有一条围绕中心旋转的线,如钟针或雷达扫描。 这就是我想要的 – 感谢所有贡献者!

你绕正确的轴旋转吗? 我是矩阵之物的新手,但在我看来,由于精灵存在于x,y空间,旋转轴应该是Z轴 – 即(0,0,1)。

您需要做的是一次一步地完成每个转换。 缩放首先绘制它。 它在你期望的地方。 然后抛出旋转,然后翻译。 这将有助于发现错误的假设。

您还可以绘制临时线以帮助确定坐标的位置。 例如,如果进行拉伸和旋转,并期望终点为0,0。 绘制另一条线,其中一个端点位于0,0将作为双重检查,以查看是否真的如此。

对于您的具体问题,问题可能出在旋转上。 缩放并旋转后,线条现在偏离中心,导致翻译时出现问题。

一般的解决方案是将线移回原点做任何涉及改变形状或方向的操作。 之后因为您位于一个已知的好位置,您可以转换到您的最终目的地。

对评论的回应

如果转换是一个问题,并且您正在转换坐标系,那么您将需要编写转换函数以在旧系统和新系统之间进行转换。

例如,如果你旋转45度。 在旋转之前,你可以翻译0,1向上移动1英寸。 旋转后,你必须翻译大致-.70707,.070707相对于原始坐标系向上移动1英寸。