【问题标题】:Resize the window while the loop is running with SDL2 and OpenGL in C++?在 C++ 中使用 SDL2 和 OpenGL 运行循环时调整窗口大小?
【发布时间】:2019-03-25 10:10:51
【问题描述】:

这是我当前的代码:

全部包含

#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>
#include "SceneOpenGL.h"
#include <SDL2/SDL_image.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);
void Rotation(float a,float b,float r, float g_theta );

主要功能

int main(int argc, char **argv)
{
SDL_Window* fenetre(0);
SDL_GLContext contexteOpenGL(0);

SDL_Event evenements;
bool terminer(false);

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;
}

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


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


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;
}

contexteOpenGL = SDL_GL_CreateContext(fenetre);

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

    return -1;
}


#ifdef WIN32

    GLenum initialisationGLEW( glewInit() );

    if(initialisationGLEW != GLEW_OK)
    {

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

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

        return -1;
    }

#endif

带有圆形和椭圆显示的主循环

 while(!terminer)
{
    SDL_WaitEvent(&evenements);

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

glClear(GL_COLOR_BUFFER_BIT);

float g_theta = 0.0f;

while (g_theta<360)
{
glClear(GL_COLOR_BUFFER_BIT);
g_theta += 1.0f;
DrawCircle(0, 0, 0.3, 50);
Rotation(0.8,0.65,0.1,g_theta);
Rotation(0.5,0.5,0.2,g_theta);
Rotation(0.1,0.1,0.01,g_theta);

    glDisableVertexAttribArray(0);
    SDL_GL_SwapWindow(fenetre);
}
}
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);

    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);

        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();
}

连接圆和椭圆的函数

    void Rotation(float a,float b,float r, float g_theta )
{

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();

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

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

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

}

此代码显示在椭圆上移动的圆圈。

我想在圆圈移动时调整窗口大小。

我已经将窗口设置为可调整大小:

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

但是当我运行代码时,我无法调整大小。

如何在循环while(!terminer) 运行时调整窗口大小?

【问题讨论】:

  • 在执行if (evenements.window.event == SDL_WINDOWEVENT_CLOSE) 之前,您必须确保evenements.type == SDL_WINDOWEVENT。否则你可能会访问一个非活动的联合字段,这不是一件好事。
  • 无法调整大小是什么意思?您的窗口管理器是否不允许拖动窗口角以调整大小或最大化它? SDL_WINDOW_RESIZABLE 应该足够了,如果不是这种情况 - 请制作 minimal 示例来说明您的问题(没有 GL 或花哨的东西 - 应该适合大约 30 行代码)并将其添加到问题中,以及您的 SDL 版本、编译器、操作系统、窗口管理器等。是的,您的事件处理是错误的,正如 HolyBlackCat 所说(加上更多 - 如果WaitEvent 返回 0,您不想阅读事件),但这不应该与调整大小有关。

标签: c++ opengl sdl-2


【解决方案1】:

问题是,您有 2 个嵌套循环,而外部循环具有事件处理功能,而内部循环则没有。
你现在的设计是这样的:

while not end

    event handling

    theta = 0
    while (theta < 360)

        theta ++;
        draw geometry

这导致所有像resize这样的窗口在内循环中长时间没有处理。

你必须像这样改变设计,才能解决你的问题:

theta = 0
while not end

    event handling

    draw geometry

    theta ++;
    if theta > 360 then theta = 0

此外,每次窗口大小发生变化时,您都必须使视口矩形适应窗口大小。这可以通过glViewport来完成:

以某种方式更改程序的主循环:

int   vp_cx   = 0;
int   vp_cy   = 0;
float g_theta = 0.0f;
while(!terminer)
{
    SDL_Event event;
    while ( SDL_PollEvent( &event ) );
    {
        switch (event.type)
        {
            case SDL_QUIT: terminer = true; break;
        }
    }

    int cx, cy;
    SDL_GetWindowSize( fenetre, &cx, &cy );
    if ( vp_cx != cx || vp_cy != cy )
    {
         vp_cx = cx; vp_cy = cy;
         glViewport( 0, 0, vp_cx, vp_cy );
    }

    glClear(GL_COLOR_BUFFER_BIT);       
    glClear(GL_COLOR_BUFFER_BIT);
    DrawCircle(0, 0, 0.3, 50);
    Rotation(0.8,0.65,0.1,g_theta);
    Rotation(0.5,0.5,0.2,g_theta);
    Rotation(0.1,0.1,0.01,g_theta);

    glDisableVertexAttribArray(0);
    SDL_GL_SwapWindow(fenetre);

    g_theta += 1.0f;
    if ( g_theta >= 360.0f-0.001f )
      g_theta = 0.0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-11
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 2011-08-02
    • 2016-03-19
    • 1970-01-01
    相关资源
    最近更新 更多