Search code examples
c++openglrotationtranslationopengl-compat

Rotation along a path in opengl


i want to move an object along a path (sine wave), lets suppose object is a roller coaster. it moves through translate but my problem is that i also want to rotate that object according to the path.

i tried this code before translate but its not working.

if (x = -4.8)
{
    glRotatef(89, 1, 1, 0);
}

my code with only translation looks like this. i want to add rotation here along sine waves

void object()
{   glPushMatrix();
    glTranslatef(x, y, 0);

    glColor3f(0.0f, 0.0f, 0.0f);//Set drawing color
    glBegin(GL_QUADS);
    glVertex2f(-0.3, 0.1);
    glVertex2f(0.3, 0.1);
    glVertex2f(0.3, -0.1);
    glVertex2f(-0.3, -0.1);
    glEnd();
    glFlush();
    glPopMatrix();
    glFlush();
}

void drawsine()
{
    glBegin(GL_LINE_STRIP);//Primitive
    glColor3f(255, 0, 0);//Set drawing color 
    int i = 0;
    float x = 0, y = 0;
    for (x = -5; x < 6; x = x + 0.1)
    {
        y = (sin(3.142*x)) / 3.142*x;
        glVertex2f(x, y);

        //int j= 0;
        sinex[i] = x;
        siney[i] = y;
        i++;
    }
    glEnd();
    glFlush();
} 

Solution

  • The angle of rotation depends on the direction vector along the sine wave.

    The direction vector can be calculated by the subtraction of 2 positions. Subtract the position before the current position from the positions after the current position, to calcaulte the direction vector. In the following i is the current position of the object:

    dx = sinex[i+1] - sinex[i-1];
    dy = siney[i+1] - siney[i-1];
    

    The angle of rotation can be calculated by the arcus tangent using atan2, which returns an angle in radians:

    float ang_rad = atan2( dy, dx );
    

    Since the angle has to be passed to glRotatef in degrees, the angle has to be converted from radians to degrees, before a rotation around the z axis can be performed. A full circle in has 360 degrees or 2*Pi radians. So the scale from radians to degrees 180/Pi:

    float ang_deg = ang_rad * 180.0f / M_PI;
    glRotatef( ang_deg, 0, 0, 1 );
    

    The following cde snippet show how to apply the code. Be aware that there is no bounds check. This means i has to be grater or equal 1 and less than the number of points - 1 (1 <= i < 110):

    #define _USE_MATH_DEFINES
    #include <math.h>
    
    {
        // [...]
    
        drawsine();
    
        x = sinex[i];
        y = siney[i];
        dx = sinex[i+1] - sinex[i-1];
        dy = siney[i+1] - siney[i-1];
    
        object();
    
        // [...]
    }
    
    void object()
    {    
        glPushMatrix();
        glTranslatef(x, y, 0);
    
        float ang_rad = atan2( dy, dx );
        float ang_deg = ang_rad * 180.0f / M_PI;
        glRotatef( ang_deg, 0, 0, 1 );
    
        glColor3f(0.0f, 0.0f, 0.0f);
        glBegin(GL_QUADS);
        glVertex2f(-0.3, 0.1);
        glVertex2f(0.3, 0.1);
        glVertex2f(0.3, -0.1);
        glVertex2f(-0.3, -0.1);
        glEnd();
    
        glPopMatrix();
    }