|
| 1 | +/* |
| 2 | +=========================================================================== |
| 3 | +Daemon BSD Source Code |
| 4 | +Copyright (c) 2024, Daemon Developers |
| 5 | +All rights reserved. |
| 6 | +
|
| 7 | +Redistribution and use in source and binary forms, with or without |
| 8 | +modification, are permitted provided that the following conditions are met: |
| 9 | + * Redistributions of source code must retain the above copyright |
| 10 | + notice, this list of conditions and the following disclaimer. |
| 11 | + * Redistributions in binary form must reproduce the above copyright |
| 12 | + notice, this list of conditions and the following disclaimer in the |
| 13 | + documentation and/or other materials provided with the distribution. |
| 14 | + * Neither the name of the Daemon developers nor the |
| 15 | + names of its contributors may be used to endorse or promote products |
| 16 | + derived from this software without specific prior written permission. |
| 17 | +
|
| 18 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| 19 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 20 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| 21 | +DISCLAIMED. IN NO EVENT SHALL DAEMON DEVELOPERS BE LIABLE FOR ANY |
| 22 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 23 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 24 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 25 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 27 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | +=========================================================================== |
| 29 | +*/ |
| 30 | + |
| 31 | +#include <gtest/gtest.h> |
| 32 | +#include <gmock/gmock.h> |
| 33 | + |
| 34 | +#include "common/Common.h" |
| 35 | + |
| 36 | +// TODO: add transform tests with quats with negative real component |
| 37 | +// the calculator I used always made it positive |
| 38 | + |
| 39 | +namespace { |
| 40 | + |
| 41 | +using ::testing::Pointwise; |
| 42 | +using ::testing::FloatNear; |
| 43 | + |
| 44 | +// Using a function for this in case we want to change how transform_t is set |
| 45 | +// to avoid undefined behaviors with the union |
| 46 | +transform_t MakeTransform( |
| 47 | + const std::array<float, 4>& quat, |
| 48 | + const std::array<float, 3>& translation, |
| 49 | + float scale) |
| 50 | +{ |
| 51 | + transform_t t; |
| 52 | + Vector4Copy(quat, t.rot); |
| 53 | + VectorCopy(translation, t.trans); |
| 54 | + t.scale = scale; |
| 55 | + return t; |
| 56 | +} |
| 57 | + |
| 58 | +void ExpectTransformEqual( |
| 59 | + const transform_t& t, |
| 60 | + const std::array<float, 4>& expectedQuat, |
| 61 | + const std::array<float, 3>& expectedTranslation, |
| 62 | + float expectedScale) |
| 63 | +{ |
| 64 | + const char* base = reinterpret_cast<const char*>(&t); |
| 65 | + std::array<float, 4> actualQuat; |
| 66 | + std::array<float, 3> actualTranslation; |
| 67 | + float actualScale; |
| 68 | + memcpy(&actualQuat, base + offsetof(transform_t, rot), sizeof(actualQuat)); |
| 69 | + memcpy(&actualTranslation, base + offsetof(transform_t, trans), sizeof(actualTranslation)); |
| 70 | + memcpy(&actualScale, base + offsetof(transform_t, scale), sizeof(actualScale)); |
| 71 | + EXPECT_THAT(actualQuat, Pointwise(FloatNear(1e-4), expectedQuat)); |
| 72 | + EXPECT_THAT(actualTranslation, Pointwise(FloatNear(1e-3), expectedTranslation)); |
| 73 | + EXPECT_THAT(actualScale, FloatNear(1e-5, expectedScale)); |
| 74 | +} |
| 75 | + |
| 76 | +TEST(QMathTransformTest, TransInit) |
| 77 | +{ |
| 78 | + transform_t t; |
| 79 | + TransInit(&t); |
| 80 | + ExpectTransformEqual(t, {0, 0, 0, 1}, {0, 0, 0}, 1); |
| 81 | +} |
| 82 | + |
| 83 | +TEST(QMathTransformTest, TransformPoint) |
| 84 | +{ |
| 85 | + transform_t t = MakeTransform( |
| 86 | + {0.3155654, 0.121273, 0.7211766, 0.6046616}, {-11, -26, 55}, 1.2); |
| 87 | + const vec3_t pointIn = {12, 19, -30}; |
| 88 | + vec3_t pointOut; |
| 89 | + TransformPoint(&t, pointIn, pointOut); |
| 90 | + const vec3_t expectedPoint = {-51.8073, -10.3551, 44.3603}; |
| 91 | + EXPECT_THAT(pointOut, Pointwise(FloatNear(0.001), expectedPoint)); |
| 92 | +} |
| 93 | + |
| 94 | +TEST(QMathTransformTest, TransformNormalVector) |
| 95 | +{ |
| 96 | + const transform_t t = MakeTransform( |
| 97 | + {0.1641059, -0.6753088, 0.2253332, -0.6828266}, {235, 52, 42}, 8); |
| 98 | + const vec3_t vector = { 0.48, 0.64, 0.6 }; |
| 99 | + vec3_t transformedVector; |
| 100 | + TransformNormalVector(&t, vector, transformedVector); |
| 101 | + const vec3_t expectedVector = {0.6462654,0.2383020,-0.7249505}; |
| 102 | + EXPECT_THAT(transformedVector, Pointwise(FloatNear(1e-6), expectedVector)); |
| 103 | +} |
| 104 | + |
| 105 | +TEST(QMathTransformTest, TransInitRotationQuat) |
| 106 | +{ |
| 107 | + const quat_t q = { -0.1423769, 0.5422508, 0.7235357, -0.402727 }; |
| 108 | + transform_t t; |
| 109 | + TransInitRotationQuat(q, &t); |
| 110 | + ExpectTransformEqual(t, {-0.1423769, 0.5422508, 0.7235357, -0.402727}, {0, 0, 0}, 1); |
| 111 | +} |
| 112 | + |
| 113 | +TEST(QMathTransformTest, TransInitTranslation) |
| 114 | +{ |
| 115 | + const vec3_t translation = {-9, -32, -0.5}; |
| 116 | + transform_t t; |
| 117 | + TransInitTranslation(translation, &t); |
| 118 | + ExpectTransformEqual(t, {0, 0, 0, 1}, {-9, -32, -0.5}, 1); |
| 119 | +} |
| 120 | + |
| 121 | +TEST(QMathTransformTest, TransInitScale) |
| 122 | +{ |
| 123 | + transform_t t; |
| 124 | + TransInitScale(4.3, &t); |
| 125 | + ExpectTransformEqual(t, {0, 0, 0, 1}, {0, 0, 0}, 4.3); |
| 126 | +} |
| 127 | + |
| 128 | +TEST(QMathTransformTest, TransInsRotationQuat) |
| 129 | +{ |
| 130 | + const quat_t q = {0.3694065, -0.6226631, 0.1538449, -0.6724294}; |
| 131 | + transform_t t = MakeTransform( |
| 132 | + {-0.5881667, -0.3748035, 0.6614826, 0.2757227}, {1.8, -1.8, -4}, 3); |
| 133 | + TransInsRotationQuat(q, &t); |
| 134 | + ExpectTransformEqual(t, {0.8515735, 0.4151890, 0.1023027, -0.3032735}, {1.8, -1.8, -4}, 3); |
| 135 | +} |
| 136 | + |
| 137 | +TEST(QMathTransformTest, TransAddRotationQuat) |
| 138 | +{ |
| 139 | + const quat_t rot = {-0.4217441, -0.6010819, -0.3683214, -0.5702384}; |
| 140 | + transform_t t = MakeTransform( |
| 141 | + {-0.1167623, -0.9282776, 0.3395844, 0.096694}, {12.5, 93.7, -14.1}, 2.9); |
| 142 | + TransAddRotationQuat(rot, &t); |
| 143 | + ExpectTransformEqual(t, {-0.5202203, 0.6574423, 0.09205336, -0.5372771}, |
| 144 | + {-5.823749, 47.07177, 82.97640}, 2.9); |
| 145 | +} |
| 146 | + |
| 147 | +TEST(QMathTransformTest, TransInsScale) |
| 148 | +{ |
| 149 | + transform_t t = MakeTransform( |
| 150 | + {-0.8678937, 0.0774454, -0.2533126, -0.4202326}, {25, 25, 17}, 4.6); |
| 151 | + TransInsScale(3, &t); |
| 152 | + ExpectTransformEqual(t, |
| 153 | + {-0.8678937, 0.0774454, -0.2533126, -0.4202326}, {25, 25, 17}, 13.8); |
| 154 | +} |
| 155 | + |
| 156 | +TEST(QMathTransformTest, TransAddScale) |
| 157 | +{ |
| 158 | + transform_t t = MakeTransform( |
| 159 | + {-0.9884186, -0.0914321, 0.1088879, 0.053031}, {-9, -12, -70}, 6); |
| 160 | + TransAddScale(1.2, &t); |
| 161 | + ExpectTransformEqual(t, |
| 162 | + {-0.9884186, -0.0914321, 0.1088879, 0.053031}, {-10.8, -14.4, -84}, 7.2); |
| 163 | +} |
| 164 | + |
| 165 | +TEST(QMathTransformTest, TransInsTranslation) |
| 166 | +{ |
| 167 | + const vec3_t translation = {3.6, 20, 5.3}; |
| 168 | + transform_t t = MakeTransform( |
| 169 | + {0.5002998, 0.3780266, 0.7196359, 0.2981948}, {-8, 28, 27}, 5.5); |
| 170 | + TransInsTranslation(translation, &t); |
| 171 | + ExpectTransformEqual(t, |
| 172 | + {0.5002998, 0.3780266, 0.7196359, 0.2981948}, {7.592672, -7.848988, 135.6898}, 5.5); |
| 173 | +} |
| 174 | + |
| 175 | +TEST(QMathTransformTest, TransAddTranslation) |
| 176 | +{ |
| 177 | + const vec3_t translation = { 18, -1.1, -6}; |
| 178 | + transform_t t = MakeTransform( |
| 179 | + {0.3917585, -0.3411706, -0.1357459, 0.8436237}, {-23, 56, 52}, 4); |
| 180 | + TransAddTranslation(translation, &t); |
| 181 | + ExpectTransformEqual(t, |
| 182 | + {0.3917585, -0.3411706, -0.1357459, 0.8436237}, {-5, 54.9, 46}, 4); |
| 183 | +} |
| 184 | + |
| 185 | +TEST(QMathTransformTest, TransCombine) |
| 186 | +{ |
| 187 | + const transform_t left = MakeTransform( |
| 188 | + {-0.5029552, 0.4741776, -0.5393551, 0.4809239}, {-3, -50, 7}, 1.9); |
| 189 | + const transform_t right = MakeTransform( |
| 190 | + {0.4461722, 0.8836869, 0.1121932, -0.0862585}, {-25, 11, 16}, 1.6); |
| 191 | + transform_t combined; |
| 192 | + TransCombine(&right, &left, &combined); |
| 193 | + ExpectTransformEqual(combined, |
| 194 | + {0.7877796, 0.1998672, -0.5555394, -0.1755917}, {29.72799, -5.378298, -16.55849}, 3.04); |
| 195 | +} |
| 196 | + |
| 197 | +TEST(QMathTransformTest, TransInverse) |
| 198 | +{ |
| 199 | + const transform_t t = MakeTransform( |
| 200 | + {0.4833702, -0.42157, -0.7551386, -0.1356377}, {2.5, 3.4, 1.4}, 2.5); |
| 201 | + transform_t inverse; |
| 202 | + TransInverse(&t, &inverse); |
| 203 | + // This quat multiplied by -1 would also be acceptable |
| 204 | + ExpectTransformEqual(inverse, |
| 205 | + {-0.4833702, 0.42157, 0.7551386, -0.1356377}, {1.244436,1.155842,-0.5278334}, 0.4); |
| 206 | +} |
| 207 | + |
| 208 | +} // namespace |
0 commit comments