Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Using Sine And Cosine For Rotation

This thread is locked; no one can reply to it. rss feed Print
Using Sine And Cosine For Rotation
Scooter
Member #16,799
January 2018

Hi all:
I normally use Allegro5 rotation function! But I decided to try my
hand at using the sine and cosine functions. BAD IDEA! Now I have a
program that is a complete MESS! My image is dancing on the screen
like crazy! I believe my rotation part is correct hopefully. Computer
is returning all kinds of errors!! Don't have a clue what is wrong!
Dizzy has helped me before on some 3D rotations but hasn't help me
on 2D rotations. I have check back on some 2D rotations I did in DOS
and think I am correct but who knows. I have uploaded the program if
someone wants to take a look at it. Thanks for your time. I have never
seen anything like this before!

Dizzy Egg
Member #10,824
March 2009
avatar

Hello Scooter. You are looping 4 times when the timer changes, and clearing/drawing 4 times. Why did you need to loop 4 times? Also, radians work for al_rotate_image but you don't need them if you just want your square to rotate around the center.

Try my attached code, should help you get started....

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Scooter
Member #16,799
January 2018

Hi Dizzy:
Thanks for the reply! Works great! I have worked most of the day
on trying to rotate image at its center. Below is all I could come
up with, which is what I had before. Using your program I plugged
in another formula but still doing the same thing, Only difference
is the program exits properly with no errors.
I know I have to zero out the coordinate, do the rotation and add back
in what i subtracted out but something is still missing somewhere.

Here is what I have now:


if (ev.type == ALLEGRO_EVENT_TIMER &&
al_event_queue_is_empty(event_queue))
{
update_angle();

box_x[0] -= 640;
box_y[0] -= 360;
new_x = (box_x[0] * cos(angle)) - (box_y[0] * sin(angle));
new_y = (box_x[0] * sin(angle)) + (box_y[0] * cos(angle));
box_x[0] = new_x + 640;
box_y[0] = new_y + 360;

redraw = true;
}

Dizzy Egg
Member #10,824
March 2009
avatar

Now I see why you were using 4 co-orinates, you wanted to draw a box with the 4 x/y points. You could do that using al_draw_prim with a texture, but personally I would just use al_draw_rotated_bitmap.

If you really want to rotate around the center, but don't want to use al_draw_rotated_bitmap, then I would just use a transform. I've attached an example for you.

If you want to use the 4 x/y co-oridinates, let me know and I'll do a demo for you using al_draw_prim.

EDIT:

I've attached another example, using vertices, which is closer to what you originally wanted. This method:

void rotate_vertices()
{
    float angleR = angle * PI / 180.0;

    for (int i = 0; i < 4; i++)
    {
        box_x[i] = cos(angleR) * (original_x[i] - center_x) - sin(angleR) * (original_y[i] - center_y) + center_x;
        box_y[i] = sin(angleR) * (original_x[i] - center_x) + cos(angleR) * (original_y[i] - center_y) + center_y;
    }
}

will do what you were trying. Notice before drawing that you have to set the image as target and transform it, otherwise you get a spinning square with a non-spinning texture!

EDIT2:

For some reason I can't attach the second version, so here is the full code, using the 4 points:

