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