/// <summary> /// Transforms a position. /// </summary> /// <param name="position">The position in screen coordinates.</param> /// <returns>The transformed position in screen coordinates.</returns> public Vector2F ToRenderPosition(Vector2F position) { // Given: // p .... point in screen space // p' ... transformed point in screen space // o .... the center of the scaling and rotation in screen space // S .... scaling matrix // R .... rotation matrix // t .... translation vector // // The transformation is: // p' = R S (p - o) + o + t position -= Origin; position *= Scale; position = Matrix22F.CreateRotation(Rotation) * position; position += Origin; position += Translation; return(position); // ----- Alternatively, using a 3x3 matrix: //Vector3 p = new Vector3(point.X, point.Y, 1); //p = ToMatrix() * p; //return new Vector2F(p.X, p.Y); }
public void CreateRotation2() { float angle = (float)MathHelper.ToRadians(30); Matrix22F m = Matrix22F.CreateRotation(angle); Assert.IsTrue(Vector2F.AreNumericallyEqual(new Vector2F((float)Math.Cos(angle), (float)Math.Sin(angle)), m * Vector2F.UnitX)); }
/// <summary> /// Converts this render transformation to a 2x2 matrix that only represents the scaling and the /// rotation (no translation). /// </summary> /// <returns> /// A 2x2-matrix that represents the scaling and the rotation (no translation). /// </returns> public Matrix22F ToMatrix22F() { Matrix22F s = new Matrix22F(Scale.X, 0, 0, Scale.Y); Matrix22F r = Matrix22F.CreateRotation(Rotation); return(r * s); }
public void CreateRotation() { Matrix22F m = Matrix22F.CreateRotation(0.0f); Assert.AreEqual(Matrix22F.Identity, m); m = Matrix22F.CreateRotation((float)Math.PI / 2); Assert.IsTrue(Vector2F.AreNumericallyEqual(Vector2F.UnitY, m * Vector2F.UnitX)); }
/// <summary> /// Multiplies two render transformation. /// </summary> /// <param name="transform2">The first render transformation.</param> /// <param name="transform1">The second render transformation.</param> /// <returns> /// The product <paramref name="transform2"/> * <paramref name="transform1"/>. /// </returns> public static RenderTransform operator *(RenderTransform transform2, RenderTransform transform1) { // Concatenation of transformations: // // p' = R1 S1 (p - o1) + o1 + t1 // p'' = R2 S2 (p' - o2) + o2 + t2 // = R2 S2 (R1 S1 (p - o1) + o1 + t1 - o2) + o2 + t2 // = R2 S2 R1 S1 (p - o1) + R2 S2 o1 + R2 S2 t1 - R2 S2 o2 + o2 + t2 // // Assuming only UNIFORM SCALINGS we can reorder the matrix product: // = R2 R1 S2 S1 (p - o1) + R2 S2 o1 + R2 S2 t1 - R2 S2 o2 + o2 + t2 // // We can add o1 - o1. This allows to bring the equation in the standard form: // = R2 R1 S2 S1 (p - o1) + R2 S2 o1 + R2 S2 t1 - R2 S2 o2 + o2 + t2 + o1 - o1 // = R2 R1 S2 S1 (p - o1) + o1 + R2 S2 o1 + R2 S2 t1 - R2 S2 o2 + o2 + t2 - o1 // = R S (p - o) + o + t // => S = S2 S1 // R = R2 R1 // o = o1 // t = R2 S2 o1 + R2 S2 t1 - R2 S2 o2 + o2 + t2 - o1 = // = -o1 + o2 + t2 + R2 S2 (o1 + t1 - o2) // Note: In the following we treat the scalings as uniform scaling. In practice, // combining non-uniform scalings with rotations creates an error. We simply ignore // these errors. (See also remarks in class description.) RenderTransform result; var s1 = transform1.Scale; var s2 = transform2.Scale; var θ1 = transform1.Rotation; var θ2 = transform2.Rotation; var o1 = transform1.Origin; var o2 = transform2.Origin; var t1 = transform1.Translation; var t2 = transform2.Translation; // S = S2 S1 // Scalings are combined by multiplying the scale factors. result.Scale = s2 * s1; // R = R2 R1 // Rotations in 2D are combined by adding the rotation angles. result.Rotation = θ2 + θ1; // o = o1 result.Origin = o1; // t = -o1 + o2 + t2 + R2 S2 (o1 + t1 - o2) result.Translation = -o1 + o2 + t2 + Matrix22F.CreateRotation(θ2) * (s2 * (o1 + t1 - o2)); return(result); }
// Compute the animation value for the given time and stores it in result. // This animation does not need defaultSource and defaultTarget parameters. protected override void GetValueCore(TimeSpan time, ref Vector2F defaultSource, ref Vector2F defaultTarget, ref Vector2F result) { const float circlePeriod = 4.0f; float angle = (float)time.TotalSeconds / circlePeriod * ConstantsF.TwoPi; Matrix22F rotation = Matrix22F.CreateRotation(angle); Vector2F offset = new Vector2F(200, 0); Vector2F rotatedOffset = rotation * offset; result.X = 500 + rotatedOffset.X; result.Y = 350 + rotatedOffset.Y; }
/// <summary> /// Transforms a direction. /// </summary> /// <param name="direction">The direction.</param> /// <returns>The transformed direction.</returns> public Vector2F ToRenderDirection(Vector2F direction) { direction *= Scale; direction = Matrix22F.CreateRotation(Rotation) * direction; return(direction); }