ďťż

Ładny brzuch

Witam

Od pewnego czasu próbuję napisać dla ćwiczeń program rysujący różne funkcje na podstawie podanych współczynników. Traktuję to jako ćwiczenie, gdyż próbuję w sposób praktyczny ułożyć sobie podstawy OpenGL i programowania obiektowego, aby w przyszłości pogłębiać swoją dalszą wiedzę na jakichkolwiek fundamentach.

Z samą mechaniką nie powinno być problemów, a nawet jakby się pojawiły, to z tym bez problemu sobie poradzę. Natomiast mam inny, dosyć dziwny problem. Otóż ustawiłem sobie Viewport na cały ekran (także punkt (0,0) jest na środku ekranu) i chciałem narysować układ współrzędnych - z osiami, grotami i jednostkami. Same osie narysowało dobrze, natomiast w ogóle nie rysuje trójkątów (czyli grotów osi) i całej reszty (tam w kodzie nie ma jednostek na osi Y, są tylko na osi X - ale i tak się nie wyświetlają). Nie mówiąc już o samych funkcjach.

Z kolei, gdy dla testu narysowałem trójkąt o wierzchołkach w punktach (-20,-20), (-20, 20) i (20,20), wyskoczył mi gigantyczny trójkąt na połowę ekranu. Nie wiem, jak mam to rozumieć. Czyżby po narysowaniu osi współrzędnych OpenGL przesunął cały swój układ?

Próbowałem już różnych manewrów - komend glPushMatrix()/glPopMatrix(), glLoadIdentity(), zmiany bryły obcinania i nic. Zdaję sobie sprawę, że oglądanie mojego kodu do przyjemnych nie należy, ale być może ktoś wpadnie na jakiś pomysł. Moim zdaniem, błąd jest gdzieś w metodzie InitProjection() lub Render(). Jest to zapewne gdzieś nieodpowiednia wartość będąca moim niedopatrzeniem, ale siedzę nad tym już jakiś czas i nie mogę wymyślić.

Oto kod felernej klasy CGraphics:

