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

如何从偏航角计算方向矢量?

舒斯伯
2023-03-14

我有一个问题,我不知道如何使用Java/LWJGL在OpenGL中渲染方向向量。

我有以下系统:

  • X位于屏幕右侧

因此我走在XZ平面上,现在我想实现/已经实现了WASD运动,它应该与我当前前进的方向有关。(W=向前到相机看方向,S=向后等)

我有一个偏航角,定义如下:

  • 如果一直向前,则为0度

现在我只想要一个代表偏航方向的3D矢量,我该怎么做呢?

我正在使用以下Java代码,包括答案,但似乎还有另一个bug:

@Override
protected void mouseMoved(final int dx, final int dy) {
    float yawDelta = dx / 10f;
    float pitchDelta = dy / 10f;
    yaw += yawDelta;
    pitch += pitchDelta;
    System.out.println("yaw = " + yaw);
    direction.updateZero().updateTranslate((float)Math.sin(Math.toRadians(yaw)), 0f, (float)Math.cos(Math.toRadians(yaw))).updateNormalized();
    System.out.println("direction = " + direction);
    updateView();
}

private void checkKeys() {
    if (isKeyCurrentlyDown(Keyboard.KEY_W)) {
        eye.updateTranslate(direction);
        updateView();
    }
    if (isKeyCurrentlyDown(Keyboard.KEY_S)) {
        eye.updateTranslate(direction.negated());
        updateView();
    }
    if (isKeyCurrentlyDown(Keyboard.KEY_A)) {
        eye.updateTranslate(direction.cross(Vector3f.Y.negated()));
        updateView();
    }
    if (isKeyCurrentlyDown(Keyboard.KEY_D)) {
        eye.updateTranslate(direction.cross(Vector3f.Y));
        updateView();
    }
    if (isKeyCurrentlyDown(Keyboard.KEY_Q)) {
        eye.updateTranslate(0.0f, -1.0f, 0.0f);
        updateView();
    }
    if (isKeyCurrentlyDown(Keyboard.KEY_Z)) {
        eye.updateTranslate(0.0f, 1.0f, 0.0f);
        updateView();
    }
}

private void updateView() {
    viewMatrix.identity().fpsView(eye, roll, yaw, pitch);
    Uniforms.setUniformMatrix4(UNIFORM_VIEW_MATRIX, false, viewMatrix);
}

然后

public Matrix4f fpsView(final Vector3f eye, final float rollAngle, final float yawAngle, final float pitchAngle) {
    //roll = rolling your head, Q&E
    //yaw = looking left/right, mouseY
    //pitch = looking up/down, mouseX
    float sinRoll = (float)Math.sin(Math.toRadians(rollAngle));
    float cosRoll = (float)Math.cos(Math.toRadians(rollAngle));
    float sinYaw = (float)Math.sin(Math.toRadians(yawAngle));
    float cosYaw = (float)Math.cos(Math.toRadians(yawAngle));
    float sinPitch = (float)Math.sin(Math.toRadians(pitchAngle));
    float cosPitch = (float)Math.cos(Math.toRadians(pitchAngle));

    //TODO cannot roll yet
    Vector3f xAxis = new Vector3f(
        cosYaw,
        -sinPitch * sinYaw,
        -cosPitch * sinYaw
    );
    Vector3f yAxis = new Vector3f(
        0.0f,
        cosPitch,
        -sinPitch
    );
    Vector3f zAxis = new Vector3f(
        sinYaw,
        sinPitch * cosYaw,
        cosPitch * cosYaw
    );

    return multiply(
        xAxis.getX(),               xAxis.getY(),               xAxis.getZ(),               0.0f,   //X column
        yAxis.getX(),               yAxis.getY(),               yAxis.getZ(),               0.0f,   //Y column  
        zAxis.getX(),               zAxis.getY(),               zAxis.getZ(),               0.0f,   //Z column
        0.0f,                       0.0f,                       0.0f,                       1.0f    //W column
    ).translate(eye);
}

不知怎的,眼睛。updateTranslate()不起作用,这只会将操作数的值添加到坐标。我的逻辑有缺陷吗?

共有2个答案

羊舌子瑜
2023-03-14

y总是0

x=sin(偏航)
z=cos(偏航)

曾元忠
2023-03-14

旋转部分比你的要复杂一些。

 R = yawMat.pitchMat.rollMat 

哪里:

    yawMat={ { cosZ, -sinZ, 0 }, { sinZ, cosZ , 0 }, {0,0,1 } };

    pitchMat =  { { cosY , 0 , sinY }, { 0, 1 , 0 }, { -sinY, 0, cosY } };

    rollMat = { {1,0,0 }, {0,cosX,-sinX }, {0,sinX,cosX } };

三者的点积是构成齐次变换中3x3旋转矩阵R的东西。点积的顺序很重要,所以要保持一致。

这是我的参考。

最终的4x4矩阵应该是这样的

T = {{R00,R01,R02,X},{R10,R11,R12,Y},{R20,R21,R22,Z},{0,0,0,1}}

编辑如果你想一次做一个旋转,那么其他两个3x3矩阵将转到标识,这样你就可以在偏航中只做一个旋转:

R = yawMat.I.I = yawMat

所以:

R = { { cosZ, -sinZ, 0 }, { sinZ, cosZ , 0 }, {0,0,1 } }

其他人也是如此。

正如您为了构建转换矩阵而编写的那样,它应该是:

Vector3f xAxis = new Vector3f(
    cosYaw*cosPitch,
    cosYaw* sinPitch*sinRoll - sinYaw*cosRoll,
    cosYaw*sinPitch*cosRoll + sinYaw*sinRoll
);

Vector3f yAxis = new Vector3f(
    sinYaw*cosPitch,
    sinYaw*sinPitch*sinRoll + cosYaw*cosRoll,
    sinYaw*sinPitch*cosRoll - cosYaw*sinRoll
);
Vector3f zAxis = new Vector3f(
    -sinPitch,
    cosPitch*sinRoll,
    cosPitch * cosYaw
);

假设固定旋转顺序x-

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

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

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

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

  • 我在过去几周的工作申请,其中涉及一些三角学,目前卡住了。如下图所示,我有一个圆形项目(位于#1位置的绿色圆),我知道它的中心点(让我们称之为X1,Y1)。这个圆圈有另一个点(橙色圆圈),它有点偏离中心--在另外两个标记(蓝色圆圈)之间。这些痕迹可以到处移动。计算出橙色点的坐标(我们称之为X2,Y2),计算出蓝色线相对于圆圈水平方向的角度(称之为角)。 我可以通过以下方法计算圆心与点之间的差值: d

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