Beispiel #1
0
        private static Matrix4x4d LookRotationToMatrix(Vector3d viewVec, Vector3d upVec)
        {
            Vector3d   z = viewVec;
            Matrix4x4d m = new Matrix4x4d();

            double mag = Vector3d.Magnitude(z);

            if (mag < 0)
            {
                m = Matrix4x4d.identity;
            }
            z /= mag;

            Vector3d x = Vector3d.Cross(upVec, z);

            mag = Vector3d.Magnitude(x);
            if (mag < 0)
            {
                m = Matrix4x4d.identity;
            }
            x /= mag;

            Vector3d y = Vector3d.Cross(z, x);

            m[0, 0] = x.x; m[0, 1] = y.x; m[0, 2] = z.x;
            m[1, 0] = x.y; m[1, 1] = y.y; m[1, 2] = z.y;
            m[2, 0] = x.z; m[2, 1] = y.z; m[2, 2] = z.z;

            return(m);
        }
Beispiel #2
0
        public static Matrix4x4d SetAxisAngle(Vector3d rotationAxis, double radians)
        {
            Matrix4x4d m = new Matrix4x4d();

            double s, c;
            double xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;

            s = Math.Sin(radians);
            c = Math.Cos(radians);

            xx    = rotationAxis.x * rotationAxis.x;
            yy    = rotationAxis.y * rotationAxis.y;
            zz    = rotationAxis.z * rotationAxis.z;
            xy    = rotationAxis.x * rotationAxis.y;
            yz    = rotationAxis.y * rotationAxis.z;
            zx    = rotationAxis.z * rotationAxis.x;
            xs    = rotationAxis.x * s;
            ys    = rotationAxis.y * s;
            zs    = rotationAxis.z * s;
            one_c = 1 - c;

            m[0, 0] = (one_c * xx) + c;
            m[0, 1] = (one_c * xy) - zs;
            m[0, 2] = (one_c * zx) + ys;

            m[1, 0] = (one_c * xy) + zs;
            m[1, 1] = (one_c * yy) + c;
            m[1, 2] = (one_c * yz) - xs;

            m[2, 0] = (one_c * zx) - ys;
            m[2, 1] = (one_c * yz) + xs;
            m[2, 2] = (one_c * zz) + c;

            return(m);
        }
Beispiel #3
0
        private static Quaterniond MatrixToQuaternion(Matrix4x4d m)
        {
            Quaterniond quat = new Quaterniond();

            double fTrace = m[0, 0] + m[1, 1] + m[2, 2];
            double root;

            if (fTrace > 0)
            {
                root   = Math.Sqrt(fTrace + 1);
                quat.w = 0.5D * root;
                root   = 0.5D / root;
                quat.x = (m[2, 1] - m[1, 2]) * root;
                quat.y = (m[0, 2] - m[2, 0]) * root;
                quat.z = (m[1, 0] - m[0, 1]) * root;
            }
            else
            {
                int[] s_iNext = new int[] { 1, 2, 0 };
                int   i       = 0;
                if (m[1, 1] > m[0, 0])
                {
                    i = 1;
                }
                if (m[2, 2] > m[i, i])
                {
                    i = 2;
                }
                int j = s_iNext[i];
                int k = s_iNext[j];

                root = Math.Sqrt(m[i, i] - m[j, j] - m[k, k] + 1);
                if (root < 0)
                {
                    throw new IndexOutOfRangeException("error!");
                }
                quat[i] = 0.5 * root;
                root    = 0.5f / root;
                quat.w  = (m[k, j] - m[j, k]) * root;
                quat[j] = (m[j, i] + m[i, j]) * root;
                quat[k] = (m[k, i] + m[i, k]) * root;
            }
            double nor = Math.Sqrt(Dot(quat, quat));

            quat = new Quaterniond(quat.x / nor, quat.y / nor, quat.z / nor, quat.w / nor);

            return(quat);
        }
Beispiel #4
0
        /// <summary>
        /// 正交矩阵
        /// </summary>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="bottom"></param>
        /// <param name="top"></param>
        /// <param name="zNear"></param>
        /// <param name="zFar"></param>
        /// <returns></returns>
        public static Matrix4x4d Ortho(double left, double right, double bottom, double top, double zNear, double zFar)
        {
            Matrix4x4d result = identity;

            double deltax = right - left;
            double deltay = top - bottom;
            double deltaz = zFar - zNear;

            result[0, 0] = 2.0F / deltax;
            result[0, 3] = -(right + left) / deltax;
            result[1, 1] = 2.0F / deltay;
            result[1, 3] = -(top + bottom) / deltay;
            result[2, 2] = -2.0F / deltaz;
            result[2, 3] = -(zFar + zNear) / deltaz;
            return(result);
        }
