Coordinate systems
neoc666

I'm a bit confused after trying to figure out how Allegro 5 sets up the coordinate system of a display.

I'm using this init sequence:

#SelectExpand

The following sequence displays points in the exact corners of my display:

#SelectExpand
1 al_draw_pixel(1, 1, al_map_rgb(255, 255, 255)); 2 al_draw_pixel(1, 600, al_map_rgb(255, 255, 255)); 3 al_draw_pixel(800, 1, al_map_rgb(255, 255, 255)); 4 al_draw_pixel(800, 600, al_map_rgb(255, 255, 255));

So the coordinate system is not zero based, but the upper left corner is (1, 1) - which was surprising for me.

Then I'm using bitmaps and primitives to draw stuff.

I noticed that only the following line will draw a bitmap exactly at the origin of my display:

#SelectExpand
1 al_draw_bitmap(bitmap, 0, 0, 0);

So while for al_draw_pixel the origin is (1, 1), al_draw_bitmap thinks it is (0, 0). Is there any simple explanation for this? I couldn't find anything in the reference documentation and neither helped searching for "Allegro coordinate system" and such.

Even trickier is the following. I'm creating a 32x32 bitmap, clearing it and then I draw lines in it:

#SelectExpand
1 int w = 32; 2 int h = 32; 3 4 auto b = al_create_bitmap(w, h); 5 assert(b); 6 al_set_target_bitmap(b); 7 al_clear_to_color(al_map_rgb(255, 192, 203)); 8 9 al_draw_line(0, 1, w, 1, al_map_rgba(0, 0, 0, 255), 0); // top 10 al_draw_line(1, 0, 1, h, al_map_rgba(0, 0, 0, 255), 0); // left 11 al_draw_line(0, h, w, h, al_map_rgba(0, 0, 0, 255), 0); // bottom 12 al_draw_line(w, 0, w, h, al_map_rgba(0, 0, 0, 255), 0); // right

Only these exact coordinates will draw lines from top left -> top right -> bottom right -> bottom left -> top left of the bitmap. I tried to change the zeros to ones and w and h to w-1 and h-1, but those coordinates will leave 1-pixel-gaps (I checked with gimp...). Replacing the ones with zeros is not necessary though to get the full width / height (but will make the line invisible in other cases...).

To sum this up: For the top line, x=0 is the leftmost. But for the left line, it is x=1. The left line has to start at y=0, while the top line is only visible for y=1.

Changing the line thickness to 1 has no effect on this.

Can someone explain those contradicting coordinate systems to me? Is it maybe that primitives are different from the bitmap graphics core? Or even floating point to integer (display) translation issues?

Edgar Reynaldo

See the documentation on Allegro's Pixel Precise Output.

Try drawing to 0.5,0.5. That should ensure you get a pixel drawn at 0,0.

Same goes with lines. Draw to x + 0.5 , y + 0.5.

neoc666

Thank you for your quick response, I should have read the primitives page more carefully :P

Yet I'm not entirely sure about it. Most important: The pixel coordinate system in Allegro 5 is meant to have the top-left pixel in (0, 0) and not in (1, 1), right?

I figured out that this will give me the desired result:

#SelectExpand
1 al_draw_line(0.1, 0.1, (float)(w-1) + 0.5997f, 0.1, al_map_rgba(0, 0, 0, 255), 0); // top

In a pure integer coordinate system with (0, 0) as the top left, a horizontal line with width w would go from (0, 0) to (w-1, 0). Considering how the GPU interpolates floats to actual screen pixels, I guess a value of 0 (which is between the coordinates -0.5 and +0.5) can be either pixel -1 or pixel 0. So if I choose 0.1 instead of 0, the GPU will interpolate to pixel 0, because 0.1 is clearly positive. Is this correct?

Adding 0.5f to (w-1) wasn't enough to cover the last pixel, I tested out that I need something about 0.5597f; any idea why?

Edgar Reynaldo

In allegro the top left pixel is at 0,0 and the bottom right pixel is at width-1,height-1. However, the center of the top left pixel is at 0.5,0.5 and the center of the bottom right pixel is at width-0.5,height-0.5.

This code actually fails to properly outline the display. I'll tell you why below. It's actually in the page I linked to as well.

   ALLEGRO_DISPLAY* display = ((Allegro5GraphicsContext*)win)->AllegroDisplay();
   float lx = 0.5;
   float rx = al_get_display_width(display) - 0.5;
   float ty = 0.5;
   float by = al_get_display_height(display) - 0.5;
   ALLEGRO_COLOR c = al_map_rgb(255,0,0);
   float t = 1.0;
   
   al_clear_to_color(al_map_rgb(255,255,255));
   al_draw_line(lx,ty,rx,ty,c,t);
   al_draw_line(lx,by,rx,by,c,t);
   al_draw_line(lx,ty,lx,by,c,t);
   al_draw_line(rx,ty,rx,by,c,t);

{"name":"610315","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/c\/7cf67f3ab41dfdd7b68e59024b51cc32.png","w":800,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/7\/c\/7cf67f3ab41dfdd7b68e59024b51cc32"}610315

So you can see that the bottom right pixel is not lit. What you actually want to do when drawing axis aligned lines is to draw at the middle of the line along its width, and extend to the full width you desire along its length.

So you can see the two lines on the bottom and the right both failed to draw the bottom right pixel. When drawing the horizontal line it should have been :

al_draw_line(0.0 , al_get_display_height(display) - 0.5 , al_get_display_width(display) , al_get_display_height(display) - 0.5 , al_map_rgb(255,0,0) , 1.0);

And the vertical line should have been :

al_draw_line(al_get_display_width(display)-0.5 , 0.0 , al_get_display_width(display)-0.5 , al_get_display_height(display) , al_map_rgb(255,0,0) , 1.0);

So the horizontal line is vertically centered around y = h - 0.5, and is drawn from x = 0 to x = w. And the vertical line is horizontally centered around x = w-0.5 and is drawn from y = 0 to y = h. You can see it in the blue line in the second image in the page I linked you to.

{"name":"primitives2.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac1f802e04dfc4830bb169c64050a142.png","w":789,"h":426,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/ac1f802e04dfc4830bb169c64050a142"}primitives2.png

Bruce Pascoe

Note also that this isn't a thing specific to Allegro - it will be the case any time you do hardware-accelerated rendering.

I find it helps if you think of the display as a sheet of graph paper. Each box on the sheet is a pixel, and points are plotted at intersections, rather than inside the boxes. Only if a fragment passes through the center of a "pixel box" will it light the pixel.

Thread #616229. Printed from Allegro.cc