2016-07-12 27 views
0

Das Spiel ist ein Top-Down-2D-Raumschiff Spiel - denken Sie an "Asteroiden".Rotierende 2D-Kamera zum Raumschiff in OpenGL (OpenTK)

Box2Dx ist die Physik-Engine, und ich erweiterte das enthaltene DebugDraw, basierend auf OpenTK, um zusätzliche Spielobjekte zu zeichnen. Bewegen Sie die Kamera so, dass sie immer auf dem Schiff des Spielers zentriert ist und das Ein- und Auszoomen perfekt funktioniert. Allerdings muss die Kamera unbedingt mit dem Schiff drehen, damit es immer in die gleiche Richtung zeigt. Das heißt, das Schiff scheint in der Mitte des Bildschirms eingefroren zu sein und der Rest der Spielwelt dreht sich um es herum, während es sich dreht.

Ich habe versucht, Codebeispiele anzupassen, aber nichts funktioniert. Das Beste, was ich erreichen konnte, ist ein verzerrtes und abgeschnittenes Rendering.

Render-Schleife:

 // Clear. 
     Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); 

     // other rendering omitted (planets, ships, etc.) 

     this.OpenGlControl.Draw(); 

Ansicht aktualisieren - Zentren auf Schiff und sollte drehen den Winkel anzupassen. Denn jetzt, ich versuche es einfach zu drehen, um einen beliebigen Winkel für ein Proof of Concept, aber keine Würfel:

public void RefreshView() 
    { 
     int width = this.OpenGlControl.Width; 
     int height = this.OpenGlControl.Height; 

     Gl.glViewport(0, 0, width, height); 

     Gl.glMatrixMode(Gl.GL_PROJECTION); 
     Gl.glLoadIdentity(); 

     float ratio = (float)width/(float)height; 

     Vec2 extents = new Vec2(ratio * 25.0f, 25.0f); 
     extents *= viewZoom; 

     // rotate the view 
     var shipAngle = 180.0f; // just a test angle for proof of concept 
     Gl.glRotatef(shipAngle, 0, 0, 0); 

     Vec2 lower = this.viewCenter - extents; 
     Vec2 upper = this.viewCenter + extents; 

     // L/R/B/T 
     Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y); 

     Gl.glMatrixMode(Gl.GL_MODELVIEW); 
    } 
Jetzt

, bin ich natürlich dieses Unrecht zu tun. Grade von 0 und 180 werden es mit der rechten Seite nach oben halten oder es spiegeln, aber jeder andere Grad wird es hinein/hinaus zoomen oder nur zu Schwarzheit führen, nichts gerendert. Im Folgenden sind Beispiele:

Wenn Schiff Winkel 0.0f ist, dann Spielwelt ist wie erwartet: enter image description here

Grad 180.0f vertikal dreht ... vielversprechend scheint: enter image description here

Grad 45 zoomt heraus und rotiert überhaupt nicht ... das ist seltsam: enter image description here

Grad von 90 kehrt alles schwarz zurück. Wenn Sie nie schwarz gesehen haben: enter image description here

Bitte helfen Sie!

+1

https: //www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml scheint anzuzeigen, dass die Argumente 2-4 von 'glRotatef' der Vektor ist, um den Sie rotieren. Wenn Sie '0, 0, 0 'eingeben, würde ich vermuten, dass Ihr Verhalten nicht definiert ist. Hast du stattdessen '0, 0, 1' probiert? (Angenommen, die Tiefe liegt in der Z-Achse) – pingul

+0

Sie wenden die Drehung auf den Projektionsmatrixstapel an. Außerdem sollte die veraltete feste Funktionspipeline nicht mehr verwendet werden. Wenn es keinen guten Grund gibt, es zu verwenden, bleiben Sie beim Core-Profil. – BDL

Antwort

0

Erstens sind die 2-4 Argumente die Achse, also bitte geben Sie sie richtig an, wie von @pingul angegeben.

Wichtiger ist, dass die Rotation auf die Projektionsmatrix angewendet wird.

// L/R/B/T 
    Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y); 

In dieser Zeile wird Ihre orthogonale 2D Projektionsmatrix mit der vorherigen Rotation multipliziert und auf Ihre Projektionsmatrix angewendet. Was ich glaube ist nicht was du willst.

Die Lösung wäre Ihre Rotation Anruf an einen Ort nach dem Model-View-Matrix-Modus ausgewählt wird bewegen wird, wie weiter unten

// L/R/B/T 
    Glu.gluOrtho2D(lower.X, upper.X, lower.Y, upper.Y); 

    Gl.glMatrixMode(Gl.GL_MODELVIEW); 

    // rotate the view 
    var shipAngle = 180.0f; // just a test angle for proof of concept 
    Gl.glRotatef(shipAngle, 0.0f, 0.0f, 1.0f); 

Und jetzt werden Ihre Drehungen auf den Model-View-Matrix-Stapel angewandt werden. (Ich glaube, das ist der Effekt, den Sie wollen). Beachten Sie, dass glRotatef() eine Rotationsmatrix erstellt und diese mit der Matrix am Anfang des ausgewählten Stapelstapels multipliziert.

Ich würde Ihnen auch dringend empfehlen, von der festen Funktionspipeline wegzukommen, wenn möglich, wie von @BDL vorgeschlagen.