libGDX - 透视摄像机和视野

时间:2014-04-13 13:37:28

标签: camera libgdx perspective fieldofview

我无法理解libGDX中透视相机的视野(或者我的计算错误)。

我想画一个盒子(例如800px宽,480px高和20px深)。该框位于x轴和y轴之间(换句话说:x轴上的宽度和y轴上的高度)。现在我想站在x轴(摄像机位置)的方框后面,朝一个方向看,我看到了我屏幕右侧的方框。 我做了一些草图:

drawing the box

camera on x-axis, looking at box

box should appear on right side

在最后一个草图上,该框位于视野的右侧。

此外,盒子的高度必须完全适合屏幕。换句话说:盒子的顶部边缘必须位于我的屏幕顶部,盒子的底部边缘必须位于我的屏幕底部。 以下是一些实现此目的的代码和计算:

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

为了适应屏幕中的盒子高度,我必须退后一步SCREEN_HEIGHT / 2,因为x = SCREEN_HEIGHT / 2 / tan(45°)= SCREEN_HEIGHT / 2/1 = SCREEN_HEIGHT / 2,这就是为什么我把这个长度加到了位置设置中的x分量。

代码代表草图2并给我正确的截图:

screenshot of sketch 2

为了实现草图3,我必须将我的视野向左旋转45°。但在这方面,我必须退一步,因为视野的两侧比中心线长。我做了两个手绘草图:

rotation of field of view

其中h = SCREEN_HEIGHT。首先,我必须计算x。 x = h / 2 / sin(45°)= h / sqrt(2)。现在我必须向后退一段x并向新方向看(距离方框45°)。为了计算我将要观察的点,我计算了该草图上的长度y:

calculation y

y = sin(45°)* h / 2 = h * sqrt(2)/ 4。所以,关键是例如(SCREEN_WIDTH +(x-y),SCREEN_HEIGHT / 2,y)。现在我改变了我的代码中的位置和观点:

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

我得到这个屏幕:

screenshot which should represent sketch 3

但是盒子不在右侧:(

所以现在的问题是:出了什么问题?我对视野的看法是错误还是我的计算?

祝你好运!

1 个答案:

答案 0 :(得分:0)

您对PerspectiveCamera的理解有点偏,特别是对第二个(viewportWidth)和第三个(viewportHeight)参数的理解。

PerspectiveCamera唯一能做的就是获取宽高比并用它来设置projectionMatrix。对于其使用的特定代码,请参阅计算纵横比的this line和设置projectionMatrix的{​​{3}}。

现在这一切都很好,除了你还要做数学处理宽高比,两次这样做会导致相机再次拉伸。解决方案非常简单,要么重做数学,要么不调整宽高比或替换

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

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

使libgdx计算的宽高比为1

我对正弦和余弦不太好,所以我无法为第一个选项提供解决方案,但你似乎没有遇到任何困难的数学问题。