我在绘制面向固定(但旋转)正交摄影机的四边形时遇到麻烦。正交摄影机正以等轴测投影显示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中。
答案 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;