3D rotation using Allegro 5.2.4
DontKnow3D

I don't quite get how the 3D rotation transformations work. In my program I first rotate an object and then move it.(you can rotate it by the arrow keys and space and m.) I would think that the object would just rotate where it is but no; in a full rotation it first is where it should be, then it rotates in a circle to 0,0,0 and then it rotates back to where it should be. Why doesn't it just rotate where the object is? Why does it move to a different place when rotated?

translation code:

1al_identity_transform(&transform); 2al_rotate_transform_3d(&transform, 1, 0, 0, x); 3al_rotate_transform_3d(&transform, 0, 1, 0, y); 4al_rotate_transform_3d(&transform, 0, 0, 1, z); 5al_translate_transform_3d(&transform, 0, 0, -4000); 6al_use_transform(&transform);

whole code:

1#include<allegro5\allegro.h> 2#include<allegro5\allegro_color.h> 3#include<allegro5\allegro_image.h> 4#include<allegro5\allegro_primitives.h> 5 6#define W 1000 7#define H 1000 8#define PPHI 100 9#define PTHETA 100 10#define XYZ_MOVE_AMOUNT 0.01 11#define AMOUNT_OF_INDEXES (PPHI*PTHETA * 2-PPHI) 12#define LOOP(var,max) for(var=0;var<max;++var) 13 14int main() { 15 16 //------------setup----------- 17 18 al_init(); 19 al_init_image_addon(); 20 al_init_primitives_addon(); 21 al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); 22 auto display = al_create_display(W, H); 23 al_install_keyboard(); 24 auto queue = al_create_event_queue(); 25 auto timer = al_create_timer(1.0 / 60.0); 26 //auto image = al_load_bitmap("C:\\Users\\ae1admin1\\Desktop\\programming_stizzle\\progz\\langtons_ant\\langtons_ant\\images\\square_pattern\\end.png"); 27 28 al_register_event_source(queue, al_get_timer_event_source(timer)); 29 al_register_event_source(queue, al_get_keyboard_event_source()); 30 al_register_event_source(queue, al_get_display_event_source(display)); 31 al_start_timer(timer); 32 33 al_set_render_state(ALLEGRO_DEPTH_TEST, 1); 34 35 ALLEGRO_EVENT ev; 36 ALLEGRO_TRANSFORM transform; 37 ALLEGRO_COLOR white = { 1, 1, 1, 1 }; 38 ALLEGRO_COLOR black = { 0,0,0, 1 }; 39 ALLEGRO_COLOR gray = { 0.5,0.5,0.5, 1 }; 40 int index_list[AMOUNT_OF_INDEXES] = { 0 }; 41 int i, j, k, index; 42 float x, y, z; 43 x = y = z = 0; 44 LOOP(i, PPHI - 1) { 45 LOOP(j, PTHETA) { 46 index_list[(i*PPHI + j) * 2] = i * PPHI + j; 47 index_list[(i*PPHI + j) * 2 + 1] = (i + 1)*PPHI + j; 48 } 49 } 50 float rotate = 0; 51 52 float r[2]; 53 float phi, theta; 54 55 float m[2] = { 2,3 }; 56 float n1[2] = { 0.7,100 }; 57 float n2[2] = { 0.3,100 }; 58 float n3[2] = { 0.2,100 }; 59 float a[2] = { 1,1 }; 60 float b[2] = { 1,1 }; 61 ALLEGRO_VERTEX v[PPHI*PTHETA] = { 0 }; 62 63 //------------create the shape------------- 64 65 LOOP(i, PPHI) { 66 LOOP(j, PTHETA) { 67 phi = i * PI * 2 / PPHI; 68 theta = j * PI * 2 / PTHETA;//half and shift 69 r[0] = 1 / pow(pow(fabs((1.0 / a[0])*cos((m[0] / 4.0)*phi)), n2[0]) + pow(fabs((1.0 / b[0])*sin((m[0] / 4.0)*phi)), n3[0]), 1.0 / n1[0]); 70 r[1] = 1 / pow(pow(fabs((1.0 / a[1])*cos((m[1] / 4.0)*theta)), n2[1]) + pow(fabs((1.0 / b[1])*sin((m[1] / 4.0)*theta)), n3[1]), 1.0 / n1[1]); 71 index = j + i * PTHETA; 72 v[index].x = r[0] * cos(theta)*r[1] * cos(phi) * 1000; 73 v[index].y = r[0] * sin(theta)*r[1] * cos(phi) * 1000; 74 v[index].z = r[1] * sin(phi) * 1000; 75 v[index].color = al_color_hsv(phi / (PI * 2) * 360, 1, 1); 76 77 al_clear_to_color(gray); 78 al_clear_depth_buffer(1000); 79 } 80 } 81 82 //------------main loop-------------- 83 84 while (1) 85 { 86 al_wait_for_event(queue, &ev); 87 switch (ev.type) 88 { 89 case ALLEGRO_EVENT_KEY_CHAR: 90 switch (ev.keyboard.keycode) 91 { 92 case ALLEGRO_KEY_ESCAPE: 93 exit(0); 94 case ALLEGRO_KEY_LEFT: 95 x -= XYZ_MOVE_AMOUNT; 96 break; 97 case ALLEGRO_KEY_RIGHT: 98 x += XYZ_MOVE_AMOUNT; 99 break; 100 case ALLEGRO_KEY_UP: 101 y -= XYZ_MOVE_AMOUNT; 102 break; 103 case ALLEGRO_KEY_DOWN: 104 y += XYZ_MOVE_AMOUNT; 105 break; 106 case ALLEGRO_KEY_SPACE: 107 z += XYZ_MOVE_AMOUNT; 108 break; 109 case ALLEGRO_KEY_M: 110 z -= XYZ_MOVE_AMOUNT; 111 break; 112 } 113 break; 114 case ALLEGRO_EVENT_TIMER: 115 116 //------------drawing----------- 117 118 al_clear_to_color(gray); 119 al_clear_depth_buffer(1000); 120 121// -------------------------Problem is here------------------------------- 122 123 al_identity_transform(&transform); 124 al_rotate_transform_3d(&transform, 1, 0, 0, x); 125 al_rotate_transform_3d(&transform, 0, 1, 0, y); 126 al_rotate_transform_3d(&transform, 0, 0, 1, z); 127 al_translate_transform_3d(&transform, 0, 0, -4000); 128 al_use_transform(&transform); 129 130 al_draw_indexed_prim(v, NULL, NULL, index_list, AMOUNT_OF_INDEXES, ALLEGRO_PRIM_TRIANGLE_STRIP); 131 132 al_perspective_transform(&transform, -W / 2, -H / 2, 1000, W / 2, H / 2, 100000000); 133 al_use_projection_transform(&transform); 134 al_flip_display(); 135 break; 136 case ALLEGRO_EVENT_DISPLAY_CLOSE: 137 exit(0); 138 } 139 } 140}

