2013-05-11 5 views
1

В последнее время я преуспеваю в реализации столкновения с камерой первого лица и местности, но я ударил еще одну стену, которая дрожит при движении по карте высоты. Хотя это не такая необычная проблема, я не мог найти четкого решения или направления, которым я должен следовать, чтобы добиться желаемого эффекта. Может ли кто-нибудь предложить, как я могу адаптировать мою реализацию, чтобы сделать рендеринг гладким?XNA 4.0: движение камеры первого лица на джиттере местности

класс камеры:

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; 
    } 
} 

`

+0

Что происходит с камерой, когда она дрожит? Вы считали [сглаживание] (http://en.wikipedia.org/wiki/Smoothing) движением? – Anko

+0

Камера следит за одной точкой, которая является вектором положения камеры (Camera.position), матрица просмотра вычисляется из Camera.position и Camera.direction, а остальная часть - в функции moveForward (float, Terrain). Я не думаю, что сглаживание поможет, если камера обновляется 60 раз в секунду (да, fps в порядке) – thormond

+0

Вы пробовали? Более частые обновления могут означать, что вам нужно более сильное сглаживание (т. Е. Рассмотрение большего количества значений для сглаживания). – Anko

ответ

1

Не могли бы вы сказать нам больше о функции GetTerrainHeight? Насколько я могу читать, вы прямо читаете высоту местности - она ​​хранится в массиве или что-то в этом роде?
Попробуйте интерполировать высоту местности между соседними точками, так как положение вашего персонажа может быть легко между двумя или более точками данных (если я правильно понял ваш код).

UPD:
Попробуйте Lerp между текущим положением камеры и вычисленным положением камеры вместо того, чтобы немедленно присвоив:
this.position = Vector3.Lerp(this.position, tmp, 0.05f);
0.05f является порогом на какой процент (в диапазоне от 0.0f до 1.0f) вы хотите двигаться к цели. Откалибруйте его или даже представите GameTime, чтобы сделать сглаживание независимым от частоты кадров.

+0

это та же функция, что и [этот] (http://www.riemers.net/Forum/index.php?var=663&var2=0) – thormond

+0

@thormond Используете ли вы функцию из первого сообщения или упрощенного? –

Смежные вопросы