JPL Spatial
Sound spatialization and propagation library
Loading...
Searching...
No Matches
MinimalBasis.h
Go to the documentation of this file.
1//
2// ██╗██████╗ ██╗ ██╗██████╗ ███████╗
3// ██║██╔══██╗ ██║ ██║██╔══██╗██╔════╝ ** JPLSpatial **
4// ██║██████╔╝ ██║ ██║██████╔╝███████╗
5// ██ ██║██╔═══╝ ██║ ██║██╔══██╗╚════██║ https://github.com/Jaytheway/JPLSpatial
6// ╚█████╔╝██║ ███████╗██║██████╔╝███████║
7// ╚════╝ ╚═╝ ╚══════╝╚═╝╚═════╝ ╚══════╝
8//
9// Copyright 2024 Jaroslav Pevno, JPLSpatial is offered under the terms of the ISC license:
10//
11// Permission to use, copy, modify, and/or distribute this software for any purpose with or
12// without fee is hereby granted, provided that the above copyright notice and this permission
13// notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
14// WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
16// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17// WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#pragma once
21
22#include "JPLSpatial/Core.h"
27
28#include <cmath>
29
30namespace JPL
31{
33 template<CVec3 Vec3>
34 struct Basis
35 {
37
38 Vec3 X, Y, Z;
39
40 [[nodiscard]] static const Basis& Identity() noexcept
41 {
42 static constexpr Basis sIdentity(
43 Vec3{ Float(1), Float(0), Float(0) },
44 Vec3{ Float(0), Float(1), Float(0) },
45 Vec3{ Float(0), Float(0), Float(1) }
46 );
47 return sIdentity;
48 }
49
52 [[nodiscard]] JPL_INLINE static Basis FromForward(const Vec3& forward) noexcept
53 {
54 Basis basis{ .Z = forward };
56 return basis;
57 }
58
60 [[nodiscard]] inline static Basis FromUpAndForward(const Vec3& up, const Vec3& forward) noexcept
61 {
62 Vec3 Y = up;
63 const Vec3 Z = forward;
64 if (Math::IsNearlyEqual(Math::Abs<Float>(DotProduct(Y, Z)), Float(1.0)))
65 Y = (Math::Abs(GetZ(Z)) < Float(0.999) ? Vec3(0, 0, 1) : Vec3(1, 0, 0));
66
67 const Vec3 X = Normalized(CrossProduct(Y, Z));
68 Y = CrossProduct(Z, X);
69
70 return Basis{ X, Y, Z };
71 }
72
77 [[nodiscard]] inline static Basis Rotation(const Vec3& axis, Float angleRad) noexcept
78 {
79 const auto [s, c] = Math::SinCos(angleRad);
80 const Float t = Float(1) - c;
81
82 const Vec3 taxyz = t * axis;
83 const Vec3 sAxis = s * axis;
84
85 // Outer-product columns: (a ⊗ a) columns are ax*a, ay*a, az*a
86 const Vec3 t_ax_a = axis * taxyz.X;
87 const Vec3 t_ay_a = axis * taxyz.Y;
88 const Vec3 t_az_a = axis * taxyz.Z;
89
90 return Basis{
91 .X = t_ax_a + Vec3{ c, sAxis.Z, -sAxis.Y },
92 .Y = t_ay_a + Vec3{ -sAxis.Z, c, sAxis.X },
93 .Z = t_az_a + Vec3{ sAxis.Y, -sAxis.X, c }
94 };
95 }
96
98 [[nodiscard]] JPL_INLINE Vec3 InverseTransform(const Vec3& pWorld) const noexcept
99 {
100 return Vec3{
101 DotProduct(pWorld, X), // component along local X
102 DotProduct(pWorld, Y), // along local Y
103 DotProduct(pWorld, Z) // along local Z
104 };
105 }
106
108 [[nodiscard]] JPL_INLINE Vec3 Transform(const Vec3& vector) const noexcept
109 {
110 // 3 FMAs, or 9 mul + 6 add
111 return GetX(vector) * X + GetY(vector) * Y + GetZ(vector) * Z;
112 }
113
117 {
118 // Take a copy of the original input values
119 // because we modify them as we compute next component
120 const simd inX = inOutX;
121 const simd inY = inOutY;
122 const simd inZ = inOutZ;
123
127 }
128
131 {
132 return Basis{ // R * R_other
133 .X = Transform(otherBasis.X),
134 .Y = Transform(otherBasis.Y),
135 .Z = Transform(otherBasis.Z)
136 };
137 }
138
141 {
142 return Basis{ // RT * R_other
146 };
147 }
148
149 };
150
151 namespace Math
152 {
155 template<CVec3 Vec3>
156 [[nodiscard]] JPL_INLINE static Basis<Vec3> MakeBasis(const Vec3& forward) noexcept
157 {
158 return Basis<Vec3>::MakeFrom(forward);
159 }
160
163 template<CVec3 Vec3>
164 [[nodiscard]] JPL_INLINE static Basis<Vec3> MakeBasis(const Vec3& forward, const Vec3& up) noexcept
165 {
167 }
168 }
169} // namespace JPL
std::remove_cvref_t< decltype(GetX(std::declval< Vec3 >()))> FloatOf
Definition Vec3Math.h:36
void CreateOrthonormalBasis(const Vec3 &normal, Vec3 &tangent, Vec3 &bitangent) noexcept
Definition Vec3Math.h:84
JPL_INLINE constexpr T FMA(T a, T b, T c) noexcept
Inlined fuse multiply-add. Compiler in some circumstances is more eager to optimize this than std::fm...
Definition Math.h:186
JPL_INLINE constexpr bool IsNearlyEqual(T a, T b, T tolerance=JPL_FLOAT_EPS_V< T >) noexcept
Definition Math.h:152
JPL_INLINE constexpr auto Abs(const T &value) noexcept
Standard abs is not constexpr in C++20.
Definition Math.h:87
JPL_INLINE std::pair< T, T > SinCos(T value) noexcept
Definition Math.h:164
Definition AcousticMaterial.h:36
JPL_INLINE auto GetX(const Vec3Type &v) noexcept
Definition Vec3Traits.h:35
JPL_INLINE auto GetZ(const Vec3Type &v) noexcept
Definition Vec3Traits.h:37
JPL_INLINE auto GetY(const Vec3Type &v) noexcept
Definition Vec3Traits.h:36
JPL_INLINE simd min(const simd &a, const simd &b) noexcept
Element-wise min.
Definition SIMD.h:1813
Orthonormal basis (column-major)
Definition MinimalBasis.h:35
JPL_INLINE Vec3 InverseTransform(const Vec3 &pWorld) const noexcept
Apply rotation world -> local.
Definition MinimalBasis.h:98
JPL_INLINE Vec3 Transform(const Vec3 &vector) const noexcept
Apply rotation local -> world.
Definition MinimalBasis.h:108
Vec3 X
Definition MinimalBasis.h:38
static const Basis & Identity() noexcept
Definition MinimalBasis.h:40
Vec3 Z
Definition MinimalBasis.h:38
Internal::FloatOf< Vec3 > Float
Definition MinimalBasis.h:36
Vec3 Y
Definition MinimalBasis.h:38
JPL_INLINE void Transform(simd &inOutX, simd &inOutY, simd &inOutZ) const noexcept
Definition MinimalBasis.h:116
static Basis Rotation(const Vec3 &axis, Float angleRad) noexcept
Definition MinimalBasis.h:77
JPL_INLINE Basis Transform(const Basis &otherBasis) const noexcept
Compose orientations: apply 'this' basis mapping to the other's axes.
Definition MinimalBasis.h:130
JPL_INLINE Basis InverseTransform(const Basis &otherBasis) const noexcept
Re-express 'other' in 'this' local frame.
Definition MinimalBasis.h:140
static Basis FromUpAndForward(const Vec3 &up, const Vec3 &forward) noexcept
Creates a basis from the given up and forward normalized unit vectors.
Definition MinimalBasis.h:60
static JPL_INLINE Basis FromForward(const Vec3 &forward) noexcept
Definition MinimalBasis.h:52
Minimal 4-wide 32-bit float vector implementation for SIMD.
Definition SIMD.h:60