OpenGL - Resize: Breiteskalierungsproblem
-
Hallo,
ich bin gerade dabei, mein Windowsfenster mit OpenGL Resizen zu können, also dass sich die enthaltenen Elemente an die Fenstergröße anpassen.
Ich kann alles super resizen, bis auf, dass ich die Breite des Fensters nie auf einen kleineren Wert als die Höhe des Fensters bringen kann.
Wenn ich das mache, dann verschwindet mein angezeigtes Element sofort.
Wenn ich das Fenster dann wieder breiter zieh, erscheint es aufeinmal wieder (nicht stückfürstück, sondern "zack" ).Mein Code (möglichst OOP):
PS: Wenn ihr sonst noch Fehler findet, dann bitte Bescheid sagenstdafx.h:
// ========== stdafx.H ========== // // ========== INCLUDES ========== // #include <Windows.h> //###### OPEN_GL - INCLUDES ######// #include <gl\gl.h> #include <gl\glu.h> //###### OPEN_GL - LIBARIES ######// #pragma comment( lib, "opengl.lib" ) #pragma comment( lib, "glu.lib" ) #pragma comment( lib, "glut32.lib" )
opengl_init.cpp:
// ========== opengl_init.CPP ========== // #include "stdafx.h" #include "opengl_init.h" LRESULT CALLBACK OpenGL_Init::WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ case WM_DESTROY: PostQuitMessage(0); break; case WM_SIZE://nachricht wenn fenstergröße geändert wird opengl_resize_scene( LOWORD(lParam), HIWORD(lParam));//in LOWORD ist der width-wert nach dem resize gespeichert und in dem HIWORD-wert von lParam der height-wert break; default: return DefWindowProc (hWnd, msg, wParam, lParam); //wenn keine besonderen events von windows dann arbeitet die defaultwindowprozedur des windows break; } return 0; } LRESULT CALLBACK OpenGL_Init::StaticWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ OpenGL_Init* pOGL_Init;//Pointer auf unsere KLasse if(msg == WM_CREATE){//wenn createfunktion aufgerufen wird pOGL_Init = (OpenGL_Init*)( ((LPCREATESTRUCT) lParam)->lpCreateParams); //lParameter enthält die CreateSruktur(deren Werte = height,.....) SetWindowLongPtr(hWnd, GWL_USERDATA, (LONG_PTR)pOGL_Init);//Userdata = wichtige Informationen des Fensters; dier werte von pOGL_Init werden dahinein gesetzt } else{ pOGL_Init = (OpenGL_Init*) GetWindowLongPtr( hWnd, GWL_USERDATA);//hohlt sich die wichtigsten informationen des fesnters } return pOGL_Init->WndProc( hWnd, msg, wParam, lParam); } unsigned char OpenGL_Init::key_pressed(){ if(PeekMessage( &msg, NULL, NULL, NULL , PM_REMOVE)){//schaut ob in der messagefunktion etwas drinnen ist wenn nicht dann beendet sie sich wenn peekmessage eine messagefindet führt es das event aus, aber löscht es danach aus der messageschlange if ( msg.message == WM_QUIT || msg.message == WM_KEYDOWN){ //wenn die msgstruktur "einen messagewert" quit oder tastendruck bekommt return true; //gibt 1 zurück } //übersetzung der Message TranslateMessage( &msg); DispatchMessage( &msg); } return 0; } //##### OPENGLSETUP - FUNKTION#####// void OpenGL_Init::opengl_setup(){ memset( &pfd, 0, sizeof( pfd )); //setzt jeden Member von pfd auf null pfd.nSize = sizeof( PIXELFORMATDESCRIPTOR ); pfd.nVersion = 1; //Versionsnummer pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; //Pixel können auch transparenz bekommen pfd.cColorBits = 32; //32 FARBENBITS pfd.cDepthBits = 32;//32 TIEFENBITS pfd.cAlphaBits = 8; hDC = GetDC( hWnd ); //legt den device context des hauptfensters fest (verbindung zum hauptfenster) iFormat = ChoosePixelFormat( hDC, &pfd); //wägt das pixelformat der parameter gegeneinander ab SetPixelFormat ( hDC, iFormat, &pfd);//setzt das pixelformat von hDC auf das neue pixelformat hGLRC = wglCreateContext( hDC ); //erstellt es mit dem richtigen pixelformat wglMakeCurrent( hDC, hGLRC ); } bool OpenGL_Init::screen_setup( HINSTANCE hInst, int iCmdShow, int iWidth, int iHeight){ this->iWidth = iWidth; this->iHeight = iHeight; char szClassName[] = "MyWndClassEx"; char szWindowTitle[] = "Sterminio OpenGL-OOP Tutorial4"; WndClassEx.cbSize = sizeof( WNDCLASSEX); WndClassEx.style = CS_OWNDC; //classstyle_own_dc = zum zeichnen des fensters (damit nicht jedes window ein neues braucht wird einmal eins initialisiert) WndClassEx.cbClsExtra = NULL; WndClassEx.cbWndExtra = NULL; WndClassEx.hInstance = hInst; //gibt der klasse die instance der mainfunktion -> mainwindow WndClassEx.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH); WndClassEx.hIcon = LoadIcon ( NULL, IDI_APPLICATION); WndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW); WndClassEx.hIconSm = NULL; WndClassEx.lpfnWndProc = StaticWndProc;//WndProzedur WndClassEx.lpszMenuName = NULL; WndClassEx.lpszClassName = szClassName; //wenn das registrieren scheitert... if( !RegisterClassEx( &WndClassEx)){ MessageBox( NULL, "Fail to register WndClassEx", "Error", MB_OK | MB_ICONERROR); return false; } hWnd = CreateWindow(szClassName, szWindowTitle, WS_OVERLAPPEDWINDOW | WS_VISIBLE, //normaler windowsfenster style CW_USEDEFAULT, //x-position CW_USEDEFAULT, //y-position iWidth, //breite iHeight, //höhe NULL, NULL, hInst, NULL); //wenn kein fenster erstellt werden konnte if (!hWnd){ MessageBox( NULL, "Fail to create Window!", "Error", MB_OK | MB_ICONERROR); return false; } //ShowWindow(hWnd, iCmdShow); brauchen wir nicht mehr, da das opengl automatisch macht //UpdateWindow (hWnd); " " " } void OpenGL_Init::opengl_reset_scene(){ if(this->iWidth == 0){ iWidth = 1; } if(this->iHeight == 0){ iHeight = 1; } glViewport(0, 0, this->iWidth, this->iHeight);//von wo man auf das "geschehen" schaut (ecken = parameter) glMatrixMode( GL_PROJECTION); //für transformationsberechnungen glLoadIdentity();//vorm arbeitewn mit einer matrix sie hiermit "leeren" gluPerspective( 45.0f, this->iWidth/this->iHeight, 1.0f, 100.0f); //45.0f = grad in dem wir auf das "geschehen" schauen 3.Parameter MinfieldofView 4.Parameter Max-field_of_view glMatrixMode(GL_MODELVIEW);//geometrische transformationen glLoadIdentity(); glEnable(GL_DEPTH_TEST); //um tiefenzu erkennen (was verdeckt was) glClearColor(0.0f, 0.4f, 0.1f, 1.0f); } void OpenGL_Init::opengl_resize_scene(int iWidth, int iHeight){//durch die parameter arbeitet er hier mit den aktuallisierten größen if(iWidth == 0){ iWidth = 1; } if(iHeight == 0){ iHeight = 1; } glViewport(0, 0, iWidth, iHeight);//von wo man auf das "geschehen" schaut (ecken = parameter) glMatrixMode( GL_PROJECTION); //für transformationsberechnungen glLoadIdentity();//vorm arbeitewn mit einer matrix sie hiermit "leeren" gluPerspective( 45.0f, iWidth/iHeight, 1.0f, 100.0f); //45.0f = grad in dem wir auf das "geschehen" schauen 3.Parameter MinfieldofView 4.Parameter Max-field_of_view glMatrixMode(GL_MODELVIEW);//geometrische transformationen glLoadIdentity(); } bool OpenGL_Init::opengl_draw_scene(){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity();//gehe zum Ursprung (nicht bei jedem funktionsaufruf weiterverschieben sondern immer an den festgelegten ursprung) glTranslatef(0.0f, 0.0f, -10.0f);//verschiebt jede x kordinate +1 und y+1 glRotatef( 20, 1.0f, 0.0f, 0.0f); glRotatef( fAngle, 0.0f, 1.0f, 0.0f); glBegin( GL_QUADS );//um ein dreieck zu zeichnen //Front glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( -1.0f, 1.0f, 0.0f); //zeichnet einen Eckpunkt(Vertex) mit 3 Floatwerten glVertex3f( -1.0f, -1.0f, 0.0f); //zeichnet einen Eckpunkt(Vertex) mit 3 Floatwerten glVertex3f( 1.0f, -1.0f, 0.0f); //zeichnet einen Eckpunkt(Vertex) mit 3 Floatwerten glVertex3f( 1.0f, 1.0f, 0.0f); //zeichnet einen Eckpunkt(Vertex) mit 3 Floatwerten //Back glColor3f(0.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -2.0f); glVertex3f( 1.0f, -1.0f, -2.0f); glVertex3f( -1.0f, -1.0f, -2.0f); glVertex3f( -1.0f, 1.0f, -2.0f); //Right glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -2.0f); glVertex3f( 1.0f, 1.0f, -2.0f); //Left glColor3f(0.0f, 0.0f, 1.0f); glVertex3f( -1.0f, 1.0f, -2.0f); glVertex3f( -1.0f, -1.0f, -2.0f); glVertex3f( -1.0f, -1.0f, 0.0f); glVertex3f( -1.0f, 1.0f, 0.0f); //Top glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( -1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, -2.0f); glVertex3f( -1.0f, 1.0f, -2.0f); //Bottom glColor3f(1.0f, 0.0f, 0.0f); glVertex3f( -1.0f, -1.0f, -2.0f); glVertex3f( 1.0f, -1.0f, -2.0f); glVertex3f( 1.0f, -1.0f, 0.0f); glVertex3f( -1.0f, -1.0f, 0.0f); glEnd(); glBegin(GL_TRIANGLES); //Roof //front glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(0.0f, 2.7f, -1.0f); glColor3f(1.0f, 0.2f, 0.0f); glVertex3f( -1.0f, 1.0f, 0.0f); glColor3f(1.0f, 0.4f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); //Back glVertex3f(0.0f, 2.7f, -1.0f); glColor3f(0.0f, 0.4f, 0.0f); glVertex3f( 1.0f, 1.0f, -2.0f); glColor3f(1.0f, 0.4f, 0.0f); glVertex3f( -1.0f, 1.0f, -2.0f); //Right glVertex3f(0.0f, 2.7f, -1.0f); glColor3f(1.0f, 0.4f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glColor3f(0.4f, 0.4f, 0.0f); glVertex3f( 1.0f, 1.0f, -2.0f); //Left glVertex3f(0.0f, 2.7f, -1.0f); glColor3f(0.0f, 0.4f, 0.5f); glVertex3f( -1.0f, 1.0f, -2.0f); glColor3f(1.0f, 0.4f, 0.2f); glVertex3f( -1.0f, 1.0f, 0.0f); glEnd(); fAngle++; return true; }
opengl_init.h:
// ========== opengl_init.H ========== // class OpenGL_Init{ private: HWND hWnd; //um das fenster "auszuwählen MSG msg; //um nachrichten von windows zu empfangen (global) WNDCLASSEX WndClassEx; //fensterklasse //=============================// HDC hDC; //Device Context HGLRC hGLRC; //Handle gl Render Context PIXELFORMATDESCRIPTOR pfd; int iFormat; int iWidth; int iHeight; float fAngle; public: OpenGL_Init(){fAngle = 1.0f;} inline HDC get_hDC(){ return this->hDC;} unsigned char key_pressed(); LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static LRESULT CALLBACK StaticWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); void opengl_setup(); //######OPENGL_SETUP funktion deklaration void opengl_reset_scene();//vorbereitung zum zeichnen static void opengl_resize_scene(int iWidth, int iHeight);//funktion um beim resize das bild anzupassen bool screen_setup(HINSTANCE hInst,int iCmdShow, int iWidth, int iHeight); bool opengl_draw_scene();//zeichnen };
main.cpp:
// ========== MAIN_CPP ========== // #include "stdafx.h" #include "opengl_init.h" int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int iCmdShow){ OpenGL_Init OpenGL_Start; //erstellt ein objekt der klasse OpenGL_Init if (!OpenGL_Start.screen_setup( hInst, iCmdShow, 1280, 720)){ MessageBox(NULL, "Func: screen_setup() failed!", "Error!", MB_OK | MB_ICONERROR); return false; } OpenGL_Start.opengl_setup();//#####setuped OPENGL#########//// OpenGL_Start.opengl_reset_scene();//bereitet das Fenster für die Nutzung vor (Opengl....) while(true){ //keypressed = true wenn quit||keypressed, da return true; if(OpenGL_Start.key_pressed()){ break; //beendet die schleife } else{ if (!OpenGL_Start.opengl_draw_scene() ){//führt die OpenGL funktion aus break; } else{ SwapBuffers(OpenGL_Start.get_hDC() ); } } } return 0; }
Hoffe ihr könnt mir helfen und werdet von dem Code nicht "erschlagen".
Liebe Grüße
Tim
-
Ich vermute da mal eine Integerdivision:
gluPerspective( 45.0f, this->iWidth/this->iHeight, 1.0f, 100.0f);
-
Ach und gluPerspective erwartet aber einen GLdouble-Wert (also einen standart Double).
Also müsste ich doch einfach mittels (double) vor der Division das Ergebnis in Double umwandeln oder ?
Nur leider funktioniert das auch nichtGruß
Tim
-
silent12 schrieb:
Nur leider funktioniert das auch nicht
Das bedeuted?
-
Gleiches Problem wie vorher:
Objekt kann man skalieren (auch über das resizen der Breite), aber sobald die Breite des Fensters geringer ist als die Höhe, wird das Objekt nicht mehr dargestellt.
Gruß
Tim
-
Und wie sieht dein Aufruf von gluPerspective() jetzt aus?
-
Das
gluPerspective( 45.0f, (double)(this->iWidth/this->iHeight), 1.0f, 100.0f);
wird auch nicht funktionieren
silent12 schrieb:
Ach und gluPerspective erwartet aber einen GLdouble-Wert (also einen stan**** Double).
Also müsste ich doch einfach mittels (double) vor der Division das Ergebnis in Double umwandeln oder ?
Nur leider funktioniert das auch nichtGruß
Tim
-
Meine gluPerspective-Funktion sieht einmal so aus:
gluPerspective( 45.0f, (double)(this->iWidth/this->iHeight), 1.0f, 100.0f);
und einmal so:
gluPerspective( 45.0f, (double)(iWidth/iHeight), 1.0f, 100.0f);
Ich habe gemerkt, wenn ich die Breite erhöh, indem ich das Fenster mit der Maus in der Breite resize, dann beobachte ich folgendes:
- ein bisschen größer: Objekt mit einem Schlag ziemlich klein (aber Verhältnis der Seitenlängen stimmt)
-um einiges größer: Objekt wird wieder größer (Verhältnis stimmt nicht mehr: breitgezogen)
Warum kann das so nicht funktionieren ?
Gruß
Tim
-
@silent12
Aua.gluPerspective( 45.0f, static_cast<double>(iWidth)/iHeight, 1.0f, 100.0f);
-
silent12 schrieb:
Ich habe gemerkt, wenn ich die Breite erhöh, indem ich das Fenster mit der Maus in der Breite resize, dann beobachte ich folgendes:
- ein bisschen größer: Objekt mit einem Schlag ziemlich klein (aber Verhältnis der Seitenlängen stimmt)
-um einiges größer: Objekt wird wieder größer (Verhältnis stimmt nicht mehr: breitgezogen)
Warum kann das so nicht funktionieren ?
Weil du da zwei Ganzzahlen dividierst und das Ergebnis einer Ganzzahldivision eine Ganzzahl ist...
-
Mit Casten habe ichs davor schon probiert, aber damit klappt es auch nicht...
Dadurch wird das Objekt nicht skaliert, sondern das Objekt wird einfach wenn ich resize "abgeschnitten".
Das mit den Ganzzahlen habe ich mir gedacht, aber eine Lösung habe ich nicht gefunden, da es mit dem Casten ja auch nicht klappt...
Gruß
Tim
-
Natürlich klappt es mit Casten, wenn man es richtig macht.
(double)(iWidth/iHeight)
Das hier ist immer noch ein Ganzzahldivision, du castest nur das Ergebnis nach double. Was du willst ist, Dividend und/oder Divisor vor der Division in einen float zu casten, damit es eben eine Gleitkommadivision wird...
-
Um es nocheinmal zusammenzufassen:
Probiert habe ich bis jetzt: gluPerspective( 45.0f, (double)(iWidth/iHeight), 1.0f, 100.0f); gluPerspective( 45.0f, (double)(iWidth)/iHeight, 1.0f, 100.0f);//macht für mich keinen Sinn gluPerspective( 45.0f, static_cast<double>(iWidth/iHeight), 1.0f, 100.0f);
Ich verzweifel einfach an diesem Problem.
Habe noch keine großen Kenntnisse von C++ und OpenGL.
Wenn jemand möchte, kann er sich auch gerne per mail (pfeifletim@gmail.com) melden und dann mal per teamviewer drüber schauen.Gruß
Tim
-
mach das
gluPerspective( 45.0f, double(iWidth)/iHeight, 1.0f, 100.0f);//macht aber Sinn
-
Das Castet dann den ersten Wert und dadurch das Ergebnis gleich mit oder ?
Nur leider funktioniert das bei mir nicht...kann es sein, dass es an etwas anderem im Code liegt (Code auf Seite 1 vollständig )?Gruß
silent12
-
silent12 schrieb:
gluPerspective( 45.0f, (double)(iWidth)/iHeight, 1.0f, 100.0f);//macht für mich keinen Sinn
warum genau?
-
silent12 schrieb:
Nur leider funktioniert das bei mir nicht...
Ich hoffe, dass dir bald endlich mal klar wird, dass "funktioinert nicht" keine Basis ist, auf der wir dir helfen können...
-
Habe den Sinn dahinter jetzt verstanden (@//macht für mich keinen Sinn)
Tut mir leid meinte Natürlich:(@funktioniert nicht)
Dadurch wird das Objekt nicht skaliert, sondern das Objekt wird einfach wenn ich resize "abgeschnitten".
Also es wird in den linken Rand "hineingeschoben", ohne seine Größe zu ändern.