当前位置: 首页 > 知识库问答 >
问题:

LWJGL只靠俯仰和偏航前进

蒲曦
2023-03-14

所以基本上在我的游戏中,我设法添加了向右移动,然后应用了相反的逻辑向左移动,但我仍然没有设法向前或向后移动。我只有一个俯仰和偏航可以使用,这意味着我没有RotationX、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;
}

共有1个答案

琴宾鸿
2023-03-14

我有几个提议给你。这是一段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;
            }
        }
 类似资料:
  • 我想做的是从我的相机中投射光线。我知道相机的x、y和z坐标,以及它的俯仰和偏航。我需要计算它的方向向量,这样我就可以把它传递给光线跟踪算法。 相机的向上向量是(0,1,0)。“音高”,从相机的角度来看,是上下看。 (我宁愿不使用矩阵,但如果有必要,我会使用)

  • 我正在努力弄清楚如何使俯仰偏航和侧倾在它们之间独立。一旦我在z轴(俯仰)上旋转某个物体,第二次旋转(yaxis yaw)取决于第一次旋转的结果,第三次旋转(x轴,roll)取决于其他两次旋转的结果。所以,我没有独立的俯仰、偏航和横滚,而是把它们三者混合在一起,很难看。 我希望有可能将物体的角度存储在一个数组中[俯仰、偏航、滚动],然后在变换过程中对这些角度进行解码,以便偏航将物体放置在给定的位置,

  • 我一直在处理3D空间(X、Y、Z)中的点,希望能够计算其中两个点之间的俯仰和偏航。 我的当前代码: 其中X1、X2、Y1、Y2、Z1、Z2在运行时之前都是未知的,此时它们是从两个随机生成的点收集的。 然而,由于某种原因,我的结果大错特错,我尝试了许多不同的组合,在google上搜索了无数的东西,但什么都没有找到。 一些制约因素是: 节距只能小于或等于90,或大于或等于-90(90= 这是我第一次使

  • 如果我有一个相机的偏航、俯仰和向上向量(在我的情况下总是[0,1,0]),计算相应滚动的最佳方法是什么?

  • 我试图从我有的方向向量(从中我可以得到俯仰和偏航)和滚动来计算一个向上向量。我需要这个,这样我就可以做一个四元数。 有人知道我怎么做吗?

  • 我的投球和打哈欠都搞砸了。我有垫子的俯仰和偏航,但光束的俯仰和偏航都搞砸了。如何计算垫的俯仰和偏航的法向量?我在stackoverflow上尝试了一大堆数学,但到目前为止都失败了。 我接下来尝试做的是将光束的俯仰和偏航从垫子的俯仰和偏航中分离出来,并分别计算它们。这基本上有效,但偏航仍然完全混乱。 我过去是通过光束的偏航和俯仰来计算方向向量的,这是一个util minecraft用来计算暴徒的方向