在正确的世界位置绘制相机对齐的四边形?

时间:2018-09-19 12:55:34

标签: java opengl libgdx

我在绘制面向固定(但旋转)正交摄影机的四边形时遇到麻烦。正交摄影机正以等轴测投影显示3D世界。现在,我需要在世界上放置异构体精灵,以便最终需要将这些四边形显示在正确的世界位置上。但是目前我正试图在世界中心画一个。

// FloorObject just holds the UV coordinates to be used.
public void addBillboard(FloorObject floorObject) {
    Vector3 direction =  new Vector3(1, 0, 0).nor();
    Vector3 cameraDirection = cam.direction;//cam.position.cpy().sub(new Vector3(0, 0, 0)).nor();

    Vector3 leftRight = direction;

    float dot = direction.cpy().dot(cameraDirection);

    cam.normalizeUp();
    Vector3 updown = cam.up;//new Vector3(0, 1, 0);

    if (Math.abs(dot) < 1f) {
        updown = direction.cpy().crs(cameraDirection);
    }
    updown.nor();

    Vector3 position = new Vector3(0, 0, 0);

    Vector3 bottomLeft = position.cpy().add(updown).sub(leftRight);
    Vector3 topLeft = position.cpy().sub(updown).sub(leftRight);
    Vector3 bottomRight = position.cpy().add(updown).add(leftRight);
    Vector3 topRight = position.cpy().sub(updown).add(leftRight);

    // Adding verts to the buffer.

    // Bottom left
    verts[vi++] = bottomLeft.x;
    verts[vi++] = bottomLeft.y;
    verts[vi++] = bottomLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Bottom right
    verts[vi++] = bottomRight.x;
    verts[vi++] = bottomRight.y;
    verts[vi++] = bottomRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Top left
    verts[vi++] = topLeft.x;
    verts[vi++] = topLeft.y;
    verts[vi++] = topLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

    // Top right
    verts[vi++] = topRight.x;
    verts[vi++] = topRight.y;
    verts[vi++] = topRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

}

将其与我的等轴测投影一起使用时,四边形会旋转27.5度。使用透视相机时,它会在整个地方旋转。我真的只想使用该等距相机将等距纹理显示在正确的世界位置。

万一重要,我需要根据场景中的其他几何图形以特定顺序绘制这些精灵。因此,每当我需要绘制等距子画面时,我都会按顺序(从后到前)调用此方法,然后以正确的顺序将其添加到VertexBuffer中。

1 个答案:

答案 0 :(得分:0)

我想出了一个非常简短的(代码中)解决方案。关于相机的视图矩阵,我对矩阵没有足够的了解,但它们本质上包含旋转,缩放和变换。因此,在我的最后一个示例中,我创建了两个向量“ leftRight”和“ upDown”,并将它们重命名为“ right”和“ up”,分别表示相机在世界视图(通常也称为模型视图)中的上下方向。这就是我从相机的视图矩阵中获取正确值的方法。

    right.x = modelview.val[0];
    right.y = modelview.val[4];
    right.z = modelview.val[8];

    up.x = modelview.val[1];
    up.y = modelview.val[5];
    up.z = modelview.val[9];

它只是查找数组中的值。我很早就尝试过,但是使用了错误的查找索引。有了这些,转换顶点的数学就非常简单了。

    float size = 1.4142135624f;

    Vector3 bottomLeft = position.cpy().sub(right.cpy().scl(size * .5f));
    Vector3 bottomRight = position.cpy().add(right.cpy().scl(size * .5f));
    Vector3 topRight = position.cpy().add(right.cpy().scl(size * .5f)).add(up.cpy().scl(size * 2));
    Vector3 topLeft = position.cpy().sub(right.cpy().scl(size * .5f)).add(up.cpy().scl(size * 2));

由于地板四边形的尺寸为1x1,因此我需要做毕达哥拉斯1.414..,因为它需要填满整个瓷砖。然后,我计算每个顶点的位置,因为我需要将四边形的底部中心放置在精确的世界位置,因此将尺寸乘以.5,广告牌的高度必须是高度的两倍,因此我将乘以用up矢量将size乘以2。要使其更快,请为此创建2个常量(宽度和高度),这样就不需要乘法了。然后,在计算完这些后,我可以像往常一样批处理我的顶点。

    // Bottom left
    verts[vi++] = bottomLeft.x;
    verts[vi++] = bottomLeft.y;
    verts[vi++] = bottomLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Bottom right halfway
    verts[vi++] = bottomRight.x;
    verts[vi++] = bottomRight.y;
    verts[vi++] = bottomRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV2();
    verts[vi++] = 1;

    // Top left
    verts[vi++] = topLeft.x;
    verts[vi++] = topLeft.y;
    verts[vi++] = topLeft.z;
    verts[vi++] = floorObject.getU();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;

    // Top right halway
    verts[vi++] = topRight.x;
    verts[vi++] = topRight.y;
    verts[vi++] = topRight.z;
    verts[vi++] = floorObject.getU2();
    verts[vi++] = floorObject.getV();
    verts[vi++] = 1;