【问题标题】:Draw camera aligned quad at correct world position?在正确的世界位置绘制相机对齐的四边形?
【发布时间】:2018-09-19 12:55:34
【问题描述】:

我在绘制面向固定(但已旋转)正交相机的四边形时遇到问题。正交相机在等距投影中显示 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 中。

【问题讨论】:

  • Vector3 leftRight = direction; 替换为Vector3 leftRight = cam.up.cpy().crs(cam.direction).scl(-1);。我认为(没有测试)。顺便说一句,您不需要在对其进行点积之前复制向量(这不会影响它)。如果您为所有精灵运行此方法,您可能希望手头有一个可重用的向量,而不是使用cpy() 进行所有这些分配。
  • @Tenfour04 谢谢,会试试这个看看结果,但我实际上得到了一段更简单(或至少更短)的代码。稍后会发布。

标签: java opengl libgdx


【解决方案1】:

我想出了一个非常简短的(在代码中)解决方案。涉及相机的视图矩阵,我对矩阵没有深入的了解,但它们本质上包含旋转、缩放和变换。所以在我的上一个示例中,我创建了 2 个向量“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,并且我的广告牌需要是高度大小的两倍,所以我将大小乘以向上向量乘以 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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-24
    • 2011-05-07
    • 2015-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多