我项目的主要目标是将玩家角色从 3D 环境投影到 2D 屏幕。我已经在网上找到了一些有用的数学,但在过去的四天里,我无法让它发挥作用。每次我移动角色时,它都会出现在随机位置和/或离开屏幕。有时它水平跟随,但通常从不垂直。
我的问题很简单:我做错了什么?
// A few numbers to play with:
// Case #1: myPos: 1104.031, 3505.031, -91.9875; myMousePos: 0, 180; myRotation: 153, 153, 25; playerPos: 1072, 3504, -91.9687 (Player Middle of Screen, Standing Behind Player)
// Case #2: myPos: 511.7656, 3549.25, -28.02344; myMousePos: 0, 347.5854; myRotation: 44, 2, 22; playerPos: 1632, 3232, -91.96875 (Player Middle of Screen, I stand higher and 1166 away)
// Case #3: myPos: 1105.523, 2898.336, -11.96875; myMousePos: 0, 58.67249; myRotation: 232, 184, 159; playerPos 1632, 3232, -91.96875 (Player Right, Lower Of Screen)
Vect3d viewAngles;
Vect3d vForward, vRight, vUpward;
float ScreenX, ScreenY;
float[] fov;
bool 3dWorldTo2dScreen(Vect3d playerpos, Vect3d mypos, PlayerData myself)
{
fov = new float[2];
viewAngles = Vect3d();
Vect3d vLocal, vTransForm;
vTransForm = new Vect3d();
vForward = new Vect3d();
vRight = new Vect3d();
vUpward = new Vect3d();
fov[0] = myself.MouseX; // Sky: -89, Ground: 89, Middle: 0
fov[1] = myself.MouseY; // 360 To 0
viewAngles.x = myself.Rotation.x;
viewAngles.y = myself.Rotation.y;
viewAngles.z = myself.Rotation.z;
int screenCenterX = 320; // 640
int screenCenterY = 240; // 480
AngleVectors();
vLocal = SubVectorDist(playerpos, mypos);
vTransForm.x = vLocal.dotproduct(vRight);
vTransForm.y = vLocal.dotproduct(vUpward);
vTransForm.z = vLocal.dotproduct(vForward);
if (vTransForm.z < 0.01)
return false;
ScreenX = screenCenterX + (screenCenterX / vTransForm.z * (1 / fov[0])) * vTransForm.x;
ScreenY = screenCenterY - (screenCenterY / vTransForm.z * (1 / fov[1])) * vTransForm.y;
return true;
}
Vect3d SubVectorDist(Vect3d playerFrom, Vect3d playerTo)
{
return new Vect3d(playerFrom.x - playerTo.x, playerFrom.y - playerTo.y, playerFrom.z - playerTo.z);
}
private void AngleVectors()
{
float angle;
float sr, sp, sy, cr, cp, cy,
cpi = (3.141f * 2 / 360);
angle = viewAngles.y * cpi;
sy = (float)Math.Sin(angle);
cy = (float)Math.Cos(angle);
angle = viewAngles.x * cpi;
sp = (float)Math.Sin(angle);
cp = (float)Math.Cos(angle);
angle = viewAngles.z * cpi;
sr = (float)Math.Sin(angle);
cr = (float)Math.Cos(angle);
vForward.x = cp * cy;
vForward.y = cp * sy;
vForward.z = -sp;
vRight.x = (-1 * sr * sp * cy + -1 * cr * -sy);
vRight.y = (-1 * sr * sp * sy + -1 * cr * cy);
vRight.z = -1 * sr * cp;
vUpward.x = (cr * sp * cy + -sr * -sy);
vUpward.y = (cr * sp * sy + -sr * cy);
vUpward.z = cr * cp;
}