【问题标题】:OpenTK/OpenGL local axis rotationOpenTK/OpenGL 局部轴旋转
【发布时间】:2012-08-05 00:02:34
【问题描述】:

这是一个场景:

对象被描述为:

  • 位置
  • 规模
  • 旋转

首先我从 OpenGL 应用模型视图(相机),然后使用以下矩阵进行平移和旋转:

    private Matrix4d AnglesToMatrix(Vector3d angles)
    {
        Vector3d left = Vector3d.UnitX;
        Vector3d up = Vector3d.UnitY;
        Vector3d forward = Vector3d.UnitZ;

        AnglesToAxes(angles, ref left, ref up, ref forward);

        return new Matrix4d(
            new Vector4d(left.X, up.X, forward.X, 0),
            new Vector4d(left.Y, up.Y, forward.Y, 0),
            new Vector4d(left.Z, up.Z, forward.Z, 0),
            new Vector4d(0, 0, 0, 1));
    }

    private void AnglesToAxes(Vector3d angles, ref Vector3d left, ref Vector3d up, ref Vector3d forward)
    {
        const double DEG2RAD = 0.0174532925;
        double sx, sy, sz, cx, cy, cz, theta;

        // rotation angle about X-axis (pitch)
        theta = angles.X * DEG2RAD;
        sx = Math.Sin(theta);
        cx = Math.Cos(theta);

        // rotation angle about Y-axis (yaw)
        theta = angles.Y * DEG2RAD;
        sy = Math.Sin(theta);
        cy = Math.Cos(theta);

        // rotation angle about Z-axis (roll)
        theta = angles.Z * DEG2RAD;
        sz = Math.Sin(theta);
        cz = Math.Cos(theta);

        // determine left axis
        left.X = cy * cz;
        left.Y = sx * sy * cz + cx * sz;
        left.Z = -cx * sy * cz + sx * sz;

        // determine up axis
        up.X = -cy * sz;
        up.Y = -sx * sy * sz + cx * cz;
        up.Z = cx * sy * sz + sx * cz;

        // determine forward axis
        forward.X = sy;
        forward.Y = -sx * cy;
        forward.Z = cx * cy;
    }

最后,我应用了比例。除了基于全局轴的旋转之外,一切看起来都很棒。

如何使用局部轴旋转物体?

使问题准确。当我在 Y 轴上将对象旋转 45 度时,X 和 Z 轴随之旋转,然后应用另一个旋转使用新轴。

为了避免以减号的形式受到惩罚……我阅读了所有与 3D 空间中的旋转相关的主题,但没有一个给我解决方案。上面的代码是应用各种尝试的结果,但它产生的结果相同:

        GL.Rotate(Rotation.X, Vector3d.UnitX);
        GL.Rotate(Rotation.Y, Vector3d.UnitY);
        GL.Rotate(Rotation.Z, Vector3d.UnitZ);

编辑: 事实证明,我们的设计师对 3D 对象的旋转抱有不好的期望,但问题仍然存在。至于使用的语言,我们用 C# 编写,但如果你用 C 或 C++ 给我指出一个解决方案,我会处理它:D

我们目前使用(可配置订单):

GL.Rotate(Rotation.X, Vector3d.UnitX);
GL.Rotate(Rotation.Y, Vector3d.UnitY);
GL.Rotate(Rotation.Z, Vector3d.UnitZ);

但这会围绕世界轴旋转对象。我们想要的是使用像这样的局部对象轴,假设我们有 X-Y-Z 轴旋转:

GL.Rotate(Rotation.X, Vector3d.UnitX);
GL.Rotate(Rotation.Y, newYaxis);
GL.Rotate(Rotation.Z, newZaxis);

或者假设我们有 Y-X-Z 轴旋转

GL.Rotate(Rotation.Y, Vector3d.UnitY);
GL.Rotate(Rotation.X, newXaxis);
GL.Rotate(Rotation.Z, newZaxis);

最有效的方法是预先计算旋转矩阵,但我仍然想知道如何确定旋转后的新轴。 (看来我必须重新阅读三角学书)。如果有人有可以快速计算旋转矩阵的解决方案,我将不胜感激。现在我将尝试在每次传递中使用三角函数计算。

【问题讨论】:

    标签: opengl rotation opentk


    【解决方案1】:

    你能准确地说出你在这里设想的是什么样的情况吗?

    我认为您的要求没有任何意义。对于任何旋转,您可以在另一个操作(全局轴)之前应用它,或者在另一个操作(局部轴)之后应用它。因此,如果要应用三个旋转,则必须先旋转一个轴,然后再旋转另一个轴,然后再旋转另一个轴。

    您是说要应用三个旋转,但您希望每个旋转发生在其他两个之前。他们不可能都是第一。

    如果您对您尝试实现的旋转类型进行更多描述(首选图片),也许我们可以消除这种误解,但您目前所问的内容在物理现实中对我来说没有意义。

    【讨论】:

    • 旋转必须以特定顺序发生,但在围绕一个轴旋转后,我必须为下一次旋转计算新轴。
    【解决方案2】:

    我不太擅长opentk,但对于C风格的opengl,这是前乘和后乘之间的区别。预乘发生在世界坐标空间中,后乘发生在局部坐标空间中。请参阅http://www.opengl.org/archives/resources/faq/technical/transformations.htm 第 9.070 节。

    如果您可以获得实际矩阵的句柄来执行矩阵乘法,那么这应该可以。

    【讨论】:

      猜你喜欢
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-06
      • 1970-01-01
      • 2015-07-17
      • 2021-10-17
      • 2021-01-05
      相关资源
      最近更新 更多