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

两个方向的3D旋转?

岳刚洁
2023-03-14

背景

我正在尝试使用LWJGL 3.0在Java中创建一个FPS游戏。我已经设置了一个camera类,它具有俯仰和偏航(roll未被使用)。相机本身扩展实体,因为它有一个模型。无论相机指向哪里,我都希望这个模型始终显示在相机的“前方”。每个实体都有一个方法getTransformationMatrix(),该方法返回一个矩阵4f,然后将其传递到实体着色器。

问题

模型需要指向相机的方向,以及围绕相机旋转,这样它总是在前面。这种情况下的物体是拿着枪的手,如下图所示。

我的尝试

我知道基本的三角学,所以我让物体分别针对俯仰和偏航正确旋转。这是我当前的实现:

偏航

@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());
}

音高

@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());
}

我已经做了一些研究,但我担心我在这方面停留的时间太长了,需要一些新鲜的眼光。当我尝试结合这两个计算时,当查看除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());
}

变换。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;
}

思想

一位朋友建议创建一个指向上方向的单位向量,(即新向量3f(0,1,0))将向量旋转到俯仰和偏航,然后将向量乘以半径并将其添加到相机的位置。我试过了,但我不知道如何将向量旋转一个角度,而且似乎没有向量3f。slick utils Vector3f类中的rotate()方法。非常感谢您的帮助,因为这几天我一直很头痛。谢谢

共有1个答案

葛修筠
2023-03-14

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

三维旋转

如果你看轴,像在2D中,你会看到这样的东西

二维旋转

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

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

矢量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());
    }

向量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);
}
 类似资料:
  • 描述 (Description) 该拾取器与拾取器相同; 除了在此选择器中,您可以将其用于3D旋转效果。 例子 (Example) 以下示例演示了在Framework7中使用2 values and 3d-rotate effect - <!DOCTYPE html> <html> <head> <meta name = "viewport" content = "width =

  • 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转。 参考《WebGl编程指南》的第四章 假设在X轴和Y轴构成的平面上,要让物体旋转角度为β,那么公式如下: 由此思路就出来了: 根据要旋转的角度,构建一个三阶旋转矩阵 获取3D tiles 的旋转矩阵modelMatrix,然后与旋转矩阵运算, 最后将计算结果再赋值给modelMatrix,完成。 参考代码: var

  • 本文向大家介绍js实现3D旋转效果,包括了js实现3D旋转效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了js实现3D旋转效果的具体代码,供大家参考,具体内容如下 实现效果: 实现过程: 步骤一:先写一个简单的html结构,创建一个box盒子,里面放对应的图片(也可以用js创建图片,这里为了好理解,我们直接用html创建). 步骤二:给盒子和图片,设置对应的样式 第三步: js

  • 问题内容: 是否有一种相对简单的旋转SKSpriteNode的方法,使其始终面对其移动方向?我班的Gamecene有一个带有相对物理实体的对象系统,它们在碰撞时会相互施加脉冲。这使得很难准确地跟踪对象的移动方向。某些对象的形状也不规则,这会使事情更加混乱。我尝试使用三角函数(例如反正切),但是它仅在非常特殊的情况下可以正常使用。可能有一种方法可以找出SKSpriteNode轨迹的角度,以便可以将对

  • 使用Rajawali的主分支,我可以使用 如果我没有设置getMONtCamera(). setLookAt(0,0,0)。如果我做setLookAt,我根本没有旋转。 使用0.9版本,等效的似乎是 但不管setLookAt()如何,这似乎都不起作用。我根本没有旋转。如果我为另一个对象更改getCamera(),旋转就像我预期的那样。 我错过了什么?非常感谢您的帮助。 谢谢

  • 我正在开发一款太空射击游戏,你可以让你的飞船绕x、y和z轴旋转,从而向任何方向拍摄。要旋转飞船(我在c中使用openGL),我可以绕x、y或z轴旋转0-360度。相机总是看同一个方向(沿着z轴向下,就像“默认”一样)。你只需看着飞船旋转。 例如:glRotatef(-90.0f,1.0f,0.0f,0.0f);上面的例子将使船绕x轴旋转-90度。如果船在旋转前像普通太空射手一样沿着正y轴向上指向,