• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z wątkiem thread open gl w C++

VPS Starter Arubacloud
0 głosów
261 wizyt
pytanie zadane 4 czerwca 2023 w C i C++ przez piotr_domanski Bywalec (2,040 p.)

Witam, mam taki program w konsoli, który przyjmuje komendę i jak komenda to show to program wyświetla okno open GL i po zamknięciu okna lub po wciśnięciu klawisza ESC okno się prawidłowo zamyka. 

Po wpisaniu show:

 

Po naciśnięciu ESC program dalej działa i czeka na komendę. Podczas gdy okno OPEN GL się wyświetla, program dalej reaguje i można w nim pisać komendy. 

Natomiast gdy wpisuje drugi raz show to mam coś takiego

Program glowny dziala dalej...
show
terminate called without an active exception

Process returned 3 (0x3)   execution time : 8.003 s
Press any key to continue.

Problem jest z wątkiem tylko nie wiem jak go naprawić ?

KOD:

#include <iostream>
#include <conio.h>
#include <thread>
#include <GL/freeglut.h>

using namespace std;
const double M_PI = 3.14159265358979323846; // Definicja stałej M_PI

// Wymiary okna
int windowWidth = 800;
int windowHeight = 600;

// Kąty obrotu
float angleX = 0.0f;
float angleY = 0.0f;

// Pozycja myszki
int mousePosX = 0;
int mousePosY = 0;

// Flaga wciśnięcia lewego przycisku myszy
bool leftButtonPressed = false;

bool showVertices = false;

// Flaga wskazująca, czy wyświetlać sześcian wypełniony
bool filledCube = false;

bool showDiagonals = false;

// Grubość linii
float lineThickness = 1.0f;

bool autoRotate = false;
bool showHigh = false;
bool showAngles = false;

void rotateCube()
{
    // Automatyczny obrót sześcianu
    angleX += 1.0f;
    angleY += 1.0f;
    glutPostRedisplay();
}

