36 using FloatOf = std::remove_cvref_t<decltype(GetX(std::declval<Vec3>()))>;
52 [[nodiscard]] JPL_INLINE
constexpr bool IsNearlyZero(
const Vec3& a,
59 [[nodiscard]] JPL_INLINE
bool HasNans(
const Vec3& vec)
61 return std::isnan(
GetX(vec))
62 || std::isnan(
GetY(vec))
63 || std::isnan(
GetZ(vec));
74 return Vec3(
GetZ(vec), FloatType(0.0), -
GetX(vec)) / len;
79 return Vec3(FloatType(0.0),
GetZ(vec), -
GetY(vec)) / len;
91 tangent = Vec3(-
GetZ(normal), FloatType(0.0),
GetX(normal));
96 tangent = Vec3(FloatType(0.0),
GetZ(normal), -
GetY(normal));
99 bitangent = CrossProduct(normal, tangent);
107 [[nodiscard]] JPL_INLINE Vec3
RotateVector(
const Vec3& vector,
const Vec3& rotationAxis,
float angleRad)
noexcept
109 const auto [sinTheta, cosTheta] =
Math::SinCos(angleRad);
110 return vector * cosTheta
111 + CrossProduct(rotationAxis, vector) * sinTheta
112 + rotationAxis * DotProduct(rotationAxis, vector) * (1.0f - cosTheta);
116 [[nodiscard]] JPL_INLINE Vec3
Lerp(
const Vec3& v0,
const Vec3& v1,
float t)
noexcept
118 return v0 + t * (v1 - v0);
124 return FMA(t, (v1 - v0), v0);
130 [[nodiscard]] JPL_INLINE Vec3
Nlerp(
const Vec3& v0,
const Vec3& v1,
float t)
noexcept
132 return Normalized(
Lerp(v0, v1, t));
137 return Normalized(
Lerp(v0, v1, t));
142 [[nodiscard]]
inline Vec3
Slerp(
const Vec3& v0,
const Vec3& v1,
float t)
noexcept
145 FloatType dot = DotProduct(v0, v1);
149 dot = std::fmax(FloatType(-1.0), std::fmin(FloatType(1.0), dot));
151 static constexpr FloatType EPSILON =
152 std::numeric_limits<FloatType>::epsilon() * FloatType(100.0);
156 if (dot > FloatType(1.0) - EPSILON)
160 return Nlerp(v0, v1, t);
164 if (dot < FloatType(-1.0) + EPSILON)
168 Vec3 axis = Vec3(1.0, 0.0, 0.0);
169 if (
Math::Abs(DotProduct(v0, axis)) > FloatType(1.0) - EPSILON)
172 axis = Vec3(0.0, 1.0, 0.0);
177 axis = CrossProduct(v0, axis);
178 const auto proj = CrossProduct(axis, v0);
181 const auto proj = Normalized((axis - v0 * DotProduct(v0, axis)));
186 const FloatType angle = t * std::numbers::pi_v<FloatType>;
192 return Normalized(v0 * cosAngle + proj * sinAngle);
196 const FloatType theta = std::acos(dot);
197 const FloatType invSinTheta = 1.0f / std::sin(theta);
199 const FloatType w0 = std::sin((FloatType(1.0) - t) * theta) * invSinTheta;
200 const FloatType w1 = std::sin(t * theta) * invSinTheta;
202 return Normalized(v0 * w0 + v1 * w1);
209 const simd& t)
noexcept
211 using FloatType =
simd;
212 static const FloatType one(1.0f);
216 const FloatType dot =
clamp(DotProduct(inOutV0, V1), -one, one);
218 static constexpr float EPSILON =
219 (std::numeric_limits<float>::epsilon() * 100.0f);
221 static const FloatType oneMinusEps(1.0f - EPSILON);
222 static const FloatType minusOnePlusEps(-1.0f + EPSILON);
226 const simd_mask isParallel = dot > oneMinusEps;
229 const simd_mask isOpposite = dot < minusOnePlusEps;
238 const simd_mask isClose =
abs(DotProduct(inOutV0, axis)) > oneMinusEps;
247 axis = CrossProduct(inOutV0, axis);
248 const Vec3Pack proj = CrossProduct(axis, inOutV0)
251 const Vec3Pack proj = (axis - inOutV0 * DotProduct(inOutV0, axis)).Normalize();
258 FloatType oppositeCaseTermA;
261 const Vec3Pack oppositeCaseTermB = proj * sinAngle;
267 const FloatType invSinTheta = one /
::JPL::sin(theta);
268 const FloatType w0 =
::JPL::sin((one - t) * theta) * invSinTheta;
269 const FloatType w1 =
::JPL::sin(t * theta) * invSinTheta;
273 FloatType sinT, cosT;
275 const FloatType w1 = sinT * invSinTheta;
276 const FloatType w0 = cosT - dot * w1;
294 const Vec3Pack parallelCase =
FMA((V1 - inOutV0), t, inOutV0);
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 Vec3 Nlerp(const Vec3 &v0, const Vec3 &v1, float t) noexcept
Definition Vec3Math.h:130
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 bool HasNans(const Vec3 &vec)
Definition Vec3Math.h:59
JPL_INLINE constexpr T Lerp(const T &v0, const T &v1, T t) noexcept
Linearly interpolate v0 towards v1.
Definition Math.h:172
JPL_INLINE constexpr T Sqrt(T x) noexcept
Definition Math.h:269
JPL_INLINE constexpr bool IsNearlyZero(T value, T errorTolerance=JPL_FLOAT_EPS_V< T >) noexcept
Definition Math.h:146
JPL_INLINE Vec3 RotateVector(const Vec3 &vector, const Vec3 &rotationAxis, float angleRad) noexcept
Definition Vec3Math.h:107
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 simd InvSqrtFast(const simd &vec) noexcept
Definition SIMD.h:1783
JPL_INLINE std::pair< T, T > SinCos(T value) noexcept
Definition Math.h:164
Vec3 GetNormalizedPerpendicular(const Vec3 &vec) noexcept
Definition Vec3Math.h:67
Vec3 Slerp(const Vec3 &v0, const Vec3 &v1, float t) noexcept
Input vectors must be normalized.
Definition Vec3Math.h:142
JPL_INLINE simd clamp(const simd &value, const simd &minV, const simd &maxV) noexcept
Element-wise clamp.
Definition SIMD.h:1838
JPL_INLINE auto GetX(const Vec3Type &v) noexcept
Definition Vec3Traits.h:35
simd acos(const simd &in)
Definition SIMDMath.h:710
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 abs(const simd &vec) noexcept
Definition SIMD.h:1827
simd sin(simd x) noexcept
Definition SIMDMath.h:540
Minimal Vec3 class for SIMD operations on 4 Vec3 at a time.
Definition Vec3Pack.h:41
static JPL_INLINE Vec3Pack select(const simd_mask &conditionMask, const Vec3Pack &ifTrue, const Vec3Pack &ifFalse)
Definition Vec3Pack.h:97
Minimal 4-wide 32-bit float vector implementation for SIMD.
Definition SIMD.h:60
static JPL_INLINE simd c_0() noexcept
Frequently used constants.
Definition SIMD.h:456
static JPL_INLINE simd c_1() noexcept
Definition SIMD.h:461
static JPL_INLINE simd c_pi() noexcept
Definition SIMD.h:471
static JPL_INLINE simd select(const simd_mask &mask, const simd &a, const simd &b) noexcept
Component-wise select, returns 'a' if mask is true, 'b' otherwise.
Definition SIMD.h:1034