Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Transform / Translate

This thread is locked; no one can reply to it. rss feed Print
Transform / Translate
AceBlkwell
Member #13,038
July 2011
avatar

A while back I asked about screen scaling. For the immediate moment I solved my problem with proportional increases to my drawing items.

During this time Edgar make a comment about transformations and/or translate that would increase / decrease overall screen without the need for mouse action adjustments based on screen size.

Now I can't find the topic with Allegro search or Google. Can someone tell me if I'm remembering wrong on the abilities of transform?

Thanks.

torhu
Member #2,727
September 2002
avatar

You can use al_transform_coordinates to transform the coordinates from mouse events by using the inverse transform of the one you use for scaling the graphics.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

While I didn't say that specifically Ace, you are right on track.

If you use the full screen size, a smaller buffer and transformations, you can use an inverted transform to find your mouse on the smaller buffer.

ALLEGRO_TRANSFORM t;
al_identity_transform(&t);
al_scale_transform(&t , SCREEN_WIDTH/BUFFER_WIDTH , SCREEN_HEIGHT/BUFFER_HEIGHT);

ALLEGRO_TRANSFORM tinverse;
al_copy_transform(&t , &tinverse);
al_inverse_transform(&tinverse);

if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
   int rmx =  ev.mouse.x, rmy = ev.mouse.y;
   al_apply_transform(&tinverse , &rmx , &rmy);
}

AceBlkwell
Member #13,038
July 2011
avatar

Thank all,

I'm not sure how all of that works just yet but knowing I'm in the ball park will allow me to start diving into it. The added code and suggestions will help as well.

Thanks again.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

An ALLEGRO_TRANSFORM is just a generic data type. Manipulate them with the API. You can scale, translate, and rotate, as well as inverse it and apply it to a set of coordinates. Use the transform to affect your screen, and the inverse transform to get your mouse coordinates.

AceBlkwell
Member #13,038
July 2011
avatar

Can anybody recommend a good Transformations tutorial? I’ve read some man pages and read through sample code. I’m just not understanding what is actually taking place. Without being able to visualize it, I can’t apply it. I’ve grabbed sections of code and dropped it in mine. The goal was to see what happens then tweak the commands and watch for changes. Unfortunately, the program continues to run, screen unchanged. I can’t tell how the transform instance is linked to my display. Well obviously it isn’t but how do you apply it to the display being flipped? I also don’t understand why the code I read has identity / translate / scale before every drawn item. Is that necessary? I guess I thought of transformations as more of a conversion. Once it’s set you just work with it until you need to alter it.

I’m sure I’m out of my depth, but I can usually adapt if I understand how something works. I don’t have to know all the matrix / algebra involved, just overall what is happening and how the various commands affect the big picture.

Any suggestions?

DanielH
Member #934
January 2001
avatar

Normally a display starts at 0,0, no tint, no rotation, etc. Transformations allow you to change that.

1. position: set the transform to position (x, y) then when you draw any item at (i, j) you're actually drawing to (x + i, y + j)

2. color: set the tint to ALL objects drawn

3. rotation: Set the rotation of all objects

3. scale: set the size of all objects

all this can be in 1 transform

Identity transform resets all back to zero.

Proper steps
1. backup the current transform
2. reset the new transform to identity
3. set the aspects of transform (position, scales, etc)
4. set the new transform as current transform
5. do the drawing
6. set the backup transform as current transform

Look at the source for this function

#SelectExpand
1static void _draw_tinted_rotated_scaled_bitmap_region(ALLEGRO_BITMAP *bitmap, 2 ALLEGRO_COLOR tint, float cx, float cy, float angle, 3 float xscale, float yscale, 4 float sx, float sy, float sw, float sh, float dx, float dy, 5 int flags) 6{ 7 ALLEGRO_TRANSFORM backup; 8 ALLEGRO_TRANSFORM t; 9 ALLEGRO_BITMAP *parent = bitmap; 10 float const orig_sw = sw; 11 float const orig_sh = sh; 12 ASSERT(bitmap); 13 14 // 1. backup current transform 15 al_copy_transform(&backup, al_get_current_transform()); 16 17 // 2. reset the new transform to identity 18 al_identity_transform(&t); 19 20 if (bitmap->parent) { 21 parent = bitmap->parent; 22 sx += bitmap->xofs; 23 sy += bitmap->yofs; 24 } 25 26 if (sx < 0) { 27 sw += sx; 28 al_translate_transform(&t, -sx, 0); 29 sx = 0; 30 } 31 if (sy < 0) { 32 sh += sy; 33 al_translate_transform(&t, 0, -sy); 34 sy = 0; 35 } 36 if (sx + sw > parent->w) 37 sw = parent->w - sx; 38 if (sy + sh > parent->h) 39 sh = parent->h - sy; 40 41 if (flags & ALLEGRO_FLIP_HORIZONTAL) { 42 al_scale_transform(&t, -1, 1); 43 al_translate_transform(&t, orig_sw, 0); 44 flags &= ~ALLEGRO_FLIP_HORIZONTAL; 45 } 46 47 if (flags & ALLEGRO_FLIP_VERTICAL) { 48 al_scale_transform(&t, 1, -1); 49 al_translate_transform(&t, 0, orig_sh); 50 flags &= ~ALLEGRO_FLIP_VERTICAL; 51 } 52 53 // 3. set the aspects of transform (position, scales, etc) 54 al_translate_transform(&t, -cx, -cy); 55 al_scale_transform(&t, xscale, yscale); 56 al_rotate_transform(&t, angle); 57 al_translate_transform(&t, dx, dy); 58 al_compose_transform(&t, &backup); 59 60 // 4. set the new transform as current transform 61 al_use_transform(&t); 62 63 // 5. do the drawing 64 _bitmap_drawer(parent, tint, sx, sy, sw, sh, flags); 65 66 // 6. set the backup transform as current transform 67 al_use_transform(&backup); 68}

AceBlkwell
Member #13,038
July 2011
avatar

Daniel,

This makes it a lot clearer. Thanks a lot.

Just to see if I understand correctly, if I set the transformation as target then draw to it, it is now in place of say a buffer bitmap. As such when I flip, the transform will flip to screen instead of buffer flipping to screen?

Also if I'm drawing to a 640x480 buffer, could I set the transformation to 1200, 800 (scale?) copy the buffer to it, then flip? Assuming the larger transformation will cause the buffer bitmap to stretch / scale?

Thanks again.

DanielH
Member #934
January 2001
avatar

Transforms are just basic numbers. Your target bitmap is still target bitmap. transforms just inform the system how and where to draw to the target.

If you have a 640x480 real buffer, but you want a 1200x800 imaginary buffer then set the transform using the scale function.

void al_scale_transform(ALLEGRO_TRANSFORM *trans, float sx, float sy);

al_scale_transform(my_transform, 640 / 1200, 480 / 800);

If you use this transform then when you draw to (1000, 600) it multiplies your position and scale. So you are actually drawing to (1000 * 640/1200), (600 * 640/1200) = (533, 360)

I use a set size buffer and scale it to whatever the display size is. This is a transform. If the display changes, the scale changes. However, my buffer doesn't change size.

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

When allegro draws, everything is multiplied by the transform in use. Normally this is an identity matrix, and draws everything exactly where you ask it to.

When you call al_use_transform, it sets that transform's matrix as the one to use when drawing. Make sure to reset this when you're done.

AceBlkwell
Member #13,038
July 2011
avatar

Thanks all,

This clarifies a lot. I'm going to play around with the commands and see how they work on screen. I appreciate it.

Go to: