diff --git a/src.cmake b/src.cmake index f157950f46..d3bf1c57f1 100644 --- a/src.cmake +++ b/src.cmake @@ -86,6 +86,18 @@ if (DAEMON_PARENT_SCOPE_DIR) set(COMMONLIST ${COMMONLIST} PARENT_SCOPE) endif() +# Tests for code shared by engine and gamelogic +set(COMMONTESTLIST + ${LIB_DIR}/tinyformat/TinyformatTest.cpp + ${COMMON_DIR}/ColorTest.cpp + ${COMMON_DIR}/FileSystemTest.cpp + ${COMMON_DIR}/StringTest.cpp + ${COMMON_DIR}/cm/unittest.cpp + ${COMMON_DIR}/MathTest.cpp + ${COMMON_DIR}/UtilTest.cpp + ${ENGINE_DIR}/qcommon/q_math_test.cpp +) + set(RENDERERLIST ${ENGINE_DIR}/renderer/DetectGLVendors.cpp ${ENGINE_DIR}/renderer/DetectGLVendors.h @@ -279,15 +291,8 @@ else() ) endif() -# Tests for engine-lib -set(ENGINETESTLIST - ${LIB_DIR}/tinyformat/TinyformatTest.cpp - ${COMMON_DIR}/ColorTest.cpp - ${COMMON_DIR}/FileSystemTest.cpp - ${COMMON_DIR}/StringTest.cpp - ${COMMON_DIR}/cm/unittest.cpp - ${COMMON_DIR}/MathTest.cpp - ${COMMON_DIR}/UtilTest.cpp +# Tests runnable for any engine variant +set(ENGINETESTLIST ${COMMONTESTLIST} ${ENGINE_DIR}/framework/CommandSystemTest.cpp ) diff --git a/src/engine/qcommon/q_math.cpp b/src/engine/qcommon/q_math.cpp index f05fccbd0a..f3af5b8e6e 100644 --- a/src/engine/qcommon/q_math.cpp +++ b/src/engine/qcommon/q_math.cpp @@ -3199,12 +3199,6 @@ void TransInit( transform_t *t ) t->scale = 1.0f; } -// copy a transform -void TransCopy( const transform_t *in, transform_t *out ) -{ - memcpy( out, in, sizeof( transform_t ) ); -} - // apply a transform to a point void TransformPoint( const transform_t *t, const vec3_t in, vec3_t out ) { @@ -3212,26 +3206,12 @@ void TransformPoint( const transform_t *t, const vec3_t in, vec3_t out ) VectorScale( out, t->scale, out ); VectorAdd( out, t->trans, out ); } -// apply the inverse of a transform to a point -void TransformPointInverse( const transform_t *t, const vec3_t in, vec3_t out ) -{ - VectorSubtract( in, t->trans, out ); - VectorScale( out, 1.0f / t->scale, out ); - QuatTransformVectorInverse( t->rot, out, out ); -} // apply a transform to a normal vector (ignore scale and translation) void TransformNormalVector( const transform_t *t, const vec3_t in, vec3_t out ) { QuatTransformVector( t->rot, in, out ); } -// apply the inverse of a transform to a normal vector (ignore scale -// and translation) -void TransformNormalVectorInverse( const transform_t *t, const vec3_t in, - vec3_t out ) -{ - QuatTransformVectorInverse( t->rot, in, out ); -} // initialize a transform with a pure rotation void TransInitRotationQuat( const quat_t quat, transform_t *t ) @@ -3240,16 +3220,6 @@ void TransInitRotationQuat( const quat_t quat, transform_t *t ) VectorClear( t->trans ); t->scale = 1.0f; } -void TransInitRotation( const vec3_t axis, float angle, transform_t *t ) -{ - float sa = sinf( 0.5f * angle ); - float ca = cosf( 0.5f * angle ); - quat_t q; - - VectorScale( axis, sa, q ); - q[3] = ca; - TransInitRotationQuat( q, t ); -} // initialize a transform with a pure translation void TransInitTranslation( const vec3_t vec, transform_t *t ) { @@ -3292,16 +3262,6 @@ void TransAddRotationQuat( const quat_t quat, transform_t *t ) QuatMultiply2( tmp, t->rot ); QuatCopy( tmp, t->rot ); } -void TransAddRotation( const vec3_t axis, float angle, transform_t *t ) -{ - float sa = sinf( 0.5f * angle ); - float ca = cosf( 0.5f * angle ); - quat_t q; - - VectorScale( axis, sa, q ); - q[3] = ca; - TransAddRotationQuat( q, t ); -} // add a scale to the start of an existing transform void TransInsScale( float factor, transform_t *t ) @@ -3319,9 +3279,9 @@ void TransAddScale( float factor, transform_t *t ) void TransInsTranslation( const vec3_t vec, transform_t *t ) { vec3_t tmp; - - TransformPoint( t, vec, tmp ); - VectorAdd( t->trans, tmp, t->trans ); + QuatTransformVector( t->rot, vec, tmp ); + VectorScale( tmp, t->scale, tmp ); + VectorAdd( tmp, t->trans, t->trans ); } // add a translation at the end of an existing transformation @@ -3334,7 +3294,7 @@ void TransAddTranslation( const vec3_t vec, transform_t *t ) void TransCombine( const transform_t *a, const transform_t *b, transform_t *out ) { - TransCopy( a, out ); + *out = *a; TransAddRotationQuat( b->rot, out ); TransAddScale( b->scale, out ); @@ -3345,7 +3305,7 @@ void TransCombine( const transform_t *a, const transform_t *b, void TransInverse( const transform_t *in, transform_t *out ) { quat_t inverse; - static transform_t tmp; // static for proper alignment in QVMs + transform_t tmp; TransInit( &tmp ); VectorNegate( in->trans, tmp.trans ); @@ -3353,7 +3313,7 @@ void TransInverse( const transform_t *in, transform_t *out ) QuatCopy( in->rot, inverse ); QuatInverse( inverse ); TransAddRotationQuat( inverse, &tmp ); - TransCopy( &tmp, out ); + *out = tmp; } // lerp between transforms diff --git a/src/engine/qcommon/q_math_test.cpp b/src/engine/qcommon/q_math_test.cpp new file mode 100644 index 0000000000..297aa9db33 --- /dev/null +++ b/src/engine/qcommon/q_math_test.cpp @@ -0,0 +1,208 @@ +/* +=========================================================================== +Daemon BSD Source Code +Copyright (c) 2024, Daemon Developers +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Daemon developers nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +=========================================================================== +*/ + +#include +#include + +#include "common/Common.h" + +// TODO: add transform tests with quats with negative real component +// the calculator I used always made it positive + +namespace { + +using ::testing::Pointwise; +using ::testing::FloatNear; + +// Using a function for this in case we want to change how transform_t is set +// to avoid undefined behaviors with the union +transform_t MakeTransform( + const std::array& quat, + const std::array& translation, + float scale) +{ + transform_t t; + Vector4Copy(quat, t.rot); + VectorCopy(translation, t.trans); + t.scale = scale; + return t; +} + +void ExpectTransformEqual( + const transform_t& t, + const std::array& expectedQuat, + const std::array& expectedTranslation, + float expectedScale) +{ + const char* base = reinterpret_cast(&t); + std::array actualQuat; + std::array actualTranslation; + float actualScale; + memcpy(&actualQuat, base + offsetof(transform_t, rot), sizeof(actualQuat)); + memcpy(&actualTranslation, base + offsetof(transform_t, trans), sizeof(actualTranslation)); + memcpy(&actualScale, base + offsetof(transform_t, scale), sizeof(actualScale)); + EXPECT_THAT(actualQuat, Pointwise(FloatNear(1e-4), expectedQuat)); + EXPECT_THAT(actualTranslation, Pointwise(FloatNear(1e-3), expectedTranslation)); + EXPECT_THAT(actualScale, FloatNear(1e-5, expectedScale)); +} + +TEST(QMathTransformTest, TransInit) +{ + transform_t t; + TransInit(&t); + ExpectTransformEqual(t, {0, 0, 0, 1}, {0, 0, 0}, 1); +} + +TEST(QMathTransformTest, TransformPoint) +{ + transform_t t = MakeTransform( + {0.3155654, 0.121273, 0.7211766, 0.6046616}, {-11, -26, 55}, 1.2); + const vec3_t pointIn = {12, 19, -30}; + vec3_t pointOut; + TransformPoint(&t, pointIn, pointOut); + const vec3_t expectedPoint = {-51.8073, -10.3551, 44.3603}; + EXPECT_THAT(pointOut, Pointwise(FloatNear(0.001), expectedPoint)); +} + +TEST(QMathTransformTest, TransformNormalVector) +{ + const transform_t t = MakeTransform( + {0.1641059, -0.6753088, 0.2253332, -0.6828266}, {235, 52, 42}, 8); + const vec3_t vector = { 0.48, 0.64, 0.6 }; + vec3_t transformedVector; + TransformNormalVector(&t, vector, transformedVector); + const vec3_t expectedVector = {0.6462654,0.2383020,-0.7249505}; + EXPECT_THAT(transformedVector, Pointwise(FloatNear(1e-6), expectedVector)); +} + +TEST(QMathTransformTest, TransInitRotationQuat) +{ + const quat_t q = { -0.1423769, 0.5422508, 0.7235357, -0.402727 }; + transform_t t; + TransInitRotationQuat(q, &t); + ExpectTransformEqual(t, {-0.1423769, 0.5422508, 0.7235357, -0.402727}, {0, 0, 0}, 1); +} + +TEST(QMathTransformTest, TransInitTranslation) +{ + const vec3_t translation = {-9, -32, -0.5}; + transform_t t; + TransInitTranslation(translation, &t); + ExpectTransformEqual(t, {0, 0, 0, 1}, {-9, -32, -0.5}, 1); +} + +TEST(QMathTransformTest, TransInitScale) +{ + transform_t t; + TransInitScale(4.3, &t); + ExpectTransformEqual(t, {0, 0, 0, 1}, {0, 0, 0}, 4.3); +} + +TEST(QMathTransformTest, TransInsRotationQuat) +{ + const quat_t q = {0.3694065, -0.6226631, 0.1538449, -0.6724294}; + transform_t t = MakeTransform( + {-0.5881667, -0.3748035, 0.6614826, 0.2757227}, {1.8, -1.8, -4}, 3); + TransInsRotationQuat(q, &t); + ExpectTransformEqual(t, {0.8515735, 0.4151890, 0.1023027, -0.3032735}, {1.8, -1.8, -4}, 3); +} + +TEST(QMathTransformTest, TransAddRotationQuat) +{ + const quat_t rot = {-0.4217441, -0.6010819, -0.3683214, -0.5702384}; + transform_t t = MakeTransform( + {-0.1167623, -0.9282776, 0.3395844, 0.096694}, {12.5, 93.7, -14.1}, 2.9); + TransAddRotationQuat(rot, &t); + ExpectTransformEqual(t, {-0.5202203, 0.6574423, 0.09205336, -0.5372771}, + {-5.823749, 47.07177, 82.97640}, 2.9); +} + +TEST(QMathTransformTest, TransInsScale) +{ + transform_t t = MakeTransform( + {-0.8678937, 0.0774454, -0.2533126, -0.4202326}, {25, 25, 17}, 4.6); + TransInsScale(3, &t); + ExpectTransformEqual(t, + {-0.8678937, 0.0774454, -0.2533126, -0.4202326}, {25, 25, 17}, 13.8); +} + +TEST(QMathTransformTest, TransAddScale) +{ + transform_t t = MakeTransform( + {-0.9884186, -0.0914321, 0.1088879, 0.053031}, {-9, -12, -70}, 6); + TransAddScale(1.2, &t); + ExpectTransformEqual(t, + {-0.9884186, -0.0914321, 0.1088879, 0.053031}, {-10.8, -14.4, -84}, 7.2); +} + +TEST(QMathTransformTest, TransInsTranslation) +{ + const vec3_t translation = {3.6, 20, 5.3}; + transform_t t = MakeTransform( + {0.5002998, 0.3780266, 0.7196359, 0.2981948}, {-8, 28, 27}, 5.5); + TransInsTranslation(translation, &t); + ExpectTransformEqual(t, + {0.5002998, 0.3780266, 0.7196359, 0.2981948}, {7.592672, -7.848988, 135.6898}, 5.5); +} + +TEST(QMathTransformTest, TransAddTranslation) +{ + const vec3_t translation = { 18, -1.1, -6}; + transform_t t = MakeTransform( + {0.3917585, -0.3411706, -0.1357459, 0.8436237}, {-23, 56, 52}, 4); + TransAddTranslation(translation, &t); + ExpectTransformEqual(t, + {0.3917585, -0.3411706, -0.1357459, 0.8436237}, {-5, 54.9, 46}, 4); +} + +TEST(QMathTransformTest, TransCombine) +{ + const transform_t left = MakeTransform( + {-0.5029552, 0.4741776, -0.5393551, 0.4809239}, {-3, -50, 7}, 1.9); + const transform_t right = MakeTransform( + {0.4461722, 0.8836869, 0.1121932, -0.0862585}, {-25, 11, 16}, 1.6); + transform_t combined; + TransCombine(&right, &left, &combined); + ExpectTransformEqual(combined, + {0.7877796, 0.1998672, -0.5555394, -0.1755917}, {29.72799, -5.378298, -16.55849}, 3.04); +} + +TEST(QMathTransformTest, TransInverse) +{ + const transform_t t = MakeTransform( + {0.4833702, -0.42157, -0.7551386, -0.1356377}, {2.5, 3.4, 1.4}, 2.5); + transform_t inverse; + TransInverse(&t, &inverse); + // This quat multiplied by -1 would also be acceptable + ExpectTransformEqual(inverse, + {-0.4833702, 0.42157, 0.7551386, -0.1356377}, {1.244436,1.155842,-0.5278334}, 0.4); +} + +} // namespace diff --git a/src/engine/qcommon/q_shared.h b/src/engine/qcommon/q_shared.h index 62d738e258..f014947496 100644 --- a/src/engine/qcommon/q_shared.h +++ b/src/engine/qcommon/q_shared.h @@ -1166,7 +1166,7 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) #define sseSwizzle( a, mask ) _mm_shuffle_ps( (a), (a), SWZ_##mask ) inline __m128 unitQuat() { - return _mm_set_ps( 1.0f, 0.0f, 0.0f, 0.0f ); // order is reversed + return _mm_setr_ps( 0.0f, 0.0f, 0.0f, 1.0f ); } inline __m128 sseLoadInts( const int vec[4] ) { return *(__m128 *)vec; @@ -1175,13 +1175,14 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) alignas(16) static const std::array vec = { 0, 0, 0, 0 }; return sseLoadInts( vec.data() ); } - inline __m128 mask_000W() { - alignas(16) static const std::array vec = { 0, 0, 0, -1 }; - return sseLoadInts( vec.data() ); - } - inline __m128 mask_XYZ0() { - alignas(16) static const std::array vec = { -1, -1, -1, 0 }; - return sseLoadInts( vec.data() ); + + // {first.x, first,y, first.z, second.w} + inline __m128 first_XYZ_second_W( __m128 first, __m128 second) + { + // second.w, dontcare, first.z, dontcare + __m128 tmp = _mm_shuffle_ps(second, first, 3 << 0 | 2 << 4); + // first.x, first.y, tmp.z, tmp.x + return _mm_shuffle_ps(first, tmp, 0 << 0 | 1 << 2 | 2 << 4 | 0 << 6); } inline __m128 sign_000W() { @@ -1197,12 +1198,15 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) return sseLoadInts( vec.data() ); } + // returns the dot product in all 4 elements inline __m128 sseDot4( __m128 a, __m128 b ) { __m128 prod = _mm_mul_ps( a, b ); __m128 sum1 = _mm_add_ps( prod, sseSwizzle( prod, YXWZ ) ); __m128 sum2 = _mm_add_ps( sum1, sseSwizzle( sum1, ZWXY ) ); return sum2; } + + // returns 0 in w component if input w's are finite inline __m128 sseCrossProduct( __m128 a, __m128 b ) { __m128 a_yzx = sseSwizzle( a, YZXW ); __m128 b_yzx = sseSwizzle( b, YZXW ); @@ -1238,6 +1242,7 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) t = _mm_mul_ps( h, t ); return _mm_mul_ps( q, t ); } + // rotates (3-dimensional) vec. vec's w component is unchanged inline __m128 sseQuatTransform( __m128 q, __m128 vec ) { __m128 t, t2; t = sseCrossProduct( q, vec ); @@ -1246,14 +1251,6 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) t = _mm_mul_ps( sseSwizzle( q, WWWW ), t ); return _mm_add_ps( _mm_add_ps( vec, t2 ), t ); } - inline __m128 sseQuatTransformInverse( __m128 q, __m128 vec ) { - __m128 t, t2; - t = sseCrossProduct( vec, q ); - t = _mm_add_ps( t, t ); - t2 = sseCrossProduct( t, q ); - t = _mm_mul_ps( sseSwizzle( q, WWWW ), t ); - return _mm_add_ps( _mm_add_ps( vec, t2 ), t ); - } inline __m128 sseLoadVec3( const vec3_t vec ) { __m128 v = _mm_load_ss( &vec[ 2 ] ); v = sseSwizzle( v, YYXY ); @@ -1274,10 +1271,6 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) t->sseRot = u; t->sseTransScale = u; } - inline void TransCopy( const transform_t *in, transform_t *out ) { - out->sseRot = in->sseRot; - out->sseTransScale = in->sseTransScale; - } inline void TransformPoint( const transform_t *t, const vec3_t in, vec3_t out ) { __m128 ts = t->sseTransScale; @@ -1286,77 +1279,34 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) tmp = _mm_add_ps( tmp, ts ); sseStoreVec3( tmp, out ); } - inline void TransformPointInverse( - const transform_t *t, const vec3_t in, vec3_t out ) { - __m128 ts = t->sseTransScale; - __m128 v = _mm_sub_ps( sseLoadVec3Unsafe( in ), ts ); - v = _mm_mul_ps( v, _mm_rcp_ps( sseSwizzle( ts, WWWW ) ) ); - v = sseQuatTransformInverse( t->sseRot, v ); - sseStoreVec3( v, out ); - } inline void TransformNormalVector( const transform_t *t, const vec3_t in, vec3_t out ) { __m128 v = sseLoadVec3Unsafe( in ); v = sseQuatTransform( t->sseRot, v ); sseStoreVec3( v, out ); } - inline void TransformNormalVectorInverse( const transform_t *t, - const vec3_t in, vec3_t out ) { - __m128 v = sseLoadVec3Unsafe( in ); - v = sseQuatTransformInverse( t->sseRot, v ); - sseStoreVec3( v, out ); - } - inline __m128 sseAxisAngleToQuat( const vec3_t axis, float angle ) { - __m128 sa = _mm_set1_ps( sinf( 0.5f * angle ) ); - __m128 ca = _mm_set1_ps( cosf( 0.5f * angle ) ); - __m128 a = sseLoadVec3( axis ); - a = _mm_mul_ps( a, sa ); - return _mm_or_ps( a, _mm_and_ps( ca, mask_000W() ) ); - } inline void TransInitRotationQuat( const quat_t quat, transform_t *t ) { t->sseRot = _mm_loadu_ps( quat ); t->sseTransScale = unitQuat(); } - inline void TransInitRotation( const vec3_t axis, float angle, - transform_t *t ) { - t->sseRot = sseAxisAngleToQuat( axis, angle ); - t->sseTransScale = unitQuat(); - } inline void TransInitTranslation( const vec3_t vec, transform_t *t ) { __m128 v = sseLoadVec3( vec ); t->sseRot = unitQuat(); t->sseTransScale = _mm_or_ps( v, unitQuat() ); } inline void TransInitScale( float factor, transform_t *t ) { - __m128 f = _mm_set1_ps( factor ); - f = _mm_and_ps( f, mask_000W() ); t->sseRot = unitQuat(); - t->sseTransScale = f; + t->sseTransScale = _mm_setr_ps( 0.0f, 0.0f, 0.0f, factor ); } inline void TransInsRotationQuat( const quat_t quat, transform_t *t ) { __m128 q = _mm_loadu_ps( quat ); t->sseRot = sseQuatMul( t->sseRot, q ); } - inline void TransInsRotation( const vec3_t axis, float angle, - transform_t *t ) { - __m128 q = sseAxisAngleToQuat( axis, angle ); - t->sseRot = sseQuatMul( q, t->sseRot ); - } inline void TransAddRotationQuat( const quat_t quat, transform_t *t ) { __m128 q = _mm_loadu_ps( quat ); - __m128 transformed = sseQuatTransform( q, t->sseTransScale ); t->sseRot = sseQuatMul( q, t->sseRot ); - t->sseTransScale = _mm_or_ps( _mm_and_ps( transformed, mask_XYZ0() ), - _mm_and_ps( t->sseTransScale, mask_000W() ) ); - } - inline void TransAddRotation( const vec3_t axis, float angle, - transform_t *t ) { - __m128 q = sseAxisAngleToQuat( axis, angle ); - __m128 transformed = sseQuatTransform( q, t->sseTransScale ); - t->sseRot = sseQuatMul( t->sseRot, q ); - t->sseTransScale = _mm_or_ps( _mm_and_ps( transformed, mask_XYZ0() ), - _mm_and_ps( t->sseTransScale, mask_000W() ) ); + t->sseTransScale = sseQuatTransform( q, t->sseTransScale ); } inline void TransInsScale( float factor, transform_t *t ) { t->scale *= factor; @@ -1367,11 +1317,10 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) } inline void TransInsTranslation( const vec3_t vec, transform_t *t ) { - __m128 v = sseLoadVec3Unsafe( vec ); + __m128 v = sseLoadVec3( vec ); __m128 ts = t->sseTransScale; v = sseQuatTransform( t->sseRot, v ); v = _mm_mul_ps( v, sseSwizzle( ts, WWWW ) ); - v = _mm_and_ps( v, mask_XYZ0() ); t->sseTransScale = _mm_add_ps( ts, v ); } inline void TransAddTranslation( @@ -1387,10 +1336,9 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) __m128 bRot = b->sseRot; __m128 bTS = b->sseTransScale; __m128 tmp = sseQuatTransform( bRot, aTS ); - tmp = _mm_or_ps( _mm_and_ps( tmp, mask_XYZ0() ), - _mm_and_ps( aTS, mask_000W() ) ); tmp = _mm_mul_ps( tmp, sseSwizzle( bTS, WWWW ) ); - out->sseTransScale = _mm_add_ps( tmp, _mm_and_ps( bTS, mask_XYZ0() ) ); + __m128 bT = first_XYZ_second_W( bTS, mask_0000() ); + out->sseTransScale = _mm_add_ps( tmp, bT ); out->sseRot = sseQuatMul( bRot, aRot ); } inline void TransInverse( const transform_t *in, @@ -1403,8 +1351,7 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) __m128 tmp = sseQuatTransform( invRot, invT ); tmp = _mm_mul_ps( tmp, invS ); out->sseRot = invRot; - out->sseTransScale = _mm_or_ps( _mm_and_ps( tmp, mask_XYZ0() ), - _mm_and_ps( invS, mask_000W() ) ); + out->sseTransScale = first_XYZ_second_W( tmp, invS ); } inline void TransStartLerp( transform_t *t ) { t->sseRot = mask_0000(); @@ -1426,28 +1373,24 @@ inline vec_t VectorNormalize2( const vec3_t v, vec3_t out ) #else // The non-SSE variants are in q_math.cpp file. void TransInit( transform_t *t ); - void TransCopy( const transform_t *in, transform_t *out ); void TransformPoint( const transform_t *t, const vec3_t in, vec3_t out ); - void TransformPointInverse( const transform_t *t, const vec3_t in, vec3_t out ); void TransformNormalVector( const transform_t *t, const vec3_t in, vec3_t out ); - void TransformNormalVectorInverse( const transform_t *t, const vec3_t in, vec3_t out ); void TransInitRotationQuat( const quat_t quat, transform_t *t ); - void TransInitRotation( const vec3_t axis, float angle, - transform_t *t ); void TransInitTranslation( const vec3_t vec, transform_t *t ); void TransInitScale( float factor, transform_t *t ); void TransInsRotationQuat( const quat_t quat, transform_t *t ); void TransInsRotation( const vec3_t axis, float angle, transform_t *t ); void TransAddRotationQuat( const quat_t quat, transform_t *t ); - void TransAddRotation( const vec3_t axis, float angle, transform_t *t ); void TransInsScale( float factor, transform_t *t ); void TransAddScale( float factor, transform_t *t ); void TransInsTranslation( const vec3_t vec, transform_t *t ); void TransAddTranslation( const vec3_t vec, transform_t *t ); + // "a" is the first one that would be applied to a vector + // so as a matrix multiplication this is B * A void TransCombine( const transform_t *a, const transform_t *b, transform_t *c ); void TransInverse( const transform_t *in, transform_t *out ); diff --git a/src/engine/renderer/tr_animation.cpp b/src/engine/renderer/tr_animation.cpp index b57f43aae8..491fc233ad 100644 --- a/src/engine/renderer/tr_animation.cpp +++ b/src/engine/renderer/tr_animation.cpp @@ -1497,7 +1497,7 @@ int RE_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float fra TransAddWeight( frac, &blend->bones[ i ].t, &trans ); TransEndLerp( &trans ); - TransCopy( &trans, &skel->bones[ i ].t ); + skel->bones[ i ].t = trans; } // calculate a bounding box in the current coordinate system diff --git a/src/engine/renderer/tr_surface.cpp b/src/engine/renderer/tr_surface.cpp index 0c5b524947..b7fa3c81ab 100644 --- a/src/engine/renderer/tr_surface.cpp +++ b/src/engine/renderer/tr_surface.cpp @@ -1002,7 +1002,7 @@ static void Tess_SurfaceMD5( md5Surface_t *srf ) for ( ; bone < lastBone; bone++, modelBone++ ) { - TransCopy( &modelBone->joint, bone ); + *bone = modelBone->joint; TransInsScale( modelScale, bone ); } } @@ -1149,7 +1149,7 @@ void Tess_SurfaceIQM( srfIQModel_t *surf ) { for ( ; bone < lastBone; bone++, modelJoint++ ) { - TransCopy( modelJoint, bone ); + *bone = *modelJoint; TransInsScale( modelScale, bone ); } } @@ -1491,7 +1491,7 @@ static void Tess_SurfaceVBOMD5Mesh( srfVBOMD5Mesh_t *srf ) for ( ; bone < lastBone; bone++, modelBone++ ) { - TransCopy( &modelBone->joint, bone ); + *bone = modelBone->joint; TransInsScale( modelScale, bone ); } } diff --git a/src/shared/client/cg_api.cpp b/src/shared/client/cg_api.cpp index 1f1892df2c..6cdf2e9338 100644 --- a/src/shared/client/cg_api.cpp +++ b/src/shared/client/cg_api.cpp @@ -528,7 +528,7 @@ int trap_R_BlendSkeleton( refSkeleton_t *skel, const refSkeleton_t *blend, float TransAddWeight( frac, &blend->bones[ i ].t, &trans ); TransEndLerp( &trans ); - TransCopy( &trans, &skel->bones[ i ].t ); + skel->bones[ i ].t = trans; } // calculate a bounding box in the current coordinate system