// Copyright (C) 2020 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include "qquick3dquaternionutils_p.h" #include #include QT_BEGIN_NAMESPACE /*! \qmltype Quaternion \inqmlmodule QtQuick3D \since 5.15 \brief Provides utility functions for quaternion. The \c Quaternion is a global object with utility functions. It is not instantiable; to use it, call the members of the global \c Quaternion object directly. For example: \qml Node { rotation: Quaternion.fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45) } \endqml */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromAxisAndAngle(vector3d axis, real angle) Creates a quaternion from \a axis and \a angle. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromAxisAndAngle(real x, real y, real z, real angle) Creates a quaternion from \a x, \a y, \a z, and \a angle. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromAxesAndAngles(vector3d axis1, real angle1, vector3d axis2, real angle2) Creates a quaternion from \a axis1, \a angle1, \a axis2, and \a angle2. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromAxesAndAngles(vector3d axis1, real angle1, vector3d axis2, real angle2, vector3d axis3, real angle3) Creates a quaternion from \a axis1, \a angle1, \a axis2, \a angle2, \a axis3, and \a angle3. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromEulerAngles(vector3d eulerAngles) Creates a quaternion from \a eulerAngles. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::fromEulerAngles(real x, real y, real z) Creates a quaternion from \a x, \a y, and \a z. Returns the resulting quaternion. */ /*! \qmlmethod quaternion QtQuick3D::Quaternion::lookAt(vector3d sourcePosition, vector3d targetPosition, vector3d forwardDirection, vector3d upDirection) Creates a quaternion from \a sourcePosition, \a targetPosition, \a forwardDirection, and \a upDirection. This is used for getting a rotation value for pointing at a particular target, and can be used to point a camera at a position in a scene. \a forwardDirection defaults to \c Qt.vector3d(0, 0, -1) \a upDirection defaults to \c Qt.vector3d(0, 1, 0) Returns the resulting quaternion. */ QQuick3DQuaternionUtils::QQuick3DQuaternionUtils(QObject *parent) : QObject(parent) { } QQuaternion QQuick3DQuaternionUtils::fromAxisAndAngle(float x, float y, float z, float angle) { return QQuaternion::fromAxisAndAngle(x, y, z, angle); } QQuaternion QQuick3DQuaternionUtils::fromAxisAndAngle(const QVector3D &axis, float angle) { return QQuaternion::fromAxisAndAngle(axis, angle); } QQuaternion QQuick3DQuaternionUtils::fromEulerAngles(float x, float y, float z) { return QQuaternion::fromEulerAngles(x, y, z); } QQuaternion QQuick3DQuaternionUtils::fromEulerAngles(const QVector3D &eulerAngles) { return QQuaternion::fromEulerAngles(eulerAngles); } QQuaternion QQuick3DQuaternionUtils::lookAt(const QVector3D &sourcePosition, const QVector3D &targetPosition, const QVector3D &forwardDirection, const QVector3D &upDirection) { QVector3D targetDirection = targetPosition - sourcePosition; targetDirection.normalize(); QVector3D rotationAxis = QVector3D::crossProduct(forwardDirection, targetDirection); const QVector3D normalizedAxis = rotationAxis.normalized(); if (qFuzzyIsNull(normalizedAxis.lengthSquared())) rotationAxis = upDirection; float dot = QVector3D::dotProduct(forwardDirection, targetDirection); float rotationAngle = qRadiansToDegrees(qAcos(dot)); return QQuaternion::fromAxisAndAngle(rotationAxis, rotationAngle); } QQuaternion QQuick3DQuaternionUtils::fromAxesAndAngles(const QVector3D &axis1, float angle1, const QVector3D &axis2, float angle2, const QVector3D &axis3, float angle3) { const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); const QQuaternion q3 = QQuaternion::fromAxisAndAngle(axis3, angle3); return q3 * q2 * q1; } QQuaternion QQuick3DQuaternionUtils::fromAxesAndAngles(const QVector3D &axis1, float angle1, const QVector3D &axis2, float angle2) { const QQuaternion q1 = QQuaternion::fromAxisAndAngle(axis1, angle1); const QQuaternion q2 = QQuaternion::fromAxisAndAngle(axis2, angle2); return q2 * q1; } QT_END_NAMESPACE