Migrated gl matrix stack to LLMatrix4a
This commit is contained in:
@@ -31,15 +31,72 @@
|
||||
#include "m4math.h"
|
||||
#include "m3math.h"
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLMatrix4a
|
||||
{
|
||||
public:
|
||||
private:
|
||||
LL_ALIGN_16(LLVector4a mMatrix[4]);
|
||||
public:
|
||||
enum
|
||||
{
|
||||
ROW_FWD = 0,
|
||||
ROW_LEFT,
|
||||
ROW_UP,
|
||||
ROW_TRANS
|
||||
};
|
||||
|
||||
void* operator new(size_t size)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
|
||||
LLMatrix4a()
|
||||
{}
|
||||
LLMatrix4a(const LLQuad& q1,const LLQuad& q2,const LLQuad& q3,const LLQuad& q4)
|
||||
{
|
||||
mMatrix[0] = q1;
|
||||
mMatrix[1] = q2;
|
||||
mMatrix[2] = q3;
|
||||
mMatrix[3] = q4;
|
||||
}
|
||||
LLMatrix4a(const LLQuaternion2& quat)
|
||||
{
|
||||
const LLVector4a& xyzw = quat.getVector4a();
|
||||
LLVector4a nyxwz = _mm_shuffle_ps(xyzw, xyzw, _MM_SHUFFLE(2,3,0,1));
|
||||
nyxwz.negate();
|
||||
|
||||
const LLVector4a xnyynx = _mm_unpacklo_ps(xyzw,nyxwz);
|
||||
const LLVector4a znwwnz = _mm_unpackhi_ps(xyzw,nyxwz);
|
||||
|
||||
LLMatrix4a mata;
|
||||
mata.setRow<0>(_mm_shuffle_ps(xyzw, xnyynx, _MM_SHUFFLE(0,1,2,3)));
|
||||
mata.setRow<1>(_mm_shuffle_ps(znwwnz, xyzw, _MM_SHUFFLE(1,0,2,3)));
|
||||
mata.setRow<2>(_mm_shuffle_ps(xnyynx, xyzw, _MM_SHUFFLE(2,3,3,2)));
|
||||
mata.setRow<3>(_mm_shuffle_ps(xnyynx, znwwnz, _MM_SHUFFLE(2,3,1,3)));
|
||||
|
||||
LLMatrix4a matb;
|
||||
matb.setRow<0>(_mm_shuffle_ps(xyzw, xnyynx, _MM_SHUFFLE(3,1,2,3)));
|
||||
matb.setRow<1>(_mm_shuffle_ps(znwwnz, xnyynx, _MM_SHUFFLE(1,0,2,3)));
|
||||
matb.setRow<2>(_mm_shuffle_ps(xnyynx, znwwnz, _MM_SHUFFLE(3,2,3,2)));
|
||||
matb.setRow<3>(xyzw);
|
||||
|
||||
setMul(matb,mata);
|
||||
}
|
||||
|
||||
inline F32* getF32ptr()
|
||||
{
|
||||
return mMatrix[0].getF32ptr();
|
||||
}
|
||||
|
||||
inline const F32* getF32ptr() const
|
||||
{
|
||||
return mMatrix[0].getF32ptr();
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
@@ -60,10 +117,10 @@ public:
|
||||
|
||||
inline void loadu(const LLMatrix4& src)
|
||||
{
|
||||
mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]);
|
||||
mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]);
|
||||
mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]);
|
||||
mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]);
|
||||
mMatrix[0].loadua(src.mMatrix[0]);
|
||||
mMatrix[1].loadua(src.mMatrix[1]);
|
||||
mMatrix[2].loadua(src.mMatrix[2]);
|
||||
mMatrix[3].loadua(src.mMatrix[3]);
|
||||
}
|
||||
|
||||
inline void loadu(const LLMatrix3& src)
|
||||
@@ -76,10 +133,10 @@ public:
|
||||
|
||||
inline void loadu(const F32* src)
|
||||
{
|
||||
mMatrix[0] = _mm_loadu_ps(src+0);
|
||||
mMatrix[1] = _mm_loadu_ps(src+4);
|
||||
mMatrix[2] = _mm_loadu_ps(src+8);
|
||||
mMatrix[3] = _mm_loadu_ps(src+12);
|
||||
mMatrix[0].loadua(src+0);
|
||||
mMatrix[1].loadua(src+4);
|
||||
mMatrix[2].loadua(src+8);
|
||||
mMatrix[3].loadua(src+12);
|
||||
}
|
||||
|
||||
inline void add(const LLMatrix4a& rhs)
|
||||
@@ -90,6 +147,75 @@ public:
|
||||
mMatrix[3].add(rhs.mMatrix[3]);
|
||||
}
|
||||
|
||||
inline void mul(const LLMatrix4a& rhs)
|
||||
{
|
||||
//Not using rotate4 to avoid extra copy of *this.
|
||||
LLVector4a x0,y0,z0,w0;
|
||||
LLVector4a x1,y1,z1,w1;
|
||||
LLVector4a x2,y2,z2,w2;
|
||||
LLVector4a x3,y3,z3,w3;
|
||||
|
||||
//16 shuffles
|
||||
x0.splat<0>(rhs.mMatrix[0]);
|
||||
x1.splat<0>(rhs.mMatrix[1]);
|
||||
x2.splat<0>(rhs.mMatrix[2]);
|
||||
x3.splat<0>(rhs.mMatrix[3]);
|
||||
|
||||
y0.splat<1>(rhs.mMatrix[0]);
|
||||
y1.splat<1>(rhs.mMatrix[1]);
|
||||
y2.splat<1>(rhs.mMatrix[2]);
|
||||
y3.splat<1>(rhs.mMatrix[3]);
|
||||
|
||||
z0.splat<2>(rhs.mMatrix[0]);
|
||||
z1.splat<2>(rhs.mMatrix[1]);
|
||||
z2.splat<2>(rhs.mMatrix[2]);
|
||||
z3.splat<2>(rhs.mMatrix[3]);
|
||||
|
||||
w0.splat<3>(rhs.mMatrix[0]);
|
||||
w1.splat<3>(rhs.mMatrix[1]);
|
||||
w2.splat<3>(rhs.mMatrix[2]);
|
||||
w3.splat<3>(rhs.mMatrix[3]);
|
||||
|
||||
//16 muls
|
||||
x0.mul(mMatrix[0]);
|
||||
x1.mul(mMatrix[0]);
|
||||
x2.mul(mMatrix[0]);
|
||||
x3.mul(mMatrix[0]);
|
||||
|
||||
y0.mul(mMatrix[1]);
|
||||
y1.mul(mMatrix[1]);
|
||||
y2.mul(mMatrix[1]);
|
||||
y3.mul(mMatrix[1]);
|
||||
|
||||
z0.mul(mMatrix[2]);
|
||||
z1.mul(mMatrix[2]);
|
||||
z2.mul(mMatrix[2]);
|
||||
z3.mul(mMatrix[2]);
|
||||
|
||||
w0.mul(mMatrix[3]);
|
||||
w1.mul(mMatrix[3]);
|
||||
w2.mul(mMatrix[3]);
|
||||
w3.mul(mMatrix[3]);
|
||||
|
||||
//12 adds
|
||||
x0.add(y0);
|
||||
z0.add(w0);
|
||||
|
||||
x1.add(y1);
|
||||
z1.add(w1);
|
||||
|
||||
x2.add(y2);
|
||||
z2.add(w2);
|
||||
|
||||
x3.add(y3);
|
||||
z3.add(w3);
|
||||
|
||||
mMatrix[0].setAdd(x0,z0);
|
||||
mMatrix[1].setAdd(x1,z1);
|
||||
mMatrix[2].setAdd(x2,z2);
|
||||
mMatrix[3].setAdd(x3,z3);
|
||||
}
|
||||
|
||||
inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2)
|
||||
{
|
||||
mMatrix[0] = r0;
|
||||
@@ -97,6 +223,44 @@ public:
|
||||
mMatrix[2] = r2;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline void setRow(const LLVector4a& row)
|
||||
{
|
||||
mMatrix[N] = row;
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline const LLVector4a& getRow() const
|
||||
{
|
||||
return mMatrix[N];
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline LLVector4a& getRow()
|
||||
{
|
||||
return mMatrix[N];
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline void setColumn(const LLVector4a& col)
|
||||
{
|
||||
mMatrix[0].copyComponent<N>(col.getScalarAt<0>());
|
||||
mMatrix[1].copyComponent<N>(col.getScalarAt<1>());
|
||||
mMatrix[2].copyComponent<N>(col.getScalarAt<2>());
|
||||
mMatrix[3].copyComponent<N>(col.getScalarAt<3>());
|
||||
}
|
||||
|
||||
template<int N>
|
||||
inline LLVector4a getColumn()
|
||||
{
|
||||
LLVector4a v;
|
||||
v.copyComponent<0>(mMatrix[0].getScalarAt<N>());
|
||||
v.copyComponent<1>(mMatrix[1].getScalarAt<N>());
|
||||
v.copyComponent<2>(mMatrix[2].getScalarAt<N>());
|
||||
v.copyComponent<3>(mMatrix[3].getScalarAt<N>());
|
||||
return v;
|
||||
}
|
||||
|
||||
inline void setMul(const LLMatrix4a& m, const F32 s)
|
||||
{
|
||||
mMatrix[0].setMul(m.mMatrix[0], s);
|
||||
@@ -136,13 +300,14 @@ public:
|
||||
|
||||
//Singu Note: Don't mess with this. It's intentionally different from LL's.
|
||||
// Note how res isn't manipulated until the very end.
|
||||
//Fast(er). Treats v[VW] as 0.f
|
||||
inline void rotate(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
@@ -152,14 +317,15 @@ public:
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
|
||||
//Proper. v[VW] as v[VW]
|
||||
inline void rotate4(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z,w;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
w = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
w.splat<3>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
@@ -171,14 +337,15 @@ public:
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
|
||||
//Fast(er). Treats v[VW] as 1.f
|
||||
inline void affineTransform(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z;
|
||||
|
||||
x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
|
||||
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
z.mul(mMatrix[2]);
|
||||
@@ -188,6 +355,36 @@ public:
|
||||
res.setAdd(x,z);
|
||||
}
|
||||
|
||||
inline void perspectiveTransform(const LLVector4a& v, LLVector4a& res) const
|
||||
{
|
||||
LLVector4a x,y,z,s,t,p,q;
|
||||
|
||||
x.splat<0>(v);
|
||||
y.splat<1>(v);
|
||||
z.splat<2>(v);
|
||||
|
||||
s.splat<3>(mMatrix[0]);
|
||||
t.splat<3>(mMatrix[1]);
|
||||
p.splat<3>(mMatrix[2]);
|
||||
q.splat<3>(mMatrix[3]);
|
||||
|
||||
s.mul(x);
|
||||
t.mul(y);
|
||||
p.mul(z);
|
||||
q.add(s);
|
||||
t.add(p);
|
||||
q.add(t);
|
||||
|
||||
x.mul(mMatrix[0]);
|
||||
y.mul(mMatrix[1]);
|
||||
z.mul(mMatrix[2]);
|
||||
|
||||
x.add(y);
|
||||
z.add(mMatrix[3]);
|
||||
res.setAdd(x,z);
|
||||
res.div(q);
|
||||
}
|
||||
|
||||
inline void transpose()
|
||||
{
|
||||
__m128 q1 = _mm_unpackhi_ps(mMatrix[0],mMatrix[1]);
|
||||
@@ -313,9 +510,186 @@ public:
|
||||
mMatrix[1] = _mm_shuffle_ps(iA,iB,0x22);
|
||||
mMatrix[2] = _mm_shuffle_ps(iC,iD,0x77);
|
||||
mMatrix[3] = _mm_shuffle_ps(iC,iD,0x22);
|
||||
|
||||
return *(float*)&det;
|
||||
|
||||
F32 ret;
|
||||
_mm_store_ss(&ret,det);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
//=============Affine transformation matrix only=========================
|
||||
|
||||
//Multiply matrix with a pure translation matrix.
|
||||
inline void applyTranslation_affine(const F32& x, const F32& y, const F32& z)
|
||||
{
|
||||
const LLVector4a xyz0(x,y,z,0); //load
|
||||
LLVector4a xxxx;
|
||||
xxxx.splat<0>(xyz0);
|
||||
LLVector4a yyyy;
|
||||
yyyy.splat<1>(xyz0);
|
||||
LLVector4a zzzz;
|
||||
zzzz.splat<2>(xyz0);
|
||||
|
||||
LLVector4a sum1;
|
||||
LLVector4a sum2;
|
||||
LLVector4a sum3;
|
||||
|
||||
sum1.setMul(xxxx,mMatrix[0]);
|
||||
sum2.setMul(yyyy,mMatrix[1]);
|
||||
sum3.setMul(zzzz,mMatrix[2]);
|
||||
|
||||
mMatrix[3].add(sum1);
|
||||
mMatrix[3].add(sum2);
|
||||
mMatrix[3].add(sum3);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure translation matrix.
|
||||
inline void applyTranslation_affine(const LLVector3& trans)
|
||||
{
|
||||
applyTranslation_affine(trans.mV[VX],trans.mV[VY],trans.mV[VZ]);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const F32& x, const F32& y, const F32& z)
|
||||
{
|
||||
const LLVector4a xyz0(x,y,z,0); //load
|
||||
LLVector4a xxxx;
|
||||
xxxx.splat<0>(xyz0);
|
||||
LLVector4a yyyy;
|
||||
yyyy.splat<1>(xyz0);
|
||||
LLVector4a zzzz;
|
||||
zzzz.splat<2>(xyz0);
|
||||
|
||||
mMatrix[0].mul(xxxx);
|
||||
mMatrix[1].mul(yyyy);
|
||||
mMatrix[2].mul(zzzz);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const LLVector3& scale)
|
||||
{
|
||||
applyScale_affine(scale.mV[VX],scale.mV[VY],scale.mV[VZ]);
|
||||
}
|
||||
|
||||
//Multiply matrix with a pure scale matrix.
|
||||
inline void applyScale_affine(const F32& s)
|
||||
{
|
||||
const LLVector4a scale(s); //load
|
||||
mMatrix[0].mul(scale);
|
||||
mMatrix[1].mul(scale);
|
||||
mMatrix[2].mul(scale);
|
||||
}
|
||||
|
||||
//Direct addition to row3.
|
||||
inline void translate_affine(const LLVector3& trans)
|
||||
{
|
||||
LLVector4a translation;
|
||||
translation.load3(trans.mV);
|
||||
mMatrix[3].add(translation);
|
||||
}
|
||||
|
||||
//Direct assignment of row3.
|
||||
inline void setTranslate_affine(const LLVector3& trans)
|
||||
{
|
||||
static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[3*4]);
|
||||
|
||||
LLVector4a translation;
|
||||
translation.load3(trans.mV);
|
||||
|
||||
mMatrix[3].setSelectWithMask(mask,mMatrix[3],translation);
|
||||
}
|
||||
|
||||
inline void mul_affine(const LLMatrix4a& rhs)
|
||||
{
|
||||
LLVector4a x0,y0,z0;
|
||||
LLVector4a x1,y1,z1;
|
||||
LLVector4a x2,y2,z2;
|
||||
LLVector4a x3,y3,z3;
|
||||
|
||||
//12 shuffles
|
||||
x0.splat<0>(rhs.mMatrix[0]);
|
||||
x1.splat<0>(rhs.mMatrix[1]);
|
||||
x2.splat<0>(rhs.mMatrix[2]);
|
||||
x3.splat<0>(rhs.mMatrix[3]);
|
||||
|
||||
y0.splat<1>(rhs.mMatrix[0]);
|
||||
y1.splat<1>(rhs.mMatrix[1]);
|
||||
y2.splat<1>(rhs.mMatrix[2]);
|
||||
y3.splat<1>(rhs.mMatrix[3]);
|
||||
|
||||
z0.splat<2>(rhs.mMatrix[0]);
|
||||
z1.splat<2>(rhs.mMatrix[1]);
|
||||
z2.splat<2>(rhs.mMatrix[2]);
|
||||
z3.splat<2>(rhs.mMatrix[3]);
|
||||
|
||||
//12 muls
|
||||
x0.mul(mMatrix[0]);
|
||||
x1.mul(mMatrix[0]);
|
||||
x2.mul(mMatrix[0]);
|
||||
x3.mul(mMatrix[0]);
|
||||
|
||||
y0.mul(mMatrix[1]);
|
||||
y1.mul(mMatrix[1]);
|
||||
y2.mul(mMatrix[1]);
|
||||
y3.mul(mMatrix[1]);
|
||||
|
||||
z0.mul(mMatrix[2]);
|
||||
z1.mul(mMatrix[2]);
|
||||
z2.mul(mMatrix[2]);
|
||||
z3.mul(mMatrix[2]);
|
||||
|
||||
//9 adds
|
||||
x0.add(y0);
|
||||
|
||||
x1.add(y1);
|
||||
|
||||
x2.add(y2);
|
||||
|
||||
x3.add(y3);
|
||||
z3.add(mMatrix[3]);
|
||||
|
||||
mMatrix[0].setAdd(x0,z0);
|
||||
mMatrix[1].setAdd(x1,z1);
|
||||
mMatrix[2].setAdd(x2,z2);
|
||||
mMatrix[3].setAdd(x3,z3);
|
||||
}
|
||||
|
||||
inline void extractRotation_affine()
|
||||
{
|
||||
static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[3*4]);
|
||||
mMatrix[0].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[0]);
|
||||
mMatrix[1].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[1]);
|
||||
mMatrix[2].setSelectWithMask(mask,_mm_setzero_ps(),mMatrix[2]);
|
||||
mMatrix[3].setSelectWithMask(mask,LLVector4a(1.f),_mm_setzero_ps());
|
||||
}
|
||||
|
||||
//======================Logic====================
|
||||
inline bool isIdentity() const
|
||||
{
|
||||
static LLMatrix4a mins;
|
||||
static LLMatrix4a maxs;
|
||||
static LLVector4a delta(0.0001f);
|
||||
|
||||
static bool init_mins = ( mins.setIdentity(),
|
||||
mins.getRow<0>().sub(delta),
|
||||
mins.getRow<1>().sub(delta),
|
||||
mins.getRow<2>().sub(delta),
|
||||
mins.getRow<3>().sub(delta), true );
|
||||
static bool init_maxs = ( maxs.setIdentity(),
|
||||
maxs.getRow<0>().add(delta),
|
||||
maxs.getRow<1>().add(delta),
|
||||
maxs.getRow<2>().add(delta),
|
||||
maxs.getRow<3>().add(delta), true );
|
||||
|
||||
LLVector4a mask1 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[0],mins.getRow<0>()), _mm_cmplt_ps(mMatrix[0],maxs.getRow<0>()));
|
||||
LLVector4a mask2 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[1],mins.getRow<1>()), _mm_cmplt_ps(mMatrix[1],maxs.getRow<1>()));
|
||||
LLVector4a mask3 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[2],mins.getRow<2>()), _mm_cmplt_ps(mMatrix[2],maxs.getRow<2>()));
|
||||
LLVector4a mask4 = _mm_and_ps(_mm_cmpgt_ps(mMatrix[3],mins.getRow<3>()), _mm_cmplt_ps(mMatrix[3],maxs.getRow<3>()));
|
||||
|
||||
mask1 = _mm_and_ps(mask1,mask2);
|
||||
mask2 = _mm_and_ps(mask3,mask4);
|
||||
|
||||
return _mm_movemask_epi8(_mm_castps_si128(_mm_and_ps(mask1, mask2))) == 0xFFFF;
|
||||
}
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -84,6 +84,8 @@ public:
|
||||
// Quantize this quaternion to 16 bit precision
|
||||
inline void quantize16();
|
||||
|
||||
inline void mul(const LLQuaternion2& b);
|
||||
|
||||
/////////////////////////
|
||||
// Quaternion inspection
|
||||
/////////////////////////
|
||||
|
||||
@@ -50,6 +50,39 @@ inline LLVector4a& LLQuaternion2::getVector4aRw()
|
||||
return mQ;
|
||||
}
|
||||
|
||||
inline void LLQuaternion2::mul(const LLQuaternion2& b)
|
||||
{
|
||||
static LL_ALIGN_16(const unsigned int signMask[4]) = { 0x0, 0x0, 0x0, 0x80000000 };
|
||||
|
||||
LLVector4a sum1, sum2, prod1, prod2, prod3, prod4;
|
||||
const LLVector4a& va = mQ;
|
||||
const LLVector4a& vb = b.getVector4a();
|
||||
|
||||
// [VX] [VY] [VZ] [VW]
|
||||
//prod1: +wx +wy +wz +ww Bwwww*Axyzw
|
||||
//prod2: +xw +yw +zw -xx Bxyzx*Awwwx [VW] sign flip
|
||||
//prod3: +yz +zx +xy -yy Byzxy*Azxyy [VW] sign flip
|
||||
//prod4: -zy -xz -yx -zz Bzxyz*Ayzzz
|
||||
|
||||
const LLVector4a Bwwww = _mm_shuffle_ps(vb,vb,_MM_SHUFFLE(3,3,3,3));
|
||||
const LLVector4a Bxyzx = _mm_shuffle_ps(vb,vb,_MM_SHUFFLE(0,2,1,0));
|
||||
const LLVector4a Awwwx = _mm_shuffle_ps(va,va,_MM_SHUFFLE(0,3,3,3));
|
||||
const LLVector4a Byzxy = _mm_shuffle_ps(vb,vb,_MM_SHUFFLE(1,0,2,1));
|
||||
const LLVector4a Azxyy = _mm_shuffle_ps(va,va,_MM_SHUFFLE(1,1,0,2));
|
||||
const LLVector4a Bzxyz = _mm_shuffle_ps(vb,vb,_MM_SHUFFLE(2,1,0,2));
|
||||
const LLVector4a Ayzxz = _mm_shuffle_ps(va,va,_MM_SHUFFLE(2,0,2,1));
|
||||
|
||||
prod1.setMul(Bwwww,va);
|
||||
prod2.setMul(Bxyzx,Awwwx);
|
||||
prod3.setMul(Byzxy,Azxyy);
|
||||
prod4.setMul(Bzxyz,Ayzxz);
|
||||
|
||||
sum1.setAdd(prod2,prod3);
|
||||
sum1 = _mm_xor_ps(sum1, _mm_load_ps((const float*)signMask));
|
||||
sum2.setSub(prod1,prod4);
|
||||
mQ.setAdd(sum1,sum2);
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// Quaternion modification
|
||||
/////////////////////////
|
||||
|
||||
@@ -127,7 +127,7 @@ public:
|
||||
inline void loadua(const F32* src);
|
||||
|
||||
// Load only three floats beginning at address 'src'. Slowest method.
|
||||
inline void load3(const F32* src);
|
||||
inline void load3(const F32* src, const F32 w=0.f);
|
||||
|
||||
// Store to a 16-byte aligned memory address
|
||||
inline void store4a(F32* dst) const;
|
||||
@@ -169,6 +169,9 @@ public:
|
||||
|
||||
// Set all 4 elements to element i of v, with i NOT known at compile time
|
||||
inline void splat(const LLVector4a& v, U32 i);
|
||||
|
||||
// Sets element N to that of src's element N. Much cleaner than.. {LLVector4Logical mask; mask.clear(); mask.setElement<N>(); target.setSelectWithMask(mask,src,target);}
|
||||
template <int N> inline void copyComponent(const LLVector4a& src);
|
||||
|
||||
// Select bits from sourceIfTrue and sourceIfFalse according to bits in mask
|
||||
inline void setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse );
|
||||
@@ -281,6 +284,8 @@ public:
|
||||
void quantize8( const LLVector4a& low, const LLVector4a& high );
|
||||
void quantize16( const LLVector4a& low, const LLVector4a& high );
|
||||
|
||||
void negate();
|
||||
|
||||
////////////////////////////////////
|
||||
// LOGICAL
|
||||
////////////////////////////////////
|
||||
|
||||
@@ -41,11 +41,11 @@ inline void LLVector4a::loadua(const F32* src)
|
||||
}
|
||||
|
||||
// Load only three floats beginning at address 'src'. Slowest method.
|
||||
inline void LLVector4a::load3(const F32* src)
|
||||
inline void LLVector4a::load3(const F32* src, const F32 w)
|
||||
{
|
||||
// mQ = { 0.f, src[2], src[1], src[0] } = { W, Z, Y, X }
|
||||
// NB: This differs from the convention of { Z, Y, X, W }
|
||||
mQ = _mm_set_ps(0.f, src[2], src[1], src[0]);
|
||||
mQ = _mm_set_ps(w, src[2], src[1], src[0]);
|
||||
}
|
||||
|
||||
// Store to a 16-byte aligned memory address
|
||||
@@ -154,6 +154,13 @@ inline void LLVector4a::splat(const LLVector4a& v, U32 i)
|
||||
}
|
||||
}
|
||||
|
||||
// Sets element N to that of src's element N
|
||||
template <int N> inline void LLVector4a::copyComponent(const LLVector4a& src)
|
||||
{
|
||||
static const LLVector4Logical mask = _mm_load_ps((F32*)&S_V4LOGICAL_MASK_TABLE[N*4]);
|
||||
setSelectWithMask(mask,src,mQ);
|
||||
}
|
||||
|
||||
// Select bits from sourceIfTrue and sourceIfFalse according to bits in mask
|
||||
inline void LLVector4a::setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse )
|
||||
{
|
||||
@@ -529,6 +536,11 @@ inline void LLVector4a::clamp( const LLVector4a& low, const LLVector4a& high )
|
||||
setSelectWithMask( lowMask, low, *this );
|
||||
}
|
||||
|
||||
inline void LLVector4a::negate()
|
||||
{
|
||||
static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 };
|
||||
mQ = _mm_xor_ps(*reinterpret_cast<const LLQuad*>(signMask), mQ);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
// LOGICAL
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
{
|
||||
static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
|
||||
ll_assert_aligned(allOnes,16);
|
||||
mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) );
|
||||
mQ = _mm_andnot_ps( mQ, _mm_load_ps((F32*)(allOnes)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public:
|
||||
|
||||
template<int N> void setElement()
|
||||
{
|
||||
mQ = _mm_or_ps( mQ, *reinterpret_cast<const LLQuad*>(S_V4LOGICAL_MASK_TABLE + 4*N) );
|
||||
mQ = _mm_or_ps( mQ, _mm_load_ps( (F32*)&S_V4LOGICAL_MASK_TABLE[4*N] ) );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -96,30 +96,29 @@ void LLXformMatrix::updateMatrix(BOOL update_bounds)
|
||||
{
|
||||
update();
|
||||
|
||||
mWorldMatrix.initAll(mScale, mWorldRotation, mWorldPosition);
|
||||
LLMatrix4 world_matrix;
|
||||
world_matrix.initAll(mScale, mWorldRotation, mWorldPosition);
|
||||
mWorldMatrix.loadu(world_matrix);
|
||||
|
||||
if (update_bounds && (mChanged & MOVED))
|
||||
{
|
||||
mMin.mV[0] = mMax.mV[0] = mWorldMatrix.mMatrix[3][0];
|
||||
mMin.mV[1] = mMax.mV[1] = mWorldMatrix.mMatrix[3][1];
|
||||
mMin.mV[2] = mMax.mV[2] = mWorldMatrix.mMatrix[3][2];
|
||||
mMax = mMin = mWorldMatrix.getRow<3>();
|
||||
|
||||
F32 f0 = (fabs(mWorldMatrix.mMatrix[0][0])+fabs(mWorldMatrix.mMatrix[1][0])+fabs(mWorldMatrix.mMatrix[2][0])) * 0.5f;
|
||||
F32 f1 = (fabs(mWorldMatrix.mMatrix[0][1])+fabs(mWorldMatrix.mMatrix[1][1])+fabs(mWorldMatrix.mMatrix[2][1])) * 0.5f;
|
||||
F32 f2 = (fabs(mWorldMatrix.mMatrix[0][2])+fabs(mWorldMatrix.mMatrix[1][2])+fabs(mWorldMatrix.mMatrix[2][2])) * 0.5f;
|
||||
LLVector4a total_sum,sum1,sum2;
|
||||
total_sum.setAbs(mWorldMatrix.getRow<0>());
|
||||
sum1.setAbs(mWorldMatrix.getRow<1>());
|
||||
sum2.setAbs(mWorldMatrix.getRow<2>());
|
||||
sum1.add(sum2);
|
||||
total_sum.add(sum1);
|
||||
total_sum.mul(.5f);
|
||||
|
||||
mMin.mV[0] -= f0;
|
||||
mMin.mV[1] -= f1;
|
||||
mMin.mV[2] -= f2;
|
||||
|
||||
mMax.mV[0] += f0;
|
||||
mMax.mV[1] += f1;
|
||||
mMax.mV[2] += f2;
|
||||
mMax.add(total_sum);
|
||||
mMin.sub(total_sum);
|
||||
}
|
||||
}
|
||||
|
||||
void LLXformMatrix::getMinMax(LLVector3& min, LLVector3& max) const
|
||||
{
|
||||
min = mMin;
|
||||
max = mMax;
|
||||
min.set(mMin.getF32ptr());
|
||||
max.set(mMax.getF32ptr());
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "v3math.h"
|
||||
#include "m4math.h"
|
||||
#include "llmatrix4a.h"
|
||||
#include "llquaternion.h"
|
||||
|
||||
const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
|
||||
@@ -130,20 +131,21 @@ public:
|
||||
const LLVector3& getWorldPosition() const { return mWorldPosition; }
|
||||
};
|
||||
|
||||
LL_ALIGN_PREFIX(16)
|
||||
class LLXformMatrix : public LLXform
|
||||
{
|
||||
public:
|
||||
LLXformMatrix() : LLXform() {};
|
||||
virtual ~LLXformMatrix();
|
||||
|
||||
const LLMatrix4& getWorldMatrix() const { return mWorldMatrix; }
|
||||
void setWorldMatrix (const LLMatrix4& mat) { mWorldMatrix = mat; }
|
||||
const LLMatrix4a& getWorldMatrix() const { return mWorldMatrix; }
|
||||
void setWorldMatrix (const LLMatrix4a& mat) { mWorldMatrix = mat; }
|
||||
|
||||
void init()
|
||||
{
|
||||
mWorldMatrix.setIdentity();
|
||||
mMin.clearVec();
|
||||
mMax.clearVec();
|
||||
mMin.clear();
|
||||
mMax.clear();
|
||||
|
||||
LLXform::init();
|
||||
}
|
||||
@@ -153,11 +155,11 @@ public:
|
||||
void getMinMax(LLVector3& min,LLVector3& max) const;
|
||||
|
||||
protected:
|
||||
LLMatrix4 mWorldMatrix;
|
||||
LLVector3 mMin;
|
||||
LLVector3 mMax;
|
||||
LL_ALIGN_16(LLMatrix4a mWorldMatrix);
|
||||
LL_ALIGN_16(LLVector4a mMin);
|
||||
LL_ALIGN_16(LLVector4a mMax);
|
||||
|
||||
};
|
||||
} LL_ALIGN_POSTFIX(16);
|
||||
|
||||
BOOL LLXform::setParent(LLXform* parent)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user