Search code examples
qt3drotationquaternionseuler-angles

Quaternion from vector x y z components - in Qt


I I would like o know if there is a direct way to get the quaternion representing the rotation of a vector that lies on one of the axes (the Z axis for instance), when I have the x,y,z components of the resulting vector.

enter image description here

In the image above, I have the x,y,z components, and I want to rotate an object (a pen for instance) with origin in 0,0,0 and parallel to the Z axis, into a pen with same direction of the vector in figure.

I could for sure use the components to get the 3 euler angles (tan-1(y/z), tan-1(y/x), tan-1(x/z) ) and then convert to quaternion. But I was wondering if there is a better way. I'm using Qt (http://doc.qt.io/qt-5/qquaternion.html), but if there is a simple formula I could implement it in C++. Thank you


Solution

  • To compute a rotation from vector to vector, there is a ready method in QQuaternion: QQuaternion::rotationTo().

    I made an MCVE to check this out and demonstrate:

    #include <QQuaternion>
    #include <QMatrix3x3>
    #include <QVector3D>
    
    int main()
    {
      QVector3D from(0.0f, 0.0f, 1.0f); // z axis
      qDebug() << "from: " << from;
      QVector3D to(1.0f, 0.0f, 1.0f); // arbitrary target vector
      qDebug() << "to  : " << to;
      QQuaternion rot = QQuaternion::rotationTo(from, to);
      qDebug() << "rot. (Quat.): " << rot;
      // Unfortunately, I cannot read quaternions.
      // so output as axis/angle:
      float x, y, z, angle;
      rot.getAxisAndAngle(&x, &y, &z, &angle);
      qDebug() << "rot. axis: " << QVector3D(x, y, z);
      qDebug() << "rog. ang.: " << angle;
      // done
      return 0;
    }
    

    Compiled and tested in VS2013:

    from:  QVector3D(0, 0, 1)
    to  :  QVector3D(1, 0, 1)
    rot. (Quat.):  QQuaternion(scalar:0.92388, vector:(0, 0.382683, 0))
    rot. axis:  QVector3D(0, 1, 0)
    rog. ang.:  45
    

    For me, the output looks reasonable...