1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "[Quat.h]"19 #include <stdlib.h>20 #include "[float3.h]"21 #include "[float4.h]"22 #include "[float3x3.h]"23 #include "[float3x4.h]"24 #include "[float4x4.h]"25 #include "../Algorithm/Random/LCG.h"26 #include "[assume.h]"27 #include "[MathFunc.h]"28 #include "[SSEMath.h]"29 #include "[float4x4_sse.h]"30 #include "[quat_simd.h]"31 #include "[float4_neon.h]"32 33 #ifdef MATH_AUTOMATIC_SSE34 #include "[sse_mathfun.h]"35 #endif36 37 #ifdef MATH_ENABLE_STL_SUPPORT38 #include <iostream>39 #endif40 41 [MATH_BEGIN_NAMESPACE]42 43 [Quat::Quat](const float *data)44 {45 [assume](data);46 #ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS47 if (!data)48 return;49 #endif50 #if defined(MATH_AUTOMATIC_SSE)51 q = loadu_ps(data);52 #else53 [x] = data[0];54 [y] = data[1];55 [z] = data[2];56 [w] = data[3];57 #endif58 }59 60 [Quat::Quat](float x_, float y_, float z_, float w_)61 #if !defined(MATH_AUTOMATIC_SSE)62 :x(x_), y(y_), z(z_), w(w_)63 #endif64 {65 #if defined(MATH_AUTOMATIC_SSE)66 q = set_ps(w_, z_, y_, x_);67 #endif68 }69 70 vec [Quat::WorldX]() const71 {72 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)73 return [FLOAT4_TO_DIR](quat_transform_vec4(q, [float4::unitX]));74 #else75 return [DIR_VEC](this->[Transform](1.f, 0.f, 0.f));76 #endif77 }78 79 vec [Quat::WorldY]() const80 {81 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)82 return [FLOAT4_TO_DIR](quat_transform_vec4(q, [float4::unitY]));83 #else84 return [DIR_VEC](this->[Transform](0.f, 1.f, 0.f));85 #endif86 }87 88 vec [Quat::WorldZ]() const89 {90 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)91 return [FLOAT4_TO_DIR](quat_transform_vec4(q, [float4::unitZ]));92 #else93 return [DIR_VEC](this->[Transform](0.f, 0.f, 1.f));94 #endif95 }96 97 vec [Quat::Axis]() const98 {99 [assume2](this->[IsNormalized](), *this, this->[Length]());100 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)101 102 [assume2](this->[IsNormalized](), *this, this->[Length]());103 simd4f cosAngle = wwww_ps(q);104 simd4f rcpSinAngle = rsqrt_ps(sub_ps(set1_ps(1.f), mul_ps(cosAngle, cosAngle)));105 simd4f a = mul_ps(q, rcpSinAngle);106 107 108 simd4f highPart = _mm_unpackhi_ps(a, zero_ps()); 109 a = _mm_movelh_ps(a, highPart); 110 return [FLOAT4_TO_DIR](a);111 #else112 113 114 115 116 float rcpSinAngle = [RSqrt](1.f - [w]*[w]);117 return [DIR_VEC]([x], [y], [z]) * rcpSinAngle;118 #endif119 }120 121 float [Quat::Angle]() const122 {123 return [Acos]([w]) * 2.f;124 }125 126 float [Quat::Dot](const [Quat] &rhs) const127 {128 #ifdef MATH_AUTOMATIC_SSE129 return dot4_float(q, rhs.q);130 #else131 return [x]*rhs.[x] + [y]*rhs.[y] + [z]*rhs.[z] + [w]*rhs.[w];132 #endif133 }134 135 float [Quat::LengthSq]() const136 {137 #ifdef MATH_AUTOMATIC_SSE138 return vec4_length_sq_float(q);139 #else140 return [x]*[x] + [y]*[y] + [z]*[z] + [w]*[w];141 #endif142 }143 144 float [Quat::Length]() const145 {146 #ifdef MATH_AUTOMATIC_SSE147 return vec4_length_float(q);148 #else149 return [Sqrt]([LengthSq]());150 #endif151 }152 153 float [Quat::Normalize]()154 {155 #ifdef MATH_AUTOMATIC_SSE156 simd4f lenSq = vec4_length_sq_ps(q);157 simd4f len = vec4_rsqrt(lenSq);158 simd4f isZero = cmplt_ps(lenSq, simd4fEpsilon); 159 simd4f normalized = mul_ps(q, len); 160 q = cmov_ps(normalized, [float4::unitX].v, isZero); 161 return s4f_x(len);162 #else163 float length = [Length]();164 if (length < 1[e]-4f)165 return 0.f;166 float rcpLength = 1.f / length;167 [x] *= rcpLength;168 [y] *= rcpLength;169 [z] *= rcpLength;170 [w] *= rcpLength;171 return length;172 #endif173 }174 175 [Quat] [Quat::Normalized]() const176 {177 #ifdef MATH_AUTOMATIC_SSE178 return [Quat](vec4_normalize(q));179 #else180 [Quat] copy = *this;181 float success = copy.[Normalize]();182 [assume](success > 0 && "Quat::Normalized failed!");183 MARK_UNUSED(success);184 return copy;185 #endif186 }187 188 bool [Quat::IsNormalized](float epsilonSq) const189 {190 return [EqualAbs]([LengthSq](), 1.f, epsilonSq);191 }192 193 bool [Quat::IsInvertible](float [epsilon]) const194 {195 return [LengthSq]() > epsilon && [IsFinite]();196 }197 198 bool [Quat::IsFinite]() const199 {200 return [MATH_NS::IsFinite]([x]) && [MATH_NS::IsFinite]([y]) && [MATH_NS::IsFinite]([z]) && [MATH_NS::IsFinite]([w]);201 }202 203 bool [Quat::Equals](const [Quat] &rhs, float [epsilon]) const204 {205 return [EqualAbs]([x], rhs.[x], epsilon) && [EqualAbs]([y], rhs.[y], epsilon) && [EqualAbs]([z], rhs.[z], epsilon) && [EqualAbs]([w], rhs.[w], epsilon);206 }207 208 bool [Quat::BitEquals](const [Quat] &other) const209 {210 return [ReinterpretAsU32]([x]) == [ReinterpretAsU32](other.[x]) &&211 [ReinterpretAsU32]([y]) == [ReinterpretAsU32](other.[y]) &&212 [ReinterpretAsU32]([z]) == [ReinterpretAsU32](other.[z]) &&213 [ReinterpretAsU32]([w]) == [ReinterpretAsU32](other.[w]);214 }215 216 void [Quat::Inverse]()217 {218 [assume]([IsNormalized]());219 [assume]([IsInvertible]());220 [Conjugate]();221 }222 223 [Quat] [MUST_USE_RESULT] [Quat::Inverted]() const224 {225 [assume]([IsNormalized]());226 [assume]([IsInvertible]());227 return [Conjugated]();228 }229 230 float [Quat::InverseAndNormalize]()231 {232 [Conjugate]();233 return [Normalize]();234 }235 236 void [Quat::Conjugate]()237 {238 #ifdef MATH_AUTOMATIC_SSE239 q = negate3_ps(q);240 #else241 [x] = -[x];242 [y] = -[y];243 [z] = -[z];244 #endif245 }246 247 [Quat] [MUST_USE_RESULT] [Quat::Conjugated]() const248 {249 #ifdef MATH_AUTOMATIC_SSE250 return negate3_ps(q);251 #else252 return [Quat](-[x], -[y], -[z], [w]);253 #endif254 }255 256 [float3] [MUST_USE_RESULT] [Quat::Transform](const [float3] &vec) const257 {258 [assume2](this->[IsNormalized](), *this, this->[LengthSq]());259 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)260 return [float4](quat_transform_vec4(q, load_vec3(vec.[ptr](), 0.f))).xyz();261 #else262 263 [float3x3] mat = this->[ToFloat3x3]();264 return mat * vec;265 #endif266 }267 268 [float3] [MUST_USE_RESULT] [Quat::Transform](float x, float y, float z) const269 {270 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)271 return [float4](quat_transform_vec4(q, set_ps(0.f, z, y, x))).[xyz]();272 #else273 return [Transform]([float3](x, y, z));274 #endif275 }276 277 [float4] [MUST_USE_RESULT] [Quat::Transform](const [float4] &vec) const278 {279 [assume](vec.[IsWZeroOrOne]());280 281 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)282 return quat_transform_vec4(q, vec);283 #else284 return [float4]([Transform](vec.[x], vec.[y], vec.[z]), vec.[w]);285 #endif286 }287 288 [Quat] [MUST_USE_RESULT] [Quat::Lerp](const [Quat] &b, float t) const289 {290 [assume](0.f <= t && t <= 1.f);291 292 #ifdef MATH_AUTOMATIC_SSE293 return vec4_lerp(q, b.q, t);294 #else295 return *this * (1.f - t) + b * t;296 #endif297 }298 299 300 [Quat] [MUST_USE_RESULT] [Quat::Slerp](const [Quat] &q2, float t) const301 {302 303 [assume](0.f <= t && t <= 1.f);304 [assume]([IsNormalized]());305 [assume](q2.[IsNormalized]());306 307 float angle = this->[Dot](q2);308 float sign = 1.f; 309 if (angle < 0.f)310 {311 angle = -angle;312 sign = -1.f;313 }314 315 float a;316 float b;317 if (angle <= 0.97f) 318 {319 angle = [Acos](angle); 320 321 float angleT = t*angle;322 323 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE2)324 325 simd4f s = set_ps(0.f, angleT, angle - angleT, angle);326 s = sin_ps(s);327 simd4f denom = xxxx_ps(s);328 s = div_ps(s, denom);329 a = s4f_y(s);330 b = s4f_z(s);331 #else332 float s[3] = { [Sin](angle), [Sin](angle - angleT), [Sin](angleT) };333 float c = 1.f / s[0];334 a = s[1] * c;335 b = s[2] * c;336 #endif337 }338 else 339 {340 a = 1.f - t;341 b = t;342 }343 344 return (*this * (a * sign) + q2 * b).Normalized();345 }346 347 [float3] [MUST_USE_RESULT] [Quat::SlerpVector](const [float3] &from, const [float3] &to, float t)348 {349 if (t <= 0.f)350 return from;351 if (t >= 1.f)352 return to;353 354 [Quat] q = [Quat::RotateFromTo](from, to);355 q = [Slerp]([Quat::identity], q, t);356 return q.[Transform](from);357 }358 359 [float3] [MUST_USE_RESULT] [Quat::SlerpVectorAbs](const [float3] &from, const [float3] &to, float angleRadians)360 {361 if (angleRadians <= 0.f)362 return from;363 [Quat] q = [Quat::RotateFromTo](from, to);364 float a = q.[Angle]();365 if (a <= angleRadians)366 return to;367 float t = angleRadians / a;368 q = [Slerp]([Quat::identity], q, t);369 return q.[Transform](from);370 }371 372 float [MUST_USE_RESULT] [Quat::AngleBetween](const [Quat] &target) const373 {374 [assume](this->[IsInvertible]());375 [Quat] q = target / *this;376 return q.[Angle]();377 }378 379 vec [MUST_USE_RESULT] [Quat::AxisFromTo](const [Quat] &target) const380 {381 [assume](this->[IsInvertible]());382 [Quat] q = target / *this;383 return q.[Axis]();384 }385 386 void [Quat::ToAxisAngle]([float3] &axis, float &angle) const387 {388 389 [assume2](this->[IsNormalized](), *this, this->[Length]());390 float halfAngle = [Acos]([w]);391 angle = halfAngle * 2.f;392 393 394 float rcpSinAngle = [RSqrt](1.f - [w]*[w]);395 axis.[x] = x * rcpSinAngle;396 axis.[y] = y * rcpSinAngle;397 axis.[z] = z * rcpSinAngle;398 }399 400 void [Quat::ToAxisAngle]([float4] &axis, float &angle) const401 {402 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)403 404 [assume2](this->[IsNormalized](), *this, this->[Length]());405 simd4f cosAngle = wwww_ps(q);406 simd4f rcpSinAngle = rsqrt_ps(sub_ps(set1_ps(1.f), mul_ps(cosAngle, cosAngle)));407 angle = [Acos](s4f_x(cosAngle)) * 2.f;408 simd4f a = mul_ps(q, rcpSinAngle);409 410 411 simd4f highPart = _mm_unpackhi_ps(a, zero_ps()); 412 axis.v = _mm_movelh_ps(a, highPart); 413 #else414 415 [ToAxisAngle](reinterpret_cast<float3&>(axis), angle);416 axis.[w] = 0.f;417 #endif418 }419 420 void [Quat::SetFromAxisAngle](const [float3] &axis, float angle)421 {422 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)423 [SetFromAxisAngle](load_vec3(axis.[ptr](), 0.f), angle);424 #else425 [assume1](axis.[IsNormalized](), axis);426 [assume1]([MATH_NS::IsFinite](angle), angle);427 float sinz, cosz;428 [SinCos](angle*0.5f, sinz, cosz);429 x = axis.[x] * sinz;430 y = axis.[y] * sinz;431 z = axis.[z] * sinz;432 [w] = cosz;433 #endif434 }435 436 void [Quat::SetFromAxisAngle](const [float4] &axis, float angle)437 {438 [assume1]([EqualAbs](axis.[w], 0.f), axis);439 [assume2](axis.[IsNormalized](1[e]-4f), axis, axis.[Length4]());440 [assume1]([MATH_NS::IsFinite](angle), angle);441 442 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE2)443 444 simd4f half = set1_ps(0.5f);445 simd4f halfAngle = mul_ps(set1_ps(angle), half);446 simd4f sinAngle, cosAngle;447 sincos_ps(halfAngle, &sinAngle, &cosAngle);448 simd4f quat = mul_ps(axis, sinAngle);449 450 451 simd4f highPart = _mm_unpackhi_ps(quat, cosAngle); 452 q = _mm_movelh_ps(quat, highPart); 453 #else454 455 [SetFromAxisAngle](axis.[xyz](), angle);456 #endif457 }458 459 460 template<typename M>461 void [SetQuatFrom]([Quat] &q, const M &m)462 {463 464 465 466 467 468 float r = m[0][0] + m[1][1] + m[2][2]; 469 470 if (r > 0) 471 {472 q.[w] = [Sqrt](r + 1.f) * 0.5f; 473 float inv4w = 1.f / (4.f * q.[w]);474 q.[x] = (m[2][1] - m[1][2]) * inv4w;475 q.[y] = (m[0][2] - m[2][0]) * inv4w;476 q.[z] = (m[1][0] - m[0][1]) * inv4w;477 }478 else if (m[0][0] > m[1][1] && m[0][0] > m[2][2]) 479 { 480 q.[x] = [Sqrt](1.f + m[0][0] - m[1][1] - m[2][2]) * 0.5f; 481 const float x4 = 1.f / (4.f * q.[x]);482 q.[y] = (m[0][1] + m[1][0]) * x4;483 q.[z] = (m[0][2] + m[2][0]) * x4;484 q.[w] = (m[2][1] - m[1][2]) * x4;485 }486 else if (m[1][1] > m[2][2]) 487 {488 q.[y] = [Sqrt](1.f + m[1][1] - m[0][0] - m[2][2]) * 0.5f; 489 const float y4 = 1.f / (4.f * q.[y]);490 q.[x] = (m[0][1] + m[1][0]) * y4;491 q.[z] = (m[1][2] + m[2][1]) * y4;492 q.[w] = (m[0][2] - m[2][0]) * y4;493 }494 else 495 {496 q.[z] = [Sqrt](1.f + m[2][2] - m[0][0] - m[1][1]) * 0.5f; 497 const float z4 = 1.f / (4.f * q.[z]);498 q.[x] = (m[0][2] + m[2][0]) * z4;499 q.[y] = (m[1][2] + m[2][1]) * z4;500 q.[w] = (m[1][0] - m[0][1]) * z4;501 }502 float oldLength = q.[Normalize]();503 [assume](oldLength > 0.f);504 MARK_UNUSED(oldLength);505 }506 507 void [Quat::Set](const [float3x3] &m)508 {509 [assume](m.[IsColOrthogonal]());510 [assume](m.[HasUnitaryScale]());511 [assume](!m.[HasNegativeScale]());512 [SetQuatFrom](*this, m);513 514 #ifdef MATH_ASSERT_CORRECTNESS515 516 [mathassert](this->[ToFloat3x3]().[Equals](m, 0.01f));517 #endif518 }519 520 void [Quat::Set](const [float3x4] &m)521 {522 [assume](m.[IsColOrthogonal]());523 [assume](m.[HasUnitaryScale]());524 [assume](!m.[HasNegativeScale]());525 [SetQuatFrom](*this, m);526 527 #ifdef MATH_ASSERT_CORRECTNESS528 529 [mathassert](this->[ToFloat3x3]().[Equals](m.[Float3x3Part](), 0.01f));530 #endif531 }532 533 void [Quat::Set](const [float4x4] &m)534 {535 [assume](m.[IsColOrthogonal3]());536 [assume](m.[HasUnitaryScale]());537 [assume](!m.[HasNegativeScale]());538 [assume](m.[Row](3).[Equals](0,0,0,1));539 [SetQuatFrom](*this, m);540 541 #ifdef MATH_ASSERT_CORRECTNESS542 543 [mathassert](this->[ToFloat3x3]().[Equals](m.[Float3x3Part](), 0.01f));544 #endif545 }546 547 void [Quat::Set](float x_, float y_, float z_, float w_)548 {549 #ifdef MATH_AUTOMATIC_SSE550 q = set_ps(w_, z_, y_, x_);551 #else552 x = x_;553 y = y_;554 z = z_;555 [w] = w_;556 #endif557 }558 559 [Quat] [MUST_USE_RESULT] [Quat::LookAt](const [float3] &localForward, const [float3] &targetDirection, const [float3] &localUp, const [float3] &worldUp)560 {561 return [float3x3::LookAt](localForward, targetDirection, localUp, worldUp).[ToQuat]();562 }563 564 [Quat] [MUST_USE_RESULT] [Quat::RotateX](float angle)565 {566 return [Quat]([float3](1,0,0), angle);567 }568 569 [Quat] [MUST_USE_RESULT] [Quat::RotateY](float angle)570 {571 return [Quat]([float3](0,1,0), angle);572 }573 574 [Quat] [MUST_USE_RESULT] [Quat::RotateZ](float angle)575 {576 return [Quat]([float3](0,0,1), angle);577 }578 579 [Quat] [MUST_USE_RESULT] [Quat::RotateAxisAngle](const [float3] &axis, float angle)580 {581 return [Quat](axis, angle);582 }583 584 [Quat] [MUST_USE_RESULT] [Quat::RotateFromTo](const [float3] &sourceDirection, const [float3] &targetDirection)585 {586 [assume](sourceDirection.[IsNormalized]());587 [assume](targetDirection.[IsNormalized]());588 589 [float3] axis = sourceDirection.[Cross](targetDirection);590 float oldLength = axis.[Normalize]();591 if (oldLength != 0.f)592 {593 float halfCosAngle = 0.5f*sourceDirection.[Dot](targetDirection);594 float cosHalfAngle = [Sqrt](0.5f + halfCosAngle);595 float sinHalfAngle = [Sqrt](0.5f - halfCosAngle);596 return [Quat](axis.x * sinHalfAngle, axis.y * sinHalfAngle, axis.z * sinHalfAngle, cosHalfAngle);597 }598 else599 return [Quat](1.f, 0.f, 0.f, 0.f);600 601 }602 603 [Quat] [MUST_USE_RESULT] [Quat::RotateFromTo](const [float4] &sourceDirection, const [float4] &targetDirection)604 {605 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)606 607 simd4f cosAngle = dot4_ps(sourceDirection.v, targetDirection.v);608 cosAngle = negate3_ps(cosAngle); 609 610 611 simd4f half = set1_ps(0.5f);612 simd4f cosSinHalfAngle = sqrt_ps(add_ps(half, mul_ps(half, cosAngle))); 613 simd4f axis = cross_ps(sourceDirection.v, targetDirection.v);614 simd4f recipLen = rsqrt_ps(dot4_ps(axis, axis));615 axis = mul_ps(axis, recipLen); 616 617 simd4f [one] = add_ps(half, half); 618 simd4f highPart = _mm_unpackhi_ps(axis, one); 619 axis = _mm_movelh_ps(axis, highPart); 620 [Quat] q;621 q.q = mul_ps(axis, cosSinHalfAngle);622 return q;623 #else624 625 [assume]([EqualAbs](sourceDirection.[w], 0.f));626 [assume]([EqualAbs](targetDirection.[w], 0.f));627 return [Quat::RotateFromTo](sourceDirection.[xyz](), targetDirection.[xyz]());628 #endif629 }630 631 [Quat] [MUST_USE_RESULT] [Quat::RotateFromTo](const [float3] &sourceDirection, const [float3] &targetDirection,632 const [float3] &sourceDirection2, const [float3] &targetDirection2)633 {634 return [LookAt](sourceDirection, targetDirection, sourceDirection2, targetDirection2);635 }636 637 [Quat] [MUST_USE_RESULT] [Quat::FromEulerXYX](float x2, float y, float x) { return ([Quat::RotateX](x2) * [Quat::RotateY](y) * [Quat::RotateX](x)).[Normalized](); }638 [Quat] [MUST_USE_RESULT] [Quat::FromEulerXZX](float x2, float z, float x) { return ([Quat::RotateX](x2) * [Quat::RotateZ](z) * [Quat::RotateX](x)).[Normalized](); }639 [Quat] [MUST_USE_RESULT] [Quat::FromEulerYXY](float y2, float x, float y) { return ([Quat::RotateY](y2) * [Quat::RotateX](x) * [Quat::RotateY](y)).[Normalized](); }640 [Quat] [MUST_USE_RESULT] [Quat::FromEulerYZY](float y2, float z, float y) { return ([Quat::RotateY](y2) * [Quat::RotateZ](z) * [Quat::RotateY](y)).[Normalized](); }641 [Quat] [MUST_USE_RESULT] [Quat::FromEulerZXZ](float z2, float x, float z) { return ([Quat::RotateZ](z2) * [Quat::RotateX](x) * [Quat::RotateZ](z)).[Normalized](); }642 [Quat] [MUST_USE_RESULT] [Quat::FromEulerZYZ](float z2, float y, float z) { return ([Quat::RotateZ](z2) * [Quat::RotateY](y) * [Quat::RotateZ](z)).[Normalized](); }643 [Quat] [MUST_USE_RESULT] [Quat::FromEulerXYZ](float x, float y, float z) { return ([Quat::RotateX](x) * [Quat::RotateY](y) * [Quat::RotateZ](z)).[Normalized](); }644 [Quat] [MUST_USE_RESULT] [Quat::FromEulerXZY](float x, float z, float y) { return ([Quat::RotateX](x) * [Quat::RotateZ](z) * [Quat::RotateY](y)).[Normalized](); }645 [Quat] [MUST_USE_RESULT] [Quat::FromEulerYXZ](float y, float x, float z) { return ([Quat::RotateY](y) * [Quat::RotateX](x) * [Quat::RotateZ](z)).[Normalized](); }646 [Quat] [MUST_USE_RESULT] [Quat::FromEulerYZX](float y, float z, float x) { return ([Quat::RotateY](y) * [Quat::RotateZ](z) * [Quat::RotateX](x)).[Normalized](); }647 [Quat] [MUST_USE_RESULT] [Quat::FromEulerZXY](float z, float x, float y) { return ([Quat::RotateZ](z) * [Quat::RotateX](x) * [Quat::RotateY](y)).[Normalized](); }648 [Quat] [MUST_USE_RESULT] [Quat::FromEulerZYX](float z, float y, float x) { return ([Quat::RotateZ](z) * [Quat::RotateY](y) * [Quat::RotateX](x)).[Normalized](); }649 650 [Quat] [MUST_USE_RESULT] [Quat::RandomRotation]([LCG] &lcg)651 {652 653 for(int i = 0; i < 1000; ++i)654 {655 float x = lcg.[Float](-1, 1);656 float y = lcg.[Float](-1, 1);657 float z = lcg.[Float](-1, 1);658 float [w] = lcg.[Float](-1, 1);659 float lenSq = x*x + y*y + z*z + w*[w];660 if (lenSq >= 1[e]-6f && lenSq <= 1.f)661 return [Quat](x, y, z, w) / [Sqrt](lenSq);662 }663 [assume](false && "Quat::RandomRotation failed!");664 return [Quat::identity];665 }666 667 668 669 [float3] [MUST_USE_RESULT] [Quat::ToEulerXYX]() const { return [ToFloat3x3]().[ToEulerXYX](); }670 [float3] [MUST_USE_RESULT] [Quat::ToEulerXZX]() const { return [ToFloat3x3]().[ToEulerXZX](); }671 [float3] [MUST_USE_RESULT] [Quat::ToEulerYXY]() const { return [ToFloat3x3]().[ToEulerYXY](); }672 [float3] [MUST_USE_RESULT] [Quat::ToEulerYZY]() const { return [ToFloat3x3]().[ToEulerYZY](); }673 [float3] [MUST_USE_RESULT] [Quat::ToEulerZXZ]() const { return [ToFloat3x3]().[ToEulerZXZ](); }674 [float3] [MUST_USE_RESULT] [Quat::ToEulerZYZ]() const { return [ToFloat3x3]().[ToEulerZYZ](); }675 [float3] [MUST_USE_RESULT] [Quat::ToEulerXYZ]() const { return [ToFloat3x3]().[ToEulerXYZ](); }676 [float3] [MUST_USE_RESULT] [Quat::ToEulerXZY]() const { return [ToFloat3x3]().[ToEulerXZY](); }677 [float3] [MUST_USE_RESULT] [Quat::ToEulerYXZ]() const { return [ToFloat3x3]().[ToEulerYXZ](); }678 [float3] [MUST_USE_RESULT] [Quat::ToEulerYZX]() const { return [ToFloat3x3]().[ToEulerYZX](); }679 [float3] [MUST_USE_RESULT] [Quat::ToEulerZXY]() const { return [ToFloat3x3]().[ToEulerZXY](); }680 [float3] [MUST_USE_RESULT] [Quat::ToEulerZYX]() const { return [ToFloat3x3]().[ToEulerZYX](); }681 682 [float3x3] [MUST_USE_RESULT] [Quat::ToFloat3x3]() const683 {684 return [float3x3](*this);685 }686 687 [float3x4] [MUST_USE_RESULT] [Quat::ToFloat3x4]() const688 {689 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)690 [float3x4] m;691 quat_to_mat3x4(q, _mm_set_ps(1,0,0,0), m.row);692 return m;693 #else694 return [float3x4](*this);695 #endif696 }697 698 [float4x4] [MUST_USE_RESULT] [Quat::ToFloat4x4]() const699 {700 [assume]([IsNormalized]());701 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)702 [float4x4] m;703 quat_to_mat4x4(q, _mm_set_ps(1,0,0,0), m.row);704 return m;705 #else706 return [float4x4](*this);707 #endif708 }709 710 [float4x4] [MUST_USE_RESULT] [Quat::ToFloat4x4](const [float3] &translation) const711 {712 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)713 return [ToFloat4x4]([float4](translation, 1.f));714 #else715 return [float4x4](*this, translation);716 #endif717 }718 719 [float4x4] [MUST_USE_RESULT] [Quat::ToFloat4x4](const [float4] &translation) const720 {721 [assume]([IsNormalized]());722 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)723 [float4x4] m;724 quat_to_mat4x4(q, translation.v, m.row);725 return m;726 #else727 return [float4x4](*this, translation.[xyz]());728 #endif729 }730 731 bool [IsNeutralCLocale]();732 733 #ifdef MATH_ENABLE_STL_SUPPORT734 std::string [MUST_USE_RESULT] [Quat::ToString]() const735 {736 char str[256];737 sprintf(str, "(%.3f, %.3f, %.3f, %.3f)", x, y, z, w);738 return str;739 }740 741 std::string [MUST_USE_RESULT] [Quat::ToString2]() const742 {743 [float3] axis;744 float angle;745 [ToAxisAngle](axis, angle);746 char str[256];747 sprintf(str, "Quat(axis:(%.2f,%.2f,%.2f) angle:%2.f)", axis.[x], axis.[y], axis.[z], [RadToDeg](angle));748 return str;749 }750 751 std::string [MUST_USE_RESULT] [Quat::SerializeToString]() const752 {753 char str[256];754 char *s = [SerializeFloat](x, str); *s = ','; ++s;755 s = [SerializeFloat](y, s); *s = ','; ++s;756 s = [SerializeFloat](z, s); *s = ','; ++s;757 s = [SerializeFloat](w, s);758 [assert](s+1 - str < 256);759 MARK_UNUSED(s);760 return str;761 }762 763 std::string [Quat::SerializeToCodeString]() const764 {765 return "Quat(" + [SerializeToString]() + ")";766 }767 #endif768 769 [Quat] [MUST_USE_RESULT] [Quat::FromString](const char *str, const char **outEndStr)770 {771 [assert]([IsNeutralCLocale]());772 [assume](str);773 if (!str)774 return [Quat::nan];775 [MATH_SKIP_WORD](str, "Quat");776 [MATH_SKIP_WORD](str, "(");777 [Quat] f;778 f.[x] = [DeserializeFloat](str, &str);779 f.[y] = [DeserializeFloat](str, &str);780 f.[z] = [DeserializeFloat](str, &str);781 f.[w] = [DeserializeFloat](str, &str);782 if (*str == ')')783 ++str;784 if (*str == ',')785 ++str;786 if (outEndStr)787 *outEndStr = str;788 return f;789 }790 791 [Quat] [Quat::operator +](const [Quat] &rhs) const792 {793 #ifdef MATH_AUTOMATIC_SSE794 return add_ps(q, rhs.q);795 #else796 return [Quat](x + rhs.[x], y + rhs.[y], z + rhs.[z], w + rhs.[w]);797 #endif798 }799 800 [Quat] Quat::operator -(const [Quat] &rhs) const801 {802 #ifdef MATH_AUTOMATIC_SSE803 return sub_ps(q, rhs.q);804 #else805 return [Quat](x - rhs.[x], y - rhs.[y], z - rhs.[z], w - rhs.[w]);806 #endif807 }808 809 [Quat] Quat::operator -() const810 {811 #ifdef MATH_AUTOMATIC_SSE812 return negate_ps(q);813 #else814 return [Quat](-x, -y, -z, -w);815 #endif816 }817 818 [Quat] [Quat::operator *](float scalar) const819 {820 #ifdef MATH_AUTOMATIC_SSE821 return vec4_mul_float(q, scalar);822 #else823 return [Quat](x * scalar, y * scalar, z * scalar, w * scalar);824 #endif825 }826 827 [float3] [Quat::operator *](const [float3] &rhs) const828 {829 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)830 return [float4](quat_transform_vec4(q, [float4](rhs, 0.f).v)).[xyz]();831 #else832 return [Transform](rhs);833 #endif834 }835 836 [float4] [Quat::operator *](const [float4] &rhs) const837 {838 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)839 return quat_transform_vec4(q, rhs);840 #else841 return [Transform](rhs);842 #endif843 }844 845 [Quat] [Quat::operator /](float scalar) const846 {847 [assume](![EqualAbs](scalar, 0.f));848 849 #ifdef MATH_AUTOMATIC_SSE850 return vec4_div_float(q, scalar);851 #else852 return *this * (1.f / scalar);853 #endif854 }855 856 [Quat] [Quat::operator *](const [Quat] &r) const857 {858 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)859 860 return quat_mul_quat(q, r.q);861 #else862 863 return [Quat](x*r.[w] + y*r.[z] - z*r.[y] + w*r.[x],864 -x*r.[z] + y*r.[w] + z*r.[x] + w*r.[y],865 x*r.[y] - y*r.[x] + z*r.[w] + w*r.[z],866 -x*r.[x] - y*r.[y] - z*r.[z] + w*r.[w]);867 #endif868 }869 870 [Quat] [Quat::operator /](const [Quat] &r) const871 {872 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)873 return quat_div_quat(q, r.q);874 #else875 return [Quat](x*r.[w] - y*r.[z] + z*r.[y] - w*r.[x],876 x*r.[z] + y*r.[w] - z*r.[x] - w*r.[y],877 -x*r.[y] + y*r.[x] + z*r.[w] - w*r.[z],878 x*r.[x] + y*r.[y] + z*r.[z] + w*r.[w]);879 #endif880 }881 882 #ifdef MATH_ENABLE_STL_SUPPORT883 std::ostream &[operator <<](std::ostream &out, const [Quat] &rhs)884 {885 out << rhs.[ToString]();886 return out;887 }888 #endif889 890 [Quat] [MUST_USE_RESULT] [Quat::Mul](const [Quat] &rhs) const { return *this * rhs; }891 [Quat] [MUST_USE_RESULT] [Quat::Mul](const [float3x3] &rhs) const { return *this * [Quat](rhs); }892 [float3] [MUST_USE_RESULT] [Quat::Mul](const [float3] &vector) const { return this->[Transform](vector); }893 [float4] [MUST_USE_RESULT] [Quat::Mul](const [float4] &vector) const { return this->[Transform](vector); }894 895 const [Quat] [Quat::identity] = [Quat](0.f, 0.f, 0.f, 1.f);896 const [Quat] [Quat::nan] = [Quat]([FLOAT_NAN], [FLOAT_NAN], [FLOAT_NAN], [FLOAT_NAN]);897 898 [MATH_END_NAMESPACE] Go back to previous page