Matrix Rotation not working the way I want it to

D.V.D

Make a wish
Reaction score
73
So I'm trying to rotate a box/rectangle around a point so that the boxes rotation constantly changes but it's location stays the same. I have my values in the rotation matrix based of a few links but when I draw the rectangle/box, it's position is changed more and more as the rotation angle increases/decreases.

rotation matrix = [ cos theta , -sin theta
sin theta , cos theta ]

Here's the output I get in my window ( I drew all of the different rotations to see their positions clearly, and the bottom is erased in paint, not in the program ):
OutputIhor.png


Note: I use a lot of constants in my code and normal arrays instead of dynamic arrays like I probably should for matrices. Also, this is my first time ever using them :p

Code:
class position {
public:
    float x,y;
};
 
void matrix_test (HDC hdc) {
    // set initial position
    int init_x = 700;
    int init_y = 700;
 
    // set matrices dimensions
    const int mat_x = 5;
    const int mat_y = 20;
 
    // load matrices
    float rotation [2][2];
    position pos [mat_x][mat_y];
    position display [mat_x][mat_y];
 
    // load colors
    COLORREF draw_col = RGB(0,0,0);
    COLORREF delete_col = RGB(255,255,255);
   
    // set the position of the box
    for ( int i=0; i < mat_x; i++ ) {
        for ( int j=0; j < mat_y; j++ ) {
            pos[i][j].x=init_x+i;
            pos[i][j].y=init_y+j;
        }
    }
    for ( int i=0; i < mat_x; i++ ) {
        for ( int j=0; j < mat_y; j++ ) {
            SetPixel(hdc,pos[i][j].x,pos[i][j].y,draw_col);
        }
    }
    //Sleep(1000);
 
    // copy pos matrix to display matrix
    for ( int i=0; i < mat_x; i++ ) {
        for ( int j=0; j < mat_y; j++ ) {
            display[i][j] = pos[i][j];
        }
    }
 
    // rotate
    for (float time=0; time < 1000; time+=2) {
        // delete previous matrix from HDC
        /*for ( int i=0; i < mat_x; i++ ) {
            for ( int j=0; j < mat_y; j++ ) {
                SetPixel(hdc,display[i][j].x,display[i][j].y,delete_col);
            }
        }*/
        // set the rotation matrix
        rotation[0][0] = cos(time);
        rotation[0][1] = (-1)*sin(time);
        rotation[1][0] = sin(time);
        rotation[1][1] = cos(time);
        // multiply rotation matrix by position matrix
        for ( int i=0; i < mat_x; i++ ) {
            for ( int j=0; j < mat_y; j++ ) {
                display[i][j].x = (pos[i][j].x*rotation[0][0])+(pos[i][j].y*rotation[0][1]);
                display[i][j].y = (pos[i][j].x*rotation[1][0])+(pos[i][j].y*rotation[1][1]);
            }
        }
        // draw the pixels
        for ( int i=0; i < mat_x; i++ ) {
            for ( int j=0; j < mat_y; j++ ) {
                SetPixel(hdc,display[i][j].x,display[i][j].y,draw_col);
            }
        }
        //Sleep(100);
 
    }
 
}
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
Here's the problem:
Code:
display[i][j].x = (pos[i][j].x*rotation[0][0])+(pos[i][j].y*rotation[0][1]);
display[i][j].y = (pos[i][j].x*rotation[1][0])+(pos[i][j].y*rotation[1][1]);

Think of a circle. Every point on a circle is the same distance (t) away from the middle/origin of the circle.
This code does the same. You're picking the point with rotation (a|b) that is a certain distance t away from your origin (0|0).

That's why all your drawings are on an imaginary circle around your (0|0) point with distance of 700 (your init_x/y).

What you want is setting t = 0, so you pick all points on a circle with radius 0.
Then you have to shift the resulting x|y coordinates so they're not displayed at 0|0 anymore.

In practice that means:

Code:
//Here we basically set t = 0, by not using init_x/y but 0.
    for ( int i=0; i < mat_x; i++ ) {
        for ( int j=0; j < mat_y; j++ ) {
            pos[i][j].x=0 + i;
            pos[i][j].y=0 + j;
        }
    }
 
...
//Here we're shifting the resulting x/y coordinates by the position we want them to be in.
display[i][j].x = (pos[i][j].x*rotation[0][0])+(pos[i][j].y*rotation[0][1]) + init_x;
display[i][j].y = (pos[i][j].x*rotation[1][0])+(pos[i][j].y*rotation[1][1]) + init_y;

If you look carefully you can actually see that pos[ i ][j] contains reduntant information and could be removed altogether now.

Similar for rotation[x][y]. You calculate cos(time) and sin(time) twice. No need for that. cos/sin are time expensive and you should avoid calling them more often than it's necessary when you're operating in tight loops (and looping 1000 times per update is pretty damn tight :p)


By the way - constant arrays are fine for matrices, usually. A matrix has a certain size and doesn't change afterwards.
You're using matrices in a .. different way than it's usually done :p

Usually you have a 4x4 matrix called the Transformation Matrix (TM). It contains the rotation, translation (position) and scaling that is to be applied to a pixel.
Then you have an array of pixels, which contain your image.
Last, you apply the TM on all pixels of your array, and print the pixel position onto the screen.

Well, that's also not exactly how it's done. It's a lot more difficult in all it's glory. That's why the fewest people do this stuff themselves. Rather, graphic APIs like OpenGL or DirectX do the job via graphics card.

PS: Writing [ i ] seriously screws with text formatting :D
 

D.V.D

Make a wish
Reaction score
73
Sorry for the super long reply, I was out of my country and traveling but thanks for the explanation. Yah I figured it was done way differently, but I wanted to teach myself some math and see what benefits really come from using matrices. So my last question, would using a matrix really be faster than other methods for something like this? Or would every way you do it require some form of a matrix?
 

s3rius

Linux is only free if your time is worthless.
Reaction score
130
Good to see I haven't written this for naught :D

So my last question, would using a matrix really be faster than other methods for something like this? Or would every way you do it require some form of a matrix?

Well, no matter how you look at it you'll always need at least an x and y coordinate for your point/model/polygon (in 2D space). This is basically just a vector of length 2. Which, again, is the same as a 1x2 matrix.

So no matter how you look at it, you almost always end up with some kind of matrix.

Even if you add more information to it (for example rotation) you can still see it as a matrix.

The usage of matrices as I described it isn't necessarily faster (maybe it is, maybe it isn't), but it's generally more useful as it's easier to do stuff with it.

I always use one of two schemes:

1) If I have a 2d space, or if I have very simple constructs I just store my x/y coordinates in a vector, because I don't need much else.

2) If I have 3d space I use matrices, because it allows me to store my x/y coordinates, rotation data and scale within a single matrix.

And if you want to continue working with 2d graphics I'd advice you to learn how to draw jpg/bmp images onto the screen.
I think drawing stuff pixel-by-pixel can make a man mad.
 

D.V.D

Make a wish
Reaction score
73
Haha exactly!!

Oh I see, that really helps clear up a lot of stuff. I always though matrices worked differently using other kinds of math to solve stuff. Hence why I was asking the question in the first place :p

Im starting to use OpenGl right now to get more of the processing offloaded into the GPU. Drawing it pixel by pixel can get frustrating but I started doing 2D stuff that way just because it was easier for me to imagine the way everything in a program would work. I tried using Win32 but that was just a hassle to learn. Everything is super over complicated especially their bitmaps -.-

Thanks for the help !! again :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top