Beispiel #5
0
        /// <summary>
        /// 透视矩阵
        /// </summary>
        /// <param name="fov"></param>
        /// <param name="aspect"></param>
        /// <param name="zNear"></param>
        /// <param name="zFar"></param>
        /// <returns></returns>
        public static Matrix4x4d Perspective(double fov, double aspect, double zNear, double zFar)
        {
            Matrix4x4d result = new Matrix4x4d();

            double cotangent, deltaZ;
            double radians = (fov / 2.0) * (Math.PI / 180);

            cotangent = Math.Cos(radians) / Math.Sin(radians);
            deltaZ    = zNear - zFar;

            result[0, 0] = cotangent / aspect; result[0, 1] = 0; result[0, 2] = 0; result[0, 3] = 0;
            result[1, 0] = 0; result[1, 1] = cotangent; result[1, 2] = 0; result[1, 3] = 0;
            result[2, 0] = 0; result[2, 1] = 0; result[2, 2] = (zFar + zNear) / deltaZ; result[2, 3] = 2 * zNear * zFar / deltaZ;
            result[3, 0] = 0; result[3, 1] = 0; result[3, 2] = -1; result[3, 3] = 0;

            return(result);
        }
Beispiel #6
0
        /// <summary>
        /// 平移旋转缩放矩阵
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="q"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public static Matrix4x4d TRS(Vector3d pos, Quaterniond q, Vector3d s)
        {
            Matrix4x4d m = Quaterniond.QuaternionToMatrix(q);

            m[0] *= s[0];
            m[1] *= s[0];
            m[2] *= s[0];

            m[4] *= s[1];
            m[5] *= s[1];
            m[6] *= s[1];

            m[8]  *= s[2];
            m[9]  *= s[2];
            m[10] *= s[2];

            m[12] = pos[0];
            m[13] = pos[1];
            m[14] = pos[2];
            return(m);
        }
Beispiel #7
0
        private Vector3d MatrixToEuler(Matrix4x4d m)
        {
            Vector3d v = new Vector3d();

            if (m[1, 2] < 1)
            {
                if (m[1, 2] > -1)
                {
                    v.x = Math.Asin(-m[1, 2]);
                    v.y = Math.Atan2(m[0, 2], m[2, 2]);
                    v.z = Math.Atan2(m[1, 0], m[1, 1]);
                }
                else
                {
                    v.x = Math.PI * 0.5;
                    v.y = Math.Atan2(m[0, 1], m[0, 0]);
                    v.z = 0;
                }
            }
            else
            {
                v.x = -Math.PI * 0.5;
                v.y = Math.Atan2(-m[0, 1], m[0, 0]);
                v.z = 0;
            }

            for (int i = 0; i < 3; i++)
            {
                if (v[i] < 0)
                {
                    v[i] += 2 * Math.PI;
                }
                else if (v[i] > 2 * Math.PI)
                {
                    v[i] -= 2 * Math.PI;
                }
            }

            return(v);
        }
Beispiel #8
0
        /// <summary>
        /// 球形插值(无限制)
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public static Vector3d SlerpUnclamped(Vector3d lhs, Vector3d rhs, double t)
        {
            double lhsMag = Magnitude(lhs);
            double rhsMag = Magnitude(rhs);

            if (lhsMag < 0 || rhsMag < 0)
            {
                return(Lerp(lhs, rhs, t));
            }

            double lerpedMagnitude = rhsMag * t + lhsMag * (1 - t);

            double dot = Dot(lhs, rhs) / (lhsMag * rhsMag);

            if (dot > 1)
            {
                return(Lerp(lhs, rhs, t));
            }
            else if (dot < -1)
            {
                Vector3d   lhsNorm = lhs / lhsMag;
                Vector3d   axis    = OrthoNormalVectorFast(lhsNorm);
                Matrix4x4d m       = SetAxisAngle(axis, Math.PI * t);
                Vector3d   slerped = m * lhsNorm;
                slerped *= lerpedMagnitude;
                return(slerped);
            }
            else
            {
                Vector3d axis    = Cross(lhs, rhs);
                Vector3d lhsNorm = lhs / lhsMag;
                axis = Normalize(axis);
                double angle = Math.Acos(dot) * t;

                Matrix4x4d m       = SetAxisAngle(axis, angle);
                Vector3d   slerped = m * lhsNorm;
                slerped *= lerpedMagnitude;
                return(slerped);
            }
        }
