简体   繁体   中英

How rotate a circle around another with an elliptical motion with GLEW, OpenGL or SDL2?

My current code:

#define GLEW_STATIC
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <math.h>
#include <stdio.h>
#include <iostream>
#include<conio.h>
#include<dos.h>
#include <GL/glew.h>

using namespace std;

#ifdef WIN32
#include <GL/glew.h>

#else
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>

#endif

#include <SDL2/SDL.h>
#include <iostream>
void DrawCircle(float cx, float cy, float r, int num_segments);
void DrawEllipse(float cx, float cy, float a, float b, int num_segments);

int main(int argc, char **argv)
{
    // the window

    SDL_Window* fenetre(0);
    SDL_GLContext contexteOpenGL(0);

    SDL_Event evenements;
    bool terminer(false);


    // Initializing the SDL

    if(SDL_Init(SDL_INIT_VIDEO) < 0)
    {
        std::cout << "Erreur lors de l'initialisation de la SDL : " << SDL_GetError() << std::endl;
        SDL_Quit();

        return -1;
    }


    // Version OpenGL

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);


    // Double Buffer

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);


    // Creating the window

    fenetre = SDL_CreateWindow("Test SDL 2.0", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 600, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

    if(fenetre == 0)
    {
        std::cout << "Erreur lors de la creation de la fenetre : " << SDL_GetError() << std::endl;
        SDL_Quit();

        return -1;
    }


    // Creating the OpenGL context

    contexteOpenGL = SDL_GL_CreateContext(fenetre);

    if(contexteOpenGL == 0)
    {
        std::cout << SDL_GetError() << std::endl;
        SDL_DestroyWindow(fenetre);
        SDL_Quit();

        return -1;
    }


    #ifdef WIN32

        // We initialize GLEW

        GLenum initialisationGLEW( glewInit() );


        //If the initialization failed :

        if(initialisationGLEW != GLEW_OK)
        {
            // We display the error thanks to the function : glewGetErrorString(GLenum code)

            std::cout << "Erreur d'initialisation de GLEW : " << glewGetErrorString(initialisationGLEW) << std::endl;


            // leave SDL

            SDL_GL_DeleteContext(contexteOpenGL);
            SDL_DestroyWindow(fenetre);
            SDL_Quit();

            return -1;
        }

    #endif


    // Vertices and coordinates
 while(!terminer)
    {
         // Event Management

        SDL_WaitEvent(&evenements);

        if(evenements.window.event == SDL_WINDOWEVENT_CLOSE)
            terminer = true;

        // clean the screen

        glClear(GL_COLOR_BUFFER_BIT);
DrawCircle(0,0,0.3,50);
DrawCircle(0.5,0.5,0.1,50);
DrawEllipse(0,0,0.8,0.65,50);

         // Disable the Vertex Attrib array

        glDisableVertexAttribArray(0);


        //refresh window

        SDL_GL_SwapWindow(fenetre);
    }


    // leave SDL

    SDL_GL_DeleteContext(contexteOpenGL);
    SDL_DestroyWindow(fenetre);
    SDL_Quit();

    return 0;
}


void DrawCircle(float cx, float cy, float r, int num_segments)
{
glBegin(GL_LINE_LOOP);
for(int ii = 0; ii < num_segments; ii++)
{
float theta = 2.0 * M_PI * float(ii) / float(num_segments); //get the current angle

float x_c = r * cosf(theta);//calculate the x component
float y_c = r * sinf(theta);//calculate the y component
        glColor3f(1.0f,0.0f,0.0f);
glVertex2f(x_c + cx, y_c + cy);//output vertex
}
glEnd();
}
void DrawEllipse(float cx, float cy, float a, float b, int num_segments)
{
glBegin(GL_LINE_LOOP);
for(int ii = 0; ii < num_segments; ii++)
{
float theta = 2.0 * M_PI * float(ii) / float(num_segments); //get the current angle

float x_e = a * cosf(theta);//calculate the x component
float y_e = b * sinf(theta);//calculate the y component
        glColor3f(0.0f,0.0f,1.0f);
glVertex2f(x_e + cx, y_e + cy);//output vertex
}
glEnd();
}

For example, I would like to rotate the little circle around the big one following the blue line:

编译结果

And I would like to decide how long it takes to complete a turn.

Do I have to combine glRotatef() and glTranslatef() and use matrices?

Where should I put it in my code?

First of all note, that drawing by glBegin / glEnd sequences is deprecated since more than 10 years.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.


Do I have to combine glRotatef() and glTranslatef() and use matrices?

No, not necessarily.

Since you calculate the geometry of the circle on the fly in every frame, it is sufficient to calculate the center point of the circle in ever frame, and pass it to DrawCircle :

Specify a global variable for the angle of the polar coordinate of the center point of the circle:

float g_theta = 0.0f;

Calculate the center point of the circle somehow like this:

float a = 0.8f;
float b = 0.65f;
float x = a * cosf(g_theta * M_PI / 180.0f);
float y = b * sinf(g_theta * M_PI / 180.0f);
g_theta += 1.0f;

DrawCircle(0, 0, 0.3, 50);
DrawCircle(x, y, 0.1, 50);
DrawEllipse(0, 0, a, b, 50);

If you want to do the same, by using the Fixed Function pipeline matrix stack, then you have to set the GL_MODELVIEW matrix.

Calculate the distance ( d ) form the center of the circle to the center of the world. Apply a translation by the distance and a rotation by the angle of the polar coordinate at the z axis of the world:

float a = 0.8f;
float b = 0.65f;
float x = a * cosf(g_theta * M_PI / 180.0f);
float y = b * sinf(g_theta * M_PI / 180.0f);
float d = sqrtf( x*x + y*y );

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

DrawCircle(0, 0, 0.3, 50);

glPushMatrix();
glRotatef( g_theta, 0, 0, 1 );  // rotation around the z axis
glTranslatef( d, 0, 0 );        // translation by the distance
g_theta += 1.0f;

DrawCircle(0, 0, 0.1, 50);
glPopMatrix();

DrawEllipse(0, 0, a, b, 50);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM