libGDX - 透视相机和视野

6

我不太理解libGDX透视相机的视野(或者我的计算有误)。

我想画一个盒子(例如800像素宽,480像素高和20像素深)。该盒子位于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并给出正确的屏幕截图:
要实现草图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();
}

我看到了这个屏幕:

应该代表sketch 3的截图

但是盒子不在最右边 :(

所以现在的问题是:错在哪里?是我的视野范围或计算有误吗?

祝好!

1个回答

0

你对 PerspectiveCamera 的理解有些偏差,特别是它如何处理第二个(viewportWidth)和第三个(viewportHeight)参数。

PerspectiveCamera 对它们唯一要做的就是获取纵横比并使用它来设置 projectionMatrix。有关它使用的具体代码,请参见 this line 计算纵横比以及 this method 设置 projectionMatrix

现在,所有的一切都很好,但你还需要进行数学计算来处理宽高比问题,而重复计算会导致相机再次拉伸。解决方案非常简单,要么重新计算数学公式以不调整宽高比,要么替换掉原有的代码。

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

使用

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

让libgdx计算的宽高比为1

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接