About this Blog

This is my first blog. Ever.

It is simply going to be about my hobby; playing with computer programming. I do not know much about blogging, but I will use this one to learn a bit more about it.

Programming has always been a bit of a passion for me, as from those early days when I first tapped in a sample BASIC program on my old Sinclair Spectrum back in 1986. I have been through many platforms, languages and OS's since, but always carried the hobby with me. I am not particularly good at it; perfection requires a large time investment and continuous practice. I do not have the luxury of the amount of time required to keep the fire burning constantly, so the hobby has inevitably gone through periods of extreme withering. I have, however, finally settled for C++, as the title of this blog implies, and play around with it for some entertainment when ever I can.

This here will serve me as a written record of what I am up to, and hopefully be a reinforcement to my memory every now and then. That is all there is to it.

So, if you read this blog, please don't expect anything snazzy, but be you welcome just the same!

Saturday, 7 January 2012

2 Dimensional Matrix Rotation - Simple

Now, if curiosity killed the cat, but the cat has nine lives, that makes the cat eight times the wiser before it finally does get killed. Sounds like a fair trade to me, just so long as the curiosity is well spent. Doing all that OpenGL stuff that was in my previous posts is all well and dandy, but would it not be nice to at least have a superficial idea of what (sort of) goes on "under the hood" in order to supplement one's global understanding of 3D computer graphics? The following two or three posts, therefore, will concentrate on the heart of the matter where OpenGL rotation transformations are concerned...

THE MATRIX

There are tons of pages that "blah - blah" on about what matrices are, how they are arranged and multiplied, etcetera, but no simple example of their implementation. In this post, I am going to attack the simplest form of them, the 2D matrix, to enable the rotation of one point around the Z axis. It will probably be obvious that the matrix itself is the least of the worries. It is easy, for 2D stuff. Here's what happens, really.

Consider first the origin. That is, point (0, 0) on the X and Y axes. I have a point that is located at (150.0, -200.0) from that origin, which I want to rotate around the Z axis by 0.5 of a degree, every 1/60th of a second. The 2D matrix takes on this form...

- X - Y
X : cos(angle) : -sin(angle)
Y : sin(angle) : cos(angle)

To which the data of the old positions can be plugged in to achieve a rotation like this...

NEW_X_POSITION = (cos(angle) * old_x_position) + (-sin(angle) * old_y_position)
NEW_Y_POSITION = (sin(angle) * old_x_position) + (cos(angle) * old_y_position)

Do the math itself, on a piece of paper with a calculator, and the understanding will dawn. It is so simple, at this stage, that no further discussion is required. Here's some working source code, using Allegro 5.1.

#define _USE_MATH_DEFINES
#include "allegro5/allegro.h"
#include "allegro5/allegro_primitives.h"
#include "math.h"

/*
`pkg-config --libs allegro-5.1 allegro_primitives-5.1`
*/

//*******************
float deg_to_rad(float deg)
{
return deg * ((float)M_PI / 180.0f);
}


void matrix_2d_handler(float _angle, float &_x_pos, float &_y_pos)
{
float Matrix_2D[2][2];
float New_X, New_Y;

Matrix_2D[0][0] = cosf(_angle); Matrix_2D[0][1] = -sinf(_angle);
Matrix_2D[1][0] = sinf(_angle); Matrix_2D[1][1] = cosf(_angle);

New_X = (Matrix_2D[0][0] * _x_pos) + (Matrix_2D[0][1] * _y_pos);
New_Y = (Matrix_2D[1][0] * _x_pos) + (Matrix_2D[1][1] * _y_pos);

_x_pos = New_X;
_y_pos = New_Y;
}



//*******************
int main(int argc, char *argv[])
{
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer = NULL;

int SCREEN_X = 800;
int SCREEN_Y = 600;
int SC_X_CENT = SCREEN_X / 2;
int SC_Y_CENT = SCREEN_Y / 2;

float FPS = 60.0f;
float X_pos = 150.0f;
float Y_pos = -200.0f;
float angle = 0.5f;

bool draw = false;
bool loop = true;

al_init();
al_init_primitives_addon();


al_set_new_display_option(ALLEGRO_VSYNC, 1, ALLEGRO_SUGGEST);

display = al_create_display(SCREEN_X, SCREEN_Y);
event_queue = al_create_event_queue();
timer = al_create_timer(1.0f / FPS);

al_register_event_source(event_queue, al_get_display_event_source(display));
al_register_event_source(event_queue, al_get_timer_event_source(timer));

al_start_timer(timer);

while(loop)
{
ALLEGRO_EVENT event;
al_wait_for_event(event_queue, &event);

switch(event.type)
{
case ALLEGRO_EVENT_DISPLAY_CLOSE:
loop = false;
break;

case ALLEGRO_EVENT_TIMER:
draw = true;
break;

default:
break;
}

if(draw == true && al_event_queue_is_empty(event_queue))
{
draw = false;
al_clear_to_color(al_map_rgb(0,0,0));
matrix_2d_handler(deg_to_rad(angle), X_pos, Y_pos);
al_draw_circle(float(X_pos + SC_X_CENT), float(Y_pos + SC_Y_CENT), 10.0f, al_map_rgb(0,255,0), 0);
al_flip_display();
}
}

al_stop_timer(timer);
al_flush_event_queue(event_queue);
al_destroy_timer(timer);
al_destroy_event_queue(event_queue);
al_destroy_display(display);

return 0;
}

1 comment:

  1. thanks for these tutorials they are very useful :D

    ReplyDelete