2014-04-13 12 views
5

Ich habe Probleme, das Sichtfeld der Perspektive Kamera in libGDX zu verstehen (oder vielleicht sind meine Berechnungen falsch).libGDX - Perspektive Kamera und Sichtfeld

Ich möchte eine Box (zum Beispiel 800px breit, 480px hoch und 20px tief) zeichnen. Die Box wird zwischen x- und y-Achse platziert (mit anderen Worten: die Breite auf der x-Achse und die Höhe auf der y-Achse). Jetzt möchte ich hinter der Box auf der X-Achse (Kameraposition) stehen und so in eine Richtung schauen, dass ich die Box auf meiner ganz rechten Bildschirmseite sehe. ich einige Skizzen gemacht:

drawing the box

camera on x-axis, looking at box

box should appear on right side

Am letzten Skizze, die Box auf der rechten Seite des Sichtfeldes.

Darüber hinaus muss die Höhe der Box genau in den Bildschirm passen. Mit anderen Worten: die obere Kante der Box muss auf meinem Bildschirm oben sein und die untere Kante der Box muss auf meinem Bildschirm unten sein. Hier ist ein Code und Berechnungen dies zu erreichen:

public class Box implements ApplicationListener { 

public PerspectiveCamera camera; 
public float SCREEN_WIDTH; 
public float SCREEN_HEIGHT; 

@Override 
public void create() { 
    SCREEN_WIDTH = Gdx.graphics.getWidth(); // 800px 
    SCREEN_HEIGHT = Gdx.graphics.getHeight(); // 480px 

    // Create camera (90°) and set position 
    camera = new PerspectiveCamera(90f, SCREEN_WIDTH, SCREEN_HEIGHT); 
    camera.position.set(SCREEN_WIDTH + SCREEN_HEIGHT/2, SCREEN_HEIGHT/2, 0f); 
    camera.lookAt(0f, SCREEN_HEIGHT/2, 0f); 
    camera.near = 1; 
    camera.far = 2 * SCREEN_WIDTH; 
    camera.update(); 
} 

@Override 
public void render() { 
    Gdx.gl.glClearColor(Color.WHITE.r, Color.WHITE.g, Color.WHITE.b, Color.WHITE.a); 
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 

    // Build the box - width is screenwidth and height is screenheight - one corner in origin 
    ModelBuilder modelBuilder = new ModelBuilder(); 
    modelBuilder.begin(); 
    MeshPartBuilder mpb = modelBuilder.part("ID", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, 
      new Material(ColorAttribute.createDiffuse(Color.GREEN))); 
    // bottom left corner of the box should be in (0,0,0) 
    mpb.box(SCREEN_WIDTH/2, SCREEN_HEIGHT/2, -10f, SCREEN_WIDTH, SCREEN_HEIGHT, 20f); 
    Model model = modelBuilder.end(); 
    ModelInstance instance = new ModelInstance(model); 

    // Build some light 
    Environment environment = new Environment(); 
    environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); 
    environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); 

    // Draw the box 
    ModelBatch modelBatch = new ModelBatch(); 
    modelBatch.begin(camera); 
    modelBatch.render(instance, environment); 
    modelBatch.end(); 
} 
} 

die Kastenhöhe in dem Bildschirm zu passen I zurück SCREEN_HEIGHT/2, da x = SCREEN_HEIGHT/2/tan (45 °) = SCREEN_HEIGHT/2 Schritt muss/1 = SCREEN_HEIGHT/2, deshalb habe ich diese Länge der X-Komponente in der Positionseinstellung hinzugefügt.

Der Code stellt Skizze 2 und geben Sie mir, dass die korrekte Screenshot:

screenshot of sketch 2

Um Skizze 3 zu erreichen, muss ich mein Sichtfeld etwa 45 ° nach links drehen. Aber in diesem Zusammenhang muss ich ein wenig zurücktreten, weil die Seiten des Sehfeldes länger sind als die Mittellinie. Ich habe zwei handgezeichnete Skizzen:

rotation of field of view

Wo h = SCREEN_HEIGHT. Zuerst muss ich x berechnen. x = h/2/sin (45 °) = h/sqrt (2). Jetzt muss ich eine Länge von x zurücktreten und in eine neue Richtung schauen (45 ° links von der Box). Um den Punkt zu berechnen, an das ich suche, I berechnen die Länge y auf dieser Skizze:

calculation y

y = sin (45 °) * h/2 = h * sqrt (2)/4. Also ist der Punkt zum Beispiel (SCREEN_WIDTH + (x-y), SCREEN_HEIGHT/2, y). Jetzt wechsle ich die Position und suchen Punkt in meinem Code:

public void create() { 
    SCREEN_WIDTH = Gdx.graphics.getWidth(); // 800px 
    SCREEN_HEIGHT = Gdx.graphics.getHeight(); // 480px 

    // Create camera (90°) and set position 
    camera = new PerspectiveCamera(90f, SCREEN_WIDTH, SCREEN_HEIGHT); 
    float x = (float) (SCREEN_HEIGHT/Math.sqrt(2)); 
    float y = (float) (SCREEN_HEIGHT * Math.sqrt(2)/4f); 
    camera.position.set(SCREEN_WIDTH + x, SCREEN_HEIGHT/2, 0f); 
    camera.lookAt(SCREEN_WIDTH + x - y, SCREEN_HEIGHT/2, y); 
    camera.near = 1; 
    camera.far = 2 * SCREEN_WIDTH; 
    camera.update(); 
} 

Und ich diesen Bildschirm:

screenshot which should represent sketch 3

Aber das Feld ist nicht auf dem ganz rechts :(

So, jetzt die Frage: was ist falsch? Ist mein Denken über das Sichtfeld falsch oder meine Berechnungen?

Mit freundlichen Grüßen!

Antwort

0

Ihr Verständnis der PerspectiveCamera ist ein bisschen aus, insbesondere was es mit dem zweiten (viewportWidth) und dem dritten (viewportHeight) Argument macht.

Das einzige, was die PerspectiveCamera mit ihnen macht, ist das Seitenverhältnis und verwenden Sie es, um die projectionMatrix einzustellen. Für den verwendeten spezifischen Code siehe this line, der das Seitenverhältnis berechnet, und this method, der projectionMatrix setzt.

Jetzt ist das alles gut und gut, außer dass Sie auch die Mathematik, um mit dem Seitenverhältnis zu tun, und tun es zweimal bewirkt, dass die Kamera wieder dehnen. Die Lösung ist ganz einfach, entweder Ihre mathematische Redo nicht für das Seitenverhältnis einzustellen oder

camera = new PerspectiveCamera(90f, SCREEN_WIDTH, SCREEN_HEIGHT); 

mit

camera = new PerspectiveCamera(90f, 1, 1); 

ersetzen, um das Seitenverhältnis zu machen, die berechnet 1 sein Libgdx.

Ich bin nicht so gut mit Sinus und Cosinus, so kann ich nicht die erste Option Lösungen anbieten, aber Sie scheinen keine Probleme mit schwieriger Mathematik zu haben.