Use doubles to calculate the listener matrix translation
To help stablize sources near the listener, when away from origin. Also clean up some related methods and move them to more appropriate places.
This commit is contained in:
+17
-42
@@ -362,33 +362,6 @@ auto GetAmbi2DLayout(AmbiLayout layouttype) noexcept -> const std::array<uint8_t
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline alu::Vector aluCrossproduct(const alu::Vector &in1, const alu::Vector &in2)
|
|
||||||
{
|
|
||||||
return alu::Vector{
|
|
||||||
in1[1]*in2[2] - in1[2]*in2[1],
|
|
||||||
in1[2]*in2[0] - in1[0]*in2[2],
|
|
||||||
in1[0]*in2[1] - in1[1]*in2[0],
|
|
||||||
0.0f
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float aluDotproduct(const alu::Vector &vec1, const alu::Vector &vec2)
|
|
||||||
{
|
|
||||||
return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
alu::Vector operator*(const alu::Matrix &mtx, const alu::Vector &vec) noexcept
|
|
||||||
{
|
|
||||||
return alu::Vector{
|
|
||||||
vec[0]*mtx[0][0] + vec[1]*mtx[1][0] + vec[2]*mtx[2][0] + vec[3]*mtx[3][0],
|
|
||||||
vec[0]*mtx[0][1] + vec[1]*mtx[1][1] + vec[2]*mtx[2][1] + vec[3]*mtx[3][1],
|
|
||||||
vec[0]*mtx[0][2] + vec[1]*mtx[1][2] + vec[2]*mtx[2][2] + vec[3]*mtx[3][2],
|
|
||||||
vec[0]*mtx[0][3] + vec[1]*mtx[1][3] + vec[2]*mtx[2][3] + vec[3]*mtx[3][3]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool CalcContextParams(ALCcontext *Context)
|
bool CalcContextParams(ALCcontext *Context)
|
||||||
{
|
{
|
||||||
ALcontextProps *props{Context->mUpdate.exchange(nullptr, std::memory_order_acq_rel)};
|
ALcontextProps *props{Context->mUpdate.exchange(nullptr, std::memory_order_acq_rel)};
|
||||||
@@ -418,19 +391,22 @@ bool CalcListenerParams(ALCcontext *Context)
|
|||||||
alu::Vector V{props->OrientUp[0], props->OrientUp[1], props->OrientUp[2], 0.0f};
|
alu::Vector V{props->OrientUp[0], props->OrientUp[1], props->OrientUp[2], 0.0f};
|
||||||
V.normalize();
|
V.normalize();
|
||||||
/* Build and normalize right-vector */
|
/* Build and normalize right-vector */
|
||||||
alu::Vector U{aluCrossproduct(N, V)};
|
alu::Vector U{N.cross_product(V)};
|
||||||
U.normalize();
|
U.normalize();
|
||||||
|
|
||||||
Listener.Params.Matrix = alu::Matrix{
|
const alu::MatrixR<double> rot{
|
||||||
U[0], V[0], -N[0], 0.0f,
|
U[0], V[0], -N[0], 0.0,
|
||||||
U[1], V[1], -N[1], 0.0f,
|
U[1], V[1], -N[1], 0.0,
|
||||||
U[2], V[2], -N[2], 0.0f,
|
U[2], V[2], -N[2], 0.0,
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
0.0, 0.0, 0.0, 1.0};
|
||||||
};
|
const alu::VectorR<double> pos{props->Position[0],props->Position[1],props->Position[2],1.0};
|
||||||
|
const alu::Vector P{alu::cast_to<float>(rot * pos)};
|
||||||
|
|
||||||
const alu::Vector P{Listener.Params.Matrix *
|
Listener.Params.Matrix = alu::Matrix{
|
||||||
alu::Vector{props->Position[0], props->Position[1], props->Position[2], 1.0f}};
|
U[0], V[0], -N[0], 0.0f,
|
||||||
Listener.Params.Matrix.setRow(3, -P[0], -P[1], -P[2], 1.0f);
|
U[1], V[1], -N[1], 0.0f,
|
||||||
|
U[2], V[2], -N[2], 0.0f,
|
||||||
|
-P[0], -P[1], -P[2], 1.0f};
|
||||||
|
|
||||||
const alu::Vector vel{props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f};
|
const alu::Vector vel{props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f};
|
||||||
Listener.Params.Velocity = Listener.Params.Matrix * vel;
|
Listener.Params.Velocity = Listener.Params.Matrix * vel;
|
||||||
@@ -905,7 +881,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con
|
|||||||
V = Listener.Params.Matrix * V;
|
V = Listener.Params.Matrix * V;
|
||||||
}
|
}
|
||||||
/* Build and normalize right-vector */
|
/* Build and normalize right-vector */
|
||||||
alu::Vector U{aluCrossproduct(N, V)};
|
alu::Vector U{N.cross_product(V)};
|
||||||
U.normalize();
|
U.normalize();
|
||||||
|
|
||||||
/* Build a rotation matrix. Manually fill the zeroth- and first-
|
/* Build a rotation matrix. Manually fill the zeroth- and first-
|
||||||
@@ -1427,8 +1403,7 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontex
|
|||||||
/* Calculate directional soundcones */
|
/* Calculate directional soundcones */
|
||||||
if(directional && props->InnerAngle < 360.0f)
|
if(directional && props->InnerAngle < 360.0f)
|
||||||
{
|
{
|
||||||
const float Angle{Rad2Deg(std::acos(-aluDotproduct(Direction, ToSource)) *
|
const float Angle{Rad2Deg(std::acos(Direction.dot_product(ToSource)) * ConeScale * -2.0f)};
|
||||||
ConeScale * 2.0f)};
|
|
||||||
|
|
||||||
float ConeGain, ConeHF;
|
float ConeGain, ConeHF;
|
||||||
if(!(Angle > props->InnerAngle))
|
if(!(Angle > props->InnerAngle))
|
||||||
@@ -1521,8 +1496,8 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ALCcontex
|
|||||||
if(DopplerFactor > 0.0f)
|
if(DopplerFactor > 0.0f)
|
||||||
{
|
{
|
||||||
const alu::Vector &lvelocity = Listener.Params.Velocity;
|
const alu::Vector &lvelocity = Listener.Params.Velocity;
|
||||||
float vss{aluDotproduct(Velocity, ToSource) * -DopplerFactor};
|
float vss{Velocity.dot_product(ToSource) * -DopplerFactor};
|
||||||
float vls{aluDotproduct(lvelocity, ToSource) * -DopplerFactor};
|
float vls{lvelocity.dot_product(ToSource) * -DopplerFactor};
|
||||||
|
|
||||||
const float SpeedOfSound{Listener.Params.SpeedOfSound};
|
const float SpeedOfSound{Listener.Params.SpeedOfSound};
|
||||||
if(!(vls < SpeedOfSound))
|
if(!(vls < SpeedOfSound))
|
||||||
|
|||||||
+71
-40
@@ -6,22 +6,26 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "alspan.h"
|
||||||
|
|
||||||
|
|
||||||
namespace alu {
|
namespace alu {
|
||||||
|
|
||||||
class Vector {
|
template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
|
||||||
alignas(16) std::array<float,4> mVals;
|
class VectorR {
|
||||||
|
alignas(16) std::array<T,4> mVals;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Vector() noexcept = default;
|
constexpr VectorR() noexcept = default;
|
||||||
constexpr Vector(float a, float b, float c, float d) noexcept
|
constexpr VectorR(const VectorR&) noexcept = default;
|
||||||
: mVals{{a, b, c, d}}
|
constexpr VectorR(T a, T b, T c, T d) noexcept : mVals{{a, b, c, d}} { }
|
||||||
{ }
|
|
||||||
|
|
||||||
float& operator[](size_t idx) noexcept { return mVals[idx]; }
|
constexpr VectorR& operator=(const VectorR&) noexcept = default;
|
||||||
constexpr const float& operator[](size_t idx) const noexcept { return mVals[idx]; }
|
|
||||||
|
|
||||||
Vector& operator+=(const Vector &rhs) noexcept
|
T& operator[](size_t idx) noexcept { return mVals[idx]; }
|
||||||
|
constexpr const T& operator[](size_t idx) const noexcept { return mVals[idx]; }
|
||||||
|
|
||||||
|
VectorR& operator+=(const VectorR &rhs) noexcept
|
||||||
{
|
{
|
||||||
mVals[0] += rhs.mVals[0];
|
mVals[0] += rhs.mVals[0];
|
||||||
mVals[1] += rhs.mVals[1];
|
mVals[1] += rhs.mVals[1];
|
||||||
@@ -30,55 +34,82 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
float normalize()
|
T normalize()
|
||||||
{
|
{
|
||||||
const float length{std::sqrt(mVals[0]*mVals[0] + mVals[1]*mVals[1] + mVals[2]*mVals[2])};
|
const T length{std::sqrt(mVals[0]*mVals[0] + mVals[1]*mVals[1] + mVals[2]*mVals[2])};
|
||||||
if(length > std::numeric_limits<float>::epsilon())
|
if(length > std::numeric_limits<T>::epsilon())
|
||||||
{
|
{
|
||||||
float inv_length = 1.0f/length;
|
T inv_length{T{1}/length};
|
||||||
mVals[0] *= inv_length;
|
mVals[0] *= inv_length;
|
||||||
mVals[1] *= inv_length;
|
mVals[1] *= inv_length;
|
||||||
mVals[2] *= inv_length;
|
mVals[2] *= inv_length;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
mVals[0] = mVals[1] = mVals[2] = 0.0f;
|
mVals[0] = mVals[1] = mVals[2] = T{0};
|
||||||
return 0.0f;
|
return T{0};
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class Matrix {
|
constexpr VectorR cross_product(const alu::VectorR<T> &rhs) const
|
||||||
alignas(16) std::array<std::array<float,4>,4> mVals;
|
{
|
||||||
|
return VectorR{
|
||||||
|
(*this)[1]*rhs[2] - (*this)[2]*rhs[1],
|
||||||
|
(*this)[2]*rhs[0] - (*this)[0]*rhs[2],
|
||||||
|
(*this)[0]*rhs[1] - (*this)[1]*rhs[0],
|
||||||
|
T{0}};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr T dot_product(const alu::VectorR<T> &rhs) const
|
||||||
|
{ return (*this)[0]*rhs[0] + (*this)[1]*rhs[1] + (*this)[2]*rhs[2]; }
|
||||||
|
};
|
||||||
|
using Vector = VectorR<float>;
|
||||||
|
|
||||||
|
template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
|
||||||
|
class MatrixR {
|
||||||
|
alignas(16) std::array<T,16> mVals;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Matrix() noexcept = default;
|
constexpr MatrixR() noexcept = default;
|
||||||
constexpr Matrix(float aa, float ab, float ac, float ad,
|
constexpr MatrixR(const MatrixR&) noexcept = default;
|
||||||
float ba, float bb, float bc, float bd,
|
constexpr MatrixR(T aa, T ab, T ac, T ad,
|
||||||
float ca, float cb, float cc, float cd,
|
T ba, T bb, T bc, T bd,
|
||||||
float da, float db, float dc, float dd) noexcept
|
T ca, T cb, T cc, T cd,
|
||||||
: mVals{{{{aa, ab, ac, ad}}, {{ba, bb, bc, bd}}, {{ca, cb, cc, cd}}, {{da, db, dc, dd}}}}
|
T da, T db, T dc, T dd) noexcept
|
||||||
|
: mVals{{aa,ab,ac,ad, ba,bb,bc,bd, ca,cb,cc,cd, da,db,dc,dd}}
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
std::array<float,4>& operator[](size_t idx) noexcept { return mVals[idx]; }
|
constexpr MatrixR& operator=(const MatrixR&) noexcept = default;
|
||||||
constexpr const std::array<float,4>& operator[](size_t idx) const noexcept { return mVals[idx]; }
|
|
||||||
|
|
||||||
void setRow(size_t idx, float a, float b, float c, float d) noexcept
|
auto operator[](size_t idx) noexcept { return al::span<T,4>{&mVals[idx*4], 4}; }
|
||||||
{
|
constexpr auto operator[](size_t idx) const noexcept
|
||||||
mVals[idx][0] = a;
|
{ return al::span<const T,4>{&mVals[idx*4], 4}; }
|
||||||
mVals[idx][1] = b;
|
|
||||||
mVals[idx][2] = c;
|
|
||||||
mVals[idx][3] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr Matrix Identity() noexcept
|
static constexpr MatrixR Identity() noexcept
|
||||||
{
|
{
|
||||||
return Matrix{
|
return MatrixR{
|
||||||
1.0f, 0.0f, 0.0f, 0.0f,
|
T{1}, T{0}, T{0}, T{0},
|
||||||
0.0f, 1.0f, 0.0f, 0.0f,
|
T{0}, T{1}, T{0}, T{0},
|
||||||
0.0f, 0.0f, 1.0f, 0.0f,
|
T{0}, T{0}, T{1}, T{0},
|
||||||
0.0f, 0.0f, 0.0f, 1.0f
|
T{0}, T{0}, T{0}, T{1}};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
using Matrix = MatrixR<float>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline VectorR<T> operator*(const MatrixR<T> &mtx, const VectorR<T> &vec) noexcept
|
||||||
|
{
|
||||||
|
return VectorR<T>{
|
||||||
|
vec[0]*mtx[0][0] + vec[1]*mtx[1][0] + vec[2]*mtx[2][0] + vec[3]*mtx[3][0],
|
||||||
|
vec[0]*mtx[0][1] + vec[1]*mtx[1][1] + vec[2]*mtx[2][1] + vec[3]*mtx[3][1],
|
||||||
|
vec[0]*mtx[0][2] + vec[1]*mtx[1][2] + vec[2]*mtx[2][2] + vec[3]*mtx[3][2],
|
||||||
|
vec[0]*mtx[0][3] + vec[1]*mtx[1][3] + vec[2]*mtx[2][3] + vec[3]*mtx[3][3]};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename U, typename T>
|
||||||
|
inline VectorR<U> cast_to(const VectorR<T> &vec) noexcept
|
||||||
|
{
|
||||||
|
return VectorR<U>{static_cast<U>(vec[0]), static_cast<U>(vec[1]),
|
||||||
|
static_cast<U>(vec[2]), static_cast<U>(vec[3])};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace alu
|
} // namespace alu
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user