| 293 | } |
| 294 | |
| 295 | Quaternion ConvertDirectionToQuat(const Vector3& dir) |
| 296 | { |
| 297 | constexpr auto SINGULARITY_THRESHOLD = 1.0f - EPSILON; |
| 298 | |
| 299 | static const auto REF_DIR = Vector3::UnitZ; |
| 300 | |
| 301 | // Vectors are nearly opposite; return orientation 180 degrees around arbitrary axis. |
| 302 | float dot = REF_DIR.Dot(dir); |
| 303 | if (dot < -SINGULARITY_THRESHOLD) |
| 304 | { |
| 305 | auto axis = Vector3::UnitX.Cross(REF_DIR); |
| 306 | if (axis.LengthSquared() < EPSILON) |
| 307 | axis = Vector3::UnitY.Cross(REF_DIR); |
| 308 | axis.Normalize(); |
| 309 | |
| 310 | auto axisAngle = AxisAngle(axis, FROM_RAD(PI)); |
| 311 | return axisAngle.ToQuaternion(); |
| 312 | } |
| 313 | |
| 314 | // Vectors are nearly identical; return identity quaternion. |
| 315 | if (dot > SINGULARITY_THRESHOLD) |
| 316 | return Quaternion::Identity; |
| 317 | |
| 318 | // Calculate axis-angle and return converted quaternion. |
| 319 | auto axisAngle = AxisAngle(REF_DIR.Cross(dir), FROM_RAD(acos(dot))); |
| 320 | return axisAngle.ToQuaternion(); |
| 321 | } |
| 322 | |
| 323 | Vector3 ConvertQuatToDirection(const Quaternion& quat) |
| 324 | { |