• 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++

Object Storage Arubacloud
0 głosów
280 wizyt
pytanie zadane 4 czerwca 2023 w C i C++ przez piotr_domanski Bywalec (2,080 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,860 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 4 czerwca 2023 przez piotr_domanski Bywalec (2,080 p.)
coś mam zmienić bo próbuje i program się zawiesza i nic nie robi
komentarz 5 czerwca 2023 przez j23 Mędrzec (194,920 p.)
edycja 5 czerwca 2023 przez j23

Użyj funkcji std::packaged_task/std::async, która zwraca obiekt klasy std::future, który to z kolei pozwala testować bez blokowania, czy zadanie zostało wykonane.

Wydaje mi się, że glutInit powinieneś przenieść do wątku.

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.

I po to dzieli się program na mniejsze funkcje, by nie uciekać się do goto. Bo jeśli to, co pokazałeś, to część czegoś większego, to na bank będzie spaghetti code z tym goto.

komentarz 5 czerwca 2023 przez adrian17 Ekspert (344,860 p.)
Tzn ja nie za bardzo rozumiem co on chce zrobić. Jeśli chce żeby każde "show" otwierało nowe okno, to zwykły thread + detach() chyba brzmi jak to czego potrzebuje? Ale trudno powiedzieć.

(plus, nie mam pojęcia jak GLUT się zachowuje gdy ktoś próbuje otworzyć kilka okien, w dodatku w osobnych wątkach)
komentarz 5 czerwca 2023 przez j23 Mędrzec (194,920 p.)

Ciężko powiedzieć, ale wydaje mi się, że chce jedno okno, tylko że jak za drugim razem próbuje je stworzyć, to coś strzela.

Tak sobie myślę, że jednak proponowane std::packaged_task, std::async i std::future mogą być trochę kłopotliwe w użyciu w tym przypadku i zwykły wątek detached + zmienna bool wystarczy.

komentarz 5 czerwca 2023 przez mokrowski Mędrzec (155,460 p.)

GLUT nie był projektowany jako bezpiecznie działający w wielu wątkach. Toteż tak inicjalizacja jak i wyłączenie kontekstu *GL, powinno odbywać się w tym samym wątku z zachowaniem reżimu jednowątkowego dostępu do danych.

goto w C++, jest bardzo nierozsądnym domyślnym wyborem. Po to masz konstruktor/destruktor i technikę RAII, aby nie posługiwać się takim narzędziem. Sytuacje naprawdę podbramkowe, pomijam. O ile w C goto bywa stosowane (kody sterowników, sekcje zagnieżdżeń parserów itp), o tyle w C++ bardzo, bardzo, bardzo sporadyczne (albo nawet bardziej... ) i to przy zachowaniu bardzo daleko idących założeń co do których masz być na 100% pewny. Ogólnie.. nie rób tego....

Osobiście do technik wspomnianych przez @j23, dodał bym jeszcze std::jthread. A z tym bool do komunikacji, to bym uważał. Okazuje się że standard nie gwarantuje zwykłego bool działającego atomowo (nie, volatile nic nie zmienia). Od C++20 jest jeszcze stop_token: https://en.cppreference.com/w/cpp/thread/stop_token do potencjalnego kontrolowanego zatrzymania wątku.

komentarz 5 czerwca 2023 przez piotr_domanski Bywalec (2,080 p.)

@adrian17, nie chce żeby wywoływać każdym poleceniem show nowe okno bo to nie wyjdzie i nie ma sensu po co komu 3 takie same okna. Chodzi o to że gdy wpisuje show to okno się pojawia i potem je zamykam i jest dobrze natomiast za drugim razem wpisuje show i program się wywala błędem   terminate called without an active exception.

komentarz 5 czerwca 2023 przez piotr_domanski Bywalec (2,080 p.)
Jaka inną bibliotekę mi polecacie żeby działała z c++ i można jej użyć do mojego programu w c++ w konsoli
komentarz 5 czerwca 2023 przez j23 Mędrzec (194,920 p.)

A z tym bool do komunikacji, to bym uważał. Okazuje się że standard nie gwarantuje zwykłego bool działającego atomowo (nie, volatile nic nie zmienia).

IMO std::atomic<bool> to tego zadania wystarczy, aczkolwiek służyłby nie do zatrzymywania a sygnalizacji, że działa. Coś w ten deseń:

std::atomic<bool> ogl_thread_is_working = false;


void OpenGLThread()
{
    ...
    
    ogl_thread_is_working = false;
}



while(1) {
    ...
    
    if (command == "show") {
        
        if (ogl_thread_is_working) {
            std::cout << "o nie kolego, najpierw zamknij okno\n";
        } else {
            ogl_thread_is_working = true;
            auto thr = std::thread(&OpenGLThread);
            thr.detach();
        }
    }
}

 

komentarz 5 czerwca 2023 przez adrian17 Ekspert (344,860 p.)
Tak jak spojrzałem na docsy, to glutMainLoop nawet nie daje gwarancji że kiedykolwiek zwróci, nawet jeśli zamkniesz okno. Więc tutaj joinowanie wątków z definicji może nie mieć sensu.

Więc albo musisz w tym samym wątku ponownie utworzyć okno od zera, albo... wyrzucić GLUTa i zastąpić czymś normalnie współcześnie (w sensie, od 10+ lat) używanym -_- Jak GLFW, SFML, SDL2...
komentarz 6 czerwca 2023 przez j23 Mędrzec (194,920 p.)

W freeGLUT można ustawić flagę określającą, co ma się stać, gdy okno się zamknie. Jest tam opcja, że po zamknięciu okna następuje wyskok z glutMainLoop.

komentarz 6 czerwca 2023 przez mokrowski Mędrzec (155,460 p.)

@j23, oczywiście. std::atomic<bool> będzie działało atomowo. Nie ma jednak gwarancji że będzie lock free :) Taka konsekwencja obsługi dziwnych platform. Ja sprawdzam przez is_lock_free() lub od C++17 przez is_always_lock_free() jeśli oczekuję ekstremalnej wydajności. Przy typach atomowych unikam także przeciążonych metod (nawet przypisania). Nie wszystkie są zaimplementowane. IMHO lepsze jest load(...), store(...) czy fetch_*(). Tym bardziej że można podać memory order i sygnalizuje w kodzie że jest to inna obsługa operacji niż w "zwykłych" zmiennych.

