【问题标题】:LWJGL move forward with only pitch and yawLWJGL 仅靠俯仰和偏航向前移动
【发布时间】:2020-08-26 04:10:13
【问题描述】:

所以基本上在我的游戏中,我以某种方式设法添加了向右移动,然后应用相反的逻辑向左移动,但我仍然没有设法向前或向后移动。 我只有俯仰和偏航可以使用, 这意味着我没有旋转 X、Y 或 Z。 如果你能帮我计算这些,如果有必要的话也很酷。 所以这是我当前的代码:

public class Camera {

    private final float maxPitch = 90.0F;
    private Vector3f position = new Vector3f(0, 0, 0);
    private float pitch;
    private float lastPitch;
    private float yaw;
    private float lastYaw;
    private float roll;
    private float forwardSpeed = 7.0f;
    private float backwardSpeed = 10.0f;
    private float sideSpeed = backwardSpeed;
    private float jumpSpeed = 8.0f;
    private float fallSpeed = 7.0f;
    private float sensitivity = 100;

    public Camera() {
    }

    public void update() {

        final double deltaTime = Main.getGame().deltaTime;
        final double forwardAmount = forwardSpeed * deltaTime;
        final double backAmount = backwardSpeed * deltaTime;

        final double sideAmount = backAmount;

        float pitch = (float) Math.toRadians(this.pitch);
        float yaw = (float) Math.toRadians(this.yaw);

        float xzLength = (float) (-0.44807361612);
        float dx = (float) (xzLength * Math.cos(yaw));
        float dz = (float) (xzLength * Math.sin(yaw));

        if (KeyUtils.isForwardDown()) {

        } else if (KeyUtils.isBackwardsDown()) {

        }

        if (KeyUtils.isLeftDown()) {
            position.x += dx * sideAmount;
            position.z += dz * sideAmount;
        } else if (KeyUtils.isRightDown()) {
            position.x -= dx * sideAmount;
            position.z -= dz * sideAmount;
        }

        if (KeyUtils.isJumping()) {
            position.y += jumpSpeed * deltaTime;
        } else if (KeyUtils.isSneaking()) {
            position.y -= fallSpeed * deltaTime;
        }

        float rotationSpeed = (float) (50F * deltaTime * sensitivity);
        this.yaw += Mouse.getDX() / rotationSpeed;
        if(pitch > maxPitch) {
            pitch = 90.0F;
            return;
        }
        this.pitch -= Mouse.getDY() / rotationSpeed;
    }

    public Vector3f getPosition() {
        return position;
    }

    public void setPosition(Vector3f position) {
        this.position = position;
    }

    public float getPitch() {
        return pitch;
    }

    public void setPitch(float pitch) {
        this.pitch = pitch;
    }

    public float getYaw() {
        return yaw;
    }

    public void setYaw(float yaw) {
        this.yaw = yaw;
    }

    public float getRoll() {
        return roll;
    }

    public void setRoll(float roll) {
        this.roll = roll;
    }

    public float getLastPitch() {
        return lastPitch;
    }

    public float getLastYaw() {
        return lastYaw;
    }
}

我还有一个创建视图矩阵的方法,就像 camera.update() 方法一样,每帧调用一次

public static Matrix4f createViewMatrix(Camera camera) {

    Matrix4f viewMatrix = new Matrix4f();
    viewMatrix.setIdentity();

    Matrix4f.rotate((float) Math.toRadians(camera.getPitch()), new Vector3f(1, 0, 0), viewMatrix, viewMatrix);
    Matrix4f.rotate((float) Math.toRadians(camera.getYaw()), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);

    Vector3f cameraPos = camera.getPosition();
    Vector3f negativeCameraPos = new Vector3f(-cameraPos.x, -cameraPos.y, -cameraPos.z);
    Matrix4f.translate(negativeCameraPos, viewMatrix, viewMatrix);

    return viewMatrix;
}