void display()
{
    // Wyczyszczenie buforów
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Reset transformacji macierzy
    glLoadIdentity();

    // Ustawienie perspektywy
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    float aspect = static_cast<float>(windowWidth) / static_cast<float>(windowHeight);
    glFrustum(-aspect, aspect, -1.0, 1.0, 1.0, 100.0);

    // Ustawienie widoku
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -3.0f);
    glRotatef(angleX, 1.0f, 0.0f, 0.0f);
    glRotatef(angleY, 0.0f, 1.0f, 0.0f);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

    // Ustawienie pogrubienia linii
    glLineWidth(lineThickness);

    // Rysowanie ostrosłupa wypełnionego
    if (filledCube)
    {
        glBegin(GL_TRIANGLES);

        // Podstawa
        glColor3f(1.0f, 0.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        // Ściana przednia
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);

        // Ściana prawa
        glColor3f(0.0f, 0.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);

        // Ściana tylna
        glColor3f(1.0f, 1.0f, 0.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);

        // Ściana lewa
        glColor3f(0.0f, 1.0f, 1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);

        glEnd();
    }
    else
    {
        // Rysowanie ostrosłupa z samymi czerwonymi krawędziami
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glColor3f(1.0f, 0.0f, 0.0f);

        glBegin(GL_TRIANGLES);

        // Podstawa
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);

        // Ściana przednia
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);

        // Ściana prawa
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);

        // Ściana tylna
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);

        // Ściana lewa
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);

        glEnd();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }

    if (showVertices) ///// pokazanie wierzcholkow /////
    {
        // Włączenie rysowania kropkowych wierzchołków
        glEnable(GL_POINT_SMOOTH);
        glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

        // Ustawienie rozmiaru punktu
        glPointSize(lineThickness + 16.0f);

        glBegin(GL_POINTS);
        glColor3f(0.0f, 1.0f, 0.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(0.0f, 1.0f, 0.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glEnd();

        // Wyłączenie rysowania kropkowych wierzchołków
        glDisable(GL_POINT_SMOOTH);
    }

    if (showDiagonals)
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        glColor3f(1.0f, 1.0f, 1.0f);
        glBegin(GL_LINES);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, 1.0f);
        glVertex3f(-1.0f, -1.0f, 1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(1.0f, -1.0f, -1.0f);
        glVertex3f(-1.0f, -1.0f, -1.0f);
        glEnd();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
    if (showHigh)
    {
        glBegin(GL_LINES);
        glColor3f(0.0f, 0.0f, 1.0f); // Ustawienie koloru linii na niebieski
        glVertex3f(0.0f, 1.0f, 0.0f); // Punkt początkowy wysokości
        glVertex3f(0.0f, -1.0f, 0.0f); // Punkt końcowy wysokości
        glEnd();
    }

    glDisable(GL_LINE_SMOOTH);
    glDisable(GL_BLEND);
    // Wyświetlenie sceny
    glutSwapBuffers();
}


void reshape(int width, int height)
{
    // Zmiana rozmiaru okna
    windowWidth = width;
    windowHeight = height;
    glViewport(0, 0, width, height);
}

void menuCallback(int option)
{
    switch (option)
    {
    case 1:
        lineThickness = 1.0f;
        break;
    case 2:
        lineThickness = 3.0f;
        break;
    case 3:
        lineThickness = 5.0f;
        break;
    case 4:
        lineThickness = 7.0f;
        break;
    case 5:
        lineThickness = 9.0f;
        break;
    case 6:
        showVertices = !showVertices;
        break;
    case 7:
        showHigh = !showHigh;
        break;
    case 8:
        showDiagonals = !showDiagonals;
        break;
    case 9:
        filledCube = !filledCube;
        break;
    case 10:
        if (!showDiagonals)
        {
            showDiagonals = !showDiagonals;
        }
        if (!showHigh)
        {
            showHigh = !showHigh;
        }
        if (!showVertices)
        {
            showVertices = !showVertices;
        }
        break;
    case 11:
        showVertices = false;
        showDiagonals = false;
        showHigh = false;
        filledCube = false;
        lineThickness = 1.0f;
        break;
    default:
        break;
    }

    glutPostRedisplay();
}

void mouse(int button, int state, int x, int y)
{
    // Obsługa wciśnięcia lewego przycisku myszy
    if (button == GLUT_LEFT_BUTTON)
    {
        leftButtonPressed = (state == GLUT_DOWN);
        mousePosX = x;
        mousePosY = y;
    }
    // Obsługa wyświetlania menu przy wciśnięciu prawego przycisku myszy
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)
    {
        // Utworzenie menu
        int menu = glutCreateMenu(menuCallback);

        // Dodanie opcji do menu - zmiana grubości linii
        glutAddMenuEntry("ThicknessLine - 1", 1);
        glutAddMenuEntry("ThicknessLine - 2", 2);
        glutAddMenuEntry("ThicknessLine - 3", 3);
        glutAddMenuEntry("ThicknessLine - 4", 4);
        glutAddMenuEntry("ThicknessLine - 5", 5);
        glutAddMenuEntry("Show Vertices", 6);
        glutAddMenuEntry("Show High", 7);
        glutAddMenuEntry("Show Diagonals", 8);
        glutAddMenuEntry("Filled", 9);
        glutAddMenuEntry("      ---- Show ALL ----", 10);
        glutAddMenuEntry("      ---- RESET ALL ----", 11);

        // Wyświetlenie menu w aktualnej pozycji myszy
        glutAttachMenu(GLUT_RIGHT_BUTTON);
        glutPostRedisplay();
    }
}

void motion(int x, int y)
{
    // Obrót sześcianu na podstawie ruchu myszki
    if (leftButtonPressed)
    {
        int dx = x - mousePosX;
        int dy = y - mousePosY;
        angleY += dx * 0.5f;
        angleX += dy * 0.5f;
        mousePosX = x;
        mousePosY = y;
        glutPostRedisplay();
    }
}

void keyboard(unsigned char key, int x, int y)
{
    // Przełączanie między wyświetlaniem sześcianu wypełnionego a sześcianu z samymi czerwonymi krawędziami
    if (key == 'f' || key == 'F')
    {
        filledCube = !filledCube;
        glutPostRedisplay();
    }
    if (key == 'v' || key == 'V')
    {
        showVertices = !showVertices;
        glutPostRedisplay();
    }
    if (key == 'h' || key == 'H')
    {
        showHigh = !showHigh;
        glutPostRedisplay();
    }
    if (key == 'r' || key == 'R')
    {
        autoRotate = !autoRotate;
        if (autoRotate)
            glutIdleFunc(rotateCube);
        else
            glutIdleFunc(nullptr);
    }
    if (key == 27) // ESC
    {
        glutDestroyWindow(glutGetWindow());
    }

    // Przełączanie wyświetlania przekątnych sześcianu
    if (key == 'd' || key == 'D')
    {
        showDiagonals = !showDiagonals;
        glutPostRedisplay();
    }
}