@piotr_domanski, jeśli potrzebujesz tylko okienka (bez multimediów, sieci i innych elementów), GLFW będzie ok. Jeśli jednak będziesz chciał więcej, to SFML. Do prostych operacji na obrazach (i nie tylko), jeszcze polecę stb: https://github.com/nothings/stb . Do GUI IMGUI jest dość przyjemne: https://github.com/ocornut/imgui . Otarłem się jeszcze u klienta o Nuklear. Tu jednak trzeba godzić się na API w C: https://github.com/Immediate-Mode-UI/Nuklear

komentarz 6 czerwca 2023 przez piotr_domanski Bywalec (2,080 p.)

@j23 jest lepiej, jak naciskam ESC to zamyka poprawnie ale potem jak wpisze show to piszę o nie kolego najpierw zamknij okno. A jak zrobić tak żeby także to działało poprawnie jak się zamknie za pomocą x.

KOD: 

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

using namespace std;
const double M_PI = 3.14159265358979323846; // Definicja stałej M_PI
std::atomic<bool> ogl_thread_is_working{false};
// 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();

    ogl_thread_is_working = false;
}

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;

while (1)
{
    cin >> command;
    if (command == "show") {

        if (ogl_thread_is_working) {
            std::cout << "o nie kolego, najpierw zamknij okno\n";
        } else {
            ogl_thread_is_working = true;
            auto thr = std::thread(&OpenGLThread);
            thr.detach();
        }
    }
}


    return 0;
}

