两个方向的3D旋转?

Kri*_*ice 6 java opengl angle rotation lwjgl

背景

我正在尝试使用LWJGL 3.0在Java中创建FPS游戏.我已经设置了一个相机类,它具有俯仰和偏航(不使用滚动).相机本身扩展了实体,因为它有一个模型.我希望这款相机始终位于相机的"前方",无论相机指向何处.每个实体都有一个getTransformationMatrix()返回a 的方法,Matrix4f然后将其传递给实体着色器.

问题

模型需要指向摄像机的方向,并围绕摄像机旋转,使其始终位于前方.这种情况下的对象是带枪的手,如下图所示.

在此输入图像描述

我的尝试

我知道基本的三角学,所以我得到的对象分别正确旋转俯仰和偏航.这是我目前的实施:

偏航

@Override
public Matrix4f getTransformationMatrix() {
    modelX = getPosition().x + (radius * (float)Math.sin(Math.toRadians(getYaw())));
    modelZ = getPosition().z + (radius * (float)Math.cos(Math.toRadians(getYaw())));

    return Transform.createTransformationMatrix(new Vector3f(modelX, getPosition().y - 5, modelZ), new Vector3f(0, getYaw(), 0), getScale());
}
Run Code Online (Sandbox Code Playgroud)

沥青

@Override
public Matrix4f getTransformationMatrix() {
    modelZ = getPosition().z + (radius * (float)Math.sin(Math.toRadians(getPitch())));
    modelY = (getPosition().y - 5) + (radius * (float)Math.cos(Math.toRadians(getPitch())));

    return Transform.createTransformationMatrix(new Vector3f(getPosition().x, modelY, modelZ), new Vector3f(getPitch(), 0, 0), getScale());
}
Run Code Online (Sandbox Code Playgroud)

我已经做了一些研究,但我担心我被困在这个问题太久了,需要一些新鲜的眼睛.当我尝试组合这两个计算时,当看到除0以外的任何偏转角时,模型似乎以图形的形式移动.下面是我尝试组合这些:

@Override
public Matrix4f getTransformationMatrix() {
    float zAxis = (radius * (float)Math.sin(Math.toRadians(getPitch())));
    modelY = (getPosition().y - 5) + (radius * (float)Math.cos(Math.toRadians(getPitch())));
    modelZ = getPosition().z + (zAxis * (float)Math.cos(Math.toRadians(getYaw())));
    modelX = getPosition().x + (radius * (float)Math.sin(Math.toRadians(getYaw())));

    return Transform.createTransformationMatrix(new Vector3f(modelX, modelY, modelZ), new Vector3f(getPitch(), getYaw(), 0), getScale());
}
Run Code Online (Sandbox Code Playgroud)

Transform.createTransformationMatrix()如下所示:

public static Matrix4f createTransformationMatrix(Vector3f translation, Vector3f rotation, Vector3f scale) {
    transform3d = new Matrix4f();
    transform3d.setIdentity();
    Matrix4f.translate(translation, transform3d, transform3d);
    Matrix4f.rotate((float) Math.toRadians(rotation.x), new Vector3f(1, 0, 0), transform3d, transform3d);
    Matrix4f.rotate((float) Math.toRadians(rotation.y), new Vector3f(0, 1, 0), transform3d, transform3d);
    Matrix4f.rotate((float) Math.toRadians(rotation.z), new Vector3f(0, 0, 1), transform3d, transform3d);
    Matrix4f.scale(scale, transform3d, transform3d);
    return transform3d;
}
Run Code Online (Sandbox Code Playgroud)

思考

一位朋友建议创建一个单位向量,指向向上的方向,(即new Vector3f(0, 1, 0))通过俯仰和偏航旋转Vector,然后将Vector乘以半径并将其添加到摄像机的位置.我尝试了这个,但我不知道如何以一个角度旋转Vector,并且似乎Vector3f.rotate()在slick-utils Vector3f类中没有方法.任何帮助都是非常感激的,因为这让我头疼了这几天.谢谢!

Cor*_*non 3

我们通常做的是,是的,取一个单位长度的向量并将其用作我们的“轴”。在 2D 旋转中,我们始终使用一个轴 - Z 轴。

3D旋转

如果你像二维一样观察轴,你会看到这样的东西

二维旋转

因此,要旋转 3D 中的点,您可以使用矩阵或向量。我首先推荐矢量,这样您就可以了解 3D 旋转的工作原理。它让你大吃一惊!

我将从 theBennyBox 的 Vector3f 类中删除代码。如果您对更多数学知识感兴趣,请查看 Youtube 上的 theBennyBox。

矢量3f

    public Vector3F rotate(float angle, Vector3F axis) {
    double a = Math.toRadians(angle / 2f);
    float hs = (float) Math.sin(a);
    float hc = (float) Math.cos(a);
    Vector4F r = new Vector4F(axis.getX() * hs, axis.getY() * hs, axis.getZ() * hs, hc);
    Vector4F rc = r.conjugate();
    r = r.multiplyAsQuat(this).multiplyAsQuat(rc);

    return new Vector3F(r.getX(), r.getY(), r.getZ());
    }
Run Code Online (Sandbox Code Playgroud)

矢量 4f

    public Vector4F multiplyAsQuat(Vector3F v) {
    float o = -x * v.getX() - y * v.getY() - z * v.getZ();
    float a = w * v.getX() + y * v.getZ() - z * v.getY();
    float b = w * v.getY() + z * v.getX() - x * v.getZ();
    float c = w * v.getZ() + x * v.getY() - y * v.getX();

    return new Vector4F(a, b, c, o);
}

    public Vector4F conjugate() {
    return new Vector4F(-x, -y, -z, w);
}

    public Vector4F multiplyAsQuat(Vector4F qt) {

    float o = w * qt.getW() - x * qt.getX() - y * qt.getY() - z * qt.getZ();
    float a = x * qt.getW() + w * qt.getX() + y * qt.getZ() - z * qt.getY();
    float b = y * qt.getW() + w * qt.getY() + z * qt.getX() - x * qt.getZ();
    float c = z * qt.getW() + w * qt.getZ() + x * qt.getY() - y * qt.getX();

    return new Vector4F(a, b, c, o);
}
Run Code Online (Sandbox Code Playgroud)