Another non-1:1 scaling issue and possible fix.

Feb 7, 2013 at 5:49 AM
Edited Feb 7, 2013 at 5:51 AM
A few weeks ago I came across another issue when scaling X,Y axis with different values, this time with lined based geometry.

I don't have any source code or images ready but you can test the problem by making a Polygon with a scale of (2,1), drawing it with both the PrimitiveDrawer and as a GeometrySprite and apply some rotation to it. What will happen is, the sprite will rotate correctly but the primitive will morph in such a way that it is always (2,1) (literally twice as long as it is tall) regardless of how much it is rotated.

I isolated this problem to inside the Transformation2D class, specifically the TransformLocalToGlobal(ref Vector2 outPosition) function. The code reads
internal void TransformLocalToGlobal(ref Vector2 outPosition)
        {
            outPosition.X -= _Origin.X;
            outPosition.Y -= _Origin.Y;

            if (_Rotation.Radians == 0)
            {
                outPosition.X *= _Scale.X;
                outPosition.Y *= _Scale.Y;
            }
            else
            {
                float length = outPosition.Length();
                float rot = (float)Math.Atan2(outPosition.Y, outPosition.X) - _Rotation.Radians;

                outPosition.X = ((float)Math.Cos(rot) * length) * _Scale.X;
                outPosition.Y = ((float)Math.Sin(rot) * length) * _Scale.Y;
            }
            outPosition.X += Position.X;// *_Scale.X;
            outPosition.Y += Position.Y;// *_Scale.Y;
      } 
Deducting from the commented out code at the bottom, I have given a try to rewrite the order of the transformation, to scale first and then rotate if necessary
 internal void TransformLocalToGlobal(ref Vector2 outPosition)
        {
            outPosition.X -= _Origin.X;
            outPosition.Y -= _Origin.Y;

            outPosition.X *= _Scale.X;
            outPosition.Y *= _Scale.Y;

            if (_Rotation.Radians != 0)
            {
                float length = outPosition.Length();
                float rot = (float)Math.Atan2(outPosition.Y, outPosition.X) - _Rotation.Radians;

                outPosition.X = ((float)Math.Cos(rot) * length);
                outPosition.Y = ((float)Math.Sin(rot) * length);
            }

            outPosition.X += Position.X;
            outPosition.Y += Position.Y;
        }
This seems to make everything scale properly and I've used it for a few weeks without any personal issues. I don't know if this will mess anything else up , as I said in the Circle post that I don't have a good grasp on this kind of math. That said, the fix, as it is, is a pretty simple rearrangement that I wanted to share.
Coordinator
Feb 27, 2013 at 5:13 PM
Hi Bicycleclops,
thank you very much for your contribution. your fix looks correct to me.

I will include it into the source code soon.