XNA / DirectX and inverted Y

General discussion about the R.U.B.E editor
Post Reply
mfagerlund
Posts: 20
Joined: Wed Jul 10, 2013 2:07 pm

XNA / DirectX and inverted Y

Post by mfagerlund »

Hi, in XNA / DirectX, Y is inverted: "Down" is positive and Origo is at the upper left corner. It's possible to change the martices of XNA / DirectX / etc so it renders the other way around, but any game that's written in XNA / DirectX will assume this convention and switching over will change face winding, mouse handling etc.

R.U.B.E. on the other hand goes the other way. So importing a world from RUBE into XNA makes the world inverted on the Y. Simly reversing Y doesn't help, because all angles and all windings are wrong. For my R.U.B.E. importer, I took care of this, but it was far from trivial.

It would be very useful to be able to decide if Y should be positive up or positive down. I realize that this isn't an issue for many people, but as R.U.B.E. usage grows, it will be a bigger problem. So add it to your vote list and maybe get to it later?

Two ways of solving it;
  • cheap and (semi) easy; do it while exporting so that it's exported in a way that can be read by XNA withoit changes
  • expensive and hart; change the editor to work either way (Y+ up or Y+ down)
/mattias
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: XNA / DirectX and inverted Y

Post by iforce2d »

In most rendering APIs there is a way to flip the projection so that the resulting rendering is inverted. Usually this goes by the name of 'scale', eg. glScalef in OpenGL. I would be very surprised if DirectX did not have the same capability. Note that this affects the projection, not the modelview (sorry, I only know the OpenGL terms!) so the winding will not need to be reversed.

If by mouse handling you mean determining what fixture the mouse is over, then yes, you will indeed need to invert the incoming mouse coordinates before doing the usual check. When porting to a new rendering API, I like to make screenToWorld/worldToScreen coordinate conversion functions so that any knowledge of the actual mapping of the world to the screen is encapsulated by them, and the rest of my code can use them the same on each platform.

This issue is not inherent in the data created by RUBE. It is only relevant to rendering, so that is where it should be addressed. In the same way that the physics scene should not be aware of the concept of the 'pixels to meter' ratio that mobile device developers are so commonly obsessed about, it should also not be aware of other visual presentation aspects like this, and scenes ideally would be constructed in a device agnostic manner.

So this type of option will not be part of RUBE in the future. On a more constructive note though, if you do want to flip things after loading, you can do it relatively easily as long as you don't need revolute joint limits. As you have noted, all positions can be flipped and then vertex windings reversed, will cover most of the problem. I think you might also have to reverse motor directions for revolute and wheel joints. Revolute joint limits though, are not trivial to convert.
mfagerlund
Posts: 20
Joined: Wed Jul 10, 2013 2:07 pm

Re: XNA / DirectX and inverted Y

Post by mfagerlund »

Ok. I was able to actually fix the joint limits but it's magic to me why it's actually working - and it might be fluke and there are special cases where it'll break.
for all regular angles;

Code: Select all

 if (FlipY)
            {
                angle = MathHelper.TwoPi - angle;
                if (angle < 0)
                {
                    angle += MathHelper.TwoPi;
                }
                else if (angle >= MathHelper.TwoPi)
                {
                    angle -= MathHelper.TwoPi;
                }
            }
            return angle;
For limits (notice the comment and the stuff I tried ;));

Code: Select all

            
if (FlipY)
            {
                // This is just crazy, I have no idea why this works...
                lower = -node["upperLimit"].AsFloat;
                upper = -node["lowerLimit"].AsFloat;
                //upper = MathHelper.TwoPi - AdjustAngle(node["lowerLimit"].AsFloat);
                //lower = MathHelper.TwoPi - AdjustAngle(node["upperLimit"].AsFloat);
                //lower = node["lowerLimit"].AsFloat;
                //upper = node["upperLimit"].AsFloat;
            }
            else
            {
                lower = node["lowerLimit"].AsFloat;
                upper = node["upperLimit"].AsFloat;
            }
iforce2d
Site Admin
Posts: 861
Joined: Sat Dec 22, 2012 7:20 pm

Re: XNA / DirectX and inverted Y

Post by iforce2d »

Yes, I had thought there was a bit more to it than that. If it's working out though, that's great.
Post Reply