Hi guys, please help me! I have a Transform2D structure with position and rotation. I can multiply one Transform2D by another Transform2D (this one is like from local coordinates to world coordinates). How do I do the opposite? I know how it works with matrices, it is necessary to multiply the inverted matrix A by B. I tried to do this, but I don’t know how to return the invert angle in radiants
public float PositionX;
public float PositionY;
public float ScaleX;
public float ScaleY;
public float Rotation;
public static Transform2D operator *(Transform2D a, Transform2D b)
{
float sin = (float)Math.Sin(b.Rotation);
float cos = (float)Math.Cos(b.Rotation);
var positionX = (cos * a.PositionX - sin * a.PositionY) * b.ScaleX;
var positionY = (sin * a.PositionX - cos * a.PositionY) * b.ScaleY;
return new Transform2D(positionX + b.PositionX, positionY + b.PositionY,
a.ScaleX * b.ScaleX, a.ScaleY * b.ScaleY, a.Rotation + b.Rotation);
}
public static Transform2D operator /(Transform2D a, Transform2D b)
{
// what do?
}
Willman
December 16, 2023, 12:38am
2
Hey are you just wanting to convert an angle to radians? Is so, here is an example:
Example, convert 145 degrees to radians
145 degrees → to convert it to radians:
Solution → Multiply by (Pi/180 degrees)
We have:
(145) Pi
----- * –
180 1
Which is the same as :
(145) * Pi
----------
180
Which gives :
(145) * 3.1415
180
And the result is approximately 2.53 Radians
public class Transform2D
{
public float PositionX;
public float PositionY;
public float ScaleX;
public float ScaleY;
public float Rotation;
public Transform2D(float positionX, float positionY, float scaleX, float scaleY, float rotation)
{
PositionX = positionX;
PositionY = positionY;
ScaleX = scaleX;
ScaleY = scaleY;
Rotation = rotation;
}
public static Transform2D operator *(Transform2D a, Transform2D b)
{
var preRotatedX = a.PositionX * b.ScaleX; // usually scale before rotating otherwise scaleX affects X & Y
var preRotatedY = a.PositionY * b.ScaleY;
float sin = (float)Math.Sin(b.Rotation);
float cos = (float)Math.Cos(b.Rotation);
var positionX = (cos * preRotatedX - sin * preRotatedY);
var positionY = (sin * preRotatedX + cos * preRotatedY); // this should be add not subtract
return new Transform2D(positionX + b.PositionX, positionY + b.PositionY,
a.ScaleX * b.ScaleX, a.ScaleY * b.ScaleY, a.Rotation + b.Rotation);
}
public static Transform2D operator /(Transform2D a, Transform2D b)
{
// what do?
// do what
// is above in reverse order
var preRotatedX = (a.PositionX - b.PositionX); // reverse translation
var preRotatedY = (a.PositionY - b.PositionY);
float sin = (float)Math.Sin(-b.Rotation);
float cos = (float)Math.Cos(-b.Rotation);
var positionX = (cos * preRotatedX - sin * preRotatedY) / b.ScaleX; // reverse rotation then scale
var positionY = (sin * preRotatedX + cos * preRotatedY) / b.ScaleY;
return new Transform2D(positionX, positionY,
a.ScaleX / b.ScaleX, a.ScaleY / b.ScaleY, a.Rotation - b.Rotation);
}
public static void OtherOptionsWithTests()
{
// Change These Values To Test
float PositionX1 = -50.0f;
float PositionY1 = 10.0f;
float ScaleX1 = 5.0f;
float ScaleY1 = 25.0f;
float Rotation1 = MathHelper.ToRadians(-15f);
float PositionX2 = -500.0f;
float PositionY2 = 600.0f;
float ScaleX2 = 75.0f;
float ScaleY2 = 10.0f;
float Rotation2 = MathHelper.ToRadians(135f);
// Option 1) Transform2D
Transform2D transformA = new Transform2D(PositionX1, PositionY1, ScaleX1, ScaleY1, Rotation1);
Transform2D transformB = new Transform2D(PositionX2, PositionY2, ScaleX2, ScaleY2, Rotation2);
Transform2D transformC = transformA * transformB;
Transform2D transformBackToA = transformC / transformB;
// Option 2) Standard Matrix But Use Z-Axis For Rotation As Shown In Image
// (Tried to make a cross-eyed 3d stereogram for fun but something doesn't look quite right with it)
Matrix matrixA = Matrix.CreateScale(new Vector3(ScaleX1, ScaleY1, 1)) *
Matrix.CreateRotationZ(Rotation1) *
Matrix.CreateTranslation(new Vector3(PositionX1, PositionY1, 0));
Matrix matrixB = Matrix.CreateScale(new Vector3(ScaleX2, ScaleY2, 1)) *
Matrix.CreateRotationZ(Rotation2) *
Matrix.CreateTranslation(new Vector3(PositionX2, PositionY2, 0));
Matrix matrixC = matrixA * matrixB;
Matrix.Invert(ref matrixB, out Matrix matrixBInverted);
Matrix matrixBackToA = matrixC * matrixBInverted;
// Option 3) System.Numerics.Matrix3x2 For 2D Transforms
System.Numerics.Matrix3x2 matrix3X2A = System.Numerics.Matrix3x2.CreateScale(ScaleX1, ScaleY1) *
System.Numerics.Matrix3x2.CreateRotation(Rotation1) *
System.Numerics.Matrix3x2.CreateTranslation(PositionX1, PositionY1);
System.Numerics.Matrix3x2 matrix3X2B = System.Numerics.Matrix3x2.CreateScale(ScaleX2, ScaleY2) *
System.Numerics.Matrix3x2.CreateRotation(Rotation2) *
System.Numerics.Matrix3x2.CreateTranslation(PositionX2, PositionY2);
System.Numerics.Matrix3x2 matrix3X2C = matrix3X2A * matrix3X2B;
System.Numerics.Matrix3x2.Invert(matrix3X2B, out System.Numerics.Matrix3x2 matrix3X2BInverted);
System.Numerics.Matrix3x2 matrix3X2BackToA = matrix3X2C * matrix3X2BInverted;
// Check Values Are Correct By Adding A Breakpoint
Vector2 transform2DTranslationC = new Vector2(transformC.PositionX, transformC.PositionY);
Vector2 matrixTranslationC = new Vector2(matrixC.Translation.X, matrixC.Translation.Y);
Vector2 matrix3X2TranslationC = new Vector2(matrix3X2C.Translation.X, matrix3X2C.Translation.Y);
Vector2 transform2DTranslationBackToA = new Vector2(transformBackToA.PositionX, transformBackToA.PositionY);
Vector2 matrixTranslationBackToA = new Vector2(matrixBackToA.Translation.X, matrixBackToA.Translation.Y);
Vector2 matrix3X2TranslationBackToA = new Vector2(matrix3X2BackToA.Translation.X, matrix3X2BackToA.Translation.Y);
} // Add Breakpoint here
}
1 Like
Thank you so much for such a detailed answer! This is an invaluable help. Thanks to your answer, I realized that it was necessary to rotate back with a negative rotation
1 Like