#define _CRT_SECURE_NO_WARNINGS #ifdef _MSC_VER // Check if MS Visual C compiler # pragma comment(lib, "opengl32.lib") // Compiler-specific directive to avoid manually configuration # pragma comment(lib, "glu32.lib") // Link libraries #endif #ifdef _MSC_VER # ifndef _MBCS # define _MBCS # endif # ifdef _UNICODE # undef _UNICODE # endif # ifdef UNICODE # undef UNICODE # endif #endif // #define GLEW_STATIC #include // Window defines #include "GL/glew.h" // Dołączony jako pliki glew.c i glew.h //#include // OpenGL #include // biblioteka GLU; program kompiluje się bez niej, ale w celu uniknięcia w przyszłości niespodzianek to została dołączona #include // Define for sqrt //#include #include #include "RESOURCE.H" // About box resource identifiers. #include "loadOBJ.h" #include "lazik.hpp" #include "plane.hpp" //#include #include "GL/glm/glm.hpp" #include "GL/glfw3.h" #include #include "timeh.hpp" #include "texture.hpp" #include "shader.hpp" #include "FPSCounter.cpp" #include using namespace glm; #define glRGB(x, y, z) glColor3ub((GLubyte)x, (GLubyte)y, (GLubyte)z) #define BITMAP_ID 0x4D42 // identyfikator formatu BMP #define GL_PI 3.1415 //#define getTime lastTime = std::time(nullptr); //#define timestampedCout(msg) {getTime; std::cout << "( " << lastTime << ") " << msg << "\n";} //using namespace std; HPALETTE hPalette = NULL; // Application name and instance storage static LPCTSTR lpszAppName = "grafikaKBT"; static HINSTANCE hInstance; GLFWwindow* window; // Rotation amounts static GLfloat xRot = 0.0f; static GLfloat yRot = 0.0f; static GLfloat zRot = 0.0f; static GLsizei lastHeight; static GLsizei lastWidth; // Opis tekstury BITMAPINFOHEADER bitmapInfoHeader; // nagłówek obrazu unsigned char* bitmapData; // dane tekstury unsigned int texture[4]; // obiekt tekstury LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam); void SetDCPixelFormat(HDC hDC); static void platforma(GLfloat xc, GLfloat yc, GLfloat zc, GLfloat xlen, GLfloat zlen); void sprawdzPostepGry(); void ustalPozycjeGracza(GLfloat gracz_x, GLfloat gracz_z, short &grid_x, short &grid_z); void ustawSiatkeNaWzorNieNadpisujacPostepu(); void nadpiszNowaSiatke(short nowy_wzor); void tworzKratke(unsigned int grid_x, unsigned int grid_z, unsigned short grid_value); void tworzKratkiZSiatki(); void aktualizujBiezacaKratke(short grid_x, short grid_z); int polygonmode = 0; std::time_t lastTime = std::time(nullptr); int monitormode = 1; int monitormodecounter = 0; std::time_t monitormodehelper; short biezacy_wzor = 0; bool panoramic_view = 0; //Zmienne do ruchu ##############################################^^^^^^^^^^^^^^^^^^^^^^^^^^^^ FPSCounter fpsCounter; static const int targetFPS = 144; // Celowany FPS //Fps counter static void LimitFPS(int targetFPS) { static auto lastTime = std::chrono::high_resolution_clock::now(); auto currentTime = std::chrono::high_resolution_clock::now(); std::chrono::duration elapsed = currentTime - lastTime; // Obliczamy czas na jedną klatkę double frameTime = 1.0 / targetFPS; // Czas na jedną klatkę w sekundach double timeToWait = frameTime - elapsed.count(); // Obliczamy czas do czekania if (timeToWait > 0.0) { // Jeśli czas do czekania jest większy niż 0, to śpimy przez tę wartość std::this_thread::sleep_for(std::chrono::duration(timeToWait)); } lastTime = currentTime; // Zaktualizuj czas dla następnej iteracji } bool Kolizja = false; bool keyWPressed = false; bool keySPressed = false; bool keyAPressed = false; bool keyDPressed = false; float Foward = 45.0f; // Pozycja łazika w przód/tył float Sides = -45.0f; // Pozycja łazika w lewo/prawo float Rotation = 270.0f; // Rotacja łazika (w stopniach) float CameraHeight = 50.0f; // Wysokość kamery float MoveSpeed = 0.5f; // Prędkość poruszania się float velocity = 0.0f; // Aktualna prędkość łazika float rotationVelocity = 0.0f; // Prędkość obrotu łazika const float friction = 0.1f; // Współczynnik tarcia (μ) const float maxSpeed = 2.0f; // Maksymalna prędkość łazika const float acceleration = 0.2f; float rotationAcceleration = 0.075f; // Przyspieszenie obrotu float rotationFriction = 0.1f; // Współczynnik tarcia obrotu float maxRotationSpeed = 0.5f; // Maksymalna prędkość obrotu // Struktura do reprezentacji płotu struct Plot { GLfloat xc; // Środek płotu w osi X GLfloat yc; // Środek płotu w osi Y (nieużywane w kolizji, ale może być pomocne) GLfloat zc; // Środek płotu w osi Z GLfloat length; // Długość płotu GLfloat gruboscY; // Grubość płotu bool mod_x; // 0 - płot pionowy, 1 - płot poziomy }; // Funkcja sprawdzająca kolizję z płotem // Funkcja sprawdzająca kolizję z płotem, uwzględniając wymiary łazika static bool CheckFenceCollision(float roverXMin, float roverXMax, float roverZMin, float roverZMax, const Plot& plot) { if (plot.mod_x == 0) { // Płot pionowy (równoległy do osi Z) float xMin = plot.xc - plot.gruboscY / 2.0f; float xMax = plot.xc + plot.gruboscY / 2.0f; float zMin = plot.zc - plot.length / 2.0f; float zMax = plot.zc + plot.length / 2.0f; // Sprawdzenie, czy którykolwiek fragment łazika wchodzi w obszar płotu if (roverXMax >= xMin && roverXMin <= xMax && // Kolizja w osi X roverZMax >= zMin && roverZMin <= zMax) { // Kolizja w osi Z return true; } } else { // Płot poziomy (równoległy do osi X) float xMin = plot.xc - plot.length / 2.0f; float xMax = plot.xc + plot.length / 2.0f; float zMin = plot.zc - plot.gruboscY / 2.0f; float zMax = plot.zc + plot.gruboscY / 2.0f; // Sprawdzenie, czy którykolwiek fragment łazika wchodzi w obszar płotu if (roverXMax >= xMin && roverXMin <= xMax && // Kolizja w osi X roverZMax >= zMin && roverZMin <= zMax) { // Kolizja w osi Z return true; } } return false; } // Funkcja ogólna do sprawdzania kolizji ze wszystkimi płotami static bool CheckAllFencesCollision(float roverXMin, float roverXMax, float roverZMin, float roverZMax, const std::vector& fences) { for (const auto& fence : fences) { if (CheckFenceCollision(roverXMin, roverXMax, roverZMin, roverZMax, fence)) { return true; // Kolizja wykryta z którymś płotem } } return false; // Brak kolizji } static void UpdateRover(const std::vector& fences) { // Przyspieszanie w przód if (keyWPressed) { velocity += acceleration; if (velocity > maxSpeed) velocity = maxSpeed; } // Przyspieszanie w tył else if (keySPressed) { velocity -= acceleration; if (velocity < -maxSpeed) velocity = -maxSpeed; } // Hamowanie (wytracanie prędkości z powodu tarcia) else { if (velocity > 0) { velocity -= friction; if (velocity < 0) velocity = 0; } else if (velocity < 0) { velocity += friction; if (velocity > 0) velocity = 0; } } // Obracanie (rotacja z driftowaniem) if (keyAPressed) { rotationVelocity += rotationAcceleration; if (rotationVelocity > maxRotationSpeed) rotationVelocity = maxRotationSpeed; } else if (keyDPressed) { rotationVelocity -= rotationAcceleration; if (rotationVelocity < -maxRotationSpeed) rotationVelocity = -maxRotationSpeed; } else { // Jeśli żadna z klawiszy A/D nie jest wciśnięta, to stopniowo spowalniamy rotację (drift) float driftFactor = 0.1f; // Mniejsza wartość = dłuższy drift if (rotationVelocity > 0) { rotationVelocity -= rotationFriction * driftFactor; if (rotationVelocity < 0) rotationVelocity = 0; } else if (rotationVelocity < 0) { rotationVelocity += rotationFriction * driftFactor; if (rotationVelocity > 0) rotationVelocity = 0; } } // Wyliczenie nowej pozycji na podstawie prędkości float radRotation = Rotation * GL_PI / 180.0f; // Przeliczamy rotację na radiany float newSides = Sides - velocity * cos(radRotation); // Nowa pozycja w osi X float newFoward = Foward - velocity * sin(radRotation); // Nowa pozycja w osi Z // Wymiary łazika (połówki w osi X i Z) const float roverHalfWidthX = 19.0f; // 38/2 const float roverHalfLengthZ = 12.0f; // 24/2 // Wyliczenie obszaru zajmowanego przez łazik float roverXMin = newSides - roverHalfWidthX; float roverXMax = newSides + roverHalfWidthX; float roverZMin = newFoward - roverHalfLengthZ; float roverZMax = newFoward + roverHalfLengthZ; // Sprawdzanie kolizji przed aktualizacją pozycji if (!Kolizja == true) { if (CheckAllFencesCollision(roverZMin, roverZMax, roverXMin, roverXMax, fences)) { // Jeśli jest kolizja, zatrzymujemy łazik velocity = 0.0f; //cout << "Kolizja podczas ruchu\n"; } else { // Jeśli brak kolizji, aktualizujemy pozycję Sides = newSides; Foward = newFoward; } // Sprawdzanie kolizji podczas obrotu if (rotationVelocity != 0.0f) { // Wyliczamy nową rotację float newRotation = Rotation + rotationVelocity; float radNewRotation = newRotation * GL_PI / 180.0f; // Obracamy narożniki łazika std::vector> corners(4); corners[0] = {Sides - roverHalfWidthX, Foward - roverHalfLengthZ}; // Lewy dolny corners[1] = {Sides + roverHalfWidthX, Foward - roverHalfLengthZ}; // Prawy dolny corners[2] = {Sides - roverHalfWidthX, Foward + roverHalfLengthZ}; // Lewy górny corners[3] = {Sides + roverHalfWidthX, Foward + roverHalfLengthZ}; // Prawy górny bool collisionDetected = false; // Obracamy wszystkie narożniki for (auto& corner : corners) { float x = corner.first; float z = corner.second; corner.first = Sides + (x - Sides) * cos(radNewRotation) - (z - Foward) * sin(radNewRotation); corner.second = Foward + (x - Sides) * sin(radNewRotation) + (z - Foward) * cos(radNewRotation); // Sprawdzamy kolizję na podstawie obróconych narożników if (CheckAllFencesCollision(corner.first, corner.first, corner.second, corner.second, fences)) { collisionDetected = true; break; } if (CheckAllFencesCollision( corner.second, corner.second, corner.first, corner.first, fences)) { collisionDetected = true; break; } } if (collisionDetected) { rotationVelocity = 0.0f; // Zatrzymujemy obrót //cout << "Kolizja podczas obrotu\n"; } else { // Aktualizujemy rotację, jeśli nie ma kolizji Rotation = newRotation; if (Rotation >= 360.0f) Rotation -= 360.0f; if (Rotation < 0.0f) Rotation += 360.0f; } } } else { // Jeśli kolizje są wyłączone, aktualizujemy wszystko bez sprawdzania Sides = newSides; Foward = newFoward; Rotation += rotationVelocity; if (Rotation >= 360.0f) Rotation -= 360.0f; if (Rotation < 0.0f) Rotation += 360.0f; } } std::vector fences = { { 450.0f, 3.0f, -90.0f, 900.0f, 4.0f, 1}, // 1 - poziomo { 0.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0}, // 0 - pionowo { 450.0f, 3.0f, 10*90.0f, 900.0f, 4.0f, 1}, // 1 - poziomo {10*90.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0} // 0 - pionowo }; std::vector> wzory = { // GK {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1}, // Ślimak {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Sygnał TTL {0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Okrąg {0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1}, // Kwadrat {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // ABACABA {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, // Paski {1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0}, // Puste pole {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }; std::vector siatka = { // Możliwe stany pól siatki: // - 0 - niezamalowana, nie do zamalowania (zielony) // - 1 - niezamalowana, do zamalowania (złoty) // - 2 - zamalowana, nie do zamalowania (czerwony) // - 3 - zamalowana, do zamalowania (jasnozielony) // 1. bit mówi o tym, czy jest do zamalowania // 2. bit mówi o tym, czy jest zamalowana 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void sprawdzPostepGry() { unsigned short zgodne_pola = 0; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { std::cout << "zgp: " << zgodne_pola << "\n"; unsigned short pole_w_siatce = siatka[10*i + (9 - j)]; bool pole_we_wzorach = wzory[biezacy_wzor][10*i + (9 - j)]; if (pole_w_siatce == 0 && pole_we_wzorach == 0) zgodne_pola++; else if (pole_w_siatce == 3 && pole_we_wzorach == 1) zgodne_pola++; else { std::cout << "dla i=" << i << " j=" << j << " otrzymano p_w_s " << pole_w_siatce << " a spodziewano sie p_w_w: " << pole_we_wzorach << "\n"; return; } } } if (zgodne_pola == 100) { biezacy_wzor = (biezacy_wzor + 1) % (wzory.size() + 1); nadpiszNowaSiatke(biezacy_wzor); } else { std::cout << "zgodne_pola: " << zgodne_pola << "\n"; } } void ustalPozycjeGracza(GLfloat gracz_x, GLfloat gracz_z, short &grid_x, short &grid_z) { grid_x = static_cast(gracz_x) / 90; grid_z = static_cast(gracz_z) / 90; // zapobiega rysowaniu ze "spawna" if (gracz_x < 0 && gracz_x > -90) grid_x = -1; // ten przypadek dotyczy tylko noclipa if (gracz_z < 0 && gracz_z > -90) grid_z = -1; } void ustawSiatkeNaWzorNieNadpisujacPostepu() { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { bool ma_byc_zamalowana = wzory[biezacy_wzor][10*i + (10 - j)]; if (ma_byc_zamalowana) siatka[10*i + (10 - j)] |= 1; else siatka[10*i + (10 - j)] = siatka[10*i + (10 - j)] - siatka[10*i + (10 - j)] % 2; } } } void nadpiszNowaSiatke(short nowy_wzor) { std::cout << "Przepisz zawartosc siatki!\n"; biezacy_wzor = nowy_wzor; for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { siatka[10*i + (10 - j)] = static_cast(wzory[biezacy_wzor][10*i + (10 - j)]); } } } void tworzKratke(unsigned int grid_x, unsigned int grid_z, unsigned short grid_value) { // https://rgbcolorpicker.com/0-1 switch (grid_value) { case 0: // niezamalowana, nie do zamalowania (zielony) glColor3d(0.031, 0.51, 0.094); break; case 1: // niezamalowana, do zamalowania (złoty) glColor3d(0.7, 0.5, 0.259); break; case 2: // zamalowana, nie do zamalowania (czerwony) glColor3d(1, 0.122, 0); break; case 3: // zamalowana, do zamalowania (biały) glColor3d(1, 1, 1); break; } platforma(45.0f + grid_x * 90.0f, 0.0f, 45.0f + grid_z * 90.0f, 45.0f, 45.0f); } void tworzKratkiZSiatki() { for (int i = 0; i < 10; i++) { // Aby nie musieć rysować wzorów w odbiciu // lustrzanym, musimy tutaj przyjąć inną sekwencję for (int j = 0; j < 10; j++) { tworzKratke(i, j, siatka[10*i + (9 - j)]); } } } void aktualizujBiezacaKratke(short grid_x, short grid_z) { if (grid_x < 0 || grid_z < 0) return; unsigned short a = siatka[10*grid_x + (9 - grid_z)]; siatka[10*grid_x + (9 - grid_z)] |= 2; // jeżeli coś się zmieniło if (siatka[10*grid_x + (9 - grid_z)] != a) { sprawdzPostepGry(); } } // Change viewing volume and viewport. Called when window is resized void static ChangeSize(GLsizei w, GLsizei h) { GLfloat nRange = 100.0f; //GLfloat fAspect; // Prevent a divide by zero if (h == 0) h = 1; lastWidth = w; lastHeight = h; //fAspect = (GLfloat)w / (GLfloat)h; // Set Viewport to window dimensions glViewport(0, 0, w, h); // Reset coordinate system glMatrixMode(GL_PROJECTION); glLoadIdentity(); // // Establish clipping volume (left, right, bottom, top, near, far) // if (w <= h) glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -nRange, nRange); // else glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -nRange, nRange); // Establish clipping volume (left, right, bottom, top, near, far) if (w <= h) glOrtho(-nRange, nRange, -nRange * h / w, nRange * h / w, -20 * nRange, 20 * nRange); else glOrtho(-nRange * w / h, nRange * w / h, -nRange, nRange, -20 * nRange, 20 * nRange); // Establish perspective: /* gluPerspective(60.0f, fAspect, 1.0, 400); */ glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } // LoadBitmapFile // opis: ładuje mapę bitową z pliku i zwraca jej adres. // Wypełnia strukturę nagłówka. // Nie obsługuje map 8-bitowych. static unsigned char* LoadBitmapFile(char* filename, BITMAPINFOHEADER* bitmapInfoHeader) { FILE* filePtr; // wskaźnik pozycji pliku BITMAPFILEHEADER bitmapFileHeader; // nagłówek pliku unsigned char* bitmapImage; // dane obrazu int imageIdx = 0; // licznik pikseli unsigned char tempRGB; // zmienna zamiany składowych // otwiera plik w trybie "read binary" filePtr = fopen(filename, "rb"); if (filePtr == NULL) return NULL; // wczytuje nagłówek pliku fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr); // sprawdza, czy jest to plik formatu BMP if (bitmapFileHeader.bfType != BITMAP_ID) { fclose(filePtr); return NULL; } // wczytuje nagłówek obrazu fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr); // ustawia wskaźnik pozycji pliku na początku danych obrazu fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET); // przydziela pamięć buforowi obrazu bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage); // sprawdza, czy udało się przydzielić pamięć if (!bitmapImage) { free(bitmapImage); fclose(filePtr); return NULL; } // wczytuje dane obrazu fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr); // sprawdza, czy dane zostały wczytane if (bitmapImage == NULL) { fclose(filePtr); return NULL; } // zamienia miejscami składowe R i B for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx += 3) { tempRGB = bitmapImage[imageIdx]; bitmapImage[imageIdx] = bitmapImage[imageIdx + 2]; bitmapImage[imageIdx + 2] = tempRGB; } // zamyka plik i zwraca wskaźnik bufora zawierającego wczytany obraz fclose(filePtr); return bitmapImage; } void SetDCPixelFormat(HDC hDC) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure 1, // Version of this structure PFD_DRAW_TO_WINDOW | // Draw to Window (not to bitmap) PFD_SUPPORT_OPENGL | // Support OpenGL calls in window PFD_DOUBLEBUFFER, // Double buffered PFD_TYPE_RGBA, // RGBA Color mode 24, // Want 24bit color 0,0,0,0,0,0, // Not used to select mode 0,0, // Not used to select mode 0,0,0,0,0, // Not used to select mode 32, // Size of depth buffer 0, // Not used to select mode 0, // Not used to select mode PFD_MAIN_PLANE, // Draw in main plane 0, // Not used to select mode 0,0,0 }; // Not used to select mode // Choose a pixel format that best matches that described in pfd nPixelFormat = ChoosePixelFormat(hDC, &pfd); // Set the pixel format for the device context SetPixelFormat(hDC, nPixelFormat, &pfd); } static void skrzynka(GLfloat k) { glColor3d(0.8, 0.7, 0.3); glEnable(GL_TEXTURE_2D); // Włącz teksturowanie glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); glNormal3d(0, 0, 1); glTexCoord2d(1.0, 1.0); glVertex3d( k, k, k); glTexCoord2d(0.0, 1.0); glVertex3d(-k, k, k); glTexCoord2d(0.0, 0.0); glVertex3d(-k, -k, k); glTexCoord2d(1.0, 0.0); glVertex3d( k, -k, k); glEnd(); glBindTexture(GL_TEXTURE_2D, texture[1]); glBegin(GL_QUADS); glNormal3d(1, 0, 0); glTexCoord2d(1.0, 1.0); glVertex3d(k, k, k); glTexCoord2d(0.0, 1.0); glVertex3d(k, -k, k); glTexCoord2d(0.0, 0.0); glVertex3d(k, -k, -k); glTexCoord2d(1.0, 0.0); glVertex3d(k, k, -k); glEnd(); glDisable(GL_TEXTURE_2D); // Wyłącz teksturowanie glBegin(GL_QUADS); glNormal3d(0, 0, -1); glVertex3d( k, k, -k); glVertex3d( k, -k, -k); glVertex3d(-k, -k, -k); glVertex3d(-k, k, -k); glNormal3d(-1, 0, 0); glVertex3d(-k, k, -k); glVertex3d(-k, -k, -k); glVertex3d(-k, -k, k); glVertex3d(-k, k, k); glNormal3d(0, 1, 0); glVertex3d( k, k, k); glVertex3d( k, k, -k); glVertex3d(-k, k, -k); glVertex3d(-k, k, k); glNormal3d(0, -1, 0); glVertex3d( k, -k, k); glVertex3d(-k, -k, k); glVertex3d(-k, -k, -k); glVertex3d( k, -k, -k); glEnd(); } static void platforma(GLfloat xc, GLfloat yc, GLfloat zc, GLfloat xlen, GLfloat zlen) { // glColor3d(0.729, 0.91, 0.51); // jasnozielony, dla grass02.bmp glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[1]); // Wybieramy teksturę // Ustawienie powtarzania tekstury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); // Powtarzanie w kierunku S glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); // Powtarzanie w kierunku T glBegin(GL_QUADS); // Powtarzające się współrzędne tekstury (np. *5, aby powtórzyła się 5 razy) glTexCoord2d(5.0, 5.0); glVertex3d(xc - xlen, yc, zc - zlen); // Lewy dolny glTexCoord2d(5.0, 0.0); glVertex3d(xc + xlen, yc, zc - zlen); // Prawy dolny glTexCoord2d(0.0, 0.0); glVertex3d(xc + xlen, yc, zc + zlen); // Prawy górny glTexCoord2d(0.0, 5.0); glVertex3d(xc - xlen, yc, zc + zlen); // Lewy górny glEnd(); glDisable(GL_TEXTURE_2D); } static void stodola(GLfloat xc, GLfloat yc, GLfloat zc, GLfloat krawedz) { glEnable(GL_TEXTURE_2D); // ściany stodoły z bruku (brickwall) glColor3d(0.612f, 0.573f, 0.478f); // ciemny szary popadający w brąz (https://rgbcolorpicker.com/0-1) glBindTexture(GL_TEXTURE_2D, texture[3]); glBegin(GL_QUADS); glTexCoord2d(1.0, 1.0); glVertex3d(xc - krawedz/2, yc, zc - krawedz/2); glTexCoord2d(1.0, 0.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2d(0.0, 0.0); glVertex3d(xc + krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2d(0.0, 1.0); glVertex3d(xc + krawedz/2, yc, zc - krawedz/2); glTexCoord2d(1.0, 1.0); glVertex3d(xc - krawedz/2, yc, zc - krawedz/2); glTexCoord2d(1.0, 0.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2d(0.0, 0.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2d(0.0, 1.0); glVertex3d(xc - krawedz/2, yc, zc + krawedz/2); glTexCoord2d(1.0, 1.0); glVertex3d(xc - krawedz/2, yc, zc + krawedz/2); glTexCoord2d(1.0, 0.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2d(0.0, 0.0); glVertex3d(xc + krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2d(0.0, 1.0); glVertex3d(xc + krawedz/2, yc, zc + krawedz/2); glEnd(); // przód i tył dachu glColor3d(0.612f, 0.573f, 0.478f); glBindTexture(GL_TEXTURE_2D, texture[3]); glBegin(GL_TRIANGLES); glTexCoord2f(1.0, 1.0); glVertex3f(xc - krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2f(1.0, 0.0); glVertex3f(xc - krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2f(0.0, 0.0); glVertex3f(xc - krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2f(1.0, 1.0); glVertex3f(xc + krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2f(1.0, 0.0); glVertex3f(xc + krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2f(0.0, 0.0); glVertex3f(xc + krawedz/2, yc + krawedz, zc + krawedz/2); glEnd(); // dach stodoły (barnroof) glColor3d(0.639, 0.553, 0.322); // wyblakły brązowy glBindTexture(GL_TEXTURE_2D, texture[2]); glBegin(GL_QUADS); glTexCoord2d(1.0, 1.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2d(1.0, 0.0); glVertex3d(xc - krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2d(0.0, 0.0); glVertex3d(xc + krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2d(0.0, 1.0); glVertex3d(xc + krawedz/2, yc + krawedz, zc + krawedz/2); glTexCoord2d(1.0, 1.0); glVertex3d(xc - krawedz/2, yc + krawedz, zc - krawedz/2); glTexCoord2d(1.0, 0.0); glVertex3d(xc - krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2d(0.0, 0.0); glVertex3d(xc + krawedz/2, yc + 1.5 * krawedz, zc); glTexCoord2d(0.0, 1.0); glVertex3d(xc + krawedz/2, yc + krawedz, zc - krawedz/2); glEnd(); glDisable(GL_TEXTURE_2D); } static void plot(GLfloat xc, GLfloat yc, GLfloat zc, GLfloat length, GLfloat gruboscY, bool mod_x) { GLfloat grubosc = 1.0f; // timestampedCout("main.cpp (plot): otrzymano xc=" << xc << " yc=" << yc << " zc=" << zc << " length=" << length << " mod_x=" << mod_x); GLfloat gruboscX = grubosc + mod_x * length; GLfloat gruboscZ = grubosc + !mod_x * length; // timestampedCout("main.cpp (plot): gruboscX=" << gruboscX << " gruboscY=" << gruboscY << " gruboscZ=" << gruboscZ); // d-----------c Y // / /| ^ // a-----------b | \ // | h | g C->X // | |/ | // e-----------f v // Z (płaszczyzna XZ, Y to trzeci wymiar) GLfloat a1_x = xc - gruboscX / 2, a1_y = yc + 1 + gruboscY, a1_z = zc + gruboscZ / 2; // 3 GLfloat b1_x = xc + gruboscX / 2, b1_y = yc + 1 + gruboscY, b1_z = zc + gruboscZ / 2; GLfloat c1_x = xc + gruboscX / 2, c1_y = yc + 1 + gruboscY, c1_z = zc - gruboscZ / 2; GLfloat d1_x = xc - gruboscX / 2, d1_y = yc + 1 + gruboscY, d1_z = zc - gruboscZ / 2; GLfloat e1_x = xc - gruboscX / 2, e1_y = yc + 1 , e1_z = zc + gruboscZ / 2; // 1 GLfloat f1_x = xc + gruboscX / 2, f1_y = yc + 1 , f1_z = zc + gruboscZ / 2; GLfloat g1_x = xc + gruboscX / 2, g1_y = yc + 1 , g1_z = zc - gruboscZ / 2; GLfloat h1_x = xc - gruboscX / 2, h1_y = yc + 1 , h1_z = zc - gruboscZ / 2; GLfloat a2_x = a1_x, a2_y = a1_y - 1 - gruboscY, a2_z = a1_z; //zc - 1; // -4 GLfloat b2_x = b1_x, b2_y = b1_y - 1 - gruboscY, b2_z = b1_z; //zc - 1; GLfloat c2_x = c1_x, c2_y = c1_y - 1 - gruboscY, c2_z = c1_z; //zc - 1; GLfloat d2_x = d1_x, d2_y = d1_y - 1 - gruboscY, d2_z = d1_z; //zc - 1; GLfloat e2_x = e1_x, e2_y = e1_y - 1 - gruboscY, e2_z = e1_z; //zc - 2; GLfloat f2_x = f1_x, f2_y = f1_y - 1 - gruboscY, f2_z = f1_z; //zc - 2; GLfloat g2_x = g1_x, g2_y = g1_y - 1 - gruboscY, g2_z = g1_z; //zc - 2; GLfloat h2_x = h1_x, h2_y = h1_y - 1 - gruboscY, h2_z = h1_z; //zc - 2; glColor3d(0.71, 0.522, 0.067); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texture[0]); glBegin(GL_QUADS); // Góra (1_x, 1_y, 1_z): // ABCD glTexCoord2d(1.0, 1.0); glVertex3d(a1_x, a1_y, a1_z); glTexCoord2d(1.0, 0.0); glVertex3d(b1_x, b1_y, b1_z); glTexCoord2d(0.0, 0.0); glVertex3d(c1_x, c1_y, c1_z); glTexCoord2d(0.0, 1.0); glVertex3d(d1_x, d1_y, d1_z); // EFGH glTexCoord2d(1.0, 1.0); glVertex3d(e1_x, e1_y, e1_z); glTexCoord2d(1.0, 0.0); glVertex3d(f1_x, f1_y, f1_z); glTexCoord2d(0.0, 0.0); glVertex3d(g1_x, g1_y, g1_z); glTexCoord2d(0.0, 1.0); glVertex3d(h1_x, h1_y, h1_z); // BCGF glTexCoord2d(1.0, 1.0); glVertex3d(b1_x, b1_y, b1_z); glTexCoord2d(1.0, 0.0); glVertex3d(c1_x, c1_y, c1_z); glTexCoord2d(0.0, 0.0); glVertex3d(g1_x, g1_y, g1_z); glTexCoord2d(0.0, 1.0); glVertex3d(f1_x, f1_y, f1_z); // ADHE glTexCoord2d(1.0, 1.0); glVertex3d(a1_x, a1_y, a1_z); glTexCoord2d(1.0, 0.0); glVertex3d(b1_x, b1_y, b1_z); glTexCoord2d(0.0, 0.0); glVertex3d(c1_x, c1_y, c1_z); glTexCoord2d(0.0, 1.0); glVertex3d(d1_x, d1_y, d1_z); // ABFE glTexCoord2d(1.0, 1.0); glVertex3d(a1_x, a1_y, a1_z); glTexCoord2d(1.0, 0.0); glVertex3d(b1_x, b1_y, b1_z); glTexCoord2d(0.0, 0.0); glVertex3d(f1_x, f1_y, f1_z); glTexCoord2d(0.0, 1.0); glVertex3d(e1_x, e1_y, e1_z); // DCGH glTexCoord2d(1.0, 1.0); glVertex3d(d1_x, d1_y, d1_z); glTexCoord2d(1.0, 0.0); glVertex3d(c1_x, c1_y, c1_z); glTexCoord2d(0.0, 0.0); glVertex3d(g1_x, g1_y, g1_z); glTexCoord2d(0.0, 1.0); glVertex3d(h1_x, h1_y, h1_z); // Dół (2_x, 2_y, 2_z): // ABCD glTexCoord2d(1.0, 1.0); glVertex3d(a2_x, a2_y, a2_z); glTexCoord2d(1.0, 0.0); glVertex3d(b2_x, b2_y, b2_z); glTexCoord2d(0.0, 0.0); glVertex3d(c2_x, c2_y, c2_z); glTexCoord2d(0.0, 1.0); glVertex3d(d2_x, d2_y, d2_z); // EFGH glTexCoord2d(1.0, 1.0); glVertex3d(e2_x, e2_y, e2_z); glTexCoord2d(1.0, 0.0); glVertex3d(f2_x, f2_y, f2_z); glTexCoord2d(0.0, 0.0); glVertex3d(g2_x, g2_y, g2_z); glTexCoord2d(0.0, 1.0); glVertex3d(h2_x, h2_y, h2_z); // BCGF glTexCoord2d(1.0, 1.0); glVertex3d(b2_x, b2_y, b2_z); glTexCoord2d(1.0, 0.0); glVertex3d(c2_x, c2_y, c2_z); glTexCoord2d(0.0, 0.0); glVertex3d(g2_x, g2_y, g2_z); glTexCoord2d(0.0, 1.0); glVertex3d(f2_x, f2_y, f2_z); // ADHE glTexCoord2d(1.0, 1.0); glVertex3d(a2_x, a2_y, a2_z); glTexCoord2d(1.0, 0.0); glVertex3d(b2_x, b2_y, b2_z); glTexCoord2d(0.0, 0.0); glVertex3d(c2_x, c2_y, c2_z); glTexCoord2d(0.0, 1.0); glVertex3d(d2_x, d2_y, d2_z); // ABFE glTexCoord2d(1.0, 1.0); glVertex3d(a2_x, a2_y, a2_z); glTexCoord2d(1.0, 0.0); glVertex3d(b2_x, b2_y, b2_z); glTexCoord2d(0.0, 0.0); glVertex3d(f2_x, f2_y, f2_z); glTexCoord2d(0.0, 1.0); glVertex3d(e2_x, e2_y, e2_z); // DCGH glTexCoord2d(1.0, 1.0); glVertex3d(d2_x, d2_y, d2_z); glTexCoord2d(1.0, 0.0); glVertex3d(c2_x, c2_y, c2_z); glTexCoord2d(0.0, 0.0); glVertex3d(g2_x, g2_y, g2_z); glTexCoord2d(0.0, 1.0); glVertex3d(h2_x, h2_y, h2_z); // Pachołki // d-----------c Y // / /| ^ // a-----------b | \ // | h | g C->X // | |/ | // e-----------f v // Z (płaszczyzna XZ, Y to trzeci wymiar) GLfloat p_a_x, p_a_y, p_a_z; GLfloat p_b_x, p_b_y, p_b_z; GLfloat p_c_x, p_c_y, p_c_z; GLfloat p_d_x, p_d_y, p_d_z; GLfloat p_e_x, p_e_y, p_e_z; GLfloat p_f_x, p_f_y, p_f_z; GLfloat p_g_x, p_g_y, p_g_z; GLfloat p_h_x, p_h_y, p_h_z; if (!mod_x) { p_a_x = xc + gruboscX / 2, p_a_y = yc + 1.5f * gruboscY, p_a_z = zc; // +3 dla y p_b_x = xc - gruboscX / 2, p_b_y = yc + 1.5f * gruboscY, p_b_z = zc; // +3 dla y p_c_x = xc + gruboscX / 2, p_c_y = yc + 1.5f * gruboscY, p_c_z = zc; // +3 dla y p_d_x = xc - gruboscX / 2, p_d_y = yc + 1.5f * gruboscY, p_d_z = zc; // +3 dla y p_e_x = xc + gruboscX / 2, p_e_y = yc - 6 , p_e_z = zc; p_f_x = xc - gruboscX / 2, p_f_y = yc - 6 , p_f_z = zc; p_g_x = xc + gruboscX / 2, p_g_y = yc - 6 , p_g_z = zc; p_h_x = xc - gruboscX / 2, p_h_y = yc - 6 , p_h_z = zc; } else { p_a_x = xc, p_a_y = yc + 1.5f * gruboscY, p_a_z = zc - gruboscZ / 2; // +3 dla y p_b_x = xc, p_b_y = yc + 1.5f * gruboscY, p_b_z = zc - gruboscZ / 2; // +3 dla y p_c_x = xc, p_c_y = yc + 1.5f * gruboscY, p_c_z = zc + gruboscZ / 2; // +3 dla y p_d_x = xc, p_d_y = yc + 1.5f * gruboscY, p_d_z = zc + gruboscZ / 2; // +3 dla y p_e_x = xc, p_e_y = yc - 6 , p_e_z = zc - gruboscZ / 2; p_f_x = xc, p_f_y = yc - 6 , p_f_z = zc - gruboscZ / 2; p_g_x = xc, p_g_y = yc - 6 , p_g_z = zc + gruboscZ / 2; p_h_x = xc, p_h_y = yc - 6 , p_h_z = zc + gruboscZ / 2; } for (int i = 0; i < 2; i++) { // d-----------c Y // / /| ^ // a-----------b | \ // | h | g C->X // | |/ | // e-----------f v // Z (płaszczyzna XZ, Y to trzeci wymiar) // timestampedCout("main.cpp (plot): p_a_x=" << p_a_x << " p_b_x=" << p_b_x << " p_c_x=" << p_c_x << " p_d_x=" << p_d_x); // ABCD glTexCoord2d(1.0, 1.0); glVertex3d(p_a_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_a_y, p_a_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_b_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_b_y, p_b_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_c_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_c_y, p_c_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_d_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_d_y, p_d_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); // EFGH glTexCoord2d(1.0, 1.0); glVertex3d(p_e_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_e_y, p_e_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_f_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_f_y, p_f_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_g_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_g_y, p_g_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_h_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_h_y, p_h_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); // BCGF glTexCoord2d(1.0, 1.0); glVertex3d(p_b_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_b_y, p_b_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_c_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_c_y, p_c_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_g_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_g_y, p_g_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_f_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_f_y, p_f_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); // ADHE glTexCoord2d(1.0, 1.0); glVertex3d(p_a_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_a_y, p_a_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_d_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_d_y, p_d_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_h_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_h_y, p_h_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_e_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_e_y, p_e_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); // ABFE glTexCoord2d(1.0, 1.0); glVertex3d(p_a_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_a_y, p_a_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_b_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_b_y, p_b_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_f_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_f_y, p_f_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_e_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_e_y, p_e_z + (2*i-1) * (gruboscZ/2 - 5) * !mod_x); // DCGH glTexCoord2d(1.0, 1.0); glVertex3d(p_d_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_d_y, p_d_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(1.0, 0.0); glVertex3d(p_c_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_c_y, p_c_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 0.0); glVertex3d(p_g_x + (2*i-1) * (gruboscX/2 - 5) * mod_x, p_g_y, p_g_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); glTexCoord2d(0.0, 1.0); glVertex3d(p_h_x + (2*i-1) * (gruboscX/2 - 8) * mod_x, p_h_y, p_h_z + (2*i-1) * (gruboscZ/2 - 8) * !mod_x); } glEnd(); glDisable(GL_TEXTURE_2D); } //GLuint programID, VertexArrayID, MatrixID; lazik user(10.0f, 0.0f, 0.0f, "res/models/lazik4.obj"); // obiekty eksportujemy z Forward Axis Z, Up Axis Y. plane mapa( 0.0f, 0.0f, 0.0f, "res/models/mapka3_nofence_noplatform.obj"); static void SetupRC() { // Light values and coordinates GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f }; GLfloat diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f }; GLfloat specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; GLfloat specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }; // Multiple light positions (for light coming from all sides) GLfloat lightPos1[] = { 50.0f, -100.0f, 50.0f, 1.0f }; // Light 0 position GLfloat lightPos2[] = { -50.0f, -100.0f, 50.0f, 1.0f }; // Light 1 position GLfloat lightPos3[] = { 50.0f, -100.0f, -50.0f, 1.0f }; // Light 2 position GLfloat lightPos4[] = { -50.0f, -100.0f, -50.0f, 1.0f }; // Light 3 position glEnable(GL_DEPTH_TEST); // Hidden surface removal glFrontFace(GL_CCW); // Counter clockwise polygons face out glDepthFunc(GL_LESS); // Enable lighting glEnable(GL_LIGHTING); // Setup and enable light 0 glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); glLightfv(GL_LIGHT0, GL_POSITION, lightPos1); glEnable(GL_LIGHT0); // Setup and enable light 1 glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT1, GL_SPECULAR, specular); glLightfv(GL_LIGHT1, GL_POSITION, lightPos2); glEnable(GL_LIGHT1); // Setup and enable light 2 glLightfv(GL_LIGHT2, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT2, GL_SPECULAR, specular); glLightfv(GL_LIGHT2, GL_POSITION, lightPos3); glEnable(GL_LIGHT2); // Setup and enable light 3 glLightfv(GL_LIGHT3, GL_AMBIENT, ambientLight); glLightfv(GL_LIGHT3, GL_DIFFUSE, diffuseLight); glLightfv(GL_LIGHT3, GL_SPECULAR, specular); glLightfv(GL_LIGHT3, GL_POSITION, lightPos4); glEnable(GL_LIGHT3); // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Set Material properties to follow glColor values glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); // All materials hereafter have full specular reflectivity // with a high shine GLfloat specref2[] = {0.2f, 0.2f, 0.2f, 0.2f}; glMaterialfv(GL_FRONT, GL_SPECULAR, specref2); glMateriali(GL_FRONT, GL_SHININESS, 128); // White background glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Initialize GLEW timestampedCout("Inicjalizowanie GLEW..."); glewExperimental = true; // Needed for core profile if (glewInit() != GLEW_OK) { timestampedCout("Failed to initialize GLEW"); return; } timestampedCout("Zainicjalizowano GLEW."); // Initialize GLFW3 timestampedCout("Inicjalizowanie GLFW3..."); if (!glfwInit()) { timestampedCout("Failed to initialize GLFW"); } timestampedCout("Zainicjalizowano GLFW3."); // Load models timestampedCout("Ladowanie modelu lazika..."); user.loadModel(); timestampedCout("Ladowanie modelu mapki..."); mapa.loadModel(); glfwSwapInterval(1); } void static RenderScene(void) { // PS: to nie zadziała, bo okno nie jest tworzone przez glfw // Ustawienie liczby próbek dla antyaliasingu // glfwWindowHint(GLFW_SAMPLES, 16); // 4x MSAA (Wielokrotne próbkowanie) // Włączenie antyaliasingu (MSAA) //glEnable(GL_MULTISAMPLE); // Przywrócenie macierzy modelu i ustawienie obrotów glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glRotatef(zRot, 0.0f, 0.0f, 1.0f); // Ustawienie trybu rysowania wielokątów switch (polygonmode) { case 1: glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Rysowanie linii break; default: glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Wypełnianie poligonów } // Czyszczenie ekranu przed rysowaniem glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Przywrócenie macierzy widoku if (panoramic_view) { maxRotationSpeed = 1.0f; rotationFriction = 0.5f; gluLookAt( Foward, // Pozycja kamery 123, // Wysokość kamery, nie ma znaczenia bo nie mamy perspektywy Sides - 1.0f, // Kamera wzdłuż osi X i Z, z jakiegoś powodu działa po "- 1.0f" Foward, 0.0f, Sides, // Punkt patrzenia (łazik) 0.0f, 1.0f, 0.0f // Wektor "góry" ); } else { maxRotationSpeed = 0.5f; rotationFriction = 0.1f; gluLookAt( Foward - 50.0f * sin((Rotation + 180.0f) * GL_PI / 180.0f), // Pozycja kamery CameraHeight / 4, // Wysokość kamery Sides - 50.0f * cos((Rotation + 180.0f) * GL_PI / 180.0f), // Kamera wzdłuż osi X i Z Foward, 0.0f, Sides, // Punkt patrzenia (łazik) 0.0f, 1.0f, 0.0f // Wektor "góry" ); } // Rysowanie mapy glPushMatrix(); glColor3f(0.0, 1.0, 0.0); // Zielony kolor // mapa.draw(); // nie rysuj mapy/terenu .obj // Platforma niebędąca częścią siatki: glColor3d(0.031, 0.51, 0.094); // ciemnozielony platforma(450.0f, 0.0f, -45.0f, 450.0f, 45.0f); glPopMatrix(); // Rysowanie łazika glPushMatrix(); glTranslatef(Foward, 0.0f, Sides); // Translacja łazika glRotatef(Rotation, 0.0f, 1.0f, 0.0f); // Obrót łazika glColor3f(1.0, 0.0, 0.0); // Czerwony kolor dla łazika user.draw(); UpdateRover(fences); fpsCounter.update(); glPopMatrix(); // std::cout << "X: " << Foward << " Z: " << Sides << " Rotation: " << Rotation << "\n"; // Rysowanie innych obiektów plot( 450.0f, 3.0f, -90.0f, 900.0f, 4.0f, 1); // 1 - poziomo plot( 0.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0); // 0 - pionowo plot( 450.0f, 3.0f, 10*90.0f, 900.0f, 4.0f, 1); // 1 - poziomo plot(10*90.0f, 3.0f, 405.0f, 990.0f, 4.0f, 0); // 0 - pionowo stodola(45.0f, 0.0f, -45.0f, 70.0f); // Mechanika gry // 1 pole siatki = 90x90m short grid_x, grid_z; ustalPozycjeGracza(Foward, Sides, grid_x, grid_z); // std::cout << "grid_X: " << grid_x << " grid_Z: " << grid_z << " status: " << siatka[10*grid_x + (9 - grid_z)] << "\n"; ustawSiatkeNaWzorNieNadpisujacPostepu(); tworzKratkiZSiatki(); aktualizujBiezacaKratke(grid_x, grid_z); // Zamiana buforów (double buffering) // glfwSwapBuffers(window); // Przełączenie buforów // glfwPollEvents(); // Obsługa zdarzeń glPopMatrix(); // Przywrócenie poprzedniej macierzy glMatrixMode(GL_MODELVIEW); // Ustawienie trybu modelu-widoku // Wymuszenie wykonania wszystkich rysunków glFlush(); } // If necessary, creates a 3-3-2 palette for the device context listed. HPALETTE static GetOpenGLPalette(HDC hDC) { HPALETTE hRetPal = NULL; // Handle to palette to be created PIXELFORMATDESCRIPTOR pfd; // Pixel Format Descriptor LOGPALETTE* pPal; // Pointer to memory for logical palette int nPixelFormat; // Pixel format index int nColors; // Number of entries in palette int i; // Counting variable BYTE RedRange, GreenRange, BlueRange; // Range for each color entry (7,7,and 3) // Get the pixel format index and retrieve the pixel format description nPixelFormat = GetPixelFormat(hDC); DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); // Does this pixel format require a palette? If not, do not create a // palette and just return NULL if (!(pfd.dwFlags & PFD_NEED_PALETTE)) return NULL; // Number of entries in palette. 8 bits yeilds 256 entries nColors = 1 << pfd.cColorBits; // Allocate space for a logical palette structure plus all the palette entries pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) + nColors * sizeof(PALETTEENTRY)); // Fill in palette header pPal->palVersion = 0x300; // Windows 3.0 pPal->palNumEntries = nColors; // table size // Build mask of all 1's. This creates a number represented by having // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and // pfd.cBlueBits. RedRange = (1 << pfd.cRedBits) - 1; GreenRange = (1 << pfd.cGreenBits) - 1; BlueRange = (1 << pfd.cBlueBits) - 1; // Loop through all the palette entries for (i = 0; i < nColors; i++) { // Fill in the 8-bit equivalents for each component pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange; pPal->palPalEntry[i].peRed = (unsigned char)( (double)pPal->palPalEntry[i].peRed * 255.0 / RedRange); pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange; pPal->palPalEntry[i].peGreen = (unsigned char)( (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange); pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange; pPal->palPalEntry[i].peBlue = (unsigned char)( (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange); // pPal->palPalEntry[i].peFlags = (unsigned char) NULL; pPal->palPalEntry[i].peFlags = 0; } // Create the palette hRetPal = CreatePalette(pPal); // Go ahead and select and realize the palette for this device context SelectPalette(hDC, hRetPal, FALSE); RealizePalette(hDC); // Free the memory used for the logical palette structure free(pPal); // Return the handle to the new palette return hRetPal; } void static CreateConsole() { // Tworzenie nowej konsoli if (AllocConsole()) { // Przekierowanie standardowych strumieni do konsoli FILE* conin; FILE* conout; FILE* conerr; freopen_s(&conin, "conin$", "r", stdin); freopen_s(&conout, "conout$", "w", stdout); freopen_s(&conerr, "conout$", "w", stderr); } else { MessageBox(NULL, "Nie udalo sie utworzyc konsoli.", "Blad", MB_OK | MB_ICONERROR); } } int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { CreateConsole(); MSG msg; // Windows message structure WNDCLASS wc{}; // Windows class structure HWND hWnd; // Storeage for window handle hInstance = hInst; // Register Window style wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = NULL; wc.hCursor = LoadCursor(NULL, IDC_ARROW); // No need for background brush for OpenGL window wc.hbrBackground = NULL; wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU); wc.lpszClassName = lpszAppName; // Register the window class if (RegisterClass(&wc) == 0) return FALSE; // Create the main application window hWnd = CreateWindow( lpszAppName, lpszAppName, // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, // Window position and size 50, 50, 800, 800, NULL, NULL, hInstance, NULL); // If window was not created, quit if (hWnd == NULL) return FALSE; const WORD ID_TIMER = 1; SetTimer(hWnd, ID_TIMER, 100, NULL); // Display the window ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); // Process application messages until the application closes while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } // Window procedure, handles all messages for this program LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; // Permenant Rendering context static HDC hDC; // Private GDI Device context float radRotation = Rotation * GL_PI / 180.0f; switch (message) { // Window creation, setup for OpenGL case WM_CREATE: // Store the device context hDC = GetDC(hWnd); // Select the pixel format SetDCPixelFormat(hDC); // Create palette if needed hPalette = GetOpenGLPalette(hDC); // Create the rendering context and make it current hRC = wglCreateContext(hDC); wglMakeCurrent(hDC, hRC); SetupRC(); glGenTextures(3, &texture[0]); // tworzy obiekt tekstury // ładuje pierwszy obraz tekstury (płotki): bitmapData = LoadBitmapFile((char*)"res/img/woodenTextureHighExposure.bmp", &bitmapInfoHeader); glBindTexture(GL_TEXTURE_2D, texture[0]); // aktywuje obiekt tekstury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); // tworzy obraz tekstury glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); if (bitmapData) free(bitmapData); // ładuje drugi obraz tekstury (ziemia): bitmapData = LoadBitmapFile((char*)"res/img/grass02.bmp", &bitmapInfoHeader); glBindTexture(GL_TEXTURE_2D, texture[1]); // aktywuje obiekt tekstury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); // tworzy obraz tekstury glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); if (bitmapData) free(bitmapData); // ładuje trzeci obraz tekstury (dach stodoły): bitmapData = LoadBitmapFile((char*)"res/img/barnroof.bmp", &bitmapInfoHeader); glBindTexture(GL_TEXTURE_2D, texture[2]); // aktywuje obiekt tekstury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // tworzy obraz tekstury glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); if (bitmapData) free(bitmapData); // ładuje czwarty obraz tekstury (kamienista ściana): bitmapData = LoadBitmapFile((char*)"res/img/brickwall.bmp", &bitmapInfoHeader); glBindTexture(GL_TEXTURE_2D, texture[3]); // aktywuje obiekt tekstury glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); // tworzy obraz tekstury glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); if (bitmapData) free(bitmapData); // ustalenie sposobu mieszania tekstury z tłem glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; // Window is being destroyed, cleanup case WM_DESTROY: user.unload(); //glDeleteProgram(programID); //glDeleteVertexArrays(1, &VertexArrayID); // Deselect the current rendering context and delete it wglMakeCurrent(hDC, NULL); wglDeleteContext(hRC); // Delete the palette if it was created if (hPalette != NULL) DeleteObject(hPalette); // Tell the application to terminate after the window // is gone. PostQuitMessage(0); break; // Window is resized. case WM_SIZE: // Call our function which modifies the clipping // volume and viewport ChangeSize(LOWORD(lParam), HIWORD(lParam)); break; // The painting function. This message sent by Windows // whenever the screen needs updating. case WM_PAINT: LimitFPS(targetFPS); // Call OpenGL drawing code RenderScene(); SwapBuffers(hDC); // Validate the newly painted client area if (!monitormode) ValidateRect(hWnd, NULL); else InvalidateRect(hWnd, NULL, FALSE); //break; // Limit FPS // Uaktualniaj FPS // Ogranicz FPS case WM_QUERYNEWPALETTE: // If the palette was created. if (hPalette) { int nRet; // Selects the palette into the current device context SelectPalette(hDC, hPalette, FALSE); // Map entries from the currently selected palette to // the system palette. The return value is the number // of palette entries modified. nRet = RealizePalette(hDC); // Repaint, forces remap of palette in current window InvalidateRect(hWnd, NULL, FALSE); return nRet; } break; // This window may set the palette, even though it is not the // currently active window. case WM_PALETTECHANGED: // Don't do anything if the palette does not exist, or if // this is the window that changed the palette. if ((hPalette != NULL) && ((HWND)wParam != hWnd)) { // Select the palette into the device context SelectPalette(hDC, hPalette, FALSE); // Map entries to system palette RealizePalette(hDC); // Remap the current colors to the newly realized palette UpdateColors(hDC); return 0; } break; case WM_KEYUP: switch (wParam) { case 'W': keyWPressed = false; break; case 'S': keySPressed = false; break; case 'A': keyAPressed = false; break; case 'D': keyDPressed = false; break; // Obsługa innych klawiszy } break; case WM_KEYDOWN: switch (wParam) { case VK_UP: xRot -= 5.0f; break; case VK_DOWN: xRot += 5.0f; break; case VK_LEFT: yRot -= 5.0f; break; case VK_RIGHT: yRot += 5.0f; break; case 'Q': zRot += 5.0f; break; case 'E': zRot -= 5.0f; break; case 'R': xRot = 0; yRot = 0; zRot = 0; break; case ' ': // 32 polygonmode = !polygonmode; if (polygonmode) timestampedCout("Uwaga! Tryb wireframe jest niewydajny i powinien sluzyc tylko do debugowania!"); break; case 'K': Kolizja = !Kolizja; break; case 'W': keyWPressed = true; break; case 'S': keySPressed = true; break; case 'A': keyAPressed = true; break; case 'D': keyDPressed = true; break; // case 114: // F3 // monitormode = !monitormode; // if (monitormode) { // monitormodehelper = std::time(nullptr) - 1; // timestampedCout("Wlaczono tryb monitorowania wydajnosci."); // } // if (!monitormode) timestampedCout("Wylaczono tryb monitorowania wydajnosci."); // break; case 116: // F5 włącza widok panoramiczny panoramic_view = !panoramic_view; break; case 16: // Shift również panoramic_view = !panoramic_view; break; case 8: // Backspace czyści postęp nadpiszNowaSiatke(biezacy_wzor); break; default: timestampedCout("Nacisnieto nierozpoznany klawisz: " << (int)wParam); } xRot = (const int)xRot % 360; yRot = (const int)yRot % 360; zRot = (const int)zRot % 360; InvalidateRect(hWnd, NULL, FALSE); break; // A menu command case WM_COMMAND: switch (LOWORD(wParam)) { // Exit the program case ID_FILE_EXIT: DestroyWindow(hWnd); break; // Display the about box case ID_HELP_ABOUT: DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, (DLGPROC)AboutDlgProc); break; } break; case WM_TIMER: RenderScene(); SwapBuffers(hDC); ValidateRect(hWnd, NULL); break; default: // Passes it on if unproccessed return (DefWindowProc(hWnd, message, wParam, lParam)); } return (0L); } // Dialog procedure. BOOL APIENTRY AboutDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) { switch (message) { // Initialize the dialog box case WM_INITDIALOG: int i; GLenum glError; // glGetString demo SetDlgItemText(hDlg, IDC_OPENGL_VENDOR, reinterpret_cast(glGetString(GL_VENDOR))); SetDlgItemText(hDlg, IDC_OPENGL_RENDERER, (LPCSTR)glGetString(GL_RENDERER)); SetDlgItemText(hDlg, IDC_OPENGL_VERSION, (LPCSTR)glGetString(GL_VERSION)); SetDlgItemText(hDlg, IDC_OPENGL_EXTENSIONS, (LPCSTR)glGetString(GL_EXTENSIONS)); // gluGetString demo SetDlgItemText(hDlg, IDC_GLU_VERSION, (LPCSTR)gluGetString(GLU_VERSION)); SetDlgItemText(hDlg, IDC_GLU_EXTENSIONS, (LPCSTR)gluGetString(GLU_EXTENSIONS)); // Display any recent error messages i = 0; do { glError = glGetError(); SetDlgItemText(hDlg, IDC_ERROR1 + i, (LPCSTR)gluErrorString(glError)); i++; } while (i < 6 && glError != GL_NO_ERROR); return (TRUE); break; // Process command messages case WM_COMMAND: // Validate and Make the changes if (LOWORD(wParam) == IDOK) EndDialog(hDlg, TRUE); break; // Closed from sysbox case WM_CLOSE: EndDialog(hDlg, TRUE); break; } return FALSE; }