Edgar Reynaldo

That's not how you use al_rotate_transform_3d. Or at least, I don't think you're doing it right. In your case, x,y, and z would be the angle you rotate around the axis. What you do is rotate around a single axis. That will make it spin. If you rotate around two axes, you can get roll, yaw, and pitch. But you need to rotate around the forward, up, and right vectors to do that.

DontKnow3D

I don't quite get what you mean. Could you post some example code?

Edgar Reynaldo

XYZ defines the vector (axis) you wish to rotate around. Theta is by how much.

If you rotate around the z (forward) vector, you get roll.

If you rotate around the x (right) vector, you get pitch.

If you rotate around the y (up) vector, you get yaw.

DontKnow3D

I thought that that is exactly what im doing. First I rotate by x amount around axis x, then by y amount around axis y etc. and at the end I move it a bit back

SiegeLord

You're missing an al_identity_transform before you construct your perspective transformation (thanks for providing the code, it took me a few minutes to figure out what was going on).

DontKnow3D

yes thank you! I forgot the identity transform...

Edgar Reynaldo

The thing you have to realize is that you're applying yaw, roll, and pitch improperly.

Time for a quick tut.

Take your left hand and open it and spread out your fingers. Now close the pinky and ring fingers into your palm while keeping your other fingers in place as best you can. Now form the 3 remaining fingers into the shape of a 3D corner. Now point your middle finger directly towards you. They now form the basis of a Left Handed Coordinate system. Your middle finger points towards positive z, towards the screen, or you. Your pointer finger points towards the positive x axis, and your thumb points towards positive y axis.

Now try to rotate your hand around one of your open fingers. You can't do it without affecting the other two axes. This means if you want to apply yaw, pitch, and roll, then you need to modify the other two vectors when you rotate around an axis. So anytime you rotate around one of the three axis vectors (forward, right, up), you change the other two.

This means you need to account for that in your code, if you truly want local roll, pitch, and yaw.

This is mostly psuedocode. Initialization of fw,rt,and up are up to you. They should be normalized to length 1, and they can simply be your xyz axes.

1ALLEGRO_TRANSFORM t,t2; 2ALLEGRO_VERTEX fw,rt,up; 3double yaw,pitch,roll; 4 5al_identity_transform(&t); 6al_identity_transform(&t2); 7al_rotate_transform_3d(&t , rt.x , rt.y , rt.z , pitch); 8al_rotate_transform_3d(&t2 , rt.x , rt.y , rt.z , pitch); 9al_transform_coordinates_3d(&t , &up.x , &up.y , &up.z); 10al_transform_coordinates_3d(&t , &fw.x , &fw.y , &fw.z); 11 12al_identity_transform(&t); 13al_rotate_transform_3d(&t , fw.x , fw.y , fw.z , roll); 14al_rotate_transform_3d(&t2 , fw.x , fw.y , fw.z , roll); 15al_transform_coordinates_3d(&t , &up.x , &up.y , &up.z); 16al_transform_coordinates_3d(&t , &rt.x , &rt.y , &rt.z); 17 18al_identity_transform(&t); 19al_rotate_transform_3d(&t , up.x , up.y , up.z , yaw); 20al_rotate_transform_3d(&t2 , up.x , up.y , up.z , yaw); 21al_transform_coordinates_3d(&t , &rt.x , &rt.y , &rt.z); 22al_transform_coordinates_3d(&t , &fw.x , &fw.y , &fw.z); 23 24al_use_transform(&t2);