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);
 
    }
 
}
 
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
 
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?
 
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.
 
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 The Helper:
    News portal has been retired. Main page of site goes to Headline News forum now
  • The Helper The Helper:
    I am working on getting access to the old news portal under a different URL for those that would rather use that for news before we get a different news view.
  • Ghan Ghan:
    Easily done
    +1
  • The Helper The Helper:
    https://www.thehelper.net/pages/news/ is a link to the old news portal - i will integrate it into the interface somewhere when i figure it out
  • Ghan Ghan:
    Need to try something
  • Ghan Ghan:
    Hopefully this won't cause problems.
  • Ghan Ghan:
    Hmm
  • Ghan Ghan:
    I have converted the Headline News forum to an Article type forum. It will now show the top 20 threads with more detail of each thread.
  • Ghan Ghan:
    See how we like that.
  • The Helper The Helper:
    I do not see a way to go past the 1st page of posts on the forum though
  • The Helper The Helper:
    It is OK though for the main page to open up on the forum in the view it was before. As long as the portal has its own URL so it can be viewed that way I do want to try it as a regular forum view for a while
  • Ghan Ghan:
    Yeah I'm not sure what the deal is with the pagination.
  • Ghan Ghan:
    It SHOULD be there so I think it might just be an artifact of having an older style.
  • Ghan Ghan:
    I switched it to a "Standard" article forum. This will show the thread list like normal, but the threads themselves will have the first post set up above the rest of the "comments"
  • The Helper The Helper:
    I don't really get that article forum but I think it is because I have never really seen it used on a multi post thread
  • Ghan Ghan:
    RpNation makes more use of it right now as an example: https://www.rpnation.com/news/
  • The Helper The Helper:
  • The Helper The Helper:
    What do you think Tom?
  • tom_mai78101 tom_mai78101:
    I will have to get used to this.
  • tom_mai78101 tom_mai78101:
    The latest news feed looks good
  • The Helper The Helper:
    I would like to see it again like Ghan had it the first time with pagination though - without the pagination that view will not work but with pagination it just might...
  • The Helper The Helper:
    This drink recipe I have had more than a few times back in the day! Mind Eraser https://www.thehelper.net/threads/cocktail-mind-eraser.194720/

      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