void OpenGLThread()
{

    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(windowWidth, windowHeight);
    glutCreateWindow("Cube");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(keyboard);
    ////glutSpecialFunc(specialKeys);

    // Ustawienie koloru tła
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    // Włączenie testu głębokości
    glEnable(GL_DEPTH_TEST);

    // Inicjalizacja wygładzania krawędzi
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_LINE_SMOOTH);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);



    glutMainLoop();
}

int main() {

    int argc = 1;
    char* argv[] = { const_cast<char*>("OpenGLThread"), nullptr };
    glutInit(&argc, argv);

    int liczba;
    std::thread openglThread; // Deklaracja wątku bez inicjalizacji

    std::string command;

start:
    system("cls");
    std::cout << "Program glowny dziala dalej..." << std::endl;

    std::cin >> command;
    if (command == "show") {

        openglThread = std::thread(OpenGLThread); // Inicjalizacja wątku w bloku "if"

        getch();

        goto start;
    }
    if (openglThread.joinable()) {
        openglThread.join();
    }


    return 0;
}

I jeszcze jedno, goto muszę (wiem nie jest to zalecane ale nie mam wyjścia) użyć gdyż to potem idzie to mojego programu głównego a tam zastosowanie pętli spowoduje spore problemy.

 

Z góry dziękuje :) 

Pozdrawiam

1 odpowiedź

0 głosów
odpowiedź 4 czerwca 2023 przez adrian17 Ekspert (344,100 p.)

I jeszcze jedno, goto muszę (wiem nie jest to zalecane ale nie mam wyjścia) użyć gdyż to potem idzie to mojego programu głównego a tam zastosowanie pętli spowoduje spore problemy.

Uhh nie, to wyjaśnienie nie ma zbytnio sensu.

Zaznaczę też że pewnie wiele osób Ci chętnie z takim kodem nie pomoże, bo coś takiego ludzie pisali 15-20 lat temu - a już 10 lat temu taki kod (jak i np ogólnie używanie GLUTa) było uważane za boleśnie przestarzałe.

W każdym razie, odpowiadając bezpośrednio na pytanie:

Problem jest z wątkiem tylko nie wiem jak go naprawić ?

openglThread = std::thread(OpenGLThread);

Tutaj niszczysz poprzedni wątek i zastępujesz go nowym - a niszczenie wątku który chodzi bez wywołania na nim wcześniej join() lub detach() automatycznie rzuca wyjątek.

komentarz 8 czerwca 2023 przez piotr_domanski Bywalec (2,040 p.)
ja mam błąd freeglut ERROR: Function <glutSetOption> called without first calling 'glutInit'.
komentarz 8 czerwca 2023 przez j23 Mędrzec (194,920 p.)
Użyłeś dokładnie tego samego kodu, który podałem?

Być może wersja windowsowa freeGLUTa jest z jakimś błędem. Ty kompilowałeś tę bibliotekę? Skąd ją wziąłeś?
komentarz 8 czerwca 2023 przez piotr_domanski Bywalec (2,040 p.)
Nie, biblioteka jest ze źródeł binaries na windows 32 bity. Kod wziąłem ten sam
komentarz 8 czerwca 2023 przez adrian17 Ekspert (344,100 p.)
(To ja tylko powtórzę przypomnienie że glut był przestarzały już 10+ lat temu, a co dopiero teraz - naprawdę rekomenduję cokolwiek innego (wymienione wyżej))
komentarz 8 czerwca 2023 przez j23 Mędrzec (194,920 p.)

@piotr_domanski, może faktycznie użyj czegoś innego, bardziej współczesnego. Wspomniana wcześniej biblioteka SFML jest dość prosta i łatwa w obsłudze.

Podobne pytania

0 głosów
1 odpowiedź 249 wizyt
pytanie zadane 2 czerwca 2023 w C i C++ przez piotr_domanski Bywalec (2,040 p.)
0 głosów
3 odpowiedzi 437 wizyt
pytanie zadane 9 września 2016 w Offtop przez Bot Użytkownik (760 p.)
0 głosów
1 odpowiedź 176 wizyt
pytanie zadane 7 kwietnia 2018 w Java przez ILikeJava Obywatel (1,230 p.)

92,452 zapytań

141,262 odpowiedzi

319,079 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...