From b4e3bf4a7dc023e4e40c42bee9caee0893c9d777 Mon Sep 17 00:00:00 2001 From: josh Date: Mon, 3 Mar 2025 03:29:12 -0600 Subject: [PATCH] Fix Quaternion::Quaternion(Matrix3x3) with more correct algorithm. --- README.md | 73 ++++++++++++++++++++------- include/J3ML/LinearAlgebra.hpp | 7 +-- src/J3ML/LinearAlgebra/Quaternion.cpp | 37 +++++++++++++- 3 files changed, 93 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b223c49..f3f995c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ J3ML is a "Modern C++" library designed to provide comprehensive support for 3D ## Features -* Vector Operations: Comprehensive support for 3D vector operations including addition, subtraction, scalar multiplication, dot product, cross product, normalization, and more. +* **Vector Operations:** Comprehensive support for 3D vector operations including addition, subtraction, scalar multiplication, dot product, cross product, normalization, and more. * **Matrix Operations:** Efficient implementation of 3x3 and 4x4 matrices with support for common operations such as multiplication, transpose, determinant calculation, and inverse calculation. * **Quaternion Operations:** Quaternion manipulation functions including conversion to/from axis-angle representation, quaternion multiplication, normalization, and interpolation (slerp). * **Transformation Functions:** Functions for transforming points, vectors, and normals using matrices and quaternions. @@ -18,29 +18,68 @@ J3ML is a "Modern C++" library designed to provide comprehensive support for 3D * **Algorithms:** Implementation of various algorithms including Gilbert-Johnson-Keerthi (GJK) algorithm for collision detection, random number generator, and more. * **Utility Functions:** Additional utilities such as conversion between degrees and radians, random number generation, and common constants. -# Usage +## Coming Soon -To use J3ML in your C++ project, simply include the necessary header files and link against the library. Here's a basic example of how to use the library to perform vector addition: +* **SIMD:** (Single-instruction, multiple-data) utilizes a vectorized instruction set to compute operations on multiple values at once. This is particularly useful in matrix maths. +* **LUTs:** Compute Lookup-tables for common operations, and bake them into your program via constexpr. (Sin, Cos, Tan, Sqrt, FastInverseSqrt) +# Installation + +We support integration via CMake Package Manager (CPM). It's quite clean and flexible. It's a single CMake script too. + +Here's what we recommend: + +Install CPM.cmake to a `cmake` directory in your project root, and add the lines below into your CMakeLists.txt + +To integrate the package manager: +```cmake +include("cmake/CPM.cmake") +``` + +To automatically download and build J3ML version 3.4.5 (Check releases for new versions!): + +```cmake +CPMAddPackage( + NAME J3ML + URL https::/git.redacted.cc/josh/J3ML/archive/3.4.5.zip +) +``` +Then you should be able to link J3ML to your project like any other library: + +```cmake +target_include_directories(MyProgramOrLib PUBLIC ${J3ML_SOURCE_DIR}/include) +### +target_link_libraries(MyProgramOrLib PUBLIC J3ML) +``` + + +# Usage Samples + +## 2D Vector Operations ```cpp +#include -#include +Vector2 position {10.f, 10.f}; +Vector2 velocity {5.f, 1.5f}; +float step = 1.f/60.f; + +void doStep() { + position = position + (velocity * step); + velocity = velocity.Lerp(Vector2::Zero, step); + float speed = velocity.Length(); +} +``` + +## Matrix3x3 and Rotation Types + +```cpp #include -int main() { - // Create two 3D vectors - Vector3 v1(1.0, 2.0, 3.0); - Vector3 v2(4.0, 5.0, 6.0); - - // Perform vector addition - Vector3 result = v1 + v2; - - // Output the result - std::cout << "Result: " << result << std::endl; - - return 0; -} +Matrix3x3 mRotation = Matrix3x3::RotateX(Math::PiOverTwo); +Quaternion qRotation(mRotation); // Convert to Quaternion +AxisAngle aRotation(qRotation); // Convert to AxisAngle +EulerAngleXYZ eRotation(aRotation); // Convert to Euler Angle (XYZ) ``` For more detailed usage instructions and examples, please refer to the documentation. diff --git a/include/J3ML/LinearAlgebra.hpp b/include/J3ML/LinearAlgebra.hpp index b37f65d..d83b488 100644 --- a/include/J3ML/LinearAlgebra.hpp +++ b/include/J3ML/LinearAlgebra.hpp @@ -1,5 +1,5 @@ //// Dawsh Linear Algebra Library - Everything you need for 3D math -/// @file LinearAlgebra.h +/// @file LinearAlgebra.hpp /// @description Includes all LinearAlgebra classes and functions /// @author Josh O'Leary, William Tomasine II /// @copyright 2024 Redacted Software @@ -9,11 +9,6 @@ #pragma once -// TODO: Enforce Style Consistency (Function Names use MicroSoft Case) -// TODO: Implement Templated Linear Algebra - - -// Library Code // #include "J3ML/LinearAlgebra/Vector2.hpp" #include "J3ML/LinearAlgebra/Vector3.hpp" diff --git a/src/J3ML/LinearAlgebra/Quaternion.cpp b/src/J3ML/LinearAlgebra/Quaternion.cpp index 073c5d6..2723345 100644 --- a/src/J3ML/LinearAlgebra/Quaternion.cpp +++ b/src/J3ML/LinearAlgebra/Quaternion.cpp @@ -16,7 +16,9 @@ namespace J3ML::LinearAlgebra { } Quaternion::Quaternion(const Matrix3x3& ro_mat) { - auto m = ro_mat.Transposed(); + // https://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/ + + auto m = ro_mat;//.Transposed(); auto m00 = m.At(0,0); auto m01 = m.At(0, 1); auto m02 = m.At(0, 2); @@ -27,6 +29,38 @@ namespace J3ML::LinearAlgebra { auto m21 = m.At(2, 1); auto m22 = m.At(2, 2); + float tr = m00 + m11 + m22; + + if (tr > 0) { + float S = Math::Sqrt(tr + 1.f) * 2; // S = 4*qw + + w = 0.25f * S; + x = (m21 - m12) / S; + y = (m02 - m20) / S; + z = (m10 - m01) / S; + } else { + if (m00 > m11 && m00 > m22) { + float S = 2.f * Math::Sqrt(1.f + m00 - m11 - m22); + w = (m21 - m12) / S; + x = 0.25f * S; + y = (m01 + m10) / S; + z = (m02 + m20) / S; + } else if (m11 > m22) { + float s = 2.f * Math::Sqrt(1.f + m11 - m00 - m22); + w = (m02 - m20) / s; + x = (m01 + m10) / s; + y = 0.25f * s; + z = (m12 + m21) / s; + } else { + float s = 2.f * Math::Sqrt(1.f + m22 - m00 - m11); + w = (m10 - m01) / s; + x = (m02 + m20) / s; + y = (m12 + m21) / s; + z = 0.25f * s; + } + } + + /* auto field_w = std::sqrt(1.f + m00 + m11 + m22) / 2.f; float w4 = (4.f * field_w); @@ -38,6 +72,7 @@ namespace J3ML::LinearAlgebra { w = field_w; bool success = Normalize(); // TODO: Validate normalization success. + */ } Quaternion::Quaternion(const Matrix4x4& ro_mat) {