Z tą pętla się uda zmieniłem w moim programie dużo rzeczy i jest git :).

komentarz 6 czerwca 2023 przez piotr_domanski Bywalec (2,080 p.)

za drugim razem jak wpisuje show to wyskakuje puste okno białe i nie wyświetla się bryła.

 

KOD: 

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

using namespace std;
const double M_PI = 3.14159265358979323846; // Definicja stałej M_PI
std::atomic<bool> ogl_thread_is_working{false};
// 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());
        ogl_thread_is_working = false;
    }

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

    ogl_thread_is_working = false;
}

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;

while (1)
{
    cin >> command;
    if (command == "show") {

        if (ogl_thread_is_working) {
            std::cout << "o nie kolego, najpierw zamknij okno\n";
        } else {
            ogl_thread_is_working = true;
            auto thr = std::thread(&OpenGLThread);
            thr.detach();
        }
    }
}


    return 0;
}

 

komentarz 6 czerwca 2023 przez j23 Mędrzec (194,920 p.)

(...) ale potem jak wpisze show to piszę o nie kolego najpierw zamknij okno.

Czyli zmienna ogl_thread_is_working nie została ustawiona na false, a to oznacza, że albo nie było wyskoku z glutMainLoop, albo wystąpił jakiś wyjątek. Wcześniej pisałem Ci, byś przeniósł wywołanie glutInit do wątku. No i jeśli używasz freeGLUT, to daj tam wywołanie:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);

To powinno być wywołane, bo ze źródeł wynika, że domyślne zachowanie to wywołanie exit(0) (jakim cudem program Ci się nie zamyka po zamknięciu okna? :|)

 

 

komentarz 6 czerwca 2023 przez j23 Mędrzec (194,920 p.)

Ten kod:

#include <iostream>
#include <atomic>
//#include <conio.h>
#include <thread>
#include <GL/freeglut.h>
 
using namespace std;
const double M_PI = 3.14159265358979323846; // Definicja stałej M_PI
std::atomic<bool> ogl_thread_is_working{false};
// 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());
        ogl_thread_is_working = false;
    }
 
    // Przełączanie wyświetlania przekątnych sześcianu
    if (key == 'd' || key == 'D')
    {
        showDiagonals = !showDiagonals;
        glutPostRedisplay();
    }
}
 
void OpenGLThread()
{
    int argc = 1;
    char* argv[2] = { "OpenGLThread", nullptr};
    glutInit(&argc, argv);
    glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_GLUTMAINLOOP_RETURNS);
    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();
 
    ogl_thread_is_working = false;
}
 
int main() 
{

    int liczba;
    std::thread openglThread; // Deklaracja wątku bez inicjalizacji
 
    std::string command;
 
    while (1)
    {
        cin >> command;
        if (command == "show") {
     
            if (ogl_thread_is_working) {
                std::cout << "o nie kolego, najpierw zamknij okno\n";
            } else {
                ogl_thread_is_working = true;
                auto thr = std::thread(&OpenGLThread);
                thr.detach();
            }
        }
    }
 
 
    return 0;
}

na Linuksie z (freeGLUT, X11) działa zgodnie z założeniami ;)

komentarz 8 czerwca 2023 przez piotr_domanski Bywalec (2,080 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,080 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,860 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ź 274 wizyt
pytanie zadane 2 czerwca 2023 w C i C++ przez piotr_domanski Bywalec (2,080 p.)
0 głosów
3 odpowiedzi 447 wizyt
pytanie zadane 9 września 2016 w Offtop przez Bot Użytkownik (760 p.)
0 głosów
1 odpowiedź 185 wizyt
pytanie zadane 7 kwietnia 2018 w Java przez ILikeJava Obywatel (1,230 p.)

92,579 zapytań

141,432 odpowiedzi

319,663 komentarzy

61,964 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...