1

对于我为 3D 游戏制作的屏幕叠加层,我需要在 3D 世界中的某些位置上显示图标。我已经设法从游戏中获得了几个使这成为可能的变量:

  • 玩家位置 (x,y,z)
  • 相机位置 (x,y,z)
  • 点位置 (x,y,z)
  • 相机角度(FOV)

使用这些变量,我设法获得了相机视图的左右边缘。使用这 2 个变量,我可以获得 0 到 1 之间的点,该点应在 x 轴上显示图标。(0 在左边缘,1 在右边缘)这似乎工作得很好,但前提是我与 X 或 Z 轴对齐,如下例所示:

在此处输入图像描述

我一直在尝试使用以下旋转矩阵来解决这个问题:

[ Math.Cos(angle), -Math.Sin(angle) ]
[ Math.Sin(angle), Math.Cos(angle) ] 

我所做的是,我将玩家位置、相机位置和相机边缘位置放在矩阵中,并以世界点作为旋转点。问题是,只要我将角度量设为 90 度,X 和 Y 就会被翻转。几天来我一直在努力寻找解决方案,但我找不到它,所以我希望任何人都可以在这里推动我朝着正确的方向前进。以下是我的代码的一些部分,可能有助于找到解决方案:

float PCDistXZ = (float)Math.Sqrt(deltaPCx * deltaPCx + deltaPCz * deltaPCz); // X/Z distance from the world point to the camera

Point fakeAvatarPos = RotateAround(new Point((int)point.x, (int)point.z), new Point((int)avatar.x, (int)avatar.z), (int)90);
Point fakeCameraPos = RotateAround(new Point((int)point.x, (int)point.z), new Point((int)camera.x, (int)camera.z), (int)90);

double edgeRight = fakeC.X + (Math.Sin(45) * PCDistXZ);
double edgeLeft = fakeC.X - (Math.Sin(45) * PCDistXZ);

float edgeTest_ScreenPositionX = (1 - (float)((edgeRight - P.x) / (edgeRight - edgeLeft))) * screenWidth;

public static Point RotateAround(Point pCenter,Point pPoint, float pAngle)
    {
        double angle = (pAngle * Math.PI) / 180;
        double[,] matrix = new Double[2, 2] {
            { Math.Cos(angle), Math.Sin(angle) }, 
            { Math.Sin(angle), Math.Cos(angle) } 
        };

        double xOffset = pPoint.X - pCenter.X;
        double yOffset = pPoint.Y - pCenter.Y;

        Point newPoint = new Point(
            (int)(((pPoint.X - xOffset) * matrix[0, 0]) - ((pPoint.Y - xOffset) * matrix[0, 1])),
            (int)(((pPoint.X - yOffset) * matrix[1, 0]) + ((pPoint.Y - yOffset) * matrix[1, 1]))
        );

        newPoint.X += (int)xOffset;
        newPoint.Y += (int)yOffset;
        return new Point(newPoint.X,newPoint.Y);
    }

注意:我已将一些变量的名称更改为更易于理解的名称,因此名称可能存在不一致。

编辑:我发现了视图和投影矩阵。我也许可以使用它们将 3D 位置转换为屏幕。我不确定是否可以用我所拥有的有限信息制作这个矩阵。

4

0 回答 0