【问题标题】:libGDX - perspective camera and field of viewlibGDX - 透视相机和视野
【发布时间】:2014-05-27 10:18:46
【问题描述】:

我在理解 libGDX 中透视相机的视野方面有问题(或者我的计算可能是错误的)。

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

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

此外,盒子的高度必须完全适合屏幕。换句话说:盒子的顶部边缘必须在我的屏幕顶部,盒子的底部边缘必须在我的屏幕底部。 这里有一些代码和计算来实现这一点:

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,并给我正确的屏幕截图:

为了实现草图 3,我必须将视野向左旋转大约 45°。但在这方面我必须退后一点,因为视野的边长于中心线。我做了两张手绘草图:

其中 h = SCREEN_HEIGHT。首先,我必须计算 x。 x = h/2 / sin(45°) = h/sqrt(2)。现在我必须后退一段 x 并朝一个新的方向看(从框向左 45°)。为了计算我要查看的点,我计算了这个草图上的长度 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();
}

我得到了这个屏幕:

但盒子不在最右边:(

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

最好的问候!

【问题讨论】:

    标签: camera libgdx perspective fieldofview


    【解决方案1】:

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

    PerspectiveCamera 对它们所做的唯一事情就是获取纵横比并使用它来设置projectionMatrix。对于它使用的具体代码,请参见计算纵横比的this line 和设置projectionMatrix 的this method。

    现在这一切都很好,除了您还要计算处理纵横比,并且这样做两次会导致相机再次拉伸。解决方案很简单,要么重做数学以不调整纵横比,要么替换

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

    与

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

    使libgdx计算的纵横比为1。

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

    【讨论】:

      猜你喜欢
      • 2014-07-18
      • 1970-01-01
      • 2014-09-20
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-28
      相关资源
      最近更新 更多