#SelectExpand
1 2 3#include <allegro5/allegro.h> 4#include <allegro5/allegro_primitives.h> 5#include <allegro5/allegro_image.h> 6#include <stdio.h> 7#include <math.h> 8#include <stdbool.h> 9 10 11bool rotate = true; 12float center_x = 640; 13float center_y = 360; 14float PI = 3.1415929; 15float box_x[4]; 16float box_y[4]; 17float original_x[4]; 18float original_y[4]; 19float old_x, old_y = 0; 20float new_x, new_y = 0; 21float image_width, image_height; 22float image_width_half, image_height_half; 23 24float angleX = 0; 25float angle = 10.0; 26int indexx = 0; 27int i; 28int radius = 80; 29 30double update_angle(); 31float get_vertices(); 32void rotate_vertices(); 33 34int main() 35 { 36 ALLEGRO_DISPLAY *display = NULL; 37 ALLEGRO_BITMAP *image = NULL; 38 ALLEGRO_EVENT_QUEUE *event_queue = NULL; 39 ALLEGRO_TIMER *timer = NULL; 40 41 int screen_height = 720; 42 int screen_width = 1280; 43 int image_height; 44 int image_width; 45 46 if(!al_init()) 47 { 48 fprintf(stderr,"Couldn't initialize allegro!\n"); 49 return -1; 50 } 51 52 if(!al_install_mouse()) 53 { 54 fprintf(stderr, "failed to initialize the mouse!\n"); 55 return -1; 56 } 57 58 if(!al_init_primitives_addon()) 59 { 60 fprintf(stderr,"Couldn't initialize primitives addon!\n"); 61 return -1; 62 } 63 64 65 display=al_create_display(screen_width, screen_height); 66 67 if(!display) 68 { 69 fprintf(stderr,"Couldn't create allegro display!\n"); 70 return -1; 71 } 72 73 if(!al_init_image_addon()) 74 { 75 fprintf(stderr,"Couldn't display image!\n"); 76 return -1; 77 } 78 79 al_install_keyboard(); 80 event_queue = al_create_event_queue(); 81 timer = al_create_timer(1.0 / 60); 82 al_register_event_source(event_queue, al_get_display_event_source(display)); 83 al_register_event_source(event_queue, al_get_timer_event_source(timer)); 84 al_register_event_source(event_queue, al_get_mouse_event_source()); 85 al_register_event_source(event_queue, al_get_keyboard_event_source()); 86 al_clear_to_color(al_map_rgb(0,0,0)); 87 88 image = al_load_bitmap("checker.jpg"); 89 90 if(!image) 91 { 92 fprintf(stderr,"Couldn't display image!\n"); 93 return -1; 94 } 95 96 image_height = al_get_bitmap_height(image); 97 image_width = al_get_bitmap_width(image); 98 image_height_half = image_height / 2.0; 99 image_width_half = image_width / 2.0; 100 101 al_start_timer(timer); 102 103 int done = false; 104 bool redraw = false; 105 get_vertices(); 106 107 const ALLEGRO_TRANSFORM* original_t = al_get_current_transform(); 108 ALLEGRO_VERTEX* vertices = NULL; 109 110 while(!done) 111 { 112 ALLEGRO_EVENT ev; 113 al_wait_for_event(event_queue, &ev); 114 115 if (ev.type == ALLEGRO_EVENT_TIMER && al_event_queue_is_empty(event_queue)) 116 { 117 update_angle(); 118 rotate_vertices(); 119 120 ALLEGRO_VERTEX v[] = { 121 {.x = box_x[0], .y = box_y[0], .z = 0, .color = al_map_rgb_f(1, 1, 1), .u = -128, .v = -128}, 122 {.x = box_x[1], .y = box_y[1], .z = 0, .color = al_map_rgb_f(1, 1, 1), .u = -128, .v = 128}, 123 {.x = box_x[2], .y = box_y[2], .z = 0, .color = al_map_rgb_f(1, 1, 1), .u = 128, .v = 128}, 124 {.x = box_x[3], .y = box_y[3], .z = 0, .color = al_map_rgb_f(1, 1, 1), .u = -128, .v = 128}}; 125 126 vertices = v; 127 128 redraw = true; 129 } 130 131 132 if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) 133 { 134 rotate = false; 135 done = true; 136 break; 137 } 138 139 if (redraw) 140 { 141 al_clear_to_color(al_map_rgb(0, 0, 0)); 142 143 al_set_target_bitmap(image); 144 ALLEGRO_TRANSFORM t; 145 al_identity_transform(&t); 146 al_rotate_transform(&t, angle * PI / 180.0); 147 148 al_set_target_backbuffer(display); 149 150 al_draw_prim(vertices, NULL, image, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN); 151 152 al_flip_display(); 153 154 redraw = false; 155 } 156 } 157 158 al_destroy_display(display); 159 al_destroy_bitmap(image); 160 al_destroy_timer(timer); 161 return 0; 162 } 163 164double update_angle() 165 { 166 angle += 0.5; 167 if(angle >= 360) angle = 0.0; 168 return(angle); 169 } 170 171float get_vertices() 172 { 173 original_x[0] = center_x - 128; 174 original_x[1] = center_x - 128; 175 original_x[2] = center_x + 128;; 176 original_x[3] = center_x + 128;; 177 178 original_y[0] = center_y - 128;; 179 original_y[1] = center_y + 128;; 180 original_y[2] = center_y + 128;; 181 original_y[3] = center_y - 128;; 182 } 183 184void rotate_vertices() 185{ 186 float angleR = angle * PI / 180.0; 187 188 for (int i = 0; i < 4; i++) 189 { 190 box_x[i] = cos(angleR) * (original_x[i] - center_x) - sin(angleR) * (original_y[i] - center_y) + center_x; 191 box_y[i] = sin(angleR) * (original_x[i] - center_x) + cos(angleR) * (original_y[i] - center_y) + center_y; 192 } 193}

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Scooter
Member #16,799
January 2018

Hi Dizzy:
I have discovered my problem. What I need is to rotate the upper
left corner of the image at 1 degree intervals counter clockwise
using this formula:

