在XNA中计算FPS风格相机的目标

3
我需要计算基于相机位置、Y旋转和Z旋转的观察3D向量会在哪里,我假设任何大于0的数字都足以表示相机到观察点的距离。
这是我正在使用的静态类,用于控制相机并计算视图和投影矩阵等。
涉及位置和旋转的类成员:
public static Vector3 Position { get; set; } //Publicly available for use outside the class
public static Vector3 Rotation { get; set; }
private static Vector3 camPos = new Vector3(0.0f, 200.0f, 300.0f); //However we work with these for manipulation of values
private static Vector3 camTarget = new Vector3(0, 0, -1200.0f);

private static float rotY = 0, rotZ = 0; //I believe that these are the correct axis following the right hand catasian coordinate system

我的相机更新功能:

public static void Update()        
{
    //Controls here

    //Update Position here
    Position = camPos;            

    //Update camTarget based on Position, rotY and rotZ <- Need help with this bit

    //After calculating camTarget update Rotation
    Rotation = camTarget;

    UpdateMatrices();
}

UpdateMatrices() 处理其他所有内容并且已经正常工作,但是在这里还是给您看一下:

public static void UpdateMatrices()
{
    Matrix rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(90));
    Vector3 transformedReference = Vector3.Transform(Vector3.Forward, rotationMatrix);

    View = Matrix.CreateLookAt(Position, Rotation, Vector3.Forward);
    Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, nearClip, farClip);
    World = Matrix.Identity;

    CamBoundingFrustrum = new BoundingFrustum(View * Projection);
}

有没有人能够分享一下这个的秘密?

2
一个与你的问题无关但很重要的点是:你的CamBoundingFrustrum是一个类,而不是结构体。这意味着每帧创建一个“新”的对象会给垃圾收集器带来很多垃圾。处理由于相机移动/旋转而导致的视锥体变化的预期方式是仅更新(每帧)一次在相机最初创建时创建的BoundingFrustum对象的Matrix属性。 - Steve H
1个回答

3

不要使用Vector3.Forward,而是从你的旋转矩阵中提取.Forward.Up向量:

    public void UpdateMatrices()
    {
        /// assumes Rotation is a Vector3 containing rotation around each axis expressed in radians
        Matrix rotationMatrix = Matrix.CreateFromYawPitchRoll(Rotation.Y, Rotation.X, Rotation.Z);
        /// View = Matrix.CreateLookAt(Position, Rotation, Vector3.Forward);

        View = Matrix.CreateLookAt(Position, Position + rotationMatrix.Forward, rotationMatrix.Up);
        Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, nearClip, farClip);

        /// World matrix needs to match your translation and rotation used above
        /// XNA expects matrices to be concatenated in SRT (scale, rotation, then translate) order:
        World = rotationMatrix * Matrix.CreateTranslation(Position);

        CamBoundingFrustrum = new BoundingFrustum(View * Projection);
    }

请注意,您必须将相机的平移(通过您存储的向量或从相机的世界矩阵.Translation属性获取)添加到RotationMatrix.Forward中以获得真正的目标。
矩阵.Forward、.Backward、.Left、.Right、.Up和.Down属性与旋转矩阵变换后的等效Vector3属性相同。因此,RotationMatrix.Forward指向您正在查看的方向,.Up则与之正交,等等。
如果只使用Vector3.Forward,则不会得到一个变换后的向量,可能会发生奇怪的事情。
其他注释:
  1. 不要将所有东西都静态化。在 Game.Initialize() 中创建一个相机类的实例并将其添加为属性。注意使用 static - 它可能会导致各种有趣的线程问题,让你疯狂。
  2. 如果你还没有这样做,我建议使用四元数而不是偏航/翻滚/俯仰 (yaw/roll/pitch),因为它可以避免万向锁,但这是另一个话题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接