Camera moves jerkily

Jan 29, 2009 at 2:28 PM
I've made a simple program - camera flows above terrain using WASD. So, the simple code:

[code]
public void Translate(Vector3 translation) {
_translation += translation;
}

public void Update(GameTime time) {
_translation *= new Vector3((float)time.ElapsedGameTime.TotalSeconds);
Matrix rotationMatrix = Matrix.CreateFromYawPitchRoll(_rotation.X, _rotation.Y, _rotation.Z);
_translation = Vector3.Transform(_translation, rotationMatrix);

Vector3 new_position = _engine.Camera.LocalPosition + _translation;
_translation = Vector3.Zero;
_engine.Camera.SetLocalOrientation(ref rotationMatrix);
_engine.Camera.LocalPosition = new_position;
}

public void MoveWithKeyboard(KeyboardState keyboard) {
float move_scale = 50;
if (keyboard.IsKeyDown(Keys.W))
Translate(Vector3.Forward * move_scale);
// the same for other keys
}
[/code]

Camera moves very jerkily,(some times per second), in spite of fps is about 100. Is my code correct? I use the last version of engine.
Jan 29, 2009 at 3:00 PM
it seems that problem because of updating camera position according to terrain height and discrete heigth of heightmap. Is there any way to get terrain height at needed point? GrabTriangle looks suitable, but I can't understand, how to use it. Is there any examples of that? (I don't want to use physics in my project)
Coordinator
Jan 29, 2009 at 5:20 PM
Edited Jan 29, 2009 at 5:23 PM

I modified HeightMap.cs to accomodate you. Check out the GrabHeight method. Hopefully this will work :)

Copy and paste all of this into HeightMap.cs -

[code]
using Microsoft.Xna.Framework;
using Ox.Engine.Utility;

namespace Ox.Engine.MathNamespace
{
    /// <summary>
    /// Represents a height map centered on the x,z origin.
    /// </summary>
    public class HeightMap
    {
        private readonly float[,] points;
        private readonly Vector3 quadScale;

        /// <summary>
        /// The height points which define the topography.
        /// </summary>
        public float this[int i, int j]
        {
            get { return points[i, j]; }
        }
        /// <summary>
        /// The amount of space between each height point.
        /// </summary>
        public Vector3 QuadScale
        {
            get { return quadScale; }
        }

        /// <summary>
        /// Create a height map.
        /// </summary>
        /// <param name="points">See property Points.</param>
        /// <param name="quadScale">See property QuadScale.</param>
        public HeightMap(float[,] points, Vector3 quadScale)
        {
            OxHelper.ArgumentNullCheck(points);

            this.points = points;
            this.quadScale = quadScale;
        }

        /// <summary>
        /// The length of the indexer.
        /// </summary>
        public int GetLength(int i)
        {
            return points.GetLength(i);
        }

        /// <summary>
        /// Grab a height from the height map.
        /// </summary>
        /// <param name="position">The x,z position to grab from.</param>
        public float GrabHeight(Vector2 position)
        {
            Triangle triangle; GrabTriangle(position, out triangle);
            Ray ray = new Ray(new Vector3(position.X, 0, position.Y), Vector3.Up);
            Vector3 intersection; OxMathHelper.Intersection(ref ray, ref triangle, out intersection);
            return intersection.Y;
        }

        /// <summary>Grab a triangle from the height map.</summary>
        /// <param name="position">The x,z position to grab from.</param>
        /// <param name="triangle">
        /// The resulting triangle. If out of range, the resulting triangle will be flat.
        /// </param>
        public void GrabTriangle(Vector2 position, out Triangle triangle)
        {
            Point index = new Point(
                (int)(position.X / quadScale.X),
                (int)(position.Y / quadScale.Z));

            if (IsIndexOutOfRange(index, points)) CreateFlatTriangle(out triangle);
            else GrabTriangle(position, index, out triangle);
        }

        private void GrabTriangle(Vector2 position, Point index, out Triangle triangle)
        {
            Vector2 localPosition = new Vector2(
                position.X - index.X * quadScale.X,
                position.Y - index.Y * quadScale.Z);

            Vector2 unitLocalPosition = new Vector2(
                localPosition.X / quadScale.X,
                localPosition.Y / quadScale.Z);

            if (InUpperRightTriangle(unitLocalPosition)) GrabUpperRightTriangle(index, out triangle);
            else GrabLowerLeftTriangle(index, out triangle);
        }

        private void GrabLowerLeftTriangle(Point index, out Triangle triangle)
        {
            float topLeft = points[index.X, index.Y];
            //float topRight = points[index.X + 1, index.Y];
            float bottomLeft = points[index.X, index.Y + 1];
            float bottomRight = points[index.X + 1, index.Y + 1];

            triangle.A = new Vector3(index.X * quadScale.X, topLeft * quadScale.Y, index.Y * quadScale.Z);
            triangle.B = new Vector3((index.X + 1) * quadScale.X, bottomRight * quadScale.Y, (index.Y + 1) * quadScale.Z);
            triangle.C = new Vector3(index.X * quadScale.X, bottomLeft * quadScale.Y, (index.Y + 1) * quadScale.Z);
        }

        private void GrabUpperRightTriangle(Point index, out Triangle triangle)
        {
            float topLeft = points[index.X, index.Y];
            float topRight = points[index.X + 1, index.Y];
            //float bottomLeft = points[index.X, index.Y + 1];
            float bottomRight = points[index.X + 1, index.Y + 1];

            triangle.A = new Vector3(index.X * quadScale.X, topLeft * quadScale.Y, index.Y * quadScale.Z);
            triangle.B = new Vector3((index.X + 1) * quadScale.X, topRight * quadScale.Y, index.Y * quadScale.Z);
            triangle.C = new Vector3((index.X + 1) * quadScale.X, bottomRight * quadScale.Y, (index.Y + 1) * quadScale.Z);
        }

        private static bool InUpperRightTriangle(Vector2 unitLocalPosition)
        {
            return unitLocalPosition.X > unitLocalPosition.Y;
        }

        private static bool IsIndexOutOfRange(Point index, float[,] points)
        {
            return
                index.X >= points.GetLength(0) - 1 ||
                index.Y >= points.GetLength(1) - 1 ||
                index.X < 0 ||
                index.Y < 0;
        }

        private static void CreateFlatTriangle(out Triangle triangle)
        {
            triangle.A = new Vector3(0, 0, 0);
            triangle.B = new Vector3(0, 0, 1);
            triangle.C = new Vector3(1, 0, 1);
        }
}

[/code]

This code will be in the next release.

Jan 30, 2009 at 3:27 AM
Thank you!!!