Thread: rotation matrix

  1. #1
    Registered User SAMSAM's Avatar
    Join Date
    Nov 2001
    Posts
    218

    rotation matrix

    Hi every1;

    i know there are built in functions that do certain rotations
    for you in opengl like glrotate but for the rest,i have to comeup
    with my own matrix.

    now im having fun with opengl and its API ,it is very straight
    forward and with practice its like any other API,
    and im okay with 3d math concept,but there is this rotation part

    that is stalling me.
    i know the formula and so on but i need to know step
    by step ,as how they get to for instance,

    M_revolve_x

    1 0 0 0
    0 cos@ -sin@ 0
    0 sin@ cos@ 0
    0 0 0 1

    ive searched the web for tutorials and find most of them
    just jump in with numbers and no diagram(drawing)

    as to explain step by step, the procedure to come up with your own rotation matrix.

    can anyone show me to one of these or better yet ,do a
    tutorial like thread to explain this to me .because this is the only

    part i have a hard time grasping.

    by the way:

    am i correct to say in order to do the rotation i must first adjust the location of the vector to be at the origin of the coordinate frame

    and then rotate and then translate back to the old location on
    the frame? is there a matrix that rotates one vector around another line(not the axis)?

    cheers!
    Last edited by SAMSAM; 02-26-2003 at 05:55 PM.

  2. #2
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    Yes you have to translate to the origin, rotate the view vector, and then add it back to the position.

    Vector temp = (View - Positin);
    Rotate(theta, x, y, z);
    View = temp + Position;

    There are several ways to create a matrix to perform rotation of the view vector in a computer game. You can create a matrix specifically designed for rotation about an arbitrary axis. Or, you can achieve the same effect by rotating about all axes. You can do this with a matrix that is called the concatenation of the X, Y and Z axis rotations(multiply all the matrices together), and is described in this thread I created today (this is pretty cool that we are doing this stuff at the same time SAMSAM, we're learning together!).

  3. #3
    Registered User SAMSAM's Avatar
    Join Date
    Nov 2001
    Posts
    218
    yes its interesting .and the person who helped you is only 18 and developing his own operating system.

    lets say goodluck to both of us. u & me in learning opengl

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    This might help if you want to create your own matrices - the rotation matrices might be switch but I cannot check them since I'm not on my own computer right now.

    I use doubles in my code so that when I use assembly I can easily use the math co-processor. Most compilers will hand off doubles to the math-co processor - check me on this, though, because some say doubles are faster and some say they are not. But all the matrices I've seen (except for those in 3Dfx) use doubles.

    Code:
    //Make this faster by unrolling the inner k loop
    //Did not do so here for clarity's sake
    //Concantenates m1[] and m2[] - result in r[]
    void MatMult(double m1[3][3],double m2[3][3],double r[3][3])
    {
      for (int i=0;i<4;i++)
      {
        for (int j=0;j<4;j++)
        {
           for (int k=0;k<4;k++)
           {
              r[i][j]+=m1[i][k]*m2[k][j];
           }
        }
      }
    }
    
    //Copies source to target - no loop
    void MatCopy(double source[3][3],double target[3][3])
    {
      target[0][0]=source[0][0];
      target[0][1]=source[0][1];
      target[0][2]=source[0][2];
      target[0][3]=source[0][3];
    
      target[1][0]=source[1][0];
      target[1][1]=source[1][1];
      target[1][2]=source[1][2];
      target[1][3]=source[1][3];
    
      target[2][0]=source[2][0];
      target[2][1]=source[2][1];
      target[2][2]=source[2][2];
      target[2][3]=source[2][3];
    
      target[3][0]=source[3][0];
      target[3][1]=source[3][1];
      target[3][2]=source[3][2];
      target[3][3]=source[3][3];
    }
    
    void Translate(double dx,double dy,double dz)
    {
      double trans[3][3];
      double result[3][3];
    
      trans[0][0]=1.0;trans[0][1]=0.0;trans[0][2]=0.0;trans[0][3]=dx;
      trans[1][0]=0.0;trans[1][1]=1.0;trans[1][2]=0.0;trans[1][3]=dy;
      trans[2][0]=0.0;trans[2][1]=0.0;trans[2][2]=1.0;trans[2][3]=dz;
      trans[3][0]=0.0;trans[3][1]=0.0;trans[3][2]=0.0;trans[3][3]=1.0;
    
      MatMult(trans,result);
      MatCopy(result,master);
    }
    
    void Scale(double sx,double sy,double sz)
    {
      
      double s[3][3];
      double result[3][3];
    
      s[0][0]=sx;s[0][1]=0.0;s[0][2]=0.0;s[0][3]=0.0;
      s[1][0]=0.0;s[1][1]=sy;s[1][2]=0.0;s[1][3]=0.0;
      s[2][0]=0.0;s[2][1]=0.0;s[2][2]=sz;s[2][3]=0.0;
      s[3][0]=0.0;s[3][1]=0.0;s[3][2]=0.0;s[3][3]=1.0;
    
      MatMult(s,result);
      MatCopy(result,master);
    }
    
    void Rotate(double ax,double ay,double az)
    {
      double xmat[3][3];
      double ymat[3][3];
      double zmat[3][3];
      double r1[3][3];
      double r2[3][3];
    
      //Order of rotations does matter
      //Concatenation of matrices is NOT commutative  
    
      //Rotate about x axis
      xmat[1][1]=cos(ax);xmat[1][2]=-sin(ax);
      xmat[2][1]=sin(ax);xmat[2][2]=cos(ax);
    
      xmat[0][0]=1.0;xmat[0][1]=0.0;xmat[0][2]=0.0;xmat[0][3]=0.0;
      xmat[1][0]=0.0;xmat[1][3]=0.0;
      xmat[2][0]=0.0;xmat[2][3]=0.0;
      xmat[3][0]=0.0;xmat[3][1]=0.0;xmat[3][2]=0.0;xmat[3][3]=1.0;
    
      //Concatenate with master
      MatMult(xmat,master,r1);
    
      //Rotate about y axis
      ymat[0][0]=cos(ay);ymat[0][2]=-sin(ay);
      ymat[2][0]=sin(ay);ymat[2][2]=cos(ay);
    
      ymat[0][1]=0.0;ymat[0][3]=0.0;
      ymat[1][0]=0.0;ymat[1][1]=1.0;ymat[1][2]=0.0;ymat[1][3]=0.0;
      ymat[2][1]=0.0;ymat[2][3]=0.0;
      ymat[3][0]=0.0;ymat[3][1]=0.0;ymat[3][2]=0.0;ymat[3][3]=1.0;
    
      //Concatenate with result of x rotation - r1[]
      MatMult(ymat,r2,r1);
    
      //Rotate about z axis
      zmat[0][0]=-sin(az);zmat[0][1]=cos(az);
      zmat[1][0]=cos(az);zmat[1][1]=sin(az);
    
      zmat[0][2]=0.0;ymat[0][3]=0.0;
      zmat[1][2]=0.0;zmat[1][3]=0.0;
      zmat[2][0]=0.0;zmat[2][1]=0.0;zmat[2][2]=1.0;zmat[2][3]=0.0;
      zmat[3][0]=0.0;zmat[3][1]=0.0;zmat[3][2]=0.0;zmat[3][3]=1.0;
    
      //Concatenate with result of y rotation - r2[] - leave in master
      MatMult(zmat,r2,master);
      
    }

    Now all you need is to transform these vertices from local space to world space to view space. I'm not familiar with OpenGL but I think it will probably do this for you - it's much faster to have your 3D card process the vertices for you. But here is an old DOS transform that I used to use - before Direct3D that is.


    Again Direct3D and OpenGL have their own vertex structures that you can use but here is a simple breakdown of a typical vertex structure.

    Code:
    struct pt2d
    {
      int x;
      iny y;
    };
    
    struct pt3d
    {
      double x;
      double y;
      double z;
    };
    
    struct vertex
    {
      pt3d local;
      pt3d world;
      pt3d view;
      pt2d screen;
    
      //pt2d texture;        //for texture mapping
      //pt3d normal;         //pre-computed normal
    };
    
    void LocalTransform(vertex *object,long numvertexes)
    {
      vertex *temp=object;
      for (int i=0;i<numvertexes;i++)
      {
        double lx=temp[i].local.x;
        double ly=temp[i].local.y;
        double lz=temp[i].local.z;
    
        double wx=lx*master[0][0]+ly*master[0][1]+
                           lz*master[0][2]+master[0][3];
        double wy=lx*master[1][0]+ly*master[1][1]+
                           lz*master[1][2]+master[1][3];
        double wz=lx*master[2][0]+ly*master[2][1]+
                           lz*master[2][2]+master[2][3];
    
        temp[i].world.x=wx;
        temp[i].world.y=wy;
        temp[i].world.z=wz;
      }
    }
    
    void ViewTransform(vertex *object,long numvertexes)
    {
      vertex *temp=object;
      for (int i=0;i<numvertexes;i++)
      {
        double wx=temp[i].world.x;
        double wy=temp[i].world.y;
        double wz=temp[i].world.z;
    
        double vx=wx*master[0][0]+wy*master[0][1]+
                          wz*master[0][2]+master[0][3];
        double vy=wx*master[1][0]+wy*master[1][1]+
                          wz*master[1][2]+ master[1][3];
        double vz=wx*master[2][0]+wy*master[2][1]+
                          wz*master[2][2]+master[2][3];
    
        temp[i].view.x=vx;
        temp[i].view.y=vy;
        temp[i].view.z=vz;
      }
    }

    Again my rotation matrices might be backwards and some of the structure operations might be wrong - I hand-coded this from memory while sitting here so I'm sure there are some errors. But most of this should work as is. Again this is old school since most APIs hand this off to the video card and they perform it much quicker than this code could.

    Hope this helps. It should give you an idea of the matrices and concatenations required for 3D. If you want to know how to concatenate different types of matrices then find a math book or get a book that explains 3D concepts and math.

    Only thing left to code for the above is the projection function but I will leave that to you. Now you can create some vertexes and rotate them about any axis. If you do not like using radians then convert them to degrees (radians*PI/180). Not the best to use euler angles but it works to start off with.

    If you are using OpenGL like you said then just set up your rotation matrix and let it do the rest.

  5. #5
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    To tell you the truth bubba I usually see updating the view vector in a computer game done in software. I'm not sure it would create a speed increase sending it to the video card. It might, I'm not sure because I've only done it in software, but it(the gpu) already has its own work to do, so both processors are usually pretty tied up. I guess I should try doing both and test it. I'm also not sure how professional titles do it.

    hmmMMmmm

    Why would doubles be faster. I thought they were the same things as floats on a 32 bit system (5 decimal places accuracy) except they hold 8 bytes instead of 4. HmmMmmm 2

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C - access violation
    By uber in forum C Programming
    Replies: 2
    Last Post: 07-08-2009, 01:30 PM
  2. camera rotation matrix
    By Vick jr in forum Game Programming
    Replies: 5
    Last Post: 05-26-2009, 08:16 AM
  3. Matrix Help
    By HelpmeMark in forum C++ Programming
    Replies: 27
    Last Post: 03-06-2008, 05:57 PM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM