如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆圈旋转一个圆圈?
Posted
技术标签:
【中文标题】如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆圈旋转一个圆圈?【英文标题】:How rotate a circle around another with an elliptical motion with GLEW, OpenGL or SDL2? 【发布时间】:2018-08-21 12:58:23 【问题描述】:我当前的代码:
#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();
例如,我想沿着蓝线围绕大圆圈旋转小圆圈:
我想决定完成一个回合需要多长时间。
我必须将glRotatef()
和glTranslatef()
组合起来并使用矩阵吗?
我应该把它放在我的代码哪里?
【问题讨论】:
“我必须将glRotatef()
和glTranslatef()
组合起来并使用矩阵吗?” - 是的,你必须这样做。在代码中,您必须在翻译之前指定旋转。另请参阅OpenGL translation before and after a rotation。
【参考方案1】:
首先请注意,glBegin
/glEnd
序列的绘图已被弃用超过 10 年。
阅读Fixed Function Pipeline 并查看Vertex Specification 和Shader,了解最先进的渲染方式。
我必须将
glRotatef()
和glTranslatef()
组合起来并使用矩阵吗?
不,不一定。
由于您在每一帧中即时计算圆的几何形状,因此在每一帧中计算圆的中心点就足够了,并将其传递给DrawCircle
:
为圆心极坐标的角度指定一个全局变量:
float g_theta = 0.0f;
以某种方式计算圆的中心点:
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);
如果你想这样做,通过使用固定函数管道矩阵堆栈,那么你必须设置GL_MODELVIEW
矩阵。
计算从圆心到世界中心的距离 (d
)。在世界的 z 轴上应用距离的平移和极坐标角度的旋转:
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);
【讨论】:
以上是关于如何使用 GLEW、OpenGL 或 SDL2 以椭圆运动围绕另一个圆圈旋转一个圆圈?的主要内容,如果未能解决你的问题,请参考以下文章