Fixed quaternion multiplication

This commit is contained in:
2025-02-07 19:19:06 -05:00
parent 28c30c5ea7
commit aa8056240a
3 changed files with 37 additions and 19 deletions

View File

@@ -1,7 +1,7 @@
#include "Quaternion.h" #include "Quaternion.h"
#include <cmath> #include <cmath>
float Quaternion::operator[](uint8_t index) float Quaternion::operator[](uint8_t index) const
{ {
if (index < 4) if (index < 4)
{ {
@@ -12,24 +12,36 @@ float Quaternion::operator[](uint8_t index)
return 1e+6; return 1e+6;
} }
Quaternion Quaternion::operator+(const Quaternion &other) Quaternion Quaternion::operator+(const Quaternion &other) const
{ {
return Quaternion{this->v1 * other.v1, this->v2 * other.v2, this->v3 * other.v3, this->w * other.w}; return Quaternion{this->v1 * other.v1, this->v2 * other.v2, this->v3 * other.v3, this->w * other.w};
} }
Quaternion & Quaternion &
Quaternion::Rotate(Quaternion &other, Quaternion &buffer) Quaternion::Q_Mult(Quaternion &other, Quaternion &buffer) const
{ {
// eq. 6 // eq. 6
buffer.v1 = this->w * other.v1 + other.w * this->v1 - this->v2 * other.v3 + this->v3 * other.v2; buffer.w = (other.w * this->w - other.v1 * this->v1 - other.v2 * this->v2 - other.v3 * this->v3);
buffer.v2 = this->w * other.v2 + other.w * this->v2 - this->v3 * other.v1 + this->v1 * other.v3; buffer.v1 = (other.w * this->v1 + other.v1 * this->w - other.v2 * this->v3 + other.v3 * this->v2);
buffer.v3 = this->w * other.v3 + other.w * this->v3 - this->v1 * other.v2 + this->v2 * other.v1; buffer.v2 = (other.w * this->v2 + other.v1 * this->v3 + other.v2 * this->w - other.v3 * this->v1);
buffer.w = this->w * other.w - this->v1 * other.v1 - this->v2 * other.v2 - this->v3 * other.v3; buffer.v3 = (other.w * this->v3 - other.v1 * this->v2 + other.v2 * this->v1 + other.v3 * this->w);
return buffer;
}
Quaternion &Quaternion::Rotate(Quaternion &other, Quaternion &buffer) const
{
Quaternion prime{-this->v1, -this->v2, -this->v3, this->w};
static_cast<Matrix<1, 4>>(buffer) = static_cast<Matrix<1, 4>>(other);
buffer.w = 0;
Quaternion temp{};
this->Q_Mult(buffer, temp);
temp.Q_Mult(prime, buffer);
return buffer; return buffer;
} }
Matrix<1, 3> & Matrix<1, 3> &
Quaternion::ToEulerAngles(Matrix<1, 3> &angleBuffer) Quaternion::ToEulerAngles(Matrix<1, 3> &angleBuffer) const
{ {
// from https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles // from https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
// rotation sequence R = Rx * Ry * Rz // rotation sequence R = Rx * Ry * Rz
@@ -53,7 +65,7 @@ Quaternion::ToEulerAngles(Matrix<1, 3> &angleBuffer)
return angleBuffer; return angleBuffer;
} }
Matrix<3, 3> &Quaternion::ToRotationMatrix(Matrix<3, 3> &rotationMatrixBuffer) Matrix<3, 3> &Quaternion::ToRotationMatrix(Matrix<3, 3> &rotationMatrixBuffer) const
{ {
// eq. 4 // eq. 4
// from https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm // from https://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/index.htm

View File

@@ -18,44 +18,50 @@ public:
* @param index The index of the element to access * @param index The index of the element to access
* @return The value of the element at the index * @return The value of the element at the index
*/ */
float operator[](uint8_t index); float operator[](uint8_t index) const;
/** /**
* @brief Add two quaternions together * @brief Add two quaternions together
* @param other The quaternion to add to this one * @param other The quaternion to add to this one
* @return The net quaternion * @return The net quaternion
*/ */
Quaternion operator+(const Quaternion &other); Quaternion operator+(const Quaternion &other) const;
/** /**
* @brief Rotate a quaternion by another quaternion * @brief Q_Mult a quaternion by another quaternion
* @param other The quaternion to rotate by * @param other The quaternion to rotate by
* @param buffer The buffer to store the result in * @param buffer The buffer to store the result in
* @return A reference to the buffer * @return A reference to the buffer
*/ */
Quaternion &Rotate(Quaternion &other, Quaternion &buffer); Quaternion &Q_Mult(Quaternion &other, Quaternion &buffer) const;
/**
* @brief Rotate a quaternion by another quaternion
* @param other The quaternion to rotate
* @param buffer The buffer to store the result in
*
*/
Quaternion &Rotate(Quaternion &other, Quaternion &buffer) const;
/** /**
* @brief Calculate the Euler angles from the quaternion * @brief Calculate the Euler angles from the quaternion
* @param angleBuffer The buffer to store the angles in * @param angleBuffer The buffer to store the angles in
* @return A reference to the buffer * @return A reference to the buffer
*/ */
Matrix<1, 3> &ToEulerAngles(Matrix<1, 3> &angleBuffer); Matrix<1, 3> &ToEulerAngles(Matrix<1, 3> &angleBuffer) const;
/** /**
* @brief Convert the quaternion to a rotation matrix * @brief Convert the quaternion to a rotation matrix
* @param rotationMatrixBuffer The buffer to store the rotation matrix in * @param rotationMatrixBuffer The buffer to store the rotation matrix in
* @return A reference to the buffer * @return A reference to the buffer
*/ */
Matrix<3, 3> &ToRotationMatrix(Matrix<3, 3> &rotationMatrixBuffer); Matrix<3, 3> &ToRotationMatrix(Matrix<3, 3> &rotationMatrixBuffer) const;
// Give people an easy way to access the elements // Give people an easy way to access the elements
float &v1{matrix[0]}; float &v1{matrix[0]};
float &v2{matrix[1]}; float &v2{matrix[1]};
float &v3{matrix[2]}; float &v3{matrix[2]};
float &w{matrix[3]}; float &w{matrix[3]};
private:
}; };
#endif // QUATERNION_H_ #endif // QUATERNION_H_

View File

@@ -73,8 +73,8 @@ TEST_CASE("Vector Math", "Vector")
SECTION("Rotation") SECTION("Rotation")
{ {
Quaternion q3; Quaternion q3;
q1.Rotate(q2, q3); q1.Q_Mult(q2, q3);
REQUIRE(q3.v1 == -24); REQUIRE(q3.v1 == 24);
REQUIRE(q3.v2 == 48); REQUIRE(q3.v2 == 48);
REQUIRE(q3.v3 == 48); REQUIRE(q3.v3 == 48);
REQUIRE(q3.w == -6); REQUIRE(q3.w == -6);