c++ - 将 OpenGL 坐标系统转换为自定义并返回

标签 c++ qt math opengl

我的任务是使用 OpenGL 在地面上绘制 3D 对象。我使用 Y 轴向上的 OpenGL 左手坐标系。但是 3D 物体和相机轨道物体应该使用具有以下属性的不同坐标系:

  • XY平面为地平面;
  • Z轴向上;
  • Y轴为“北”;
  • X轴为“东”;
  • 方位(或水平)角为[0, 360]度;
  • 仰角(或垂直)角与 XY 平面成 [0, 90] 度。 最终用户使用方位角和仰角围绕某个中心旋转相机。所以我编写了以下代码以将球坐标转换为四元数:
//polar: x - radius, y - horizontal angle, z - vertical 
    QQuaternion CoordinateSystemGround::fromPolarToQuat(const QVector3D& polar) const {
    QQuaternion dest = QQuaternion::fromEulerAngles({0, polar.y(), polar.z()});
    //convert user coord system back to OpenGL by rotation around X-axis
    QQuaternion orig = QQuaternion::fromAxisAndAngle(1, 0, 0, -90);
    return dest * orig;
}

返回:

    QVector3D CoordinateSystemGround::fromQuatToPolar(const QQuaternion& q) const {
    //convert OpenGL coord system to destination by rotation around X-axis
    QQuaternion dest = QQuaternion::fromAxisAndAngle(1, 0, 0, 90);
    QQuaternion out = q * dest;
    QVector3D euler = out.toEulerAngles();

    float hor = euler.y();
    if(hor < 0.0f)
        hor += 360.0f;

    float ver = euler.z();
    if(ver > 90.0f)
        ver = 90.0f;
    else if(ver < 0.0f)
        ver = 0.0f;

    //x changes later
    return QVector3D(0, hor, ver);
}

但它不能正常工作。我想 fromPolarToQuat 转换在某处有错误,我不明白在哪里。

最佳答案

看来我找到了解决办法。因此,要从四元数中获取极角:

QVector3D CoordinateSystemGround::fromQuatToPolar(const QQuaternion& q) const {
    QQuaternion coord1 = QQuaternion::fromAxisAndAngle(0, 1, 0, -180);
    QQuaternion coord2 = QQuaternion::fromAxisAndAngle(1, 0, 0, -90);
    QQuaternion out = orig1 * orig2 * q;
    QVector3D euler = out.toEulerAngles();

    float hor = euler.y();
    if(hor < 0.0f)
        hor += 360.0f;

    float ver = euler.x();

    return QVector3D(0, hor, -ver);
}

然后返回:

QQuaternion CoordinateSystemGround::fromPolarToQuat(const QVector3D& polar) const {
    QQuaternion dest = QQuaternion::fromEulerAngles({-polar.z(), polar.y(), 0});
    QQuaternion coord1 = QQuaternion::fromAxisAndAngle(1, 0, 0, 90);
    QQuaternion coord2 = QQuaternion::fromAxisAndAngle(0, 1, 0, 180);
    return coord1 * coord2 * dest;
}

尽管不确定它是否是最佳解决方案,但它可以正常工作。

已编辑

经过一些研究,我发现了一些错误并进行了优化,希望正确的转换版本:

QVector3D CoordinateSystemGround::fromQuatToPolar(const QQuaternion& q) const {
    // back to OpenGL coord system: just multiplication on inverted destination coord system
    QQuaternion dest = QQuaternion::fromAxes({-1, 0, 0}, {0, 0, 1}, {0, 1, 0}).inverted();
    QVector3D euler = (dest * q).toEulerAngles();

    float hor = euler.y();
    if(hor < 0.0f)
        hor += 360.0f;

    float ver = euler.x();

    return QVector3D(0, hor, -ver);
}

然后返回:

QQuaternion CoordinateSystemGround::fromPolarToQuat(const QVector3D& polar) const {
    //just rotate if we were in OpenGL coord system
    QQuaternion orig = QQuaternion::fromEulerAngles({-polar.z(), polar.y(), 0});
    //and then multiply on destination coord system
    QQuaternion dest = QQuaternion::fromAxes({-1, 0, 0}, {0, 0, 1}, {0, 1, 0});
    return dest * orig;
}

关于c++ - 将 OpenGL 坐标系统转换为自定义并返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57547524/

相关文章:

c++ - 从 for 循环开始线程会阻塞 UI

c# - 如何解决 Windows Certificate app Supported "API test"test result fail

c++ - 删除 C++ 中的多余空格

c++ - 为什么字符串文字是左值而所有其他文字都是右值?

algorithm - 资源配置(最优策略)

javascript - 减去10的最大倍数

c - 如何在 MATLAB 中获取矩阵的指数?

c++ - C++11 上的嵌套类成员访问

qt - 如何在 QGraphicsItem 中换行文本?

linux - ubuntu 11.04 系统无密码关机