Beispiel #9
0
        public static Matrix4x4d QuaternionToMatrix(Quaterniond quat)
        {
            Matrix4x4d m = new Matrix4x4d();

            double x  = quat.x * 2;
            double y  = quat.y * 2;
            double z  = quat.z * 2;
            double xx = quat.x * x;
            double yy = quat.y * y;
            double zz = quat.z * z;
            double xy = quat.x * y;
            double xz = quat.x * z;
            double yz = quat.y * z;
            double wx = quat.w * x;
            double wy = quat.w * y;
            double wz = quat.w * z;

            m[0] = 1.0f - (yy + zz);
            m[1] = xy + wz;
            m[2] = xz - wy;
            m[3] = 0.0F;

            m[4] = xy - wz;
            m[5] = 1.0f - (xx + zz);
            m[6] = yz + wx;
            m[7] = 0.0F;

            m[8]  = xz + wy;
            m[9]  = yz - wx;
            m[10] = 1.0f - (xx + yy);
            m[11] = 0.0F;

            m[12] = 0.0F;
            m[13] = 0.0F;
            m[14] = 0.0F;
            m[15] = 1.0F;

            return(m);
        }
Beispiel #10
0
        /// <summary>
        /// 向目标向量旋转
        /// </summary>
        /// <param name="current"></param>
        /// <param name="target"></param>
        /// <param name="maxRadiansDelta"></param>
        /// <param name="maxMagnitudeDelta"></param>
        /// <returns></returns>
        public static Vector3d RotateTowards(Vector3d current, Vector3d target, double maxRadiansDelta, double maxMagnitudeDelta)
        {
            double currentMag = Magnitude(current);
            double targetMag  = Magnitude(target);

            if (currentMag > 0 && targetMag > 0)
            {
                Vector3d currentNorm = current / currentMag;
                Vector3d targetNorm  = target / targetMag;

                double dot = Dot(currentNorm, targetNorm);

                if (dot > 1)
                {
                    return(MoveTowards(current, target, maxMagnitudeDelta));
                }
                else if (dot < -1)
                {
                    Vector3d   axis    = OrthoNormalVectorFast(currentNorm);
                    Matrix4x4d m       = SetAxisAngle(axis, maxRadiansDelta);
                    Vector3d   rotated = m * currentNorm;
                    rotated *= ClampedMove(currentMag, targetMag, maxMagnitudeDelta);
                    return(rotated);
                }
                else
                {
                    double     angle   = Math.Acos(dot);
                    Vector3d   axis    = Normalize(Cross(currentNorm, targetNorm));
                    Matrix4x4d m       = SetAxisAngle(axis, Math.Min(maxRadiansDelta, angle));
                    Vector3d   rotated = m * currentNorm;
                    rotated *= ClampedMove(currentMag, targetMag, maxMagnitudeDelta);
                    return(rotated);
                }
            }
            else
            {
                return(MoveTowards(current, target, maxMagnitudeDelta));
            }
        }
Beispiel #11
0
        /// <summary>
        /// 注视旋转
        /// </summary>
        /// <param name="forward"></param>
        /// <param name="upwards"></param>
        /// <returns></returns>
        public static Quaterniond LookRotation(Vector3d forward, [DefaultValue("Vector3d.up")] Vector3d upwards)
        {
            Matrix4x4d m = LookRotationToMatrix(forward, upwards);

            return(MatrixToQuaternion(m));
        }
Beispiel #12
0
 /// <summary>
 /// 转置矩阵
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public static Matrix4x4d Transpose(Matrix4x4d m)
 {
     return(m.transpose);
 }
Beispiel #13
0
 /// <summary>
 /// 逆矩阵
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public static Matrix4x4d Inverse(Matrix4x4d m)
 {
     return(m.inverse);
 }
Beispiel #14
0
 /// <summary>
 /// 行列式
 /// </summary>
 /// <param name="m"></param>
 /// <returns></returns>
 public static double Determinant(Matrix4x4d m)
 {
     return(m.determinant);
 }