new_x = (box_x[0] * cos(angle)) - (box_y[0] * sin(angle));
new_y = (box_y[0] * cos(angle)) + (box_x[0] * sin(angle));

I wrote a separate program to determine that this will not work
with allegro5. I believe you mention in your post that it did not
work without declaring the image a target and using transformations.
Is there any way possible to do it without using transformations?
I don't understand why it doesn't work, I guess its the way the library
was written. I would like to not use them if possible. This is the
reason the image was jumping all over the screen because those
functions do not work on their own. I did not know that. If you have
the time, could you work something up for me?

Thanks for your time!!!!

DanielH
Member #934
January 2001
avatar

Let's say you have a rectangle with 4 points.

1. pick a point of rotation cx, cy

2. center it to your point of rotation by subtracting cx, cy from px, py
3. apply rotation to point (your formula above)
4. add cx, cy back to px, py

repeat steps 2 to 4 for each point in your rectangle

Actually that what Dizzy put here

void rotate_vertices()
{
    float angleR = angle * PI / 180.0;

    for (int i = 0; i < 4; i++)
    {
        box_x[i] = cos(angleR) * (original_x[i] - center_x) - sin(angleR) * (original_y[i] - center_y) + center_x;
        box_y[i] = sin(angleR) * (original_x[i] - center_x) + cos(angleR) * (original_y[i] - center_y) + center_y;
    }
}

Dizzy Egg
Member #10,824
March 2009
avatar

Scooter, I'm not really sure what you're asking for. You already had a rotating image in the centre when I helped with this post:

shoot a ball

I don't know why you don't want to use al_draw_rotated_bitmap. If you want to use 4 points like you originally tried, I posted that above in Edit2.

If you use al_draw_prim you have to transform the texture or it will be a spinning square with a non-spinning texture.

At this point I don't know why you don't just use al_draw_rotated_bitmap, like you did in your shoot_a_ball question??

You can't rotate an image using al_draw_bitmap, because it just draws a bitmap at x/y?

Again, I'm not sure what you're trying to achieve....

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

Scooter
Member #16,799
January 2018

Hi Dizzy:
I have been trying to work with transformations, Not going
too good. It's trying to rotate the whole screen. Not sure why.

I am going to try a very simple program to see if I can get a
handle on what is going on. I am still confused an how this works.
Maybe I need to find a tutorial on this. Can't get my head around
not using coordinates like before.

Stay tuned, it"s going to be a bumpy ride!

Dizzy Egg
Member #10,824
March 2009
avatar

You need to get a copy of the transform before you enter your game loop. Then after making a new transform and drawing (rotating), set back the original before doing any more drawing.

----------------------------------------------------
Please check out my songs:
https://soundcloud.com/dont-rob-the-machina

DanielH
Member #934
January 2001
avatar

Look at the code for rotating a bitmap.

#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 al_copy_transform(&backup, al_get_current_transform()); 15 al_identity_transform(&t); 16 17 if (bitmap->parent) { 18 parent = bitmap->parent; 19 sx += bitmap->xofs; 20 sy += bitmap->yofs; 21 } 22 23 if (sx < 0) { 24 sw += sx; 25 al_translate_transform(&t, -sx, 0); 26 sx = 0; 27 } 28 if (sy < 0) { 29 sh += sy; 30 al_translate_transform(&t, 0, -sy); 31 sy = 0; 32 } 33 if (sx + sw > parent->w) 34 sw = parent->w - sx; 35 if (sy + sh > parent->h) 36 sh = parent->h - sy; 37 38 if (flags & ALLEGRO_FLIP_HORIZONTAL) { 39 al_scale_transform(&t, -1, 1); 40 al_translate_transform(&t, orig_sw, 0); 41 flags &= ~ALLEGRO_FLIP_HORIZONTAL; 42 } 43 44 if (flags & ALLEGRO_FLIP_VERTICAL) { 45 al_scale_transform(&t, 1, -1); 46 al_translate_transform(&t, 0, orig_sh); 47 flags &= ~ALLEGRO_FLIP_VERTICAL; 48 } 49 50 al_translate_transform(&t, -cx, -cy); 51 al_scale_transform(&t, xscale, yscale); 52 al_rotate_transform(&t, angle); 53 al_translate_transform(&t, dx, dy); 54 al_compose_transform(&t, &backup); 55 56 al_use_transform(&t); 57 _bitmap_drawer(parent, tint, sx, sy, sw, sh, flags); 58 al_use_transform(&backup); 59}

It saves current transform. Processes all needed data for the bitmap transform. draws the bitmap, then restores the backup to the current transform.

Go to: