Jump to content
  • Advertisement
Sign in to follow this  
TheSilverHammer

Aspect Ratio, Virtual Coordiantes, and HUDs

This topic is 4002 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want to create a virtual coordinate system so that I can ignore the actual viewport size and aspect ratio. The idea is that I can build some kind of '2d' space that is consistent reguardless of the viewport size (if it is in a window) or Aspect ratio. Lets say I want to put some HUD elements together, a few squares, a few rectangles and whatnot. I want them to appear in a certain spot on my screen and appear the right size. Starting off in a pure screen space, if My real resolution is 2000 x 1000 and I place a 200 x 200 quad at 900, 800 I should have a square at the bottom center of my screen. The clear problems with this are that if my viewport shrinks and/or my resolution changes, my quad is no longer centered, and in fact may be off screen. IE: I shrink my window or change to a resolution of 1000 x 500, my quad is gone. My first trick was to 'scale' everything by the viewport size. This seemed to solve the problem completly except for a minor detail, however an example of it working first. I decided I would like to have a virtual screen space of 1000 x 1000 (or perhaps 0.0 to 1.0 in both axis. So if my viewport was 500 x 500, my X and Y scales would be 0.5. I would just scale positions and sizes by those values. This almost works, except that you will end up with distorted sprites if you didn't increase the Y scale by the aspect ration, ie: YScale = YScale * AspectRatio. As a result, however, I lose my true 'square' 1000 x 1000. This is evident when you make a row of 10 sprites at 100 units long. As you would expect, if the virtual screen space is 1000 wide, then you should fit 10 sprites across if they are 100 units each. The fly in the ointment is the Y side. You can't fit 10 sprites virtically. If your aspect ratio was 2:1 (for argument's sake) each sprite would have to be 200 units tall to appear to be square. As a result you can only fit 5 virtically. You will notice that everything is consistent and if you design a hud with this aspect ratio, it will scale and stretch just fine as long as you are running a 2:1 aspect ratio. Even if the viewport is square, things will still be aligned right. Now lets say you change resolution to one that has an aspect ratio of 1.5: 1. Suddenly you can now fit 7.5 sprites virtically. Your X alignment is fine, but now things are 'off' in the Y direction. So the question comes down to, how do you design a virtual coordinate system so you can design stuff such as a hud that appears correctly reguardless of resolution and aspect ratio? I am sure this must be a very basic problem which everyone has to deal with at some point.

Share this post


Link to post
Share on other sites
Advertisement
Its simple actually. What I do is to fit a 2x2 square in the viewport, with at least 2 opposing sides touching the edges of the screen. The coordinates of this square goes from -1 to +1 in both axis, X and Y, and its center (0,0) is always located at the center of the screen.

This way if my screen has an aspect ratio of 4:3, the logical coordinates go from -1.333 to +1.333 in X, and from -1.0 to +1.0 in Y. If the ratio is 10:16, the logical coordinates go from -1.0 to +1.0 in X, and from -1.6 to +1.6 in Y. If the ratio is 1:1, then the square fits perfectly inside the screen, from -1.0 to +1.0 in X, and from -1.0 to +1.0 in Y.

Now, everything and anything you put inside this the square will always be visible. If you want to place something in a corner of the screen just make some functions to get the extents of the viewport, for instance, getMinX() would return -1.33 if the aspect ratio is 4:3. Also I keep all my sprites sizes in this logical coordinates so they are drawn at the same relative size independently of screen resolution.

Example: If you want to place a sprite in the top left corner of the screen then you should draw it at (getMinX() + sprite.logicalWidth/2, getMaxY() - sprite.logicalHeight/2) (Assuming that the X axis goes from negative to positive from left to right, and the Y axis goes from negative to positive from bottom to top and the sprites origin is at its center). Then the renderer transforms from logical to screen coordinates depending on the screen resolution.

Hope its clear enough!

Share this post


Link to post
Share on other sites
I am sorry, but I do not understand what you mean here. On the surface it seems logical, but the details are missing. Let me give you an example and maybe you can give me the 'logical' transformation for the same example.

I have a screen of 2000 x 1000 and 5 sprites that are 200 x 100 (to appear square on this screen). The are arranged in a checkerboard pattern around the middle of the screen, with the center square centered on the screen.

It would look like this:


_____1 2
______3
_____4 5


The number 1 square would be centered at 800, 400. It's LR corner is at 900, 450.
The number 3 square would be centered at 1000, 500. It's UL corner is at 900, 450.
We can see the LR corner 1 and UL corner of 3 touch.

Now consider two scenerios:

1. Shrink the viewport to 1000 x 500, keep the aspect ratio.
The new position for 1 should be 400, 200 and the size should be 100 x 50. LR Corner = 450, 225.
The new position for 3 should be 500, 250 and the size should be 100 x 50. UL Corner = 450, 335.
We can see the LR corner 1 and UL corner of 3 should touch, and they still do, so this scenerio is fine.

2. Keep the viewport size and set the aspect ratio to 1:1.
This is the part that I am stuck on. We can see that the sprites dimensions should be 100 x 100 since it is now an even aspect ratio. We can also see that the center of the screen is still 1000, 500 despite the fact the aspect ratio is now 1:1.

Since the screen space hasn't changed, should the sprite's location change, and if so, how? We can see that 1000, 500 is still the right choice of sprite 3's location. Would sprite 1's location still be 800, 400?

Sprite 1's LR corner would be at 850, 450.
Sprite 3's UL corner would be at 950, 450.
Ooops, they are misaligned on the X side by 100 units!

How am I supposed to figure out going from 2:1 aspect ratio to a 1:1 aspect ratio means that Sprite 1's center needs to go from 800,400 to 900, 400? This is easy to see since I used some squares and the center of the screen. Now imagine a HUD with lots of odd shapes in all locations? If I have a long rectangular bar that is supposed to be aligned with a square, it will get all messed up.

I can see what you are saying about 'logical' coordinates, but the whole trick is translating them into real coordiantes. So in this case I would have had an original X logical boundry of -2 to 2. It would have become -1 to 1. So what do I do with those numbers? I mean in the case of sprite 1 it would have to be something like this:

Sprite1.X = N * MagicFunction() = 800 for the 2:1 setup
Sprite1.X = N * MagicFunction() = 900 for the 1:1 setup

What is N? What is the MagicFunction?

Furthermore, it will also have to include Width and Height as well as X and Y, unless that is taken care of somewhere else.

If you can elaborate and fill in the gaps here, it would greatly be appricated.

Share this post


Link to post
Share on other sites
Sorry, I just had a very looooong weekend here.

It seems you are confusing between the screen (or viewport) aspect ratio and the pixel aspect ratio. Nowadays most monitors (pc, tv, etc) have a 1:1 pixel aspect ratio, in other words, pixels are square; that means that a 100x100 block of pixels will look like a square independent of the resolution of the screen.

For instance: a widescreen tv with a resolution of 1920x1080 pixels, has a view aspect ratio of 16:9 and thus each pixel has an aspect ratio of 1:1; a pc monitor with a resolution of 1600x1200 has a view aspect ratio of 4:3 and also the pixel aspect ratio is 1:1; or a notebook screen with a resolution of 1440x900 has a view aspect ratio of 16:10, so it also has a pixel aspect ratio of 1:1.

So you could assume a pixel aspect ratio of 1:1 and deduct the screen aspect ratio from the resolution. This way a 200x100 block of pixels should always look as a rectangle when drawn, whatever the resolution of the screen is, while a 75x75 block of pixels should always look like a square. If you want to support different pixel aspect ratios, you have to get or know this value from somewhere, since you cant get that information just by knowing the resolution.

If you need something more specific, you could tell me a little more about what are you trying to accomplish and what king of screens do you want to target.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!