1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336 |
- /*
- Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans http://continuousphysics.com/Bullet/
- This software is provided 'as-is', without any express or implied warranty.
- In no event will the authors be held liable for any damages arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it freely,
- subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #ifndef BT_VECTOR3_H
- #define BT_VECTOR3_H
- //#include <stdint.h>
- #include "btScalar.h"
- #include "btMinMax.h"
- #include "btAlignedAllocator.h"
- #ifdef BT_USE_DOUBLE_PRECISION
- #define btVector3Data btVector3DoubleData
- #define btVector3DataName "btVector3DoubleData"
- #else
- #define btVector3Data btVector3FloatData
- #define btVector3DataName "btVector3FloatData"
- #endif //BT_USE_DOUBLE_PRECISION
- #if defined BT_USE_SSE
- //typedef uint32_t __m128i __attribute__ ((vector_size(16)));
- #ifdef _MSC_VER
- #pragma warning(disable : 4556) // value of intrinsic immediate argument '4294967239' is out of range '0 - 255'
- #endif
- #define BT_SHUFFLE(x, y, z, w) (((w) << 6 | (z) << 4 | (y) << 2 | (x)) & 0xff)
- //#define bt_pshufd_ps( _a, _mask ) (__m128) _mm_shuffle_epi32((__m128i)(_a), (_mask) )
- #define bt_pshufd_ps(_a, _mask) _mm_shuffle_ps((_a), (_a), (_mask))
- #define bt_splat3_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, 3))
- #define bt_splat_ps(_a, _i) bt_pshufd_ps((_a), BT_SHUFFLE(_i, _i, _i, _i))
- #define btv3AbsiMask (_mm_set_epi32(0x00000000, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
- #define btvAbsMask (_mm_set_epi32(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF))
- #define btvFFF0Mask (_mm_set_epi32(0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF))
- #define btv3AbsfMask btCastiTo128f(btv3AbsiMask)
- #define btvFFF0fMask btCastiTo128f(btvFFF0Mask)
- #define btvxyzMaskf btvFFF0fMask
- #define btvAbsfMask btCastiTo128f(btvAbsMask)
- //there is an issue with XCode 3.2 (LCx errors)
- #define btvMzeroMask (_mm_set_ps(-0.0f, -0.0f, -0.0f, -0.0f))
- #define v1110 (_mm_set_ps(0.0f, 1.0f, 1.0f, 1.0f))
- #define vHalf (_mm_set_ps(0.5f, 0.5f, 0.5f, 0.5f))
- #define v1_5 (_mm_set_ps(1.5f, 1.5f, 1.5f, 1.5f))
- //const __m128 ATTRIBUTE_ALIGNED16(btvMzeroMask) = {-0.0f, -0.0f, -0.0f, -0.0f};
- //const __m128 ATTRIBUTE_ALIGNED16(v1110) = {1.0f, 1.0f, 1.0f, 0.0f};
- //const __m128 ATTRIBUTE_ALIGNED16(vHalf) = {0.5f, 0.5f, 0.5f, 0.5f};
- //const __m128 ATTRIBUTE_ALIGNED16(v1_5) = {1.5f, 1.5f, 1.5f, 1.5f};
- #endif
- #ifdef BT_USE_NEON
- const float32x4_t ATTRIBUTE_ALIGNED16(btvMzeroMask) = (float32x4_t){-0.0f, -0.0f, -0.0f, -0.0f};
- const int32x4_t ATTRIBUTE_ALIGNED16(btvFFF0Mask) = (int32x4_t){static_cast<int32_t>(0xFFFFFFFF),
- static_cast<int32_t>(0xFFFFFFFF), static_cast<int32_t>(0xFFFFFFFF), 0x0};
- const int32x4_t ATTRIBUTE_ALIGNED16(btvAbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF};
- const int32x4_t ATTRIBUTE_ALIGNED16(btv3AbsMask) = (int32x4_t){0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x0};
- #endif
- /**@brief btVector3 can be used to represent 3D points and vectors.
- * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
- * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
- */
- ATTRIBUTE_ALIGNED16(class)
- btVector3
- {
- public:
- BT_DECLARE_ALIGNED_ALLOCATOR();
- #if defined(__SPU__) && defined(__CELLOS_LV2__)
- btScalar m_floats[4];
- public:
- SIMD_FORCE_INLINE const vec_float4& get128() const
- {
- return *((const vec_float4*)&m_floats[0]);
- }
- public:
- #else //__CELLOS_LV2__ __SPU__
- #if defined(BT_USE_SSE) || defined(BT_USE_NEON) // _WIN32 || ARM
- union {
- btSimdFloat4 mVec128;
- btScalar m_floats[4];
- };
- SIMD_FORCE_INLINE btSimdFloat4 get128() const
- {
- return mVec128;
- }
- SIMD_FORCE_INLINE void set128(btSimdFloat4 v128)
- {
- mVec128 = v128;
- }
- #else
- btScalar m_floats[4];
- #endif
- #endif //__CELLOS_LV2__ __SPU__
- public:
- /**@brief No initialization constructor */
- SIMD_FORCE_INLINE btVector3()
- {
- }
- /**@brief Constructor from scalars
- * @param x X value
- * @param y Y value
- * @param z Z value
- */
- SIMD_FORCE_INLINE btVector3(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = btScalar(0.f);
- }
- #if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- // Set Vector
- SIMD_FORCE_INLINE btVector3(btSimdFloat4 v)
- {
- mVec128 = v;
- }
- // Copy constructor
- SIMD_FORCE_INLINE btVector3(const btVector3& rhs)
- {
- mVec128 = rhs.mVec128;
- }
- // Assignment Operator
- SIMD_FORCE_INLINE btVector3&
- operator=(const btVector3& v)
- {
- mVec128 = v.mVec128;
- return *this;
- }
- #endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- /**@brief Add a vector to this one
- * @param The vector to add to this one */
- SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_add_ps(mVec128, v.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vaddq_f32(mVec128, v.mVec128);
- #else
- m_floats[0] += v.m_floats[0];
- m_floats[1] += v.m_floats[1];
- m_floats[2] += v.m_floats[2];
- #endif
- return *this;
- }
- /**@brief Subtract a vector from this one
- * @param The vector to subtract */
- SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_sub_ps(mVec128, v.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vsubq_f32(mVec128, v.mVec128);
- #else
- m_floats[0] -= v.m_floats[0];
- m_floats[1] -= v.m_floats[1];
- m_floats[2] -= v.m_floats[2];
- #endif
- return *this;
- }
- /**@brief Scale the vector
- * @param s Scale factor */
- SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- mVec128 = _mm_mul_ps(mVec128, vs);
- #elif defined(BT_USE_NEON)
- mVec128 = vmulq_n_f32(mVec128, s);
- #else
- m_floats[0] *= s;
- m_floats[1] *= s;
- m_floats[2] *= s;
- #endif
- return *this;
- }
- /**@brief Inversely scale the vector
- * @param s Scale factor to divide by */
- SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s)
- {
- btFullAssert(s != btScalar(0.0));
- #if 0 //defined(BT_USE_SSE_IN_API)
- // this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(v1110, vs);
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
- mVec128 = _mm_mul_ps(mVec128, vs);
-
- return *this;
- #else
- return *this *= btScalar(1.0) / s;
- #endif
- }
- /**@brief Return the dot product
- * @param v The other vector in the dot product */
- SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vd = _mm_mul_ps(mVec128, v.mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
- return _mm_cvtss_f32(vd);
- #elif defined(BT_USE_NEON)
- float32x4_t vd = vmulq_f32(mVec128, v.mVec128);
- float32x2_t x = vpadd_f32(vget_low_f32(vd), vget_low_f32(vd));
- x = vadd_f32(x, vget_high_f32(vd));
- return vget_lane_f32(x, 0);
- #else
- return m_floats[0] * v.m_floats[0] +
- m_floats[1] * v.m_floats[1] +
- m_floats[2] * v.m_floats[2];
- #endif
- }
- /**@brief Return the length of the vector squared */
- SIMD_FORCE_INLINE btScalar length2() const
- {
- return dot(*this);
- }
- /**@brief Return the length of the vector */
- SIMD_FORCE_INLINE btScalar length() const
- {
- return btSqrt(length2());
- }
- /**@brief Return the norm (length) of the vector */
- SIMD_FORCE_INLINE btScalar norm() const
- {
- return length();
- }
- /**@brief Return the norm (length) of the vector */
- SIMD_FORCE_INLINE btScalar safeNorm() const
- {
- btScalar d = length2();
- //workaround for some clang/gcc issue of sqrtf(tiny number) = -INF
- if (d > SIMD_EPSILON)
- return btSqrt(d);
- return btScalar(0);
- }
- /**@brief Return the distance squared between the ends of this and another vector
- * This is symantically treating the vector like a point */
- SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
- /**@brief Return the distance between the ends of this and another vector
- * This is symantically treating the vector like a point */
- SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
- SIMD_FORCE_INLINE btVector3& safeNormalize()
- {
- btScalar l2 = length2();
- //triNormal.normalize();
- if (l2 >= SIMD_EPSILON * SIMD_EPSILON)
- {
- (*this) /= btSqrt(l2);
- }
- else
- {
- setValue(1, 0, 0);
- }
- return *this;
- }
- /**@brief Normalize this vector
- * x^2 + y^2 + z^2 = 1 */
- SIMD_FORCE_INLINE btVector3& normalize()
- {
- btAssert(!fuzzyZero());
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- // dot product first
- __m128 vd = _mm_mul_ps(mVec128, mVec128);
- __m128 z = _mm_movehl_ps(vd, vd);
- __m128 y = _mm_shuffle_ps(vd, vd, 0x55);
- vd = _mm_add_ss(vd, y);
- vd = _mm_add_ss(vd, z);
- #if 0
- vd = _mm_sqrt_ss(vd);
- vd = _mm_div_ss(v1110, vd);
- vd = bt_splat_ps(vd, 0x80);
- mVec128 = _mm_mul_ps(mVec128, vd);
- #else
- // NR step 1/sqrt(x) - vd is x, y is output
- y = _mm_rsqrt_ss(vd); // estimate
- // one step NR
- z = v1_5;
- vd = _mm_mul_ss(vd, vHalf); // vd * 0.5
- //x2 = vd;
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0
- vd = _mm_mul_ss(vd, y); // vd * 0.5 * y0 * y0
- z = _mm_sub_ss(z, vd); // 1.5 - vd * 0.5 * y0 * y0
- y = _mm_mul_ss(y, z); // y0 * (1.5 - vd * 0.5 * y0 * y0)
- y = bt_splat_ps(y, 0x80);
- mVec128 = _mm_mul_ps(mVec128, y);
- #endif
- return *this;
- #else
- return *this /= length();
- #endif
- }
- /**@brief Return a normalized version of this vector */
- SIMD_FORCE_INLINE btVector3 normalized() const;
- /**@brief Return a rotated version of this vector
- * @param wAxis The axis to rotate about
- * @param angle The angle to rotate by */
- SIMD_FORCE_INLINE btVector3 rotate(const btVector3& wAxis, const btScalar angle) const;
- /**@brief Return the angle between this and another vector
- * @param v The other vector */
- SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const
- {
- btScalar s = btSqrt(length2() * v.length2());
- btFullAssert(s != btScalar(0.0));
- return btAcos(dot(v) / s);
- }
- /**@brief Return a vector with the absolute values of each element */
- SIMD_FORCE_INLINE btVector3 absolute() const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_and_ps(mVec128, btv3AbsfMask));
- #elif defined(BT_USE_NEON)
- return btVector3(vabsq_f32(mVec128));
- #else
- return btVector3(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
- btFabs(m_floats[2]));
- #endif
- }
- /**@brief Return the cross product between this and another vector
- * @param v The other vector */
- SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 T, V;
- T = bt_pshufd_ps(mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = bt_pshufd_ps(v.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = _mm_mul_ps(V, mVec128);
- T = _mm_mul_ps(T, v.mVec128);
- V = _mm_sub_ps(V, T);
- V = bt_pshufd_ps(V, BT_SHUFFLE(1, 2, 0, 3));
- return btVector3(V);
- #elif defined(BT_USE_NEON)
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(mVec128);
- float32x2_t Vlow = vget_low_f32(v.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v.mVec128), 1), Vlow);
- V = vmulq_f32(V, mVec128);
- T = vmulq_f32(T, v.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
- V = (float32x4_t)vandq_s32((int32x4_t)V, btvFFF0Mask);
- return btVector3(V);
- #else
- return btVector3(
- m_floats[1] * v.m_floats[2] - m_floats[2] * v.m_floats[1],
- m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
- m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
- #endif
- }
- SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- // cross:
- __m128 T = _mm_shuffle_ps(v1.mVec128, v1.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- __m128 V = _mm_shuffle_ps(v2.mVec128, v2.mVec128, BT_SHUFFLE(1, 2, 0, 3)); // (Y Z X 0)
- V = _mm_mul_ps(V, v1.mVec128);
- T = _mm_mul_ps(T, v2.mVec128);
- V = _mm_sub_ps(V, T);
- V = _mm_shuffle_ps(V, V, BT_SHUFFLE(1, 2, 0, 3));
- // dot:
- V = _mm_mul_ps(V, mVec128);
- __m128 z = _mm_movehl_ps(V, V);
- __m128 y = _mm_shuffle_ps(V, V, 0x55);
- V = _mm_add_ss(V, y);
- V = _mm_add_ss(V, z);
- return _mm_cvtss_f32(V);
- #elif defined(BT_USE_NEON)
- // cross:
- float32x4_t T, V;
- // form (Y, Z, X, _) of mVec128 and v.mVec128
- float32x2_t Tlow = vget_low_f32(v1.mVec128);
- float32x2_t Vlow = vget_low_f32(v2.mVec128);
- T = vcombine_f32(vext_f32(Tlow, vget_high_f32(v1.mVec128), 1), Tlow);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(v2.mVec128), 1), Vlow);
- V = vmulq_f32(V, v1.mVec128);
- T = vmulq_f32(T, v2.mVec128);
- V = vsubq_f32(V, T);
- Vlow = vget_low_f32(V);
- // form (Y, Z, X, _);
- V = vcombine_f32(vext_f32(Vlow, vget_high_f32(V), 1), Vlow);
- // dot:
- V = vmulq_f32(mVec128, V);
- float32x2_t x = vpadd_f32(vget_low_f32(V), vget_low_f32(V));
- x = vadd_f32(x, vget_high_f32(V));
- return vget_lane_f32(x, 0);
- #else
- return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) +
- m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) +
- m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
- #endif
- }
- /**@brief Return the axis with the smallest value
- * Note return values are 0,1,2 for x, y, or z */
- SIMD_FORCE_INLINE int minAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[0] < m_floats[2] ? 0 : 2) : (m_floats[1] < m_floats[2] ? 1 : 2);
- }
- /**@brief Return the axis with the largest value
- * Note return values are 0,1,2 for x, y, or z */
- SIMD_FORCE_INLINE int maxAxis() const
- {
- return m_floats[0] < m_floats[1] ? (m_floats[1] < m_floats[2] ? 2 : 1) : (m_floats[0] < m_floats[2] ? 2 : 0);
- }
- SIMD_FORCE_INLINE int furthestAxis() const
- {
- return absolute().minAxis();
- }
- SIMD_FORCE_INLINE int closestAxis() const
- {
- return absolute().maxAxis();
- }
- SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vrt = _mm_load_ss(&rt); // (rt 0 0 0)
- btScalar s = btScalar(1.0) - rt;
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- __m128 r0 = _mm_mul_ps(v0.mVec128, vs);
- vrt = bt_pshufd_ps(vrt, 0x80); // (rt rt rt 0.0)
- __m128 r1 = _mm_mul_ps(v1.mVec128, vrt);
- __m128 tmp3 = _mm_add_ps(r0, r1);
- mVec128 = tmp3;
- #elif defined(BT_USE_NEON)
- float32x4_t vl = vsubq_f32(v1.mVec128, v0.mVec128);
- vl = vmulq_n_f32(vl, rt);
- mVec128 = vaddq_f32(vl, v0.mVec128);
- #else
- btScalar s = btScalar(1.0) - rt;
- m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
- m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
- m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
- //don't do the unused w component
- // m_co[3] = s * v0[3] + rt * v1[3];
- #endif
- }
- /**@brief Return the linear interpolation between this and another vector
- * @param v The other vector
- * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
- SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vt = _mm_load_ss(&t); // (t 0 0 0)
- vt = bt_pshufd_ps(vt, 0x80); // (rt rt rt 0.0)
- __m128 vl = _mm_sub_ps(v.mVec128, mVec128);
- vl = _mm_mul_ps(vl, vt);
- vl = _mm_add_ps(vl, mVec128);
- return btVector3(vl);
- #elif defined(BT_USE_NEON)
- float32x4_t vl = vsubq_f32(v.mVec128, mVec128);
- vl = vmulq_n_f32(vl, t);
- vl = vaddq_f32(vl, mVec128);
- return btVector3(vl);
- #else
- return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
- m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
- m_floats[2] + (v.m_floats[2] - m_floats[2]) * t);
- #endif
- }
- /**@brief Elementwise multiply this vector by the other
- * @param v The other vector */
- SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_mul_ps(mVec128, v.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vmulq_f32(mVec128, v.mVec128);
- #else
- m_floats[0] *= v.m_floats[0];
- m_floats[1] *= v.m_floats[1];
- m_floats[2] *= v.m_floats[2];
- #endif
- return *this;
- }
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
- /**@brief Set the x value */
- SIMD_FORCE_INLINE void setX(btScalar _x) { m_floats[0] = _x; };
- /**@brief Set the y value */
- SIMD_FORCE_INLINE void setY(btScalar _y) { m_floats[1] = _y; };
- /**@brief Set the z value */
- SIMD_FORCE_INLINE void setZ(btScalar _z) { m_floats[2] = _z; };
- /**@brief Set the w value */
- SIMD_FORCE_INLINE void setW(btScalar _w) { m_floats[3] = _w; };
- /**@brief Return the x value */
- SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
- /**@brief Return the y value */
- SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
- /**@brief Return the z value */
- SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
- /**@brief Return the w value */
- SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
- //SIMD_FORCE_INLINE btScalar& operator[](int i) { return (&m_floats[0])[i]; }
- //SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
- ///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
- SIMD_FORCE_INLINE operator btScalar*() { return &m_floats[0]; }
- SIMD_FORCE_INLINE operator const btScalar*() const { return &m_floats[0]; }
- SIMD_FORCE_INLINE bool operator==(const btVector3& other) const
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return (0xf == _mm_movemask_ps((__m128)_mm_cmpeq_ps(mVec128, other.mVec128)));
- #else
- return ((m_floats[3] == other.m_floats[3]) &&
- (m_floats[2] == other.m_floats[2]) &&
- (m_floats[1] == other.m_floats[1]) &&
- (m_floats[0] == other.m_floats[0]));
- #endif
- }
- SIMD_FORCE_INLINE bool operator!=(const btVector3& other) const
- {
- return !(*this == other);
- }
- /**@brief Set each element to the max of the current values and the values of another btVector3
- * @param other The other btVector3 to compare with
- */
- SIMD_FORCE_INLINE void setMax(const btVector3& other)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_max_ps(mVec128, other.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vmaxq_f32(mVec128, other.mVec128);
- #else
- btSetMax(m_floats[0], other.m_floats[0]);
- btSetMax(m_floats[1], other.m_floats[1]);
- btSetMax(m_floats[2], other.m_floats[2]);
- btSetMax(m_floats[3], other.w());
- #endif
- }
- /**@brief Set each element to the min of the current values and the values of another btVector3
- * @param other The other btVector3 to compare with
- */
- SIMD_FORCE_INLINE void setMin(const btVector3& other)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = _mm_min_ps(mVec128, other.mVec128);
- #elif defined(BT_USE_NEON)
- mVec128 = vminq_f32(mVec128, other.mVec128);
- #else
- btSetMin(m_floats[0], other.m_floats[0]);
- btSetMin(m_floats[1], other.m_floats[1]);
- btSetMin(m_floats[2], other.m_floats[2]);
- btSetMin(m_floats[3], other.w());
- #endif
- }
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = btScalar(0.f);
- }
- void getSkewSymmetricMatrix(btVector3 * v0, btVector3 * v1, btVector3 * v2) const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 V = _mm_and_ps(mVec128, btvFFF0fMask);
- __m128 V0 = _mm_xor_ps(btvMzeroMask, V);
- __m128 V2 = _mm_movelh_ps(V0, V);
- __m128 V1 = _mm_shuffle_ps(V, V0, 0xCE);
- V0 = _mm_shuffle_ps(V0, V, 0xDB);
- V2 = _mm_shuffle_ps(V2, V, 0xF9);
- v0->mVec128 = V0;
- v1->mVec128 = V1;
- v2->mVec128 = V2;
- #else
- v0->setValue(0., -z(), y());
- v1->setValue(z(), 0., -x());
- v2->setValue(-y(), x(), 0.);
- #endif
- }
- void setZero()
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- mVec128 = (__m128)_mm_xor_ps(mVec128, mVec128);
- #elif defined(BT_USE_NEON)
- int32x4_t vi = vdupq_n_s32(0);
- mVec128 = vreinterpretq_f32_s32(vi);
- #else
- setValue(btScalar(0.), btScalar(0.), btScalar(0.));
- #endif
- }
- SIMD_FORCE_INLINE bool isZero() const
- {
- return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
- }
- SIMD_FORCE_INLINE bool fuzzyZero() const
- {
- return length2() < SIMD_EPSILON * SIMD_EPSILON;
- }
- SIMD_FORCE_INLINE void serialize(struct btVector3Data & dataOut) const;
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3DoubleData& dataIn);
- SIMD_FORCE_INLINE void deSerialize(const struct btVector3FloatData& dataIn);
- SIMD_FORCE_INLINE void serializeFloat(struct btVector3FloatData & dataOut) const;
- SIMD_FORCE_INLINE void deSerializeFloat(const struct btVector3FloatData& dataIn);
- SIMD_FORCE_INLINE void serializeDouble(struct btVector3DoubleData & dataOut) const;
- SIMD_FORCE_INLINE void deSerializeDouble(const struct btVector3DoubleData& dataIn);
- /**@brief returns index of maximum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The maximum dot product */
- SIMD_FORCE_INLINE long maxDot(const btVector3* array, long array_count, btScalar& dotOut) const;
- /**@brief returns index of minimum dot product between this and vectors in array[]
- * @param array The other vectors
- * @param array_count The number of other vectors
- * @param dotOut The minimum dot product */
- SIMD_FORCE_INLINE long minDot(const btVector3* array, long array_count, btScalar& dotOut) const;
- /* create a vector as btVector3( this->dot( btVector3 v0 ), this->dot( btVector3 v1), this->dot( btVector3 v2 )) */
- SIMD_FORCE_INLINE btVector3 dot3(const btVector3& v0, const btVector3& v1, const btVector3& v2) const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 a0 = _mm_mul_ps(v0.mVec128, this->mVec128);
- __m128 a1 = _mm_mul_ps(v1.mVec128, this->mVec128);
- __m128 a2 = _mm_mul_ps(v2.mVec128, this->mVec128);
- __m128 b0 = _mm_unpacklo_ps(a0, a1);
- __m128 b1 = _mm_unpackhi_ps(a0, a1);
- __m128 b2 = _mm_unpacklo_ps(a2, _mm_setzero_ps());
- __m128 r = _mm_movelh_ps(b0, b2);
- r = _mm_add_ps(r, _mm_movehl_ps(b2, b0));
- a2 = _mm_and_ps(a2, btvxyzMaskf);
- r = _mm_add_ps(r, btCastdTo128f(_mm_move_sd(btCastfTo128d(a2), btCastfTo128d(b1))));
- return btVector3(r);
- #elif defined(BT_USE_NEON)
- static const uint32x4_t xyzMask = (const uint32x4_t){static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), static_cast<uint32_t>(-1), 0};
- float32x4_t a0 = vmulq_f32(v0.mVec128, this->mVec128);
- float32x4_t a1 = vmulq_f32(v1.mVec128, this->mVec128);
- float32x4_t a2 = vmulq_f32(v2.mVec128, this->mVec128);
- float32x2x2_t zLo = vtrn_f32(vget_high_f32(a0), vget_high_f32(a1));
- a2 = (float32x4_t)vandq_u32((uint32x4_t)a2, xyzMask);
- float32x2_t b0 = vadd_f32(vpadd_f32(vget_low_f32(a0), vget_low_f32(a1)), zLo.val[0]);
- float32x2_t b1 = vpadd_f32(vpadd_f32(vget_low_f32(a2), vget_high_f32(a2)), vdup_n_f32(0.0f));
- return btVector3(vcombine_f32(b0, b1));
- #else
- return btVector3(dot(v0), dot(v1), dot(v2));
- #endif
- }
- };
- /**@brief Return the sum of two vectors (Point symantics)*/
- SIMD_FORCE_INLINE btVector3
- operator+(const btVector3& v1, const btVector3& v2)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_add_ps(v1.mVec128, v2.mVec128));
- #elif defined(BT_USE_NEON)
- return btVector3(vaddq_f32(v1.mVec128, v2.mVec128));
- #else
- return btVector3(
- v1.m_floats[0] + v2.m_floats[0],
- v1.m_floats[1] + v2.m_floats[1],
- v1.m_floats[2] + v2.m_floats[2]);
- #endif
- }
- /**@brief Return the elementwise product of two vectors */
- SIMD_FORCE_INLINE btVector3
- operator*(const btVector3& v1, const btVector3& v2)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector3(_mm_mul_ps(v1.mVec128, v2.mVec128));
- #elif defined(BT_USE_NEON)
- return btVector3(vmulq_f32(v1.mVec128, v2.mVec128));
- #else
- return btVector3(
- v1.m_floats[0] * v2.m_floats[0],
- v1.m_floats[1] * v2.m_floats[1],
- v1.m_floats[2] * v2.m_floats[2]);
- #endif
- }
- /**@brief Return the difference between two vectors */
- SIMD_FORCE_INLINE btVector3
- operator-(const btVector3& v1, const btVector3& v2)
- {
- #if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- // without _mm_and_ps this code causes slowdown in Concave moving
- __m128 r = _mm_sub_ps(v1.mVec128, v2.mVec128);
- return btVector3(_mm_and_ps(r, btvFFF0fMask));
- #elif defined(BT_USE_NEON)
- float32x4_t r = vsubq_f32(v1.mVec128, v2.mVec128);
- return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
- #else
- return btVector3(
- v1.m_floats[0] - v2.m_floats[0],
- v1.m_floats[1] - v2.m_floats[1],
- v1.m_floats[2] - v2.m_floats[2]);
- #endif
- }
- /**@brief Return the negative of the vector */
- SIMD_FORCE_INLINE btVector3
- operator-(const btVector3& v)
- {
- #if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 r = _mm_xor_ps(v.mVec128, btvMzeroMask);
- return btVector3(_mm_and_ps(r, btvFFF0fMask));
- #elif defined(BT_USE_NEON)
- return btVector3((btSimdFloat4)veorq_s32((int32x4_t)v.mVec128, (int32x4_t)btvMzeroMask));
- #else
- return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
- #endif
- }
- /**@brief Return the vector scaled by s */
- SIMD_FORCE_INLINE btVector3
- operator*(const btVector3& v, const btScalar& s)
- {
- #if defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 vs = _mm_load_ss(&s); // (S 0 0 0)
- vs = bt_pshufd_ps(vs, 0x80); // (S S S 0.0)
- return btVector3(_mm_mul_ps(v.mVec128, vs));
- #elif defined(BT_USE_NEON)
- float32x4_t r = vmulq_n_f32(v.mVec128, s);
- return btVector3((float32x4_t)vandq_s32((int32x4_t)r, btvFFF0Mask));
- #else
- return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
- #endif
- }
- /**@brief Return the vector scaled by s */
- SIMD_FORCE_INLINE btVector3
- operator*(const btScalar& s, const btVector3& v)
- {
- return v * s;
- }
- /**@brief Return the vector inversely scaled by s */
- SIMD_FORCE_INLINE btVector3
- operator/(const btVector3& v, const btScalar& s)
- {
- btFullAssert(s != btScalar(0.0));
- #if 0 //defined(BT_USE_SSE_IN_API)
- // this code is not faster !
- __m128 vs = _mm_load_ss(&s);
- vs = _mm_div_ss(v1110, vs);
- vs = bt_pshufd_ps(vs, 0x00); // (S S S S)
- return btVector3(_mm_mul_ps(v.mVec128, vs));
- #else
- return v * (btScalar(1.0) / s);
- #endif
- }
- /**@brief Return the vector inversely scaled by s */
- SIMD_FORCE_INLINE btVector3
- operator/(const btVector3& v1, const btVector3& v2)
- {
- #if defined BT_USE_SIMD_VECTOR3 && (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE))
- __m128 vec = _mm_div_ps(v1.mVec128, v2.mVec128);
- vec = _mm_and_ps(vec, btvFFF0fMask);
- return btVector3(vec);
- #elif defined(BT_USE_NEON)
- float32x4_t x, y, v, m;
- x = v1.mVec128;
- y = v2.mVec128;
- v = vrecpeq_f32(y); // v ~ 1/y
- m = vrecpsq_f32(y, v); // m = (2-v*y)
- v = vmulq_f32(v, m); // vv = v*m ~~ 1/y
- m = vrecpsq_f32(y, v); // mm = (2-vv*y)
- v = vmulq_f32(v, x); // x*vv
- v = vmulq_f32(v, m); // (x*vv)*(2-vv*y) = x*(vv(2-vv*y)) ~~~ x/y
- return btVector3(v);
- #else
- return btVector3(
- v1.m_floats[0] / v2.m_floats[0],
- v1.m_floats[1] / v2.m_floats[1],
- v1.m_floats[2] / v2.m_floats[2]);
- #endif
- }
- /**@brief Return the dot product between two vectors */
- SIMD_FORCE_INLINE btScalar
- btDot(const btVector3& v1, const btVector3& v2)
- {
- return v1.dot(v2);
- }
- /**@brief Return the distance squared between two vectors */
- SIMD_FORCE_INLINE btScalar
- btDistance2(const btVector3& v1, const btVector3& v2)
- {
- return v1.distance2(v2);
- }
- /**@brief Return the distance between two vectors */
- SIMD_FORCE_INLINE btScalar
- btDistance(const btVector3& v1, const btVector3& v2)
- {
- return v1.distance(v2);
- }
- /**@brief Return the angle between two vectors */
- SIMD_FORCE_INLINE btScalar
- btAngle(const btVector3& v1, const btVector3& v2)
- {
- return v1.angle(v2);
- }
- /**@brief Return the cross product of two vectors */
- SIMD_FORCE_INLINE btVector3
- btCross(const btVector3& v1, const btVector3& v2)
- {
- return v1.cross(v2);
- }
- SIMD_FORCE_INLINE btScalar
- btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
- {
- return v1.triple(v2, v3);
- }
- /**@brief Return the linear interpolation between two vectors
- * @param v1 One vector
- * @param v2 The other vector
- * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
- SIMD_FORCE_INLINE btVector3
- lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
- {
- return v1.lerp(v2, t);
- }
- SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
- {
- return (v - *this).length2();
- }
- SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
- {
- return (v - *this).length();
- }
- SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
- {
- btVector3 nrm = *this;
- return nrm.normalize();
- }
- SIMD_FORCE_INLINE btVector3 btVector3::rotate(const btVector3& wAxis, const btScalar _angle) const
- {
- // wAxis must be a unit lenght vector
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- __m128 O = _mm_mul_ps(wAxis.mVec128, mVec128);
- btScalar ssin = btSin(_angle);
- __m128 C = wAxis.cross(mVec128).mVec128;
- O = _mm_and_ps(O, btvFFF0fMask);
- btScalar scos = btCos(_angle);
- __m128 vsin = _mm_load_ss(&ssin); // (S 0 0 0)
- __m128 vcos = _mm_load_ss(&scos); // (S 0 0 0)
- __m128 Y = bt_pshufd_ps(O, 0xC9); // (Y Z X 0)
- __m128 Z = bt_pshufd_ps(O, 0xD2); // (Z X Y 0)
- O = _mm_add_ps(O, Y);
- vsin = bt_pshufd_ps(vsin, 0x80); // (S S S 0)
- O = _mm_add_ps(O, Z);
- vcos = bt_pshufd_ps(vcos, 0x80); // (S S S 0)
- vsin = vsin * C;
- O = O * wAxis.mVec128;
- __m128 X = mVec128 - O;
- O = O + vsin;
- vcos = vcos * X;
- O = O + vcos;
- return btVector3(O);
- #else
- btVector3 o = wAxis * wAxis.dot(*this);
- btVector3 _x = *this - o;
- btVector3 _y;
- _y = wAxis.cross(*this);
- return (o + _x * btCos(_angle) + _y * btSin(_angle));
- #endif
- }
- SIMD_FORCE_INLINE long btVector3::maxDot(const btVector3* array, long array_count, btScalar& dotOut) const
- {
- #if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- #if defined _WIN32 || defined(BT_USE_SSE)
- const long scalar_cutoff = 10;
- long _maxdot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
- #elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_maxdot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
- #endif
- if (array_count < scalar_cutoff)
- #endif
- {
- btScalar maxDot1 = -SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for (i = 0; i < array_count; i++)
- {
- btScalar dot = array[i].dot(*this);
- if (dot > maxDot1)
- {
- maxDot1 = dot;
- ptIndex = i;
- }
- }
- dotOut = maxDot1;
- return ptIndex;
- }
- #if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- return _maxdot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
- #endif
- }
- SIMD_FORCE_INLINE long btVector3::minDot(const btVector3* array, long array_count, btScalar& dotOut) const
- {
- #if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- #if defined BT_USE_SSE
- const long scalar_cutoff = 10;
- long _mindot_large(const float* array, const float* vec, unsigned long array_count, float* dotOut);
- #elif defined BT_USE_NEON
- const long scalar_cutoff = 4;
- extern long (*_mindot_large)(const float* array, const float* vec, unsigned long array_count, float* dotOut);
- #else
- #error unhandled arch!
- #endif
- if (array_count < scalar_cutoff)
- #endif
- {
- btScalar minDot = SIMD_INFINITY;
- int i = 0;
- int ptIndex = -1;
- for (i = 0; i < array_count; i++)
- {
- btScalar dot = array[i].dot(*this);
- if (dot < minDot)
- {
- minDot = dot;
- ptIndex = i;
- }
- }
- dotOut = minDot;
- return ptIndex;
- }
- #if (defined BT_USE_SSE && defined BT_USE_SIMD_VECTOR3 && defined BT_USE_SSE_IN_API) || defined(BT_USE_NEON)
- return _mindot_large((float*)array, (float*)&m_floats[0], array_count, &dotOut);
- #endif //BT_USE_SIMD_VECTOR3
- }
- class btVector4 : public btVector3
- {
- public:
- SIMD_FORCE_INLINE btVector4() {}
- SIMD_FORCE_INLINE btVector4(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- : btVector3(_x, _y, _z)
- {
- m_floats[3] = _w;
- }
- #if (defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)) || defined(BT_USE_NEON)
- SIMD_FORCE_INLINE btVector4(const btSimdFloat4 vec)
- {
- mVec128 = vec;
- }
- SIMD_FORCE_INLINE btVector4(const btVector3& rhs)
- {
- mVec128 = rhs.mVec128;
- }
- SIMD_FORCE_INLINE btVector4&
- operator=(const btVector4& v)
- {
- mVec128 = v.mVec128;
- return *this;
- }
- #endif // #if defined (BT_USE_SSE_IN_API) || defined (BT_USE_NEON)
- SIMD_FORCE_INLINE btVector4 absolute4() const
- {
- #if defined BT_USE_SIMD_VECTOR3 && defined(BT_USE_SSE_IN_API) && defined(BT_USE_SSE)
- return btVector4(_mm_and_ps(mVec128, btvAbsfMask));
- #elif defined(BT_USE_NEON)
- return btVector4(vabsq_f32(mVec128));
- #else
- return btVector4(
- btFabs(m_floats[0]),
- btFabs(m_floats[1]),
- btFabs(m_floats[2]),
- btFabs(m_floats[3]));
- #endif
- }
- btScalar getW() const { return m_floats[3]; }
- SIMD_FORCE_INLINE int maxAxis4() const
- {
- int maxIndex = -1;
- btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
- if (m_floats[0] > maxVal)
- {
- maxIndex = 0;
- maxVal = m_floats[0];
- }
- if (m_floats[1] > maxVal)
- {
- maxIndex = 1;
- maxVal = m_floats[1];
- }
- if (m_floats[2] > maxVal)
- {
- maxIndex = 2;
- maxVal = m_floats[2];
- }
- if (m_floats[3] > maxVal)
- {
- maxIndex = 3;
- }
- return maxIndex;
- }
- SIMD_FORCE_INLINE int minAxis4() const
- {
- int minIndex = -1;
- btScalar minVal = btScalar(BT_LARGE_FLOAT);
- if (m_floats[0] < minVal)
- {
- minIndex = 0;
- minVal = m_floats[0];
- }
- if (m_floats[1] < minVal)
- {
- minIndex = 1;
- minVal = m_floats[1];
- }
- if (m_floats[2] < minVal)
- {
- minIndex = 2;
- minVal = m_floats[2];
- }
- if (m_floats[3] < minVal)
- {
- minIndex = 3;
- }
- return minIndex;
- }
- SIMD_FORCE_INLINE int closestAxis4() const
- {
- return absolute4().maxAxis4();
- }
- /**@brief Set x,y,z and zero w
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- */
- /* void getValue(btScalar *m) const
- {
- m[0] = m_floats[0];
- m[1] = m_floats[1];
- m[2] =m_floats[2];
- }
- */
- /**@brief Set the values
- * @param x Value of x
- * @param y Value of y
- * @param z Value of z
- * @param w Value of w
- */
- SIMD_FORCE_INLINE void setValue(const btScalar& _x, const btScalar& _y, const btScalar& _z, const btScalar& _w)
- {
- m_floats[0] = _x;
- m_floats[1] = _y;
- m_floats[2] = _z;
- m_floats[3] = _w;
- }
- };
- ///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
- SIMD_FORCE_INLINE void btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
- {
- #ifdef BT_USE_DOUBLE_PRECISION
- unsigned char* dest = (unsigned char*)&destVal;
- const unsigned char* src = (const unsigned char*)&sourceVal;
- dest[0] = src[7];
- dest[1] = src[6];
- dest[2] = src[5];
- dest[3] = src[4];
- dest[4] = src[3];
- dest[5] = src[2];
- dest[6] = src[1];
- dest[7] = src[0];
- #else
- unsigned char* dest = (unsigned char*)&destVal;
- const unsigned char* src = (const unsigned char*)&sourceVal;
- dest[0] = src[3];
- dest[1] = src[2];
- dest[2] = src[1];
- dest[3] = src[0];
- #endif //BT_USE_DOUBLE_PRECISION
- }
- ///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
- SIMD_FORCE_INLINE void btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
- {
- for (int i = 0; i < 4; i++)
- {
- btSwapScalarEndian(sourceVec[i], destVec[i]);
- }
- }
- ///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
- SIMD_FORCE_INLINE void btUnSwapVector3Endian(btVector3& vector)
- {
- btVector3 swappedVec;
- for (int i = 0; i < 4; i++)
- {
- btSwapScalarEndian(vector[i], swappedVec[i]);
- }
- vector = swappedVec;
- }
- template <class T>
- SIMD_FORCE_INLINE void btPlaneSpace1(const T& n, T& p, T& q)
- {
- if (btFabs(n[2]) > SIMDSQRT12)
- {
- // choose p in y-z plane
- btScalar a = n[1] * n[1] + n[2] * n[2];
- btScalar k = btRecipSqrt(a);
- p[0] = 0;
- p[1] = -n[2] * k;
- p[2] = n[1] * k;
- // set q = n x p
- q[0] = a * k;
- q[1] = -n[0] * p[2];
- q[2] = n[0] * p[1];
- }
- else
- {
- // choose p in x-y plane
- btScalar a = n[0] * n[0] + n[1] * n[1];
- btScalar k = btRecipSqrt(a);
- p[0] = -n[1] * k;
- p[1] = n[0] * k;
- p[2] = 0;
- // set q = n x p
- q[0] = -n[2] * p[1];
- q[1] = n[2] * p[0];
- q[2] = a * k;
- }
- }
- struct btVector3FloatData
- {
- float m_floats[4];
- };
- struct btVector3DoubleData
- {
- double m_floats[4];
- };
- SIMD_FORCE_INLINE void btVector3::serializeFloat(struct btVector3FloatData& dataOut) const
- {
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = float(m_floats[i]);
- }
- SIMD_FORCE_INLINE void btVector3::deSerializeFloat(const struct btVector3FloatData& dataIn)
- {
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
- }
- SIMD_FORCE_INLINE void btVector3::serializeDouble(struct btVector3DoubleData& dataOut) const
- {
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = double(m_floats[i]);
- }
- SIMD_FORCE_INLINE void btVector3::deSerializeDouble(const struct btVector3DoubleData& dataIn)
- {
- for (int i = 0; i < 4; i++)
- m_floats[i] = btScalar(dataIn.m_floats[i]);
- }
- SIMD_FORCE_INLINE void btVector3::serialize(struct btVector3Data& dataOut) const
- {
- ///could also do a memcpy, check if it is worth it
- for (int i = 0; i < 4; i++)
- dataOut.m_floats[i] = m_floats[i];
- }
- SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3FloatData& dataIn)
- {
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
- }
- SIMD_FORCE_INLINE void btVector3::deSerialize(const struct btVector3DoubleData& dataIn)
- {
- for (int i = 0; i < 4; i++)
- m_floats[i] = (btScalar)dataIn.m_floats[i];
- }
- #endif //BT_VECTOR3_H
|