Use proper classes for Vector and Matrix types

This commit is contained in:
Chris Robinson
2018-12-12 04:22:11 -08:00
parent 19c5c41c70
commit 5a283c66ee
10 changed files with 198 additions and 189 deletions
+2 -2
View File
@@ -2425,8 +2425,8 @@ static ALvoid InitContext(ALCcontext *Context)
Context->ExtensionList = alExtList;
listener.Params.Matrix = aluMatrixf::Identity;
aluVectorSet(&listener.Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f);
listener.Params.Matrix = alu::Matrix::Identity();
listener.Params.Velocity = alu::Vector{};
listener.Params.Gain = listener.Gain;
listener.Params.MetersPerUnit = Context->MetersPerUnit;
listener.Params.DopplerFactor = Context->DopplerFactor;
+63 -97
View File
@@ -260,50 +260,30 @@ inline ALuint dither_rng(ALuint *seed) noexcept
}
inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
inline alu::Vector aluCrossproduct(const alu::Vector &in1, const alu::Vector &in2)
{
outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
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 ALfloat aluDotproduct(const aluVector *vec1, const aluVector *vec2)
inline ALfloat aluDotproduct(const alu::Vector &vec1, const alu::Vector &vec2)
{
return vec1->v[0]*vec2->v[0] + vec1->v[1]*vec2->v[1] + vec1->v[2]*vec2->v[2];
return vec1[0]*vec2[0] + vec1[1]*vec2[1] + vec1[2]*vec2[2];
}
ALfloat aluNormalize(ALfloat *vec)
{
const ALfloat length{std::sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])};
if(length > FLT_EPSILON)
{
ALfloat inv_length = 1.0f/length;
vec[0] *= inv_length;
vec[1] *= inv_length;
vec[2] *= inv_length;
return length;
}
vec[0] = vec[1] = vec[2] = 0.0f;
return 0.0f;
}
void aluMatrixfFloat3(ALfloat *vec, ALfloat w, const aluMatrixf *mtx)
alu::Vector operator*(const alu::Matrix &mtx, const alu::Vector &vec) noexcept
{
const ALfloat v[4]{ vec[0], vec[1], vec[2], w };
vec[0] = v[0]*mtx->m[0][0] + v[1]*mtx->m[1][0] + v[2]*mtx->m[2][0] + v[3]*mtx->m[3][0];
vec[1] = v[0]*mtx->m[0][1] + v[1]*mtx->m[1][1] + v[2]*mtx->m[2][1] + v[3]*mtx->m[3][1];
vec[2] = v[0]*mtx->m[0][2] + v[1]*mtx->m[1][2] + v[2]*mtx->m[2][2] + v[3]*mtx->m[3][2];
}
aluVector aluMatrixfVector(const aluMatrixf *mtx, const aluVector *vec)
{
aluVector v;
v.v[0] = vec->v[0]*mtx->m[0][0] + vec->v[1]*mtx->m[1][0] + vec->v[2]*mtx->m[2][0] + vec->v[3]*mtx->m[3][0];
v.v[1] = vec->v[0]*mtx->m[0][1] + vec->v[1]*mtx->m[1][1] + vec->v[2]*mtx->m[2][1] + vec->v[3]*mtx->m[3][1];
v.v[2] = vec->v[0]*mtx->m[0][2] + vec->v[1]*mtx->m[1][2] + vec->v[2]*mtx->m[2][2] + vec->v[3]*mtx->m[3][2];
v.v[3] = vec->v[0]*mtx->m[0][3] + vec->v[1]*mtx->m[1][3] + vec->v[2]*mtx->m[2][3] + vec->v[3]*mtx->m[3][3];
return v;
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]
};
}
@@ -350,29 +330,27 @@ bool CalcListenerParams(ALCcontext *Context)
if(!props) return false;
/* AT then UP */
ALfloat N[3]{ props->Forward[0], props->Forward[1], props->Forward[2] };
aluNormalize(N);
ALfloat V[3]{ props->Up[0], props->Up[1], props->Up[2] };
aluNormalize(V);
alu::Vector N{props->Forward[0], props->Forward[1], props->Forward[2], 0.0f};
N.normalize();
alu::Vector V{props->Up[0], props->Up[1], props->Up[2], 0.0f};
V.normalize();
/* Build and normalize right-vector */
ALfloat U[3];
aluCrossproduct(N, V, U);
aluNormalize(U);
alu::Vector U{aluCrossproduct(N, V)};
U.normalize();
aluMatrixfSet(&Listener.Params.Matrix,
U[0], V[0], -N[0], 0.0,
U[1], V[1], -N[1], 0.0,
U[2], V[2], -N[2], 0.0,
0.0, 0.0, 0.0, 1.0
);
Listener.Params.Matrix = alu::Matrix{
U[0], V[0], -N[0], 0.0f,
U[1], V[1], -N[1], 0.0f,
U[2], V[2], -N[2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
ALfloat P[3]{ props->Position[0], props->Position[1], props->Position[2] };
aluMatrixfFloat3(P, 1.0, &Listener.Params.Matrix);
aluMatrixfSetRow(&Listener.Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f);
alu::Vector P{props->Position[0], props->Position[1], props->Position[2], 1.0f};
P = Listener.Params.Matrix * P;
Listener.Params.Matrix.setRow(3, -P[0], -P[1], -P[2], 1.0f);
aluVector vel;
aluVectorSet(&vel, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
Listener.Params.Velocity = aluMatrixfVector(&Listener.Params.Matrix, &vel);
alu::Vector vel{props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f};
Listener.Params.Velocity = Listener.Params.Matrix * vel;
Listener.Params.Gain = props->Gain * Context->GainBoost;
@@ -666,46 +644,43 @@ void CalcPanningAndFilters(ALvoice *voice, const ALfloat Azi, const ALfloat Elev
* to the orientation.
*/
/* AT then UP */
ALfloat N[3]{ props->Orientation[0][0], props->Orientation[0][1],
props->Orientation[0][2] };
aluNormalize(N);
ALfloat V[3]{ props->Orientation[1][0], props->Orientation[1][1],
props->Orientation[1][2] };
aluNormalize(V);
alu::Vector N{props->Orientation[0][0], props->Orientation[0][1],
props->Orientation[0][2], 0.0f};
N.normalize();
alu::Vector V{props->Orientation[1][0], props->Orientation[1][1],
props->Orientation[1][2], 0.0f};
V.normalize();
if(!props->HeadRelative)
{
const aluMatrixf *lmatrix = &Listener.Params.Matrix;
aluMatrixfFloat3(N, 0.0f, lmatrix);
aluMatrixfFloat3(V, 0.0f, lmatrix);
N = Listener.Params.Matrix * N;
V = Listener.Params.Matrix * V;
}
/* Build and normalize right-vector */
ALfloat U[3];
aluCrossproduct(N, V, U);
aluNormalize(U);
alu::Vector U{aluCrossproduct(N, V)};
U.normalize();
/* Build a rotate + conversion matrix (FuMa -> ACN+N3D). NOTE: This
* matrix is transposed, for the inputs to align on the rows and
* outputs on the columns.
*/
aluMatrixf matrix;
aluMatrixfSet(&matrix,
const alu::Matrix matrix{
// ACN0 ACN1 ACN2 ACN3
SQRTF_2, 0.0f, 0.0f, 0.0f, // Ambi W
0.0f, -N[0]*SQRTF_3, N[1]*SQRTF_3, -N[2]*SQRTF_3, // Ambi X
0.0f, U[0]*SQRTF_3, -U[1]*SQRTF_3, U[2]*SQRTF_3, // Ambi Y
0.0f, -V[0]*SQRTF_3, V[1]*SQRTF_3, -V[2]*SQRTF_3 // Ambi Z
);
};
voice->Direct.Buffer = Device->FOAOut.Buffer;
voice->Direct.Channels = Device->FOAOut.NumChannels;
for(ALsizei c{0};c < num_channels;c++)
ComputePanGains(&Device->FOAOut, matrix.m[c], DryGain,
ComputePanGains(&Device->FOAOut, matrix[c].data(), DryGain,
voice->Direct.Params[c].Gains.Target);
for(ALsizei i{0};i < NumSends;i++)
{
if(const ALeffectslot *Slot{SendSlots[i]})
for(ALsizei c{0};c < num_channels;c++)
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, matrix.m[c],
ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, matrix[c].data(),
WetGain[i], voice->Send[i].Params[c].Gains.Target
);
}
@@ -1125,34 +1100,25 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
}
/* Transform source to listener space (convert to head relative) */
aluVector Position, Velocity, Direction;
aluVectorSet(&Position, props->Position[0], props->Position[1], props->Position[2], 1.0f);
aluVectorSet(&Direction, props->Direction[0], props->Direction[1], props->Direction[2], 0.0f);
aluVectorSet(&Velocity, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
alu::Vector Position{props->Position[0], props->Position[1], props->Position[2], 1.0f};
alu::Vector Velocity{props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f};
alu::Vector Direction{props->Direction[0], props->Direction[1], props->Direction[2], 0.0f};
if(props->HeadRelative == AL_FALSE)
{
const aluMatrixf *Matrix = &Listener.Params.Matrix;
/* Transform source vectors */
Position = aluMatrixfVector(Matrix, &Position);
Velocity = aluMatrixfVector(Matrix, &Velocity);
Direction = aluMatrixfVector(Matrix, &Direction);
Position = Listener.Params.Matrix * Position;
Velocity = Listener.Params.Matrix * Velocity;
Direction = Listener.Params.Matrix * Direction;
}
else
{
const aluVector *lvelocity = &Listener.Params.Velocity;
/* Offset the source velocity to be relative of the listener velocity */
Velocity.v[0] += lvelocity->v[0];
Velocity.v[1] += lvelocity->v[1];
Velocity.v[2] += lvelocity->v[2];
Velocity += Listener.Params.Velocity;
}
bool directional{aluNormalize(Direction.v) > 0.0f};
aluVector SourceToListener;
SourceToListener.v[0] = -Position.v[0];
SourceToListener.v[1] = -Position.v[1];
SourceToListener.v[2] = -Position.v[2];
SourceToListener.v[3] = 0.0f;
ALfloat Distance{aluNormalize(SourceToListener.v)};
const bool directional{Direction.normalize() > 0.0f};
alu::Vector SourceToListener{-Position[0], -Position[1], -Position[2], 0.0f};
const ALfloat Distance{SourceToListener.normalize()};
/* Initial source gain */
ALfloat DryGain{props->Gain};
@@ -1235,7 +1201,7 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
/* Calculate directional soundcones */
if(directional && props->InnerAngle < 360.0f)
{
ALfloat Angle{std::acos(aluDotproduct(&Direction, &SourceToListener))};
ALfloat Angle{std::acos(aluDotproduct(Direction, SourceToListener))};
Angle = RAD2DEG(Angle * ConeScale * 2.0f);
ALfloat ConeVolume, ConeHF;
@@ -1334,9 +1300,9 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
ALfloat DopplerFactor{props->DopplerFactor * Listener.Params.DopplerFactor};
if(DopplerFactor > 0.0f)
{
const aluVector *lvelocity = &Listener.Params.Velocity;
ALfloat vss{aluDotproduct(&Velocity, &SourceToListener) * DopplerFactor};
ALfloat vls{aluDotproduct(lvelocity, &SourceToListener) * DopplerFactor};
const alu::Vector &lvelocity = Listener.Params.Velocity;
ALfloat vss{aluDotproduct(Velocity, SourceToListener) * DopplerFactor};
ALfloat vls{aluDotproduct(lvelocity, SourceToListener) * DopplerFactor};
const ALfloat SpeedOfSound{Listener.Params.SpeedOfSound};
if(!(vls < SpeedOfSound))
@@ -1382,12 +1348,12 @@ void CalcAttnSourceParams(ALvoice *voice, const ALvoicePropsBase *props, const A
/* Clamp Y, in case rounding errors caused it to end up outside of
* -1...+1.
*/
ev = std::asin(clampf(-SourceToListener.v[1], -1.0f, 1.0f));
ev = std::asin(clampf(-SourceToListener[1], -1.0f, 1.0f));
/* Double negation on Z cancels out; negate once for changing source-
* to-listener to listener-to-source, and again for right-handed coords
* with -Z in front.
*/
az = std::atan2(-SourceToListener.v[0], SourceToListener.v[2]*ZScale);
az = std::atan2(-SourceToListener[0], SourceToListener[2]*ZScale);
}
ALfloat spread{0.0f};
+1 -1
View File
@@ -122,7 +122,7 @@ void ALautowahState::update(const ALCcontext *context, const ALeffectslot *slot,
mOutBuffer = device->FOAOut.Buffer;
mOutChannels = device->FOAOut.NumChannels;
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&device->FOAOut, aluMatrixf::Identity.m[i], slot->Params.Gain,
ComputePanGains(&device->FOAOut, alu::Matrix::Identity()[i].data(), slot->Params.Gain,
mChans[i].TargetGains);
}
+2 -1
View File
@@ -81,7 +81,8 @@ void ALcompressorState::update(const ALCcontext *context, const ALeffectslot *sl
mOutBuffer = device->FOAOut.Buffer;
mOutChannels = device->FOAOut.NumChannels;
for(ALsizei i{0};i < 4;i++)
ComputePanGains(&device->FOAOut, aluMatrixf::Identity.m[i], slot->Params.Gain, mGain[i]);
ComputePanGains(&device->FOAOut, alu::Matrix::Identity()[i].data(),
slot->Params.Gain, mGain[i]);
}
void ALcompressorState::process(ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesIn)[BUFFERSIZE], ALfloat (*RESTRICT SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+1 -1
View File
@@ -155,7 +155,7 @@ void ALequalizerState::update(const ALCcontext *context, const ALeffectslot *slo
mOutBuffer = device->FOAOut.Buffer;
mOutChannels = device->FOAOut.NumChannels;
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&device->FOAOut, aluMatrixf::Identity.m[i], slot->Params.Gain,
ComputePanGains(&device->FOAOut, alu::Matrix::Identity()[i].data(), slot->Params.Gain,
mChans[i].TargetGains);
}
+1 -1
View File
@@ -134,7 +134,7 @@ void ALmodulatorState::update(const ALCcontext *context, const ALeffectslot *slo
mOutBuffer = device->FOAOut.Buffer;
mOutChannels = device->FOAOut.NumChannels;
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&device->FOAOut, aluMatrixf::Identity.m[i], slot->Params.Gain,
ComputePanGains(&device->FOAOut, alu::Matrix::Identity()[i].data(), slot->Params.Gain,
mChans[i].TargetGains);
}
+38 -44
View File
@@ -68,20 +68,20 @@ ALfloat ReverbBoost = 1.0f;
* tetrahedron, but it's close enough. Should the model be extended to 8-lines
* in the future, true opposites can be used.
*/
static const aluMatrixf B2A = {{
{ 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f },
{ 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f },
{ 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f },
{ 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f }
}};
static constexpr alu::Matrix B2A{
0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f,
0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f,
0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f,
0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f
};
/* Converts A-Format to B-Format. */
static const aluMatrixf A2B = {{
{ 0.866025403785f, 0.866025403785f, 0.866025403785f, 0.866025403785f },
{ 0.866025403785f, -0.866025403785f, 0.866025403785f, -0.866025403785f },
{ 0.866025403785f, -0.866025403785f, -0.866025403785f, 0.866025403785f },
{ 0.866025403785f, 0.866025403785f, -0.866025403785f, -0.866025403785f }
}};
static constexpr alu::Matrix A2B{
0.866025403785f, 0.866025403785f, 0.866025403785f, 0.866025403785f,
0.866025403785f, -0.866025403785f, 0.866025403785f, -0.866025403785f,
0.866025403785f, -0.866025403785f, -0.866025403785f, 0.866025403785f,
0.866025403785f, 0.866025403785f, -0.866025403785f, -0.866025403785f
};
static const ALfloat FadeStep = 1.0f / FADE_SAMPLES;
@@ -755,12 +755,8 @@ static ALvoid UpdateLateLines(const ALfloat density, const ALfloat diffusion, co
* focal strength. This function results in a B-Format transformation matrix
* that spatially focuses the signal in the desired direction.
*/
static aluMatrixf GetTransformFromVector(const ALfloat *vec)
static alu::Matrix GetTransformFromVector(const ALfloat *vec)
{
aluMatrixf focus;
ALfloat norm[3];
ALfloat mag;
/* Normalize the panning vector according to the N3D scale, which has an
* extra sqrt(3) term on the directional components. Converting from OpenAL
* to B-Format also requires negating X (ACN 1) and Z (ACN 3). Note however
@@ -768,7 +764,8 @@ static aluMatrixf GetTransformFromVector(const ALfloat *vec)
* rest of OpenAL which use right-handed. This is fixed by negating Z,
* which cancels out with the B-Format Z negation.
*/
mag = sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
ALfloat norm[3];
ALfloat mag{sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])};
if(mag > 1.0f)
{
norm[0] = vec[0] / mag * -SQRTF_3;
@@ -787,50 +784,47 @@ static aluMatrixf GetTransformFromVector(const ALfloat *vec)
norm[2] = vec[2] * SQRTF_3;
}
aluMatrixfSet(&focus,
return alu::Matrix{
1.0f, 0.0f, 0.0f, 0.0f,
norm[0], 1.0f-mag, 0.0f, 0.0f,
norm[1], 0.0f, 1.0f-mag, 0.0f,
norm[2], 0.0f, 0.0f, 1.0f-mag
);
return focus;
};
}
/* Update the early and late 3D panning gains. */
static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, const ALfloat earlyGain, const ALfloat lateGain, ReverbState *State)
{
aluMatrixf transform, rot;
ALsizei i;
State->mOutBuffer = Device->FOAOut.Buffer;
State->mOutChannels = Device->FOAOut.NumChannels;
/* Note: _res is transposed. */
#define MATRIX_MULT(_res, _m1, _m2) do { \
int row, col; \
for(col = 0;col < 4;col++) \
{ \
for(row = 0;row < 4;row++) \
_res.m[col][row] = _m1.m[row][0]*_m2.m[0][col] + _m1.m[row][1]*_m2.m[1][col] + \
_m1.m[row][2]*_m2.m[2][col] + _m1.m[row][3]*_m2.m[3][col]; \
} \
} while(0)
/* Note: ret is transposed. */
auto MatrixMult = [](const alu::Matrix &m1, const alu::Matrix &m2) noexcept -> alu::Matrix
{
alu::Matrix ret;
for(int col{0};col < 4;col++)
{
for(int row{0};row < 4;row++)
ret[col][row] = m1[row][0]*m2[0][col] + m1[row][1]*m2[1][col] +
m1[row][2]*m2[2][col] + m1[row][3]*m2[3][col];
}
return ret;
};
/* Create a matrix that first converts A-Format to B-Format, then
* transforms the B-Format signal according to the panning vector.
*/
rot = GetTransformFromVector(ReflectionsPan);
MATRIX_MULT(transform, rot, A2B);
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&Device->FOAOut, transform.m[i], earlyGain,
alu::Matrix rot{GetTransformFromVector(ReflectionsPan)};
alu::Matrix transform{MatrixMult(rot, A2B)};
for(ALsizei i{0};i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&Device->FOAOut, transform[i].data(), earlyGain,
State->mEarly.PanGain[i]);
rot = GetTransformFromVector(LateReverbPan);
MATRIX_MULT(transform, rot, A2B);
for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&Device->FOAOut, transform.m[i], lateGain,
transform = MatrixMult(rot, A2B);
for(ALsizei i{0};i < MAX_EFFECT_CHANNELS;i++)
ComputePanGains(&Device->FOAOut, transform[i].data(), lateGain,
State->mLate.PanGain[i]);
#undef MATRIX_MULT
}
void ReverbState::update(const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props)
@@ -1380,7 +1374,7 @@ void ReverbState::process(ALsizei SamplesToDo, const ALfloat (*RESTRICT SamplesI
for(c = 0;c < NUM_LINES;c++)
{
std::fill(std::begin(afmt[c]), std::end(afmt[c]), 0.0f);
MixRowSamples(afmt[c], B2A.m[c],
MixRowSamples(afmt[c], B2A[c].data(),
SamplesIn, MAX_EFFECT_CHANNELS, base, todo
);
}
+2 -2
View File
@@ -35,8 +35,8 @@ struct ALlistener {
std::atomic<ALlistenerProps*> Update{nullptr};
struct {
aluMatrixf Matrix;
aluVector Velocity;
alu::Matrix Matrix;
alu::Vector Velocity;
ALfloat Gain;
ALfloat MetersPerUnit;
-8
View File
@@ -2,11 +2,3 @@
#include "config.h"
#include "vecmat.h"
const aluMatrixf aluMatrixf::Identity{{
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f },
}};
+88 -32
View File
@@ -1,46 +1,102 @@
#ifndef COMMON_VECMAT_H
#define COMMON_VECMAT_H
#include "AL/al.h"
#include <cmath>
#include <array>
#include <algorithm>
#include "math_defs.h"
struct aluVector {
alignas(16) ALfloat v[4];
namespace alu {
class Vector {
alignas(16) std::array<float,4> mVals{};
public:
constexpr Vector() noexcept = default;
constexpr Vector(float a, float b, float c, float d) noexcept
: mVals{{a, b, c, d}}
{ }
Vector(const Vector &rhs) noexcept
{ std::copy(rhs.mVals.begin(), rhs.mVals.end(), mVals.begin()); }
Vector& operator=(const Vector &rhs) noexcept
{
std::copy(rhs.mVals.begin(), rhs.mVals.end(), mVals.begin());
return *this;
}
float& operator[](size_t idx) noexcept { return mVals[idx]; }
constexpr const float& operator[](size_t idx) const noexcept { return mVals[idx]; }
Vector& operator+=(const Vector &rhs) noexcept
{
mVals[0] += rhs.mVals[0];
mVals[1] += rhs.mVals[1];
mVals[2] += rhs.mVals[2];
mVals[3] += rhs.mVals[3];
return *this;
}
float normalize()
{
const float length{std::sqrt(mVals[0]*mVals[0] + mVals[1]*mVals[1] + mVals[2]*mVals[2])};
if(length > FLT_EPSILON)
{
float inv_length = 1.0f/length;
mVals[0] *= inv_length;
mVals[1] *= inv_length;
mVals[2] *= inv_length;
return length;
}
mVals[0] = mVals[1] = mVals[2] = 0.0f;
return 0.0f;
}
};
inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
{
vector->v[0] = x;
vector->v[1] = y;
vector->v[2] = z;
vector->v[3] = w;
}
class Matrix {
alignas(16) std::array<std::array<float,4>,4> mVals{};
public:
constexpr Matrix() noexcept = default;
constexpr Matrix(float aa, float ab, float ac, float ad,
float ba, float bb, float bc, float bd,
float ca, float cb, float cc, float cd,
float da, float db, float dc, float dd) noexcept
: mVals{{{{aa, ab, ac, ad}}, {{ba, bb, bc, bd}}, {{ca, cb, cc, cd}}, {{da, db, dc, dd}}}}
{ }
Matrix(const Matrix &rhs) noexcept
{ std::copy(rhs.mVals.begin(), rhs.mVals.end(), mVals.begin()); }
struct aluMatrixf {
alignas(16) ALfloat m[4][4];
Matrix& operator=(const Matrix &rhs) noexcept
{
std::copy(rhs.mVals.begin(), rhs.mVals.end(), mVals.begin());
return *this;
}
static const aluMatrixf Identity;
std::array<float,4>& operator[](size_t idx) noexcept { return mVals[idx]; }
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
{
mVals[idx][0] = a;
mVals[idx][1] = b;
mVals[idx][2] = c;
mVals[idx][3] = d;
}
static const Matrix &Identity() noexcept
{
static constexpr Matrix identity{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
return identity;
}
};
inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
{
matrix->m[row][0] = m0;
matrix->m[row][1] = m1;
matrix->m[row][2] = m2;
matrix->m[row][3] = m3;
}
inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
{
aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
}
} // namespace alu
#endif /* COMMON_VECMAT_H */