【问题讨论】:

    标签: java math opengl vector lwjgl


    【解决方案1】:

    我有几个报价给你。这是一个 youtube 视频,展示了基本的相机控制。

    https://www.youtube.com/watch?v=OO_yNzAuDe4

    这是我的游戏中正在使用的一些当前代码:

    using SharpDX;
    using System;
    
    namespace VoidwalkerEngine.Framework.DirectX
    {
        public enum CameraMode
        {
            FreeLook,
            Orbit
        }
    
        public class Camera
        {
            /// <summary>
            /// The name of this camera
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// The eye location of this camera
            /// </summary>
            public Vector3 Location { get; set; }
            /// <summary>
            /// The Pitch of this Camera, as Radians
            /// </summary>
            public float Pitch { get; set; }
            /// <summary>
            /// The Yaw of this Camera, as Radians
            /// </summary>
            public float Yaw { get; set; }
            /// <summary>
            /// The Roll of this Camera, as Radians
            /// </summary>
            public float Roll { get; set; }
            /// <summary>
            /// The NearZ of this Camera
            /// </summary>
            public float NearZ { get; set; }
            /// <summary>
            /// The FarZ of this Camera
            /// </summary>
            public float FarZ { get; set; }
            /// <summary>
            /// The Field of View of this Camera, value should be
            /// between 0.70 and 1.20
            /// </summary>
            public float FieldOfView { get; set; }
            public float AspectRatio { get; set; }
            public float LookSpeed { get; set; }
            public float MoveSpeed { get; set; }
            /// <summary>
            /// Determines if this Camera is currently accelerating.
            /// </summary>
            public bool IsAccelerating { get; set; }
            /// <summary>
            /// The acceleration speed multiplier of this Camera.
            /// </summary>
            public float AccelerationMultiplier { get; set; }
            public CameraMode Mode { get; set; }
            public float ViewportWidth;
            public float ViewportHeight;
    
            /// <summary>
            /// The BoundingSphere of this Camera
            /// </summary>
            public BoundingSphere Bounds
            {
                get
                {
                    return new BoundingSphere()
                    {
                        Center = this.Location,
                        Radius = 2.0f
                    };
                }
            }
    
            /// <summary>
            /// The Target Vector of this Camera
            /// </summary>
            public Vector3 Target
            {
                get
                {
                    return new Vector3(
                        (float)Math.Sin(this.Yaw),
                        (float)Math.Tan(this.Pitch),
                        (float)Math.Cos(this.Yaw));
                }
            }
    
            /// <summary>
            /// The Frustum of this Camera
            /// </summary>
            public BoundingFrustum Frustum
            {
                get
                {
                    return new BoundingFrustum(this.ModelViewProjectionMatrix);
                }
            }
    
            public Matrix ModelViewMatrix
            {
                get
                {
                    return Matrix.LookAtLH(this.Location, Location + Target, Up);
                }
            }
    
            public Matrix ProjectionMatrix
            {
                get
                {
                    return Matrix.PerspectiveFovLH(FieldOfView, AspectRatio, NearZ, FarZ);
                }
            }
    
            public Matrix ModelViewProjectionMatrix
            {
                get
                {
                    return ModelViewMatrix * ProjectionMatrix;
                }
            }
    
            //public CardinalDirectionType Direction
            //{
            //    get
            //    {
            //        return VoidwalkerMath.GetCardinalDirection(VoidwalkerMath.ToDegrees(Yaw));
            //    }
            //}
    
            public Vector3 Forward
            {
                get
                {
                    return new Vector3((float)Math.Cos(Pitch), 0, (float)Math.Sin(Pitch));
                }
            }
    
            public Vector3 Right
            {
                get
                {
                    return new Vector3(Forward.X, 0, -Forward.X);
                }
            }
    
            public Vector3 Up
            {
                get
                {
                    return new Vector3(-(float)Math.Sin(Roll), (float)Math.Cos(Roll), 0);
                }
            }
    
            public Camera()
            {
    
            }
    
            public Camera(string name)
                : this()
            {
                this.Name = name;
                this.Location = new Vector3();
            }
    
            public void ToOrigin()
            {
                Transform(Vector3.Zero, 0, 0, 0);
            }
    
            public void Transform(Vector3 location, float pitch, float yaw, float roll)
            {
                this.Location = location;
                this.Pitch = pitch;
                this.Yaw = yaw;
                this.Roll = roll;
            }
    
            public float GetCurrentMoveSpeed()
            {
                if (IsAccelerating)
                {
                    return this.MoveSpeed * this.AccelerationMultiplier;
                }
                return this.MoveSpeed;
            }
    
            public void TranslateLeft(float deltaTime)
            {
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    Location.X - (float)Math.Sin(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime,
                    Location.Y,
                    Location.Z - (float)Math.Cos(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime);
            }
    
            public void TranslateRight(float deltaTime)
            {
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    Location.X + (float)Math.Sin(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime,
                    Location.Y,
                    Location.Z + (float)Math.Cos(Yaw + MathUtil.PiOverTwo) * moveSpeed * deltaTime);
            }
    
            public void TranslateForward(float deltaTime)
            {
                float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
                float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    this.Location.X + (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
                    this.Location.Y + (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
                    this.Location.Z + (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
            }
    
            public void TranslateBackward(float deltaTime)
            {
    
                float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
                float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    this.Location.X - (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
                    this.Location.Y - (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
                    this.Location.Z - (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
            }
    
            public void TransformYawPitch(float dx, float dy)
            {
                Yaw += dx * LookSpeed;
                Pitch -= dy * LookSpeed;
                const float pitchClamp = 1.56f;
                if (Pitch <= -pitchClamp)
                {
                    Pitch = -pitchClamp;
                }
                if (Pitch >= pitchClamp)
                {
                    Pitch = pitchClamp;
                }
            }
    
            public void TranslateUp(float deltaTime)
            {
                this.Location = new Vector3(
                    this.Location.X,
                    this.Location.Y + GetCurrentMoveSpeed() * deltaTime,
                    this.Location.Z); // TODO implement up/down based upon roll orientation.
            }
    
            public void TranslateDown(float deltaTime)
            {
                this.Location = new Vector3(
                    this.Location.X,
                    this.Location.Y - GetCurrentMoveSpeed() * deltaTime,
                    this.Location.Z);
            }
    
            public void LookAt(Vector3 location, float pitch, float yaw, float roll)
            {
                this.Location = location;
                this.Pitch = pitch;
                this.Yaw = yaw;
                this.Roll = roll;
            }
    
            public void SetAspectRatio(int width, int height)
            {
                this.ViewportWidth = width;
                this.ViewportHeight = height;
                this.AspectRatio = width / (float)height;
            }
        }
    }
    

    该代码本身只会帮助您查看实现细节。我现在无法提供显示初始化和鼠标输入的最小相机示例。我建议观看 youtube 视频,因为这是我多年前开始使用的内容,并且随着时间的推移进行了修改。该教程也使用 LWJGL,正如您所要求的那样。 (尽管 API 确实没有实际意义,考虑到框架通常是可以互换的)。

    计算向前和向后移动的代码是(这可能最终是左右,这取决于你的场景是如何设置的;记住,方向是完全主观的):

    public void TranslateForward(float deltaTime)
            {
                float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
                float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    this.Location.X + (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
                    this.Location.Y + (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
                    this.Location.Z + (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
            }
    
            public void TranslateBackward(float deltaTime)
            {
    
                float degreesX = MathUtil.RadiansToDegrees(Pitch) * 0.01745329F; // X rotation
                float degreesY = MathUtil.RadiansToDegrees(Yaw) * 0.01745329F; // Y rotation
                float moveSpeed = GetCurrentMoveSpeed();
                this.Location = new Vector3(
                    this.Location.X - (float)(moveSpeed * Math.Sin(degreesY) * Math.Cos(degreesX)) * deltaTime,
                    this.Location.Y - (float)(moveSpeed * Math.Sin(degreesX)) * deltaTime,
                    this.Location.Z - (float)(moveSpeed * Math.Cos(degreesY) * Math.Cos(degreesX)) * deltaTime);
            }
    

    其实这是我的鼠标输入代码。您不会在网上找到与此类似的任何内容,因为我实际上是在查询原始鼠标输入。大多数人不这样做,这就是为什么大多数示例会在鼠标按下时导致非常糟糕的“相机捕捉”。

    private void OnMouseMove(object sender, MouseEventArgs args)
            {
                this.CurrentMouseLocation = new Point(args.X, args.Y);
                if (IsMouseLookEnabled)
                {
                    MouseUpdate[] updates = Mouse.GetBufferedData();
                    if (updates != null && updates.Length > 0)
                    {
                        int xAccumulation = 0;
                        int yAccumulation = 0;
                        if (updates != null && updates.Length > 0)
                        {
                            for (int i = 0; i < updates.Length; i++)
                            {
                                if (updates[i].IsButton)
                                {
                                    // Reject Buffered Data
                                    return;
                                }
                                if (updates[i].Offset == MouseOffset.X)
                                {
                                    xAccumulation += updates[i].Value;
                                }
                                if (updates[i].Offset == MouseOffset.Y)
                                {
                                    yAccumulation += updates[i].Value;
                                }
                            }
                            float dx = MathUtil.DegreesToRadians(xAccumulation) * 0.25F;
                            float dy = MathUtil.DegreesToRadians(yAccumulation) * 0.25F;
                            Camera.TransformYawPitch(dx, dy);
                        }
                    }
                    Cursor.Position = new System.Drawing.Point(_mouseLockLocation.X, _mouseLockLocation.Y);
                    this.CurrentMouseLocation = _mouseLockLocation;
                }
            }
    

    【讨论】:

    • 我明天会这样做,因为我现在不在电脑上,但我非常感谢您的答案以及您如何花费时间和精力来详细回答它并将您的代码和视频链接起来一些关于运动的基础知识。我真的很讨厌向量数学。感激不尽。
    • 我也不需要快速回答,直到明天才有时间,我看到这里的人真的很有帮助所以我在这里发帖。
    • @purplex 没问题,伙计。事实是,有一百种方法可以做到这一点,但没有一种是平等的。这是您必须努力完成的编码工作之一,直到它变得完美。
    • 出于某种原因,我在该外观代码中两次检查了缓冲数据是否为空和空。不知道我为什么这样做。那天晚上可能在喝酒,或者别的什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多