Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: trig model FPS angle generation

  1. #1
    Intern Contributor
    Join Date
    May 2017
    Posts
    80

    trig model FPS angle generation

    I have come across a lot of math models lately for 3D camera systems. I am stuck on the easiest, which is so frustrating. Basically to calculate all of the trig functions, one has to know 'the angle'. Or 2. I understand that if the spherical nomenclature is applied to the system, and then translated into cartesian coordinates, this would be explanatory. But I have seen programmers use the cartesian without the spherical system as well.

    So, in the trig model, where exactly are the angles coming from that when broken down to the unit circle are used for translation and rotation. Is it a single angle for XZ b/c y = 0? I can figure out the rest of the trig math from here if I can imagine the proper use the angles.

    my example with 'w' :

    Code :
     
     
     if (key=='w')  //forwards
    				    {
    				    float xrotrad, yrotrad;
    				    yrotrad = (pRot->yrot / 180 * 3.141592654f);
    				    xrotrad = (pRot->xrot / 180 * 3.141592654f);
    				    pPos->xpos += float(sin(yrotrad)) ;
    				    pPos->zpos -= float(cos(yrotrad)) ;
    				    pPos->ypos -= float(sin(xrotrad)) ;
    				    }

    Where do the rotation angles come from above, yrotrad, xrotrad etc. Are they more for analysis within unit circle, or do they represent a "heading"?
    I think I am overthinking this, but there it is. I think I may be getting these mixed up with vectors.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,522
    Quote Originally Posted by technologist View Post
    Where do the rotation angles come from above, yrotrad, xrotrad etc. Are they more for analysis within unit circle, or do they represent a "heading"?
    yrotrad is the heading, xrotrad is the elevation (angle from horizontal). However, the change to xpos/zpos should also be multiplied by cos(xrotrad).

    For the most part, the only trigonometry required for 3D graphics (and related simulation aspects) is conversion between polar and rectangular (Cartesian) coordinates.
    Code :
    void polar_to_rectangular(float angle, float radius, float& x, float& y)
    {
        x = radius * cos(angle);
        y = radius * sin(angle);
    }
     
    void rectangular_to_polar(float x, float y, float &angle, float &radius)
    {
        angle = atan2(y, x);
        radius = sqrt(x*x+y*y); // equivalent to hypot(x, y);
    }

    Spherical coordinates are just repeated application:
    Code :
    // +y is forward, +z is up
    void spherical_to_rectangular(float heading, float elevation, float radius, float& x, float& y, float &z)
    {
        float d;
        polar_to_rectangular(elevation, radius, d, z);
        polar_to_rectangular(heading, d, x, y);
    }
    If you expand out the polar_to_rectangular() calls, you'll end up with something a lot like your existing code.

  3. #3
    Intern Contributor
    Join Date
    May 2017
    Posts
    80
    yrotrad is the heading, xrotrad is the elevation (angle from horizontal). However, the change to xpos/zpos should also be multiplied by cos(xrotrad).
    Thanks for the response, it broke loose an avalanche of ideas as I thought it would. I was surprised to learn there were not 1 or 3 unit circles, but (2) for 3 Euler angles. Working out the math from that I had some questions:
    0. is the unit vector from the Euler angles the "front" of the camera?
    1. which is the simplest way to "display" what's in front of my camera now? double buffering? gluLookAt? Another way?
    2. I've noticed that the Euler rotations are also found in rotational matrices. I was able to calculate all of the trig "by hand" without matrices. Doesn't make it the best way though - should I use the rotational matrices? I am eventually going to try Quats.
    3. can I derive my own rotational matrices, or this pennywise/poundfoolish.
    4. I want to implement a keyboard scheme - I have several prototypes already. What should my strategy be here on forwards/reverse/strafe - in general.

    Thanks in advance for any answers you all could provide.

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,522
    Quote Originally Posted by technologist View Post
    0. is the unit vector from the Euler angles the "front" of the camera?
    In terms of your code, it's the direction you move when you press W. In the more general sense, Euler angles are just a way of representing a rotation (i.e. an orthonormal matrix). What that matrix represents depends upon how its used.

    Quote Originally Posted by technologist View Post
    1. which is the simplest way to "display" what's in front of my camera now? double buffering? gluLookAt? Another way?
    Construct matrices which rotate about the X and Y axes, and multiply them. Once you've done that, you can replace the movement code (the columns of the view matrix are the local X/Y/Z axes).

    Quote Originally Posted by technologist View Post
    2. I've noticed that the Euler rotations are also found in rotational matrices. I was able to calculate all of the trig "by hand" without matrices. Doesn't make it the best way though - should I use the rotational matrices? I am eventually going to try Quats.
    I'd suggest using matrices.

    Quote Originally Posted by technologist View Post
    3. can I derive my own rotational matrices, or this pennywise/poundfoolish.
    I'd suggest using GLM.

    Quote Originally Posted by technologist View Post
    4. I want to implement a keyboard scheme - I have several prototypes already. What should my strategy be here on forwards/reverse/strafe - in general.
    Whatever works. The main thing to bear in mind is that view orientation and motion orientation aren't necessarily the same thing. E.g. if you look up or down, you may still want to rotate about the world's vertical axis rather than the view axes (unless you're piloting a spaceship, where there isn't a global "up" direction).

  5. #5
    Intern Contributor
    Join Date
    May 2017
    Posts
    80
    Construct matrices which rotate about the X and Y axes, and multiply them. Once you've done that, you can replace the movement code (the columns of the view matrix are the local X/Y/Z axes).
    Can you please expand on that? I think I understand how to make the Euler angle matrices for the angles, but I've lost you in *bold* & view matrix.

    Another question:


    Code :
    roty(int a){
       s, c = sincos(a)
       return np.matrix([[c,0,s,0],
                         [0,1,0,0],
                         [-s,0,c,0],
                         [0,0,0,1]])
    	}

    I understand the math here. I believe this was written in python, just not c++. How do I write this snippet in c++?
    Last edited by technologist; 11-26-2017 at 11:10 AM. Reason: add to it

  6. #6
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,522
    Quote Originally Posted by technologist View Post
    Can you please expand on that? I think I understand how to make the Euler angle matrices for the angles, but I've lost you in *bold* & view matrix.
    Code :
    glm::mat4 my = glm::rotate(yrot, 0.0f, 1.0f, 0.0f);
    glm::mat4 mx = glm::rotate(xrot, 1.0f, 0.0f, 0.0f);
    glm::mat4 m = my * mx;
    or:
    Code :
    glm::mat4 m = glm::mat4(1.0);
    glm::rotate(m, yrot, 0.0f, 1.0f, 0.0f);
    glm::rotate(m, xrot, 1.0f, 0.0f, 0.0f);

    Quote Originally Posted by technologist View Post
    I understand the math here. I believe this was written in python, just not c++. How do I write this snippet in c++?
    Code :
    glm::mat4 roty(float a) {
        float s = std::sin(a);
        float c = std::cos(a);
        return glm::mat4(
               c, 0.0f,   -s, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,  
               s, 0.0f,    c, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f);
    }

    Note that GLM wants the components in column-major order, while numpy uses row-major order.

    Also, in the Python version (assuming that it's my original code), sincos() converts its argument from degrees to radians, so code which uses it will be using angles in degrees (that was for compatibility with the legacy OpenGL functions; trig functions in languages or their libraries invariably use radians).

  7. #7
    Intern Contributor
    Join Date
    May 2017
    Posts
    80

    update on coding rotation function

    Thank you for the snippet....my hypothesis is that the result of roty(theta) customized is the same as the glm::rotation function for the same degree input. Its turning out differently. Maybe someone could please point out why??

    Code :
    glm::mat4 roty(float a) {
        float s = std::sin(a);
        float c = std::cos(a);
        return glm::mat4(
               c, 0.0f,   -s, 0.0f,
            0.0f, 1.0f, 0.0f, 0.0f,
               s, 0.0f,    c, 0.0f,
            0.0f, 0.0f, 0.0f, 1.0f);    
    }
     
    int main()
    {
             // per function above
    	glm::vec4 _vector(4.0f,5.0f,6.0f,1.0f);
    	glm::mat4 _trans = glm::mat4(1.0f);
    	_trans = roty(30.0f);
    	_vector = _vector * _trans;
    	std::cout<<glm::to_string(_vector)<<std::endl;
     
            // ::glm
    	glm::vec4 _vector2(4.0f,5.0f,6.0f,1.0f);
    	glm::mat4 _trans2 = glm::mat4(1.0f);
    	_trans2 = glm::rotate(_trans2, 30.0f, glm::vec3(0,1,0));
    	_vector2 = _trans2 * _vector2;
    	std::cout<<glm::to_string(_vector2)<<std::endl;

    Output for theta = 30 degrees(should I convert to radians for these functions?):
    vec4(6.545196, 5.000000, -3.026618, 1.000000)
    vec4(-5.311184, 5.000000, 4.877635, 1.000000)

    Should be identical.

  8. #8
    Intern Contributor
    Join Date
    May 2017
    Posts
    80
    Code :
    glm::mat4 my = glm::rotate(yrot, 0.0f, 1.0f, 0.0f);
    glm::mat4 mx = glm::rotate(xrot, 1.0f, 0.0f, 0.0f);
    glm::mat4 m = my * mx;

    Q: I can see the logic in adding and subtracting vectors. Even multiplying them (like scale) by a scalar. What does multiplying rotational matrices my, mx(above) do, per se. What are we after with the product? What does multiplying them 'do'?

  9. #9
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,522
    Quote Originally Posted by technologist View Post
    Code :
    	_vector = _vector * _trans;
    This should be the other way around:
    Code :
    	_vector = _trans * _vector;
    Reversing the order has the same effect as transposing the matrix:

    (A.B)T=BT.AT

    GLM has the same behaviour as GLSL: matrix*vector treats the vector as a column vector, vector*matrix treats it as a row vector (i.e. it's implicitly transposed to make the multiplication valid).

  10. #10
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,522
    Quote Originally Posted by technologist View Post
    Q: I can see the logic in adding and subtracting vectors. Even multiplying them (like scale) by a scalar. What does multiplying rotational matrices my, mx(above) do, per se. What are we after with the product? What does multiplying them 'do'?
    A matrix represents a linear function. Multiplying matrices is equivalent to composing the functions.

    Matrix multiplication is associative: (A.B).v = A.(B.v) (vectors are just matrices with a single row or column). So transforming a vector by the product of two matrices is equivalent to transforming it by the second matrix then by the first matrix.

    Note that the GLM matrix generating functions (translate, rotate, scale) which take a matrix as the first parameter perform an implicit multiplication: the result is the product of the first parameter and the matrix defined by the other parameters. So e.g.
    Code :
    glm::mat4 m = glm::rotate(m0, angle, x, y, z);
    is equivalent to
    Code :
    glm::mat4 m1 = glm::rotate(angle, x, y, z);
    glm::mat4 m = m0 * m1;
    Similarly, the legacy OpenGL matrix functions are equivalent to calling glMultMatrix() with a matrix defined by the parameters (the generated matrix is given in the function's reference page).

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •