Libgdx: PerspectiveCamera bewegen ohne die Rotation zu ignorieren

  • Java
  • Libgdx: PerspectiveCamera bewegen ohne die Rotation zu ignorieren

    Grüß euch ;)

    Wieder mal seit langen eine Frage meinerseits. Seid ich für die Uni ein Spiel für Android programmieren muss, habe ich wieder etwas Lust auf Spieleentwicklung bekommen. Und zwar versuche ich zurzeit ein kleines 3d Spiel zu entwickeln, welches ähnlich diesem Spiel hier ausschauen soll: store.steampowered.com/app/569480/Kingdoms_and_Castles/

    Bin relativ neu in der 3d Welt und habe gerade Schwierigkeiten folgendes abzubilden:
    Ich habe eine PerspectiveCamera definiert, welche die position 100, 200, 100 besitzt. Somit wird die "Karte" rotiert angezeigt. Nun soll sich die Kamera aufgrund von einer Touchbewegung bewegen. Soweit so gut - und es funktioniert sogar ein wenig. Schaut wie folgt aus (Bild: example1):

    Die Bewegung folgt nun "leider" auf den Axen (x und z), was bei einer 0 Rotation korrekt wäre, aber leider nicht bei der aktuellen rotation. Das Objekt befindet sich somit bei einer Bewegung von rechts nach links rechtsunten (example2), welches sich aber rechts mittig befinden soll (example3):

    Mein Code ist folgender:

    Java-Quellcode

    1. // camera init
    2. camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    3. camera.position.set(100f, 200f, 100f);
    4. camera.lookAt(0, 0, 0);
    5. camera.near = 1f;
    6. camera.far = 3000f;
    7. camera.update();
    8. // moving
    9. float d = Gdx.graphics.getDeltaTime();
    10. float dX = (float) (screenX - dragX);
    11. float dY = (float) (screenY - dragY);
    12. dragX = screenX;
    13. dragY = screenY;
    14. Vector3 tmpV = new Vector3().add(-dX, 0, -dY).scl(d).scl(10);
    Alles anzeigen

    Beim Code wird quasi nur x und y verschoben, welches aber bei einer Rotation eben nicht korrekt ist. Ich krieg zwar von der Camera diverse Rotations vektoren, kann aber mit diesem leider nicht viel anfgangen. Hat da jemand von euch Ideen oder ähnliches schon gemacht? Da sowas ja "quasi" jedes Framework ähnlich behandel muss dachte ich mir ich frag mal euch.

    Danke
    Rodrog
    Bilder
    • example1.png

      12,68 kB, 611×348, 58 mal angesehen
    • example2.png

      11,15 kB, 603×331, 43 mal angesehen
    • example3.png

      11,83 kB, 596×333, 48 mal angesehen
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Ergo: Je mehr Käse, desto weniger Käse.
  • Was du brauchst ist das Kreuzprodukt zwischen deinem Kamera forward vektor und up-vektor.
    Dieses wird dir einen Vektor im Raum geben der (je nach dem ob du AxB oder BxA rechnest) nach "links" oder "rechts" gerichtet sein wird. (relativ zur kameraperspektive)

    Das Kreuzprodukt:


    Was du dann machen kannst ist diesen vektor dann mit einem Wert zu multiplizieren (den du z.B: von der Mausbewegung am Bildschirm ausrechnest) und diesen addierst du dann zu deinen kamerakoordinaten.
    Das ermöglicht dir die Bewegung auf der x-achse aus der sicht der Kamera.

    Für die Y-achse machst du dasselbe blos da kannst du gleich den Up-vektor der kamera verwenden da dieser schon gegeben ist. (Musst kein kreuzprodukt mehr rechnen.)

    Pseudocode schaut in etwa so aus:

    Quellcode

    1. //movement auf der x-achse
    2. Vector3 sideVector = cross(cameraForward,cameraUp);//cross product
    3. sideVector = normalize(sideVector);//cross product muss normalisiert werden da dieses keinen Einheitsvektor zurückgibt.
    4. float mX = mouse_previous_x - mouse_current_x;//relative mouse movement
    5. float mY = mouse_previous_y - mouse_current_y;//relative mouse movement
    6. //cameraTransform ist deine 3D koordinate der Kamera
    7. camera.transform += sideVector*mX + cameraUp*mY;
    Kann sein dass die Bewegung auf einer der Achsen spiegelverkehrt sein wird. In dem Fall multipliziere mX oder mY (je nachdem was betroffen ist) mit -1.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von LEWA ()

  • Super danke. Hab ähnliches bereits gefunden, jedoch hilft mir der Pseudocode hier sehr gut. Ich werd das die Tage mal ausprobieren und mich sonst bei Problemen noch melden ;)


    P.S.: Da soll mal jemand sagen, das man Vector und Matrizen Rechnung nie mehr im Leben braucht ;)
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Ergo: Je mehr Käse, desto weniger Käse.
  • Sorry für den Doppelpost, bin mir aber nicht sicher ob sonst das Thema erneuert wird und es dadurch untergeht.. Falls doch, weiß ich das dann demnächst ;)

    Lewa: Jetzt funktionierts schon ziemlich gut, jedoch ist mir aufgefallen das sich die Y Position mitbewegt, was aber quasi immer die gleiche sein sollte. (Ich könnte als workaround diese einfach immer auf den Standard setzen, aber damit wär ich nicht so zufrieden)

    Mein Code ist jetzt folgender:

    Java-Quellcode

    1. @Override
    2. public boolean touchDragged(int screenX, int screenY, int pointer) {
    3. if (pointer != 0) return false; // only allow 1 touch point
    4. float d = Gdx.graphics.getDeltaTime();
    5. float dX = (float) (screenX - dragX);
    6. float dY = (float) (screenY - dragY);
    7. dragX = screenX;
    8. dragY = screenY;
    9. Vector3 camUp = new Vector3(camera.up);
    10. Vector3 tmpV2 = new Vector3(camera.direction).crs(camUp).nor().scl(dX * -1);
    11. Vector3 tmpV1 = camUp.scl(dY);
    12. camera.translate(tmpV1.add(tmpV2).scl(d * CAMERA_SPEED));
    13. return true;
    14. }
    Alles anzeigen
    Ich bin zwar kein Vector experte, aber ich denke das diese Berechnungen ziemlich viel CPU in Anspruch nehmen, gibts da noch möglichkeiten diese Performanter zu gestalten? Ich dachte mir nur das man quasi diverse Werte sich merkt, weil diese sich nie verändern, ob das aber Sinn macht kann ich jetzt noch nicht sagen.

    Ich frage deshalb weil ich die App auf einem relativen altem handy (Huawaii P8 lite) ausgeführt habe und es ab und zu große Sprünge gegeben hat. Auf einem neueren (Huawaii P10 lite) ging es ziemlich gut.

    Mfg und danke
    Rodrog
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Ergo: Je mehr Käse, desto weniger Käse.
  • Wenn 2 cross products und ein paar vektoradditionen die pro updateloop aufgerufen werden zu Performanceproblemen führen sollen, dann frage ich mich wie du überhaupt ein Spiel auf der jeweiligen platform ausführen möchtest. :P
    Das sind bei weitem keine aufwendigen kalkulationen die der CPU irgendwelche probleme bereiten sollten. (Falls du Performanceeinbrüche hast dann würde ich das genauer Benchmarken um zu prüfen von welchen instruktionen genau diese verursacht werden.)

    Rodrog schrieb:

    Lewa: Jetzt funktionierts schon ziemlich gut, jedoch ist mir aufgefallen das sich die Y Position mitbewegt, was aber quasi immer die gleiche sein sollte. (Ich könnte als workaround diese einfach immer auf den Standard setzen, aber damit wär ich nicht so zufrieden)
    Was genau meinst du mit der mitbewegung der Y position? Wenn du deine kamera nur auf der X-achse bewegen möchtest, dann addierst du einfach nicht den Y vektor zur translation welchen du mit dem Cross product berechnet hast.

  • LEWA schrieb:

    Wenn 2 cross products und ein paar vektoradditionen die pro updateloop aufgerufen werden zu Performanceproblemen führen sollen, dann frage ich mich wie du überhaupt ein Spiel auf der jeweiligen platform ausführen möchtest.
    Das sind bei weitem keine aufwendigen kalkulationen die der CPU irgendwelche probleme bereiten sollten. (Falls du Performanceeinbrüche hast dann würde ich das genauer Benchmarken um zu prüfen von welchen instruktionen genau diese verursacht werden.)
    Sehr gut ^^ Ich werd demnächst versuchen ein wenig weitere "features" einzubauen um weitere infos über die performance zu erhalten.

    Werde demnächst die Zeiten mitmessen um zu schauen was diese "Sprünge" verursachen.

    Alles in allem funktionierts und somit ist das Thema geschlossen. Die Y Koordinate bei der Addition wird jetzt einfach immer auf 0 gesetzt ;) Danke für die Hilfe :sauf:
    Je mehr Käse, desto mehr Löcher.
    Je mehr Löcher, desto weniger Käse.
    Ergo: Je mehr Käse, desto weniger Käse.