XNA 4.0:第一人称相机在地形抖动上的移动

时间:2013-05-11 13:46:55

标签: xna camera collision-detection terrain

最近我成功地实现了第一人称相机和地形碰撞,但是当我穿过高度图时,我又撞到了另一面相机抖动的墙。虽然这不是一个不常见的问题,但我找不到任何明确的解决方案,也没有找到应该遵循的方向来达到预期的效果。 任何人都可以建议我如何调整我的实现以使渲染表现平稳?

相机类:

public class Camera
{
    public Matrix view { get; protected set; }
    public Matrix projection { get; protected set; }
    public Vector3 direction { get; protected set; }
    public Vector3 side_direction { get; protected set; }
    public Vector3 position { get; set; }
    public Vector3 up { get; protected set; }
    public float _rotationX { get; protected set; }
    public float _rotationY { get; protected set; }
    public float rotX
    {
        get { return _rotationX; }
        set
        {
            _rotationX = value;
            RotateX(value);
        }
    }
    public float rotY
    {
        get { return _rotationY; }
        set
        {
            _rotationY = value;
            RotateY(value);
        }
    }
    public Matrix rotationX;
    public Matrix rotationY;
    public Camera(Game game, Vector3 pos, Vector3 up)
        : base(game)
    {
        this.direction = new Vector3(0, 0, 1);
        this.side_direction = new Vector3(1, 0, 1);
        this.rotationX = Matrix.Identity;
        this.rotationY = Matrix.Identity;
        this.position = pos;
        this.up = up;
        this.view = Matrix.CreateLookAt(pos, pos + direction, up);
        this.projection = Matrix.CreatePerspectiveFieldOfView(
                     MathHelper.PiOver4, (float)Game.Window.ClientBounds.Width /
                     (float)Game.Window.ClientBounds.Height,
                     1, 3000);
    }
    public override void Initialize()
    {
        base.Initialize();
    }
    public void RotateX (float degree)
    {
        if (_rotationX + degree >= 89)
            _rotationX = 89;
        else if (_rotationX + degree <= -89)
            _rotationX = -89;
        else
            _rotationX = _rotationX + degree;
        float radians = MathHelper.ToRadians(_rotationX);
        rotationX = Matrix.CreateRotationX(radians);
        updateView();
    }
    public void RotateY (float degree)
    {
        _rotationY = (_rotationY + degree) % 360;
        float radians = MathHelper.ToRadians(_rotationY);
        rotationY = Matrix.CreateRotationY(radians);
        updateView();
    }
    protected void updateView()
    {
        this.side_direction = Vector3.Transform(new Vector3(1, 0, 1), rotationX);
        this.direction = Vector3.Transform(new Vector3(0, 0, 1), rotationX);
        this.side_direction = Vector3.Transform(side_direction, rotationY);
        this.direction = Vector3.Transform(direction, rotationY);
        this.view = Matrix.CreateLookAt(position, position + direction, up);
    }
    public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);
    }
    public void moveForward(float p)
    {
        this.position = position + direction * p;
        updateView();
    }
    public void moveSide(float p)
    {
        this.position = position + side_direction * p;
        updateView();
    }
    public void moveForward(float p, Terrain t)
    {
        Vector3 tmp = position + direction * p;
        tmp.Y = t.GetTerrainHeight(tmp.X, tmp.Z);
        this.position = tmp;
        updateView();
    }
    public void moveSide(float p, Terrain t)
    {
        Vector3 tmp = position + side_direction * p;
        tmp.Y = t.GetTerrainHeight(tmp.X, tmp.Z);
        this.position = tmp; 
        updateView();
    }
    public void Draw(ref BasicEffect effect)
    {
        effect.Projection = this.projection;
        effect.View = this.view;
    }
}

`

1 个答案:

答案 0 :(得分:1)

您能否详细介绍一下GetTerrainHeight功能? 据我所知,您正在直接读取地形高度 - 是存储在数组中还是什么? 尝试在相邻点之间插入地形高度,因为您的角色位置可以很容易地在两个或多个数据点之间(如果我理解您的代码正确的话)。

<强> UPD:
尝试在当前摄像机位置和计算出的摄像机位置之间进行搜索,而不是立即分配它:
this.position = Vector3.Lerp(this.position, tmp, 0.05f);
0.05f是您希望向目标移动的百分比(在0.0f到1.0f范围内)的阈值。校准它甚至引入GameTime以使平滑与帧速率无关。