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

XNA 4.0:第一人称摄影机在地形抖动上的移动,xna,camera,collision-detection,terrain,Xna,Camera,Collision Detection,Terrain,最近,我成功地实现了第一人称摄影机和地形碰撞,但我遇到了另一堵墙,当在高度地图上移动时,摄影机会抖动。虽然这个问题并不少见,但我找不到任何明确的解决方案,也找不到达到预期效果的方向。 有人能建议我如何调整我的实现以使渲染执行平滑吗 摄像机等级: public class Camera { public Matrix view { get; protected set; } public Matrix projection { get; protected set; } p

最近,我成功地实现了第一人称摄影机和地形碰撞,但我遇到了另一堵墙,当在高度地图上移动时,摄影机会抖动。虽然这个问题并不少见,但我找不到任何明确的解决方案,也找不到达到预期效果的方向。 有人能建议我如何调整我的实现以使渲染执行平滑吗

摄像机等级:

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;
    }
}
公共级摄像机
{
公共矩阵视图{get;protected set;}
公共矩阵投影{get;保护集;}
公共向量3方向{get;受保护集;}
公共向量3侧_方向{get;受保护集;}
公共向量3位置{get;set;}
公共向量3 up{get;受保护集;}
公共浮点_rotationX{get;protected set;}
公共浮点_rotationY{get;protected set;}
公共浮动轮换
{
获取{return\u rotationX;}
设置
{
_旋转X=值;
RotateX(值);
}
}
公共浮球
{
获取{return\u rotationY;}
设置
{
_旋转Y=值;
RotateY(值);
}
}
公共矩阵旋转X;
公共矩阵轮换;
公共摄像机(游戏、Vector3 pos、Vector3 up)
:基地(游戏)
{
这个方向=新矢量3(0,0,1);
该方向=新矢量3(1,0,1);
this.rotationX=矩阵.Identity;
this.rotationY=矩阵.Identity;
这个位置=位置;
this.up=up;
this.view=Matrix.CreateLookAt(位置,位置+方向,向上);
this.projection=Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,(浮动)Game.Window.ClientBounds.Width/
(float)Game.Window.ClientBounds.Height,
1, 3000);
}
公共覆盖无效初始化()
{
base.Initialize();
}
公共空间旋转度(浮动度)
{
如果(_旋转X+度>=89)
_旋转X=89;

否则如果(_rotationX+degree你能告诉我们更多关于GetTerrainHeight函数的信息吗? 据我所知,您正在直接读取地形高度-它是存储在阵列中还是其他什么东西中?
尝试在相邻点之间插入地形高度,因为角色位置很容易位于两个或多个数据点之间(如果我正确理解代码)。

UPD:
尝试在当前相机位置和计算的相机位置之间进行lerp,而不是立即分配:
this.position=Vector3.Lerp(this.position,tmp,0.05f);


0.05f是您希望向目标移动的百分比的阈值(范围从0.0f到1.0f)。校准它,甚至引入游戏时间,使平滑独立于您的帧速率。

您能告诉我们更多关于GetTerrainHeight函数的信息吗? 据我所知,您正在直接读取地形高度-它是存储在阵列中还是其他什么东西中?
尝试在相邻点之间插入地形高度,因为角色位置很容易位于两个或多个数据点之间(如果我正确理解代码)。

UPD:
尝试在当前相机位置和计算的相机位置之间进行lerp,而不是立即分配:
this.position=Vector3.Lerp(this.position,tmp,0.05f);


0.05f是阈值的百分比(在0.0f到1.0f的范围内)你想向目标移动。校准它,甚至引入游戏时间,使平滑独立于你的帧速率。

当相机抖动时,它跟随的是什么?你考虑过移动吗?相机跟随的是一个点,它是相机位置向量(camera.position),视图矩阵是根据Camera.position和Camera.direction normal计算的,其余部分在向前移动(浮动,地形)功能下。我不认为平滑会有帮助,因为相机每秒更新60次(是的,fps很好),你试过了吗?更频繁的更新可能意味着你需要更强的平滑(即考虑更多的值进行平滑处理)。我没有,我应该首先尝试哪种技术/过滤器?一个简单的方法是保存相机计算到的最后
n
点的存储,并将相机的实际可见位置设置为这些点的平均值。(根据需要调整
n
)“运行平均值”的变化比原始数据更平稳。相机抖动时跟随的是什么?您考虑过移动吗?相机跟随的是一个点,该点是相机位置向量(相机位置),视图矩阵是根据相机位置和相机方向法线计算的,其余点在向前移动(浮动,地形)功能。我不认为平滑会有帮助,因为相机每秒更新60次(是的,fps很好),你试过了吗?更频繁的更新可能意味着你需要更强的平滑(即考虑更多的平滑值)。我没有,我应该先试用哪种技术/过滤器?一个简单的方法是保存相机计算到的最后一个
n
点的存储,并将相机的实际可见位置设置为这些点的平均值。(根据需要调整
n
。)这是“运行平均值”“更改比原始数据更平滑。它的功能与@thormond相同您使用的是第一篇文章中的功能还是简化的功能?它的功能与@thormond相同您使用的是第一篇文章中的功能还是简化的功能?