OpenGL: Kamera bewegen
-
Hallo,
Naechste Frage von mir
Ich habe ja jetzt meinen Wuerfel, jetzt moechte ich die Kamera um alle 3 Achsen rotieren. Mein Problem liegt dabei, dass ich es nicht hinbekomme, die Kamera um ihre lokalen Achsen zu rotieren. Wenn ich bspw. die Kamera um 45 Grad Rolle, sind Links/Rechts mit Oben/Unten Rotationen ploetzlich vertauscht. Rolle ich um 90 Grad, so sind die Vorzeichen verkehrt. Ohne Rollen stimmen die Rotationen nach mehreren konsekutiven Rotationen auch nicht mehr.Ich habe schon so viel probiert, dass ich gar nicht mehr weiss, was ich alles probiert habe. Hier mein Code:
#include <cmath> #include <iostream> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include "error.hpp" #include "gl.hpp" #include "shader.hpp" #include "shader_list.hpp" #include "shader_program.hpp" #include "types.hpp" #include "buffer.hpp" #include "stopwatch.hpp" glfloat const cube_vertices[] { 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, }; glubyte const cube_indices[] { 0, 2, 1, 0, 3, 2, 0, 5, 4, 0, 1, 5, 0, 4, 7, 0, 7, 3, 6, 3, 7, 6, 2, 3, 6, 5, 1, 6, 1, 2, 6, 7, 4, 6, 4, 5, }; glm::mat4 from_rot_pos(glm::mat3 rot, glm::vec3 pos) { return glm::mat4 { rot[0][0], rot[0][1], rot[0][2], 0.0f, rot[1][0], rot[1][1], rot[1][2], 0.0f, rot[2][0], rot[2][1], rot[2][2], 0.0f, pos[0], pos[1], pos[2], 1.0f, }; } glm::mat3 rotate_axis(glfloat angle, glm::vec3 axis) { //std::cout << axis.x << ',' << axis.y << ',' << axis.z << '\n'; auto sin = std::sin(angle); auto cos = std::cos(angle); auto x = axis.x; auto y = axis.y; auto z = axis.z; auto omc = 1 - cos; return glm::mat3 { x * x * omc + cos, x * y * omc - z * sin, x * z * omc + y * sin, x * y * omc + z * sin, y * y * omc + cos, y * y * omc - x * sin, x * z * omc - y * sin, y * z * omc + x * sin, z * z * omc + cos, }; } int main() { int const width = 1024; int const height = 768; create_context(width, height, "0 fps"); glEnable(GL_CULL_FACE); shader_list l; l += shader("test.vs", shader_type::vertex); l += shader("test.fs", shader_type::fragment); shader_program sp(l); gluint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); buffer cube_vertex_buffer(cube_vertices, sizeof cube_vertices, GL_ARRAY_BUFFER); buffer cube_index_buffer(cube_indices, sizeof cube_indices, GL_ELEMENT_ARRAY_BUFFER); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(glfloat), nullptr); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(glfloat), reinterpret_cast<void*>(4 * sizeof(glfloat))); glClearColor(0.5f, 0.5f, 0.5f, 10.f); auto uf_proj_cam_mat = sp.uniform("proj_cam_mat"); auto uf_obj_transf_mat = sp.uniform("obj_transf_mat"); auto projection_matrix = glm::perspective(90.0f, static_cast<glfloat>(width) / height, 0.1f, 20.0f); glm::vec3 campos; glm::mat3 camrot; glm::mat4 cube = glm::translate(glm::mat4{}, glm::vec3{ 0.0f, 0.0f, -2.0f }); glfloat const camera_movement_speed = 1.0f; glfloat const camera_rotation_speed = 1.0f; //glfloat const cube_rotation_speed = 50.0f; stopwatch<> sw; glfloat prev_fps; while(!glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED)) { check_errors(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); auto proj_cam_mat = projection_matrix * from_rot_pos(camrot, campos); glUniformMatrix4fv(uf_proj_cam_mat, 1, GL_FALSE, &proj_cam_mat[0][0]); glUniformMatrix4fv(uf_obj_transf_mat, 1, GL_FALSE, &cube[0][0]); glDrawElements(GL_TRIANGLES, sizeof cube_indices / sizeof *cube_indices, GL_UNSIGNED_BYTE, nullptr); glfwSwapBuffers(); auto elapsed = duration_cast<glfloat>(sw.tick()); auto fps = static_cast<unsigned>(1.0f / elapsed); if(fps != prev_fps) { auto title = std::to_string(fps) + " fps"; glfwSetWindowTitle(title.c_str()); prev_fps = fps; } //cube = glm::rotate(cube, elapsed * cube_rotation_speed, glm::vec3{ 0.0f, 1.0f, 0.0f }); auto camera_translation = elapsed * camera_movement_speed; auto camera_rotation = elapsed * camera_rotation_speed; if(glfwGetKey(GLFW_KEY_UP)) campos += glm::vec3{ 0.0f, 0.0f, camera_translation }; if(glfwGetKey(GLFW_KEY_DOWN)) campos += glm::vec3{ 0.0f, 0.0f, -camera_translation }; if(glfwGetKey(GLFW_KEY_LEFT)) campos += glm::vec3{ camera_translation, 0.0f, 0.0f }; if(glfwGetKey(GLFW_KEY_RIGHT)) campos += glm::vec3{ -camera_translation, 0.0f, 0.0f }; //auto rot = glm::vec3{ camrot[0][0], camrot[0][1], camrot[0][2] }; if(glfwGetKey('W')) camrot *= rotate_axis(camera_rotation, glm::normalize(camrot * glm::vec3{ 1.0f, 0.0f, 0.0f })); if(glfwGetKey('S')) camrot *= rotate_axis(-camera_rotation, glm::normalize(camrot * glm::vec3{ 1.0f, 0.0f, 0.0f })); if(glfwGetKey('A')) camrot *= rotate_axis(camera_rotation, glm::normalize(camrot * glm::vec3{ 0.0f, 1.0f, 0.0f })); if(glfwGetKey('D')) camrot *= rotate_axis(-camera_rotation, glm::normalize(camrot * glm::vec3{ 0.0f, 1.0f, 0.0f })); if(glfwGetKey('Q')) camrot *= rotate_axis(camera_rotation, glm::normalize(camrot * glm::vec3{ 0.0f,0.0f, 1.0f })); if(glfwGetKey('E')) camrot *= rotate_axis(-camera_rotation, glm::normalize(camrot * glm::vec3{ 0.0f,0.0f, 1.0f })); } destroy_context(); }
Ich hoffe, ihr koennt mir weiterhelfen.
Mit freundlichen Gruessen,
Der Kellerautomat
-
Hallo
In OpenGL bewegt man keine Kamera sondern den Raum.
Bin mir auch nicht ganz sicher wieso bei Dir Sinus Werte auftauchen,
eigentlich managed OpenGL das unter der Haube ganz gut
weil so Dinge wie Rotation über die Befehle der Graphikkarte erledigt werden.Hier ist mal ein Beispiel
http://nehe.gamedev.net/tutorial/loading_and_moving_through_a_3d_world/22003/Viel Spass
-
Aber das ist veraltetes OpenGL, im modernen (ab 3.3 aufwärts) gibt es die Matrix-Funktionen nicht mehr.
Edit: Vielleicht hilft das weiter: http://ogldev.atspace.co.uk/www/tutorial15/tutorial15.html
-
pVoid: Aua. Und dann kommt da auch noch so ein Tutorial aus der vor-vorletzten Version.
-
Kellerautomat schrieb:
Mein Problem liegt dabei, dass ich es nicht hinbekomme, die Kamera um ihre lokalen Achsen zu rotieren. Wenn ich bspw. die Kamera um 45 Grad Rolle, sind Links/Rechts mit Oben/Unten Rotationen ploetzlich vertauscht. Rolle ich um 90 Grad, so sind die Vorzeichen verkehrt. Ohne Rollen stimmen die Rotationen nach mehreren konsekutiven Rotationen auch nicht mehr.
So funktioniert das nunmal. Wenn du rotierst, rotieren die lokalen Achsen mit. Erklär uns doch mal, was für eine Art von Bewegung du genau erreichen willst.
pVoid schrieb:
In OpenGL bewegt man keine Kamera sondern den Raum.
Wo liegt der Unterschied?
-
Ich dachte auch mal es müssten immer die neusten Shader sein..
..und dann kamen Smartphones ^^Nach den Smartphones dann WebGL *graus*
Viel Spass
-
dot schrieb:
pVoid schrieb:
In OpenGL bewegt man keine Kamera sondern den Raum.
Wo liegt der Unterschied?
Z.b. darin das wie KellerAutomat beschreibt sich die Richtungen scheinbar willkürlich ändern weil allers invers verläuft.
Viel Spass
-
dot schrieb:
So funktioniert das nunmal. Wenn du rotierst, rotieren die lokalen Achsen mit. Erklär uns doch mal, was für eine Art von Bewegung du genau erreichen willst.
Na ja. Mit vertauscht meint er sicherlich, dass die Kamera sich dann nicht mehr nach "links" dreht wenn er A drückt. Insofern ändern sich die Achsen um die er rotiert ja gerade nicht.
-
Wie gesagt - einen Würfel vor einer Kamera auf den Kopf zu stellen
ändert nichts daran wie der Betrachter den Würfel drehen könnte.Stellt man allerdings die Welt/Raum auf den Kopf,
dann sind oben, unten, links, rechts vertauscht..
..dasselbe passiert wenn man die Welt seitwärts dreht.
-
Um das abzuschließen und zum eigentlichen Thema zurückzukehren: Worauf ich hinaus wollte ist, dass die Bewegung der Kamera und die inverse Bewegung der Welt rein prinzipiell nicht voneinander unterscheidbar und beide Interpretationen damit gleich gut sind.
-
cooky451 schrieb:
pVoid: Aua. Und dann kommt da auch noch so ein Tutorial aus der vor-vorletzten Version.
Hehe dann reich mal den Code für Tesselation Shading auf Smartphones rüber
Schon erstaunlich das dieses "veraltete Tutorial" im Download Bereich 30 IDEs/Compiler/Betriebssysteme/Programmiersprachen unterstützt, oder ? ^^
Nicht jeder OpenGL Einsteiger ist Spieleprogrammierer,
dem es egal sein kann, ob der blau-glühende Avatar
auf anderen Plattformen/älteren Rechnern nun auch wirklich glüht.Viel Spass
-
Auch auf Smartphones ist die fixed-function Pipeline veraltet...
-
Hier war vorher ein Link auf ein englisches Forum
in dem es sinngemäss hiess
"bei mehr als 1 mio Vertices wird man naturgemäss sowieso schnellere Funktionen benutzen"
-
Ja, da steht genau das was ich geschrieben habe noch mal, OpenGL ES 2.0 kennt die fixed-function Pipeline nicht einmal mehr. So.. what's your point?
Edit: Jetzt haste alles gelöscht..
-
cooky451 schrieb:
Ja, da steht genau das was ich geschrieben habe noch mal, OpenGL ES 2.0 kennt die fixed-function Pipeline nicht einmal mehr. So.. what's your point?
Edit: Jetzt haste alles gelöscht..Du unterstellst hier (wie schon in Deinen vorherigen Postings)
Dinge die so nicht gesagt wurden.Das im 1. Post verlinkte Beispiel war wie die Einleitung erkentlich machte
auf die Kamera bezogen und wie man das (mit eben jenem Code den KellerAutomat verwendet hat) realisiert, Kernaussage war - In OpenGL gibts keine Kamera, wenn muss man die selber implementieren.Auf Deine "vor-vor-version" Aussage hab ich Dir mitgeteilt das Dinge sich wiederholt haben, was nun einmal so war, wodurch "alte" Versionen dann plötzlich doch nicht mehr so alt waren..
Und der Wink mit Zaunpfeiler das es eben ein komplettes Versionschaos gibt
hast Du mit dem obigen Quote "gekontert".Fakt ist,
weder bekommst Du die neuesten Shader auf Deinem Smartphone zum Laufen,
noch ist die Welt GL 2.0 frei (und wird s so schnell auch nicht werden).Und damit war s das für mich weil diese "veraltet" Debatte einfach zu nichts führt
-
Also, ich will, dass meine Kamera immer nach Links/Rechts rotiert, wenn ich A/D druecke, nach Oben/Unten bei W/S und rollen ueber Q/E, also ein lokale Koordinatensystem. Genau das ist aber nicht der Fall.
-
pVoid schrieb:
Kernaussage war - In OpenGL gibts keine Kamera, wenn muss man die selber implementieren.
Was extrem sinnlos war, weil Kellerautomat das offensichtlich bereits verstanden hat. (Er hat ja schon eine Kamera selbst implementiert, sie funktioniert nur nicht.)
pVoid schrieb:
Und der Wink mit Zaunpfeiler das es eben ein komplettes Versionschaos gibt
Es gibt kein komplettes Versionschaos und dass man auf Smartphones keine Tessellation-Shader bekommt hat nichts damit zu tun, dass dein verlinktes Tutorial auf der fixed-function Pipeline aufbaut, die er nicht benutzt, die wie bereits erwähnt auf so ziemlich jedem Gerät der Welt völlig veraltet ist, und die ihm deswegen auch kein Stück weiter hilft.
-
in OpenGL gibt es keine Kamera, aber in vielen Applikationen gibt es eine Kamera, die mit Hilfe von OpenGL implementiert wird. die Frage ist nun, wie implementiere ich mit OpenGL eine Kamera
wenn man sich wie in der fixed Pipeline mit einer Projektionsmatrix in festen Weltkoordinaten bewegt, verwendet man für die Kamera die Winkel Heading (Yaw), Pitch und Roll. diese müssen in der richtigen Reihenfolge multipliziert werden, weil man sonst einen Drehwurm bekommt
http://www.google.de/#hl=de&sclient=psy-ab&q=opengl+heading+pitch+roll
-
Scheinbar kann Kellerautomat nicht darauf hoffen, hier noch mal Hilfe zu bekommen.
-
ich habe mir den Programmcode nicht so im Detail angesehen. aber die Fehlerbeschreibung klingt so, als würde er Heading, Pitch und Roll in der falschen Reihenfolge multiplizieren.