【初心者向け】Qt GUIで四元数を使って3D回転を実現する:QQuaternion::operator+=()の使い方


QQuaternion::operator+=()は、Qt GUIライブラリで提供される四元数型 QQuaternion のクラスメソッドの一つです。このメソッドは、二つの四元数を加算し、その結果を QQuaternion オブジェクトとして返します。

四元数とは

四元数は、3次元の回転とスケーリングを表す数学的なオブジェクトです。通常、w と呼ばれるスカラー成分と、xyz と呼ばれるベクトル成分を持つ四元数として表現されます。

QQuaternion::operator+=() の役割

QQuaternion::operator+=() は、二つの四元数を直接加算する演算子です。具体的には、以下の操作を行います。

  1. メソッドの呼び出し側となる QQuaternion オブジェクトを q1 と仮定します。
  2. メソッド引数となる QQuaternion オブジェクトを q2 と仮定します。
  3. q1 の各成分と q2 の各成分をそれぞれ加算します。
  4. 加算結果を新しい QQuaternion オブジェクトとして生成します。
  5. 生成した QQuaternion オブジェクトをメソッドの戻り値として返します。
QQuaternion q1(1.0f, 2.0f, 3.0f, 4.0f);
QQuaternion q2(5.0f, 6.0f, 7.0f, 8.0f);

QQuaternion q3 = q1 += q2;

// q3 は (6.0f, 8.0f, 10.0f, 12.0f) となります。
  • 四元数の加算は、以下の式で定義されます。
  • 四元数の加算は、非可換演算です。つまり、q1 + q2q2 + q1 は一般的に異なる値になります。
  • QQuaternion::operator+=() は、代入演算子 = と同様に、左辺のオブジェクトを変更します。
(w1, x1, y1, z1) + (w2, x2, y2, z2) = (w1 + w2, x1 + x2, y1 + y2, z1 + z2)


#include <QtWidgets/QApplication>
#include <Qt3D/Q3DScene>
#include <Qt3D/Q3DNode>
#include <Qt3D/Q3DTransform>
#include <Qt3D/QRenderPass>
#include <Qt3D/QEffect>
#include <Qt3D/QGeometry>
#include <Qt3D/QMaterial>
#include <Qt3D/QPhongMaterial>
#include <Qt3D/QTexture>
#include <Qt3D/QTextureImage>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // シーンとビューアを作成
    Q3DScene scene;
    Q3DViewer viewer(&scene);
    viewer.setWindowTitle("Qt 3D - Quaternion Rotation");

    // 立方体をシーンに追加
    Q3DCubeMesh *cube = new Q3DCubeMesh();
    scene.rootObject()->addChild(cube);

    // Phongマテリアルを作成
    QPhongMaterial *material = new QPhongMaterial();
    material->setDiffuse(QColor(100, 150, 200));
    cube->setMaterial(material);

    // 回転アニメーションを作成
    QPropertyAnimation *rotationAnimation = new QPropertyAnimation(cube, "transform");
    rotationAnimation->setDuration(10000);
    rotationAnimation->setLoopCount(-1); // 無限ループ
    rotationAnimation->setPropertyName("rotation");

    // QQuaternion::operator+=() を使って回転を更新
    QQuaternion currentRotation;
    for (int i = 0; i < 100; ++i) {
        QQuaternion rotationDelta(0.0f, 0.1f, 0.2f, 0.3f);
        currentRotation += rotationDelta;
        rotationAnimation->setKeyFrameValue(i * 0.1f, currentRotation);
    }

    // アニメーションを開始
    rotationAnimation->start();

    // ビューアを表示
    viewer.show();

    return app.exec();
}

このコードでは、まず Q3DSceneQ3DViewer オブジェクトを作成して、3Dシーンとビューアを作成します。次に、Q3DCubeMesh オブジェクトを作成してシーンに追加し、QPhongMaterial オブジェクトを作成して立方体にマテリアルを設定します。

その後、QPropertyAnimation オブジェクトを作成して回転アニメーションを作成します。QQuaternion::operator+=() を使って、アニメーションごとに回転量を更新します。最後に、アニメーションを開始してビューアを表示します。

  • 回転軸を変更するには、QQuaternion::setAxisAngle() メソッドを使用します。
  • 回転速度を変更するには、QPropertyAnimation::setDuration() メソッドの値を変更します。
  • QQuaternion::operator+=() は、他の種類のアニメーションにも使用できます。
  • このコードは、Qt 3D Graphics 2.0 を使用しています。


明示的な加算

QQuaternion::operator+=() の代わりに、以下の式で四元数を明示的に加算することができます。

QQuaternion result = q1 + q2;

長所

  • コンパイラによる最適化の余地が増える
  • コードがより分かりやすくなる

短所

  • テンポラリ変数を必要とする
  • QQuaternion::operator+=() よりも冗長になる

QVector3D を使用する

四元数の回転部分を QVector3D として表現し、加算を行う方法もあります。

QVector3D axis1(q1.axis());
float angle1 = q1.angle();
QVector3D axis2(q2.axis());
float angle2 = q2.angle();

QVector3D combinedAxis = (axis1 * angle1 + axis2 * angle2) / (angle1 + angle2);
float combinedAngle = angle1 + angle2;

QQuaternion result(combinedAngle, combinedAxis);

長所

  • 回転軸と回転角を個別に操作しやすい

短所

  • 四元数の正規化が必要になる場合がある
  • 計算量が多くなる

独自の関数を作成する

特定のニーズに合わせて、独自の関数を作成することもできます。

長所

  • 性能を最適化できる
  • 完全に制御できる

短所

  • コードが読みづらくなる可能性がある
  • 開発と保守の手間がかかる
  • 独自の処理を組み込む必要があるか
  • 回転軸と回転角を個別に操作する必要があるか
  • コードの簡潔性とパフォーマンスのどちらを重視するか