Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <gl/gl.h>
- #include <gl/glut.h>
- #include <math.h>
- #include <iostream>
- #define PI 3.14159265
- static int model = 1; // wybór modelu wyświetlanego jajka
- static GLfloat azymut = 0.0; // kąt azymutu (kierunek patrzenia na obiekt)
- static GLfloat elewacja = 0.0; // kąt elewacji (wysokość położenia obserwatora)
- static GLfloat R = 10.0;
- // wartość promienia R sfery o środku w środku układu współrzędnych,
- // po której porusza się obserwator
- static GLfloat pix2angle; // przelicznik pikseli na stopnie
- static GLint status = 0;
- // stan klawiszy myszy:
- // 0 - nie naciśnięto żadnego klawisza
- // 1 - naciśnięty został lewy klawisz
- // 2 - naciśnięty został prawy klawisz
- static int x_pos_old = 0; // poprzednia pozycja kursora myszy
- static int delta_x = 0;
- // różnica pomiędzy pozycją bieżącą i poprzednią kursora myszy
- static int y_pos_old = 0;
- static int delta_y = 0;
- // jw. ale dla parametru y
- static int R_pos_old = 0;
- static int delta_R = 0;
- // jw. ale dla parametru zoom
- typedef float point3[3];
- // typ danych przechowujący 3 współrzędne float (do tworzenia osi)
- static GLfloat viewer[] = { 0.0, 0.0, 10.0 };
- // współrzędne obserwatora (kamery) w układzie współrzędnych
- // funkcja odpowiedzialna za tworzenie trójwymiarowego jajka z wcześniejszych zajęć
- void Egg() {
- int N = 50;
- // ilość stref, na które dzielimy bok kwadratu jednostkowego dziedziny parametrycznej
- float u, v;
- // wspolrzędne u, v dla dziedziny parametrycznej (kwadrat jednostkowy)
- point3 **tab = new point3*[N];
- // tablica do zapisywania punktów w przestrzeni 3-D (x, y, z)
- point3 **tabRGB = new point3*[N];
- // tablica kolorów (R, G, B)
- for (int i = 0; i < N; i++) { // dynamiczne tworzenie tablicy dwuwymiarowej
- tab[i] = new point3[N]; // (trójwymiarowej uwzględniając typ danych point3 będący tablicą)
- tabRGB[i] = new point3[N];
- }
- // poniżej wypełnianie tablicy RGB losowymi kolorami dla modelu 3 - jajka stworzonego z kolorowych trójkątów
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- tabRGB[i][j][0] = ((rand() % 101)*0.01);
- tabRGB[i][j][1] = ((rand() % 101)*0.01);
- tabRGB[i][j][2] = ((rand() % 101)*0.01);
- }
- }
- // poniżej wypełnianie tablicy obliczonymi wartościami dla punktów x, y, z w przestrzeni 3-D z odpowiednich wzorów
- for (int i = 0; i < N; i++) {
- for (int j = 0; j < N; j++) {
- u = (float)i / (N - 1);
- v = (float)j / (N - 1);
- tab[i][j][0] = (-90 * pow(u, 5) + 225 * pow(u, 4) - 270 * pow(u, 3) + 180 * pow(u, 2) - 45 * u) * cos(PI*v); // x
- tab[i][j][1] = 160 * pow(u, 4) - 320 * pow(u, 3) + 160 * pow(u, 2) - 5.0; // y z lekka translacja
- tab[i][j][2] = (-90 * pow(u, 5) + 225 * pow(u, 4) - 270 * pow(u, 3) + 180 * pow(u, 2) - 45 * u) * sin(PI*v); // z
- }
- }
- // ponizej rysowanie odpowiedniego modelu jajka
- glColor3f(1.0f, 1.0f, 1.0f);
- if (model == 1) { // punkty
- glBegin(GL_POINTS);
- for (int i = 0; i<N; i++) {
- for (int j = 0; j<N; j++) {
- glVertex3fv(tab[i][j]);
- }
- }
- glEnd();
- }
- else if (model == 2) { // siatka
- glBegin(GL_LINES);
- for (int i = 0; i<N - 1; i++) {
- for (int j = 0; j<N - 1; j++) {
- glVertex3fv(tab[i][j]);
- glVertex3fv(tab[i + 1][j]);
- // rysowanie siatki "pionowej"
- glVertex3fv(tab[i][j]);
- glVertex3fv(tab[i][j + 1]);
- // rysowanie siatki "poziomej"
- glVertex3fv(tab[i + 1][j]);
- glVertex3fv(tab[i][j + 1]);
- // rysowanie siatki "pochyłej"
- }
- }
- glEnd();
- }
- else if (model == 3) { // kolorowe trójkąty
- glBegin(GL_TRIANGLES);
- for (int i = 0; i<N - 1; i++) {
- for (int j = 0; j<N - 1; j++) {
- glColor3fv(tabRGB[i][j]); // Pierwszy trójkąt
- glVertex3fv(tab[i][j]);
- glColor3fv(tabRGB[i + 1][j]);
- glVertex3fv(tab[i + 1][j]);
- glColor3fv(tabRGB[i][j + 1]);
- glVertex3fv(tab[i][j + 1]);
- /*************************************************************************************/
- glColor3fv(tabRGB[i + 1][j + 1]); // Drugi, 'uzupełniający' trójkąt
- glVertex3fv(tab[i + 1][j + 1]);
- glColor3fv(tabRGB[i + 1][j]);
- glVertex3fv(tab[i + 1][j]);
- glColor3fv(tabRGB[i][j + 1]);
- glVertex3fv(tab[i][j + 1]);
- // Jeśli nie stworzymy trójkątów tak, by sklejały się w prostokąty (uzupełniały na całej powierzchni),
- // pozostawimy pustą przestrzeń na płaszczyźnie jajka.
- }
- }
- glEnd();
- }
- // zwolnienie zaalokowanej wcześniej pamięci
- for (int i = 0; i < N; i++) {
- delete[] tab[i];
- delete[] tabRGB[i];
- }
- delete[]tab;
- delete[]tabRGB;
- }
- // Funkcja "bada" stan myszy i ustawia wartości odpowiednich zmiennych globalnych
- void Mouse(int btn, int state, int x, int y)
- {
- if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
- {
- x_pos_old = x; // przypisanie aktualnie odczytanej pozycji kursora
- y_pos_old = y; // jako pozycji poprzedniej
- status = 1; // wciśnięty został lewy klawisz myszy
- }
- else if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
- R_pos_old = y; // jw. - wersja dla R
- // tylko ruch pionowy myszki
- status = 2; // wciśnięty został prawy przycisk myszy
- }
- else status = 0; // nie został wciśnięty żaden klawisz
- }
- // Funkcja "monitoruje" położenie kursora myszy i ustawia wartości odpowiednich
- // zmiennych globalnych
- void Motion(GLsizei x, GLsizei y)
- {
- delta_x = x - x_pos_old; // obliczenie różnicy położenia kursora myszy
- delta_y = y - y_pos_old; // dla współrzędnych x, y (zoom wyliczany jak y)
- delta_R = y - R_pos_old;
- x_pos_old = x; // podstawienie bieżącego położenia jako poprzednie
- y_pos_old = y; // dla wszystkich zmiennych dot. sterowania myszą
- R_pos_old = y;
- glutPostRedisplay(); // przerysowanie obrazu sceny
- }
- // Funkcja rysująca osie układu wspó?rz?dnych
- void Axes(void)
- {
- point3 x_min = { -5.0, 0.0, 0.0 };
- point3 x_max = { 5.0, 0.0, 0.0 };
- // początek i koniec obrazu osi x
- point3 y_min = { 0.0, -5.0, 0.0 };
- point3 y_max = { 0.0, 5.0, 0.0 };
- // początek i koniec obrazu osi y
- point3 z_min = { 0.0, 0.0, -5.0 };
- point3 z_max = { 0.0, 0.0, 5.0 };
- // początek i koniec obrazu osi z
- glColor3f(1.0f, 0.0f, 0.0f); // kolor rysowania osi - czerwony
- glBegin(GL_LINES); // rysowanie osi x
- glVertex3fv(x_min);
- glVertex3fv(x_max);
- glEnd();
- glColor3f(0.0f, 1.0f, 0.0f); // kolor rysowania - zielony
- glBegin(GL_LINES); // rysowanie osi y
- glVertex3fv(y_min);
- glVertex3fv(y_max);
- glEnd();
- glColor3f(0.0f, 0.0f, 1.0f); // kolor rysowania - niebieski
- glBegin(GL_LINES); // rysowanie osi z
- glVertex3fv(z_min);
- glVertex3fv(z_max);
- glEnd();
- }
- // Funkcja określająca co ma być rysowane (zawsze wywoływana, gdy trzeba
- // przerysować scenę)
- void RenderScene(void)
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- // Czyszczenie okna aktualnym kolorem czyszczącym
- glLoadIdentity();
- // Czyszczenie macierzy bieżącej
- gluLookAt(viewer[0], viewer[1], viewer[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
- // Zdefiniowanie położenia obserwatora
- Axes();
- // Narysowanie osi przy pomocy funkcji zdefiniowanej powyżej
- if (status == 1) // jeśli został wciśnięty lewy przycisk myszy
- {
- azymut += (delta_x*pix2angle)/50; // modyfikacja kąta obrotu o kąt proporcjonalny
- elewacja += (delta_y*pix2angle)/50; // do różnicy położeń kursora myszy
- // odpowiednio przeskalowane dane dla wygodniejszego sterowania
- }
- else if (status == 2) { // jeśli został wciśnięty prawy przycisk myszy
- R += (delta_R*pix2angle)/50;
- // odpowiednio przeskalowany promień dla wygodniejszego sterowania
- }
- glColor3f(1.0f, 1.0f, 1.0f);
- // Ustawienie koloru rysowania na biały
- viewer[0] = R*cos(azymut)*cos(elewacja);
- viewer[1] = R*sin(elewacja);
- viewer[2] = R*sin(azymut)*cos(elewacja);
- // Zmiana położenia obserwatora w zależności od ruchu myszy
- Egg(); // rysowanie jajka
- glFlush();
- // Przekazanie poleceń rysujących do wykonania
- glutSwapBuffers();
- }
- // funkcja zmieniająca model w zależności od wciśniętego klawisza
- void keys(unsigned char key, int x, int y)
- {
- if (key == 'p') model = 1;
- if (key == 'w') model = 2;
- if (key == 's') model = 3;
- // zmiana modelu za pomocą klawiszy p, w, s
- RenderScene(); // przerysowanie obrazu sceny
- }
- // Funkcja ustalająca stan renderowania
- void MyInit(void)
- {
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
- // Kolor czyszczący (wypełnienia okna) ustawiono na czarny
- }
- // Funkcja ma za zadanie utrzymanie stałych proporcji rysowanych
- // w przypadku zmiany rozmiarów okna.
- // Parametry vertical i horizontal (wysokość i szerokość okna) są
- // przekazywane do funkcji za każdym razem gdy zmieni się rozmiar okna.
- void ChangeSize(GLsizei horizontal, GLsizei vertical)
- {
- pix2angle = 360.0 / (float)horizontal; // przeliczenie pikseli na stopnie
- glMatrixMode(GL_PROJECTION);
- // Przełączenie macierzy bieżącej na macierz projekcji
- glLoadIdentity();
- // Czyszcznie macierzy bieżącej
- gluPerspective(70, 1.0, 1.0, 30.0);
- // Ustawienie parametrów dla rzutu perspektywicznego
- if (horizontal <= vertical)
- glViewport(0, (vertical - horizontal) / 2, horizontal, horizontal);
- else
- glViewport((horizontal - vertical) / 2, 0, vertical, vertical);
- // Ustawienie wielkości okna okna widoku (viewport) w zależności
- // relacji pomiędzy wysokością i szerokością okna
- glMatrixMode(GL_MODELVIEW);
- // Przełączenie macierzy bieżącej na macierz widoku modelu
- glLoadIdentity();
- // Czyszczenie macierzy bieżącej
- }
- // Główny punkt wejścia programu. Program działa w trybie konsoli
- void main(void)
- {
- glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
- glutInitWindowSize(1000, 1000);
- glutCreateWindow("Zad2 - jajko i zmiana położenia obserwatora");
- glutKeyboardFunc(keys);
- // Funkcja określająca, że funkcja keys będzie funkcją zwrotną
- // wywoływaną do obsługi klawiatury
- if (model == 1 || model == 2 || model == 3) {
- glutDisplayFunc(RenderScene);
- // Określenie, że funkcja RenderScene będzie funkcją zwrotną
- // (callback function). Będzie ona wywoływana za każdym razem
- // gdy zajdzie potrzeba przerysowania okna
- glutReshapeFunc(ChangeSize);
- // Dla aktualnego okna ustala funkcję zwrotną odpowiedzialną
- // za zmiany rozmiaru okna
- glutMouseFunc(Mouse);
- // Ustala funkcję zwrotną odpowiedzialną za badanie stanu myszy
- glutMotionFunc(Motion);
- // Ustala funkcję zwrotną odpowiedzialną za badanie ruchu myszy
- MyInit();
- // Funkcja MyInit() (zdefiniowana powyżej) wykonuje wszelkie
- // inicjalizacje konieczne przed przystąpieniem do renderowania
- glEnable(GL_DEPTH_TEST);
- // Włączenie mechanizmu usuwania niewidocznych elementów sceny
- glutMainLoop();
- // Funkcja uruchamia szkielet biblioteki GLUT
- }
- // w przypadku nieprawidłowej danej model na wejściu programu
- // zostanie on zamknięty po 5 sekundach
- else {
- std::cout << "Podano nieprawidlowe dane dla parametru model! Dostepne opcje: 1 - punkty, 2 - siatka, 3 - trojkaty.";
- Sleep(5000);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement