2014-04-13 35 views
5

Mam problemy z rozumieniem pola widzenia kamery perspektywicznej w libGDX (a może moje obliczenia są błędne).libGDX - kamera perspektywiczna i pole widzenia

Chcę narysować pudełko (na przykład o szerokości 800 pikseli, wysokości 480 pikseli i głębokości 20 pikseli). Skrzynka jest umieszczona między osią X i Y (innymi słowy: szerokość na osi X i wysokość na osi Y). Teraz chcę stanąć za pudłem na osi X (pozycja kamery) i patrzeć w kierunku w taki sposób, że widzę pudełko po mojej prawej stronie ekranu. Zrobiłem kilka szkiców:

drawing the box

camera on x-axis, looking at box

box should appear on right side

na ostatnim szkicu, okno znajduje się po prawej stronie pola widzenia.

Co więcej, wysokość pudełka musi dokładnie pasować do ekranu. Innymi słowy: górna krawędź pola musi znajdować się na górze ekranu, a dolna krawędź pola musi znajdować się na dole ekranu. Oto kodu oraz obliczenia, które to umożliwiają

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(); 
} 
} 

Aby dopasować wysokość skrzynki na ekranie muszę cofnąć SCREEN_HEIGHT/2, ponieważ X = SCREEN_HEIGHT/2/tan (45 °) = SCREEN_HEIGHT/2/1 = SCREEN_HEIGHT/2, dlatego dodałem tę długość do komponentu x w ustawieniu pozycji.

kod stanowi szkic 2 i daj mi, że prawidłowym zrzucie:

screenshot of sketch 2

W celu osiągnięcia szkic 3, muszę obracać moje pole widzenia o 45 ° w lewo. Ale w związku z tym muszę trochę cofnąć, ponieważ boki pola widzenia są dłuższe niż linia środkowa. I wykonane dwa ręcznie wyciągnąć rysunki:

rotation of field of view

gdzie h = SCREEN_HEIGHT. Przede wszystkim muszę obliczyć x. x = h/2/sin (45 °) = h/sqrt (2). Teraz muszę cofnąć się o x i spojrzeć w nowym kierunku (45 ° w lewo od pudełka). W celu wyznaczenia punktu, w której będę wyglądzie, obliczać na długość Y na szkicu:

calculation y

y = sin (45 °) * h/2 = H * sqrt (2)/4. Tak więc punkt jest na przykład (SCREEN_WIDTH + (x-y), SCREEN_HEIGHT/2, y). Teraz mogę zmienić pozycję i punkt patrząc w moim kodu:

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(); 
} 

I mam taki ekran:

screenshot which should represent sketch 3

Ale pole nie jest na bardzo prawej strony :(

Więc teraz pytanie: co jest nie tak? Czy moje myślenie o polu widzenia jest błędne lub moje obliczenia?

Pozdrawiam!

Odpowiedz

0

Twoje zrozumienie wartości PerspectiveCamera jest nieco mniejsze, szczególnie jeśli chodzi o argument drugi (viewportWidth) i trzeci (viewportHeight).

Jedyne, co robi z nimi PerspectiveCamera, to uzyskaj współczynnik kształtu i użyj go do ustawienia wartości projectionMatrix. Aby uzyskać szczegółowy kod, zobacz this line, który oblicza współczynnik kształtu i this method, który ustawia wartość projectionMatrix.

Teraz wszystko jest w porządku, z tym wyjątkiem, że wykonujesz także matematykę, aby poradzić sobie z proporcjami, a dwukrotne wykonanie powoduje ponowne rozciągnięcie aparatu. Rozwiązanie jest dość proste, albo przerobić matematyki nie dostosować do proporcji lub wymienić

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

z

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

aby proporcje że libgdx oblicza się 1.

Nie jestem tak dobry z sinusem i cosinusem, więc nie mogę dostarczyć rozwiązań do pierwszej opcji, ale wydaje się, że nie masz żadnych problemów z trudną matematyką.