123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- using System;
- using UnityEngine;
- namespace Util
- {
- class MathUtil
- {
- public static bool Decompose(Matrix4x4 matrix, out Vector3 scale, out Quaternion rotation, out Vector3 translation)
- {
- Matrix4x4 rotationMatrix;
- Decompose(matrix, out scale, out rotationMatrix, out translation);
- RotationMatrix(rotationMatrix, out rotation);
- return true;
- }
- private static bool Decompose(Matrix4x4 matrix, out Vector3 scale, out Matrix4x4 rotation, out Vector3 translation)
- {
- //Get the translation.
- translation.x = matrix.m30;
- translation.y = matrix.m31;
- translation.z = matrix.m32;
- //Scaling is the length of the rows.
- scale.x = (float)Math.Sqrt((matrix.m00 * matrix.m00) + (matrix.m01 * matrix.m01) + (matrix.m02 * matrix.m02));
- scale.y = (float)Math.Sqrt((matrix.m10 * matrix.m10) + (matrix.m11 * matrix.m11) + (matrix.m12 * matrix.m12));
- scale.z = (float)Math.Sqrt((matrix.m20 * matrix.m20) + (matrix.m21 * matrix.m21) + (matrix.m22 * matrix.m22));
- //If any of the scaling factors are zero, than the rotation matrix can not exist.
- if (IsZero(scale.x) || IsZero(scale.y) || IsZero(scale.z))
- {
- rotation = Matrix4x4.identity;
- return false;
- }
- Vector3 at = new Vector3(matrix.m20 / scale.z, matrix.m21 / scale.z, matrix.m22 / scale.z);
- Vector3 up = Vector3.Cross(at, new Vector3(matrix.m00 / scale.x, matrix.m01 / scale.x, matrix.m02 / scale.x));
- Vector3 right = Vector3.Cross(up, at);
- rotation = Matrix4x4.identity;
- rotation.m00 = right.x;
- rotation.m01 = right.y;
- rotation.m02 = right.z;
- rotation.m10 = up.x;
- rotation.m11 = up.y;
- rotation.m12 = up.z;
- rotation.m20 = at.x;
- rotation.m21 = at.y;
- rotation.m22 = at.z;
- // In case of reflexions
- scale.x = Vector3.Dot(right, new Vector3(matrix.m00, matrix.m01, matrix.m02)) > 0.0f ? scale.x : -scale.x;
- scale.y = Vector3.Dot(up, new Vector3(matrix.m10, matrix.m11, matrix.m12)) > 0.0f ? scale.y : -scale.y;
- scale.z = Vector3.Dot(at, new Vector3(matrix.m20, matrix.m21, matrix.m22)) > 0.0f ? scale.z : -scale.z;
- return true;
- }
- private static void RotationMatrix(Matrix4x4 matrix, out Quaternion result)
- {
- float sqrt;
- float half;
- float scale = matrix.m00 + matrix.m11 + matrix.m22;
- if (scale > 0.0f)
- {
- sqrt = (float)Math.Sqrt(scale + 1.0f);
- result.w = sqrt * 0.5f;
- sqrt = 0.5f / sqrt;
- result.x = (matrix.m12 - matrix.m21) * sqrt;
- result.y = (matrix.m20 - matrix.m02) * sqrt;
- result.z = (matrix.m01 - matrix.m10) * sqrt;
- }
- else if ((matrix.m00 >= matrix.m11) && (matrix.m00 >= matrix.m22))
- {
- sqrt = (float)Math.Sqrt(1.0f + matrix.m00 - matrix.m11 - matrix.m22);
- half = 0.5f / sqrt;
- result.x = 0.5f * sqrt;
- result.y = (matrix.m01 + matrix.m10) * half;
- result.z = (matrix.m02 + matrix.m20) * half;
- result.w = (matrix.m12 - matrix.m21) * half;
- }
- else if (matrix.m11 > matrix.m22)
- {
- sqrt = (float)Math.Sqrt(1.0f + matrix.m11 - matrix.m00 - matrix.m22);
- half = 0.5f / sqrt;
- result.x = (matrix.m10 + matrix.m01) * half;
- result.y = 0.5f * sqrt;
- result.z = (matrix.m21 + matrix.m12) * half;
- result.w = (matrix.m20 - matrix.m02) * half;
- }
- else
- {
- sqrt = (float)Math.Sqrt(1.0f + matrix.m22 - matrix.m00 - matrix.m11);
- half = 0.5f / sqrt;
- result.x = (matrix.m20 + matrix.m02) * half;
- result.y = (matrix.m21 + matrix.m12) * half;
- result.z = 0.5f * sqrt;
- result.w = (matrix.m01 - matrix.m10) * half;
- }
- }
- private static bool IsZero(float a)
- {
- return Math.Abs(a) < 1e-6f;
- }
- public static bool isSimilar(float a, float b)
- {
- return a - b <= 0.001;
- }
- public static float Interpolate(float startX, float endX, float start, float end, float tanPoint1, float tanPoint2, float t, out float tangent)
- {
- // Catmull-Rom splines are Hermite curves with special tangent values.
- // Hermite curve formula:
- // (2t^3 - 3t^2 + 1) * p0 + (t^3 - 2t^2 + t) * m0 + (-2t^3 + 3t^2) * p1 + (t^3 - t^2) * m1
- // For points p0 and p1 passing through points m0 and m1 interpolated over t = [0, 1]
- // Tangent M[k] = (P[k+1] - P[k-1]) / 2
- // With [] indicating subscript
- float value = (2.0f * t * t * t - 3.0f * t * t + 1.0f) * start
- + (t * t * t - 2.0f * t * t + t) * tanPoint1
- + (-2.0f * t * t * t + 3.0f * t * t) * end
- + (t * t * t - t * t) * tanPoint2;
- // Calculate tangents
- // p'(t) = (6t² - 6t)p0 + (3t² - 4t + 1)m0 + (-6t² + 6t)p1 + (3t² - 2t)m1
- tangent = (6 * t * t - 6 * t) * start
- + (3 * t * t - 4 * t + 1) * tanPoint1
- + (-6 * t * t + 6 * t) * end
- + (3 * t * t - 2 * t) * tanPoint2;
- tangent /= (endX - startX);
- return value;
- }
- }
- }
|