1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "QuatTest" 18 19 #include <math.h> 20 #include <stdlib.h> 21 22 #include <random> 23 #include <functional> 24 25 #include <math/quat.h> 26 #include <math/mat4.h> 27 #include <math/vec3.h> 28 #include <math/vec4.h> 29 30 #include <gtest/gtest.h> 31 32 namespace android { 33 34 class QuatTest : public testing::Test { 35 protected: 36 }; 37 38 TEST_F(QuatTest, Basics) { 39 quatd q; 40 double4& v(q.xyzw); 41 42 EXPECT_EQ(sizeof(quatd), sizeof(double)*4); 43 EXPECT_EQ(reinterpret_cast<void*>(&q), reinterpret_cast<void*>(&v)); 44 } 45 46 TEST_F(QuatTest, Constructors) { 47 quatd q0; 48 EXPECT_EQ(q0.x, 0); 49 EXPECT_EQ(q0.y, 0); 50 EXPECT_EQ(q0.z, 0); 51 EXPECT_EQ(q0.w, 0); 52 53 quatd q1(1); 54 EXPECT_EQ(q1.x, 0); 55 EXPECT_EQ(q1.y, 0); 56 EXPECT_EQ(q1.z, 0); 57 EXPECT_EQ(q1.w, 1); 58 59 quatd q2(1, 2, 3, 4); 60 EXPECT_EQ(q2.x, 2); 61 EXPECT_EQ(q2.y, 3); 62 EXPECT_EQ(q2.z, 4); 63 EXPECT_EQ(q2.w, 1); 64 65 quatd q3(q2); 66 EXPECT_EQ(q3.x, 2); 67 EXPECT_EQ(q3.y, 3); 68 EXPECT_EQ(q3.z, 4); 69 EXPECT_EQ(q3.w, 1); 70 71 quatd q4(q3.xyz, 42); 72 EXPECT_EQ(q4.x, 2); 73 EXPECT_EQ(q4.y, 3); 74 EXPECT_EQ(q4.z, 4); 75 EXPECT_EQ(q4.w, 42); 76 77 quatd q5(double3(q2.xy, 42), 24); 78 EXPECT_EQ(q5.x, 2); 79 EXPECT_EQ(q5.y, 3); 80 EXPECT_EQ(q5.z, 42); 81 EXPECT_EQ(q5.w, 24); 82 83 quatd q6; 84 q6 = 12; 85 EXPECT_EQ(q6.x, 0); 86 EXPECT_EQ(q6.y, 0); 87 EXPECT_EQ(q6.z, 0); 88 EXPECT_EQ(q6.w, 12); 89 90 quatd q7 = 1 + 2_id + 3_jd + 4_kd; 91 EXPECT_EQ(q7.x, 2); 92 EXPECT_EQ(q7.y, 3); 93 EXPECT_EQ(q7.z, 4); 94 EXPECT_EQ(q7.w, 1); 95 96 quatf qf(2); 97 EXPECT_EQ(qf.x, 0); 98 EXPECT_EQ(qf.y, 0); 99 EXPECT_EQ(qf.z, 0); 100 EXPECT_EQ(qf.w, 2); 101 } 102 103 TEST_F(QuatTest, Access) { 104 quatd q0(1, 2, 3, 4); 105 q0.x = 10; 106 q0.y = 20; 107 q0.z = 30; 108 q0.w = 40; 109 EXPECT_EQ(q0.x, 10); 110 EXPECT_EQ(q0.y, 20); 111 EXPECT_EQ(q0.z, 30); 112 EXPECT_EQ(q0.w, 40); 113 114 q0[0] = 100; 115 q0[1] = 200; 116 q0[2] = 300; 117 q0[3] = 400; 118 EXPECT_EQ(q0.x, 100); 119 EXPECT_EQ(q0.y, 200); 120 EXPECT_EQ(q0.z, 300); 121 EXPECT_EQ(q0.w, 400); 122 123 q0.xyz = double3(1, 2, 3); 124 EXPECT_EQ(q0.x, 1); 125 EXPECT_EQ(q0.y, 2); 126 EXPECT_EQ(q0.z, 3); 127 EXPECT_EQ(q0.w, 400); 128 } 129 130 TEST_F(QuatTest, UnaryOps) { 131 quatd q0(1, 2, 3, 4); 132 133 q0 += 1; 134 EXPECT_EQ(q0.x, 2); 135 EXPECT_EQ(q0.y, 3); 136 EXPECT_EQ(q0.z, 4); 137 EXPECT_EQ(q0.w, 2); 138 139 q0 -= 1; 140 EXPECT_EQ(q0.x, 2); 141 EXPECT_EQ(q0.y, 3); 142 EXPECT_EQ(q0.z, 4); 143 EXPECT_EQ(q0.w, 1); 144 145 q0 *= 2; 146 EXPECT_EQ(q0.x, 4); 147 EXPECT_EQ(q0.y, 6); 148 EXPECT_EQ(q0.z, 8); 149 EXPECT_EQ(q0.w, 2); 150 151 q0 /= 2; 152 EXPECT_EQ(q0.x, 2); 153 EXPECT_EQ(q0.y, 3); 154 EXPECT_EQ(q0.z, 4); 155 EXPECT_EQ(q0.w, 1); 156 157 quatd q1(10, 20, 30, 40); 158 159 q0 += q1; 160 EXPECT_EQ(q0.x, 22); 161 EXPECT_EQ(q0.y, 33); 162 EXPECT_EQ(q0.z, 44); 163 EXPECT_EQ(q0.w, 11); 164 165 q0 -= q1; 166 EXPECT_EQ(q0.x, 2); 167 EXPECT_EQ(q0.y, 3); 168 EXPECT_EQ(q0.z, 4); 169 EXPECT_EQ(q0.w, 1); 170 171 q1 = -q1; 172 EXPECT_EQ(q1.x, -20); 173 EXPECT_EQ(q1.y, -30); 174 EXPECT_EQ(q1.z, -40); 175 EXPECT_EQ(q1.w, -10); 176 177 // TODO(mathias): multiplies 178 } 179 180 TEST_F(QuatTest, ComparisonOps) { 181 quatd q0(1, 2, 3, 4); 182 quatd q1(10, 20, 30, 40); 183 184 EXPECT_TRUE(q0 == q0); 185 EXPECT_TRUE(q0 != q1); 186 EXPECT_FALSE(q0 != q0); 187 EXPECT_FALSE(q0 == q1); 188 } 189 190 TEST_F(QuatTest, ArithmeticOps) { 191 quatd q0(1, 2, 3, 4); 192 quatd q1(10, 20, 30, 40); 193 194 quatd q2(q0 + q1); 195 EXPECT_EQ(q2.x, 22); 196 EXPECT_EQ(q2.y, 33); 197 EXPECT_EQ(q2.z, 44); 198 EXPECT_EQ(q2.w, 11); 199 200 q0 = q1 * 2; 201 EXPECT_EQ(q0.x, 40); 202 EXPECT_EQ(q0.y, 60); 203 EXPECT_EQ(q0.z, 80); 204 EXPECT_EQ(q0.w, 20); 205 206 q0 = 2 * q1; 207 EXPECT_EQ(q0.x, 40); 208 EXPECT_EQ(q0.y, 60); 209 EXPECT_EQ(q0.z, 80); 210 EXPECT_EQ(q0.w, 20); 211 212 quatf qf(2); 213 q0 = q1 * qf; 214 EXPECT_EQ(q0.x, 40); 215 EXPECT_EQ(q0.y, 60); 216 EXPECT_EQ(q0.z, 80); 217 EXPECT_EQ(q0.w, 20); 218 219 EXPECT_EQ(1_id * 1_id, quat(-1)); 220 EXPECT_EQ(1_jd * 1_jd, quat(-1)); 221 EXPECT_EQ(1_kd * 1_kd, quat(-1)); 222 EXPECT_EQ(1_id * 1_jd * 1_kd, quat(-1)); 223 } 224 225 TEST_F(QuatTest, ArithmeticFunc) { 226 quatd q(1, 2, 3, 4); 227 quatd qc(conj(q)); 228 __attribute__((unused)) quatd qi(inverse(q)); 229 quatd qn(normalize(q)); 230 231 EXPECT_EQ(qc.x, -2); 232 EXPECT_EQ(qc.y, -3); 233 EXPECT_EQ(qc.z, -4); 234 EXPECT_EQ(qc.w, 1); 235 236 EXPECT_EQ(~q, qc); 237 EXPECT_EQ(length(q), length(qc)); 238 EXPECT_EQ(sqrt(30), length(q)); 239 EXPECT_FLOAT_EQ(1, length(qn)); 240 EXPECT_FLOAT_EQ(1, dot(qn, qn)); 241 242 quatd qr = quatd::fromAxisAngle(double3(0, 0, 1), M_PI / 2); 243 EXPECT_EQ(mat4d(qr).toQuaternion(), qr); 244 EXPECT_EQ(1_id, mat4d(1_id).toQuaternion()); 245 EXPECT_EQ(1_jd, mat4d(1_jd).toQuaternion()); 246 EXPECT_EQ(1_kd, mat4d(1_kd).toQuaternion()); 247 248 249 EXPECT_EQ(qr, log(exp(qr))); 250 251 quatd qq = qr * qr; 252 quatd q2 = pow(qr, 2); 253 EXPECT_NEAR(qq.x, q2.x, 1e-15); 254 EXPECT_NEAR(qq.y, q2.y, 1e-15); 255 EXPECT_NEAR(qq.z, q2.z, 1e-15); 256 EXPECT_NEAR(qq.w, q2.w, 1e-15); 257 258 quatd qa = quatd::fromAxisAngle(double3(0, 0, 1), 0); 259 quatd qb = quatd::fromAxisAngle(double3(0, 0, 1), M_PI / 2); 260 quatd qs = slerp(qa, qb, 0.5); 261 qr = quatd::fromAxisAngle(double3(0, 0, 1), M_PI / 4); 262 EXPECT_FLOAT_EQ(qr.x, qs.x); 263 EXPECT_FLOAT_EQ(qr.y, qs.y); 264 EXPECT_FLOAT_EQ(qr.z, qs.z); 265 EXPECT_FLOAT_EQ(qr.w, qs.w); 266 267 qs = nlerp(qa, qb, 0.5); 268 EXPECT_FLOAT_EQ(qr.x, qs.x); 269 EXPECT_FLOAT_EQ(qr.y, qs.y); 270 EXPECT_FLOAT_EQ(qr.z, qs.z); 271 EXPECT_FLOAT_EQ(qr.w, qs.w); 272 } 273 274 TEST_F(QuatTest, MultiplicationExhaustive) { 275 static constexpr double value_eps = double(1000) * std::numeric_limits<double>::epsilon(); 276 277 std::default_random_engine generator(171717); 278 std::uniform_real_distribution<double> distribution(-10.0, 10.0); 279 auto rand_gen = std::bind(distribution, generator); 280 281 for (size_t i = 0; i < (1024 * 1024); ++i) { 282 double3 axis_a = normalize(double3(rand_gen(), rand_gen(), rand_gen())); 283 double angle_a = rand_gen(); 284 quatd a = quatd::fromAxisAngle(axis_a, angle_a); 285 286 double3 axis_b = normalize(double3(rand_gen(), rand_gen(), rand_gen())); 287 double angle_b = rand_gen(); 288 quatd b = quatd::fromAxisAngle(axis_b, angle_b); 289 290 quatd ab = a * b; 291 quatd ab_other(a.w * b.xyz + b.w * a.xyz + cross(a.xyz, b.xyz), 292 (a.w * b.w) - dot(a.xyz, b.xyz)); 293 294 ASSERT_NEAR(ab.x, ab_other.x, value_eps); 295 ASSERT_NEAR(ab.y, ab_other.y, value_eps); 296 ASSERT_NEAR(ab.z, ab_other.z, value_eps); 297 ASSERT_NEAR(ab.w, ab_other.w, value_eps); 298 } 299 } 300 301 }; // namespace android 302