glViewport - resize - Objekte verzerren sich
-
Heyho,
ich habe ein GLFWWindow, das mit mehreren glViewports ausgestattet ist.
in diesen glViewports ist jeweils eine eigene Camera definiert.
Und dort befinden sich Objekte die unabhängig von einander manipuliert werden (scale, translate, rotate).
Wenn ich das Fenster vergrößer/verkleiner, berechne ich die Maße von jedem Viewport neu, damit die relative Position von den Viewports untereinander erhalten bleibt.Beispiel:
Ich habe einen Viewport in meinem Window
//main.cpp //..... // window ist ein GLFWWindow // xPos, yPos, width, height // initial 0 0 509 748 Viewport *angioVP = new Viewport(0, 0, window->getWidth()/2 -3, window->getHeight()-20); //....
in diesem Viewport befindet sich ein Objekt auf das ich eine 2D Image Textur ziehe
// 2DImage.cpp - init // Rechne ich mir aus, da mein Viewport Rechteckig ist, aber meine Textur Quadratisch sein soll, // wenn ich einfach -512 bis 512 angeben würde oder -1 bis 1 dann würde sich mein Objekt hier schon verzerren // 1.0f / breite des viewport * ( breite der Textur / 2) float relativeWidth = 1.0f/this->viewport->getWidth() * (this->dcmReader->getWidth()/2.0f); float relativeHeight = 1.0f/this->viewport->getHeight() * (this->dcmReader->getHeight()/2.0f); //first Triangle this->vertices->push_back(glm::vec3( relativeWidth, relativeHeight, 1)); this->vertices->push_back(glm::vec3(-relativeWidth, relativeHeight, 1)); this->vertices->push_back(glm::vec3(-relativeWidth, -relativeHeight, 1)); //second Triangle this->vertices->push_back(glm::vec3(-relativeWidth, -relativeHeight, 1)); this->vertices->push_back(glm::vec3( relativeWidth, -relativeHeight, 1)); this->vertices->push_back(glm::vec3( relativeWidth, relativeHeight, 1)); // .......
Dieses Objekt kann skaliert und translatiert werden
// 2DImage erbt von GLObject // GLObject.cpp void GLObject::translate(float transX, float transY, float transZ) { this->modelMatrix = glm::translate(this->modelMatrix, glm::vec3(transX, transY, transZ)); } //2DImage.cpp void 2DImage::scale(float factor) { this->modelMatrix = glm::scale(this->modelMatrix, glm::vec3(factor, factor, 1.0f)); }
Wenn ich nun mein Window resize, wird für jeden Viewport im Window folgende Funktion aufgerufen
void Viewport::resize(int xPos, int yPos, int width, int height) { this->xPos = xPos; this->yPos = yPos; this->width = width; this->height = height; }
in der do-while-(rendering) schleife von GLFW wird immer folgender code ausgeführt
// Window.cpp // do { // ...... // für jeden Viewport // Viewport.cpp glViewport(this->xPos, this->yPos, this->width, this->height); glScissor(this->xPos, this->yPos, this->width, this->height); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Code aus GLObject->draw() (z.B. glDrawArrays(GL_TRIANGLES, 0, 2*3); usw) // ... // wieder Window.cpp // ... // glfwSwapBuffers(this->window); // glfwPollEvents(); // } while(glfwWindowShouldClose(this->window) == 0 );
Meine Camera ist wie folgt Initialisiert.
Camera *cam = new Camera(); cam->lookAt(glm::vec3(0, 0, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); cam->ortho(-1.2f, 1.2f, -1.2f, 1.2f, 0.1f, 5.0f);
die Funktionen der Klasse Camera machen auch nichts anderes als die gleichnamigen funktionen von glm:: auf zu rufen.
Wo muss ich nun Ansetzen um zu verhindern, dass sich mein Objekt nach dem Window-resize verzerrt.
Die einzige möglichkeit, die mir eingefallen ist, ist das Objekt jedes mal zu löschen und neu zu Zeichnen um mir anhand des neuen Seitenverhältnisses vom Viewport die neuen Werte aus zu rechnen.
Allerdings denke ich, dass das zu Problemen bezüglich den vorgenommenen Translationen/skalierungen kommen kann.
Und ich bin mir sicher, dass es da noch einen besseren Weg geben muss...
Nur ich finde keinen
Grüße
Jango
-
JangoK schrieb:
Wo muss ich nun Ansetzen um zu verhindern, dass sich mein Objekt nach dem Window-resize verzerrt.
cam->ortho(-1.2f, 1.2f, -1.2f, 1.2f, 0.1f, 5.0f);
das seitenverhaeltnis der kamera sollte mit dem des fensters zu deiner virtuellen welt uebereinstimmen (klingt doch logisch, oder? ).
-
Ja,
das klang für mich auch ziemlich logisch.
Deshalb hatte ich das auch am Anfang so gemacht.
Allerdings hab ich es mit den Daten nicht geschafft etwas in mein Fenster rein zu kriegen.Wenn meine Ortho-Daten gleich dem Viewport sind, also:
// .... Viewport *angioVP = new Viewport(0, 0, window->getWidth()/2 -3, window->getHeight()-20); // .... cam->lookAt(glm::vec3(0, 0, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); cam->ortho(0, 0, window->getWidth()/2 -3, window->getHeight()-20, 0.1f, 5.0f); // ....
und mein Bild auf den relativen Koordinaten bleibt wie zuvor, sehe ich nichts.
Ich vermute, dass das daran liegt, dass mein Sichtfeld werte zwischen 0 und 500-700 annimmt.
und mein Objekt mit werten zwischen ca -1,1 und 1,1 gezeichet wird.Nehme ich dann allerdings die Original Daten des Objektes (male also von -512 bis 512)
sehe ich auch nichts.Falls das der Richtige weg sein soll, dann ist mein Verständnis für die Projektion wohl noch falsch Oo
Gruß
-
seiterverhaeltnis berechnet man mittels z.b.
width/height
-
Aber ich hab doch Orthogonalen View...
detail::tmat4x4<T> glm::gtc::matrix_transform::ortho (
T const & left,
T const & right,
T const & bottom,
T const & top,
T const & zNear,
T const & zFar )Da geb ich doch absolute an oder nicht?
Ok, habs gefunden - habe beim ändern gerade bei ortho die übergabe paramelter in der falschen reihenfolge angegeben.
Allerdings löst das das Problem mit der Verzerrung nicht.
Wenn ich resize wird aus meinem Quadrat immernoch ein Rechteck
-
Nimm als Basis ein Quadrat. Nun gibt es zwei Möglichkeiten.
Anhand des Seitenverhältnisses des Fensters plazierst du dieses Quadrat so:
1. dass man nie außerhalb des Quadrates sehen kann und an den zueinander kürzeren Fensterseiten etwas vom Quadrat verdeckt ist.
oder
2. dass man immer min. das ganze Quadrat sieht und an den weiter auseinander gehenden Fensterseiten über das Quadrat hinaussehen kann.
Hier die Variante 1:
glm::mat4 getOrthoInsideSquare(int resX, int resY, float zNear, float zFar) { float x = resX; float y = resY; if (x > y) { float portion = y / x; return glm::ortho(-1.0f, 1.0f, -portion, portion, zNear, zFar); } else if (x < y) { float portion = x / y; return glm::ortho(-portion, portion, -1.0f, 1.0f, zNear, zFar); } else { return glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, zNear, zFar); } }