class CGraphics // klasa graficzna (implementacja OpenGL) { private: enum // opcje menu { LINEAR, // funkcja liniowa QUADRATIC, // funkcja kwadratowa CUBIC, // funkcja wielomianowa trzeciego stopnia SINE, // sinusoida COSINE, // cosinusoida TANGENT, // tangensoida COTANGENT, // cotangensoida HOMOGRAPHIC, // funkcja homograficzna EXPONENTIAL, // funkcja wykładnicza LOGARITHM, // funkcja logarytmiczna EXIT // wyjście }; static void Keyboard (unsigned char key, int x, int y) { // obsługa klawiatury if (key == 27) // wyjście z programu { exit(EXIT_SUCCESS); } } static void SpecialKeys (int key, int x, int y) { // obsługa klawiszy funkcyjnych switch (key) // wybór klawisza funkcyjnego { // zmiana rodzaju funkcji case GLUT_KEY_F1: // funkcja liniowa g_rsFunction = RS_LINEAR; Render(); break; case GLUT_KEY_F2: // funkcja kwadratowa g_rsFunction = RS_QUADRATIC; Render(); break; case GLUT_KEY_F3: // funkcja wielomianowa trzeciego stopnia g_rsFunction = RS_CUBIC; Render(); break; case GLUT_KEY_F4: // sinusoida g_rsFunction = RS_SINE; Render(); break; case GLUT_KEY_F5: // cosinusoida g_rsFunction = RS_COSINE; Render(); break; case GLUT_KEY_F6: // tangensoida g_rsFunction = RS_TANGENT; Render(); break; case GLUT_KEY_F7: // cotangensoida g_rsFunction = RS_COTANGENT; Render(); break; case GLUT_KEY_F8: // funkcja homograficzna g_rsFunction = RS_HOMOGRAPHIC; Render(); break; case GLUT_KEY_F9: // funkcja wykładnicza g_rsFunction = RS_EXPONENTIAL; Render(); break; case GLUT_KEY_F10: // funkcja logarytmiczna g_rsFunction = RS_LOGARITHM; Render(); break; } } void InitProjection() // inicjalizacja "projekcji" { // ustalenie obszaru renderowania (punkt P=(0,0) jest w centrum) glViewport(0, 0, glutGet(GLUT_SCREEN_WIDTH), glutGet(GLUT_SCREEN_HEIGHT)); glMatrixMode(GL_PROJECTION); // tryb projekcji glLoadIdentity(); // macierz jednostkowa gluOrtho2D(0.0f, 0.0f, 0.0f, 0.0f); glutFullScreen(); // pełny ekran } static void Render() // funkcja renderująca { glClearColor( 0.2f, 0.2f, 0.4f, 1.0f ); // kolor tła glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // wyczyszczenie buforów glMatrixMode(GL_MODELVIEW); // tryb modelowania glLoadIdentity(); // macierz jednostkowa glEnable(GL_DEPTH_TEST); // włączony test głębi // narysowanie układu współrzędnych glColor3f(1.0f, 1.0f, 1.0f); // ustawienie koloru na biały (dla układu) glLineWidth(0.5f); // szerokość linii glBegin(GL_LINES); // osie X i Y glVertex2f(floor(-glutGet(GLUT_SCREEN_WIDTH)/2), 0.0f); glVertex2f(ceil(glutGet(GLUT_SCREEN_WIDTH)/2), 0.0f); glVertex2f(0.0f, floor(-glutGet(GLUT_SCREEN_HEIGHT)/2)); glVertex2f(0.0f, ceil(glutGet(GLUT_SCREEN_HEIGHT)/2)); glEnd(); glBegin(GL_TRIANGLES); glVertex2f(ceil(glutGet(GLUT_SCREEN_WIDTH)/2), 0.0f); glVertex2f(ceil(glutGet(GLUT_SCREEN_WIDTH)/2)-10.0f, 10.0f); glVertex2f(ceil(glutGet(GLUT_SCREEN_WIDTH)/2)-10.0f, -10.0f); glVertex2f(0.0f, ceil(glutGet(GLUT_SCREEN_HEIGHT)/2)); glVertex2f(10.0f, ceil(glutGet(GLUT_SCREEN_HEIGHT)/2)-10.0f); glVertex2f(-10.0f, ceil(glutGet(GLUT_SCREEN_HEIGHT)/2)-10.0f); glEnd(); glBegin(GL_LINES); // jednostki na osiach glVertex2f(1.0f, 2.0f); glVertex2f(1.0f, -2.0f); for (GLfloat i = 5; i <= (glutGet(GLUT_SCREEN_WIDTH)/2); i+=5) { glVertex2f(i, 2.0f); glVertex2f(-i, 2.0f); } glEnd(); // zmienne pomocnicze dla ustalaniu ilości pikseli okna GLint* r_iLeft = new GLint; // najmniejszy x GLint* r_iRight = new GLint; // największy x // najmniejszy i największy możliwy x *r_iLeft = static_cast<GLint>(floor(-glutGet(GLUT_SCREEN_WIDTH)/2)); *r_iRight = static_cast<GLint>(ceil(glutGet(GLUT_SCREEN_WIDTH)/2)); // rysowanie odpowiedniej funkcji glColor3f(1.0f, 1.0f, 0.0f); // kolor funkcji for (GLint i = *r_iLeft; i <= *r_iRight; ++i) { GLdouble* y = new GLdouble; // wartość dla danego argumentu switch (g_rsFunction) // liczenei wartości i narysowanie punktu { case RS_LINEAR: *y = g_dA * i + g_dB; break; case RS_QUADRATIC: *y = g_dA * (i*i) + g_dB * i + g_dC; break; case RS_CUBIC: *y = g_dA * (i*i*i) + g_dB * (i*i) + g_dC * i + g_dD; break; case RS_SINE: *y = g_dA * sin(g_dB * (i*PI/180) + g_dC) + g_dD; break; case RS_COSINE: *y = g_dA * cos(g_dB * (i*PI/180) + g_dC) + g_dD; break; case RS_TANGENT: *y = g_dA * tan(g_dB * (i*PI/180) + g_dC) + g_dD; break; case RS_COTANGENT: *y = g_dA * (1 / (tan(g_dB * (i*PI/180) + g_dC))) + g_dD; break; case RS_HOMOGRAPHIC: *y = (g_dA * i + g_dB) / (g_dC * i + g_dD); break; case RS_EXPONENTIAL: *y = g_dA * pow(g_dB, i + g_dC) + g_dD; break; case RS_LOGARITHM: *y = g_dA * (log(g_dC) / log(g_dB)) + g_dD; break; } glPointSize(1.0f); // ustalenie wielkości punktu glBegin(GL_POINTS); // narysowanie go glVertex2d(static_cast<GLdouble>(i), *y); glEnd(); delete y; // dealokacja y = NULL; } delete r_iLeft; // dealokacja zmiennych współrzędnych x r_iLeft = NULL; delete r_iRight; r_iRight = NULL; glFlush(); // skierowanie poleceń do wykonania glutSwapBuffers(); // zamiana buforów } static void Reshape (int width, int height) // zmiana rozmiaru okna { Render(); } static void Menu (int value) // obsługa menu podręcznego { switch (value) // wybór pozycji w menu { // zmiana rodzaju funkcji lub wyjście z programu case LINEAR: // funkcja liniowa g_rsFunction = RS_LINEAR; Render(); break; case QUADRATIC: // funkcja kwadratowa g_rsFunction = RS_QUADRATIC; Render(); break; case CUBIC: // funkcja wielomianowa trzeciego stopnia g_rsFunction = RS_CUBIC; Render(); break; case SINE: // sinusoida g_rsFunction = RS_SINE; Render(); break; case COSINE: // cosinusoida g_rsFunction = RS_COSINE; Render(); break; case TANGENT: // tangensoida g_rsFunction = RS_TANGENT; Render(); break; case COTANGENT: // cotangensoida g_rsFunction = RS_COTANGENT; Render(); break; case HOMOGRAPHIC: // funkcja homograficzna g_rsFunction = RS_HOMOGRAPHIC; Render(); break; case EXPONENTIAL: // funkcja wykładnicza g_rsFunction = RS_EXPONENTIAL; Render(); break; case LOGARITHM: // funkcja logarytmiczna g_rsFunction = RS_LOGARITHM; Render(); break; case EXIT: // wyjście exit (0); } } public: CGraphics() // konstruktor { // wartości początkowe g_rsFunction = RS_LINEAR; // rodzaj funkcji } ~CGraphics() // destruktor { } void InitPureGL() // główna funkcja inicjalizująca OpenGL { glutInitDisplayMode(GLUT_DOUBLE); // wybranie sposobu renderowania glutCreateWindow("Graphrator"); // utworzenie okna o danej nazwie InitProjection(); // inicjalizacja "projekcji" glutKeyboardFunc(Keyboard); // obsługa klawiatury glutSpecialFunc(SpecialKeys); // obsługa klawiszy funkcyjnych glutDisplayFunc(Render); // renderowanie glutReshapeFunc(Reshape); // zmiana rozmiaru okna // obsługa menu podręcznego // podmenu (Funkcje) int g_iSubMenu = glutCreateMenu(Menu); glutAddMenuEntry("liniowa", LINEAR); glutAddMenuEntry("kwadratowa", QUADRATIC); glutAddMenuEntry("wielomianowa (3. stopnia)", CUBIC); glutAddMenuEntry("sinusoida", SINE); glutAddMenuEntry("cosinusoida", COSINE); glutAddMenuEntry("tangensoida", TANGENT); glutAddMenuEntry("cotangesoida", COTANGENT); glutAddMenuEntry("homograficzna", HOMOGRAPHIC); #ifdef WIN32 glutAddMenuEntry("wykładnicza", EXPONENTIAL); #else glutAddMenuEntry("wykladnicza", EXPONENTIAL); #endif glutAddMenuEntry("logarytmiczna", LOGARITHM); // główne menu glutCreateMenu(Menu); glutAddSubMenu("Funkcje", g_iSubMenu); glutAddMenuEntry("Koniec", EXIT); // określenie przycisku myszki obsługującego menu podręczne glutAttachMenu (GLUT_RIGHT_BUTTON); glutMainLoop(); // główna pętla } };

Z góry dziękuję za jakąkolwiek pomoc. Pozdrawiam

/// EDIT:

Problem już (prawie) rozwiązany - okazało się, że zrobiłem nieprawidłowe założenie, iż 1 piksel ekranu to 1.0f. Cała szerokość ekranu ma 2.0f czyli od -1.0f do 1.0f.

Pozdrawiam
Użytkownik SceNtriC edytował ten post 29 grudzień 2007, 16:02


Poczytaj o OrthoMode i PerspectiveMode, na nehe sa jakiejs przyklady do tego, w orthomode podajesz wsp w pikselach a nie wsp 3d tak jak w perspectivemode. Na nehe jest do tego przyklad gdzies w lekcjach i jest to dokladnie to czego szukasz :)

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •