好的,这应该是一个简单的矩阵问题,但我对矩阵的理解有些局限。这是场景:我有一个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中。我做错了什么?
答案 0 :(得分:12)
我刚刚经历了学习矩阵变换的痛苦,但是使用了XNA。
我发现these articles to be very有助于了解发生的情况。 XNA中的方法调用非常相似,其背后的理论都适用于您,即使使用SlimDX也是如此。
从瞥了一眼你的代码,我认为你应该在开始时转换到原点,然后在最后再翻译到最终位置,尽管我仍然是一个新手。好。
我要做的顺序是:
首先转换为原点的原因是旋转基于原点。因此,要在某个点周围旋转某些东西,请在旋转之前将该点放在原点上。
答案 1 :(得分:3)
好的,现在正在运作。这是我的工作代码,以防其他人需要它:
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 );
这将绘制您所选长度的倾斜线,其厚度等于您选择的厚度(假设您的纹理是1x1像素的白色图像)。源位置是线将从中发出的位置,以您指定的任何角度(以弧度表示)。因此,如果你从0开始并以0.1之类的值递增,直到你达到2PI,然后重置为0,那么你将有一条围绕中心旋转的线,如钟针或雷达扫描。这就是我所寻找的 - 感谢所有贡献的人!
答案 2 :(得分:1)
您需要做的是一次一步地完成每个转换。缩放首先绘制它。它在你期望的地方。然后抛出旋转,然后翻译。这将有助于发现错误的假设。
您还可以绘制临时线以帮助确定坐标的位置。例如,如果进行拉伸和旋转,并期望终点为0,0。绘制另一条线,其中一个端点位于0,0将作为双重检查,以查看是否真的如此。
针对您的具体问题,问题可能出在旋转上。缩放并旋转后,线条现在偏离中心,导致翻译时出现问题。
一般解决方案是将线条移回原点进行涉及更改形状或方向的任何操作。之后因为您位于一个知名的好位置,您可以转换到您的最终目的地。
对评论的回应
如果翻译是一个问题而你正在改变坐标系,那么你需要编写一个转换函数来在旧系统和新系统之间进行转换。
例如,如果你旋转45度。在旋转之前,你可以翻译0,1向上移动1英寸。旋转后,你必须大致翻译-.70707,.070707,相对于原始坐标系向上移动1英寸。
答案 3 :(得分:1)
您是围绕正确的轴旋转吗?我是矩阵之物的新手,但在我看来,由于精灵存在于x,y空间,旋转轴应该是Z轴 - 即(0,0,1)。