예제 #1
0
파일: Matrix34.cs 프로젝트: iniside/CryCIL
        /// <summary>
        /// Creates a matrix that represents a spherical linear interpolation from one
        /// matrix to another.
        /// </summary>
        /// <remarks>
        /// <para>This is an implementation of interpolation without quaternions.</para>
        /// <para>
        /// Given two orthonormal 3x3 matrices this function calculates the shortest
        /// possible interpolation-path between the two rotations. The interpolation curve
        /// forms the shortest great arc on the rotation sphere (geodesic).
        /// </para>
        /// <para>Angular velocity of the interpolation is constant.</para>
        /// <para>Possible stability problems:</para>
        /// <para>
        /// There are two singularities at angle = 0 and angle = <see cref="Math.PI"/> .
        /// At 0 the interpolation-axis is arbitrary, which means any axis will produce
        /// the same result because we have no rotation. (1,0,0) axis is used in this
        /// case. At <see cref="Math.PI"/> the rotations point away from each other and
        /// the interpolation-axis is unpredictable. In this case axis (1,0,0) is used as
        /// well. If the angle is ~0 or ~PI, then a very small vector has to be normalized
        /// and this can cause numerical instability.
        /// </para>
        /// </remarks>
        /// <param name="m">First matrix.</param>
        /// <param name="n">Second matrix.</param>
        /// <param name="t">Interpolation parameter.</param>
        public void SetSlerp(Matrix34 m, Matrix34 n, float t)
        {
            // calculate delta-rotation between m and n (=39 flops)
            Matrix33 d = new Matrix33(), i = new Matrix33();

            d.M00 = m.M00 * n.M00 + m.M10 * n.M10 + m.M20 * n.M20; d.M01 = m.M00 * n.M01 + m.M10 * n.M11 + m.M20 * n.M21; d.M02 = m.M00 * n.M02 + m.M10 * n.M12 + m.M20 * n.M22;
            d.M10 = m.M01 * n.M00 + m.M11 * n.M10 + m.M21 * n.M20; d.M11 = m.M01 * n.M01 + m.M11 * n.M11 + m.M21 * n.M21; d.M12 = m.M01 * n.M02 + m.M11 * n.M12 + m.M21 * n.M22;
            d.M20 = d.M01 * d.M12 - d.M02 * d.M11; d.M21 = d.M02 * d.M10 - d.M00 * d.M12; d.M22 = d.M00 * d.M11 - d.M01 * d.M10;

            // extract angle and axis
            double cosine = MathHelpers.Clamp((d.M00 + d.M11 + d.M22 - 1.0) * 0.5, -1.0, +1.0);
            double angle  = Math.Atan2(Math.Sqrt(1.0 - cosine * cosine), cosine);
            var    axis   = new Vector3(d.M21 - d.M12, d.M02 - d.M20, d.M10 - d.M01);
            double l      = Math.Sqrt(axis | axis); if (l > 0.00001)

            {
                axis /= (float)l;
            }
            else
            {
                axis = new Vector3(1, 0, 0);
            }

            i.SetRotationAroundAxis((float)angle * t, axis);             // angle interpolation and calculation of new delta-matrix (=26 flops)

            // final concatenation (=39 flops)
            this.M00 = m.M00 * i.M00 + m.M01 * i.M10 + m.M02 * i.M20; this.M01 = m.M00 * i.M01 + m.M01 * i.M11 + m.M02 * i.M21; this.M02 = m.M00 * i.M02 + m.M01 * i.M12 + m.M02 * i.M22;
            this.M10 = m.M10 * i.M00 + m.M11 * i.M10 + m.M12 * i.M20; this.M11 = m.M10 * i.M01 + m.M11 * i.M11 + m.M12 * i.M21; this.M12 = m.M10 * i.M02 + m.M11 * i.M12 + m.M12 * i.M22;
            this.M20 = this.M01 * this.M12 - this.M02 * this.M11; this.M21 = this.M02 * this.M10 - this.M00 * this.M12; this.M22 = this.M00 * this.M11 - this.M01 * this.M10;

            this.M03 = m.M03 * (1 - t) + n.M03 * t;
            this.M13 = m.M13 * (1 - t) + n.M13 * t;
            this.M23 = m.M23 * (1 - t) + n.M23 * t;
        }
예제 #2
0
        /// <summary>
        /// Creates new matrix that is set to represent rotation around given axis.
        /// </summary>
        /// <param name="rot">
        /// <see cref="Vector3"/> which length represents an angle of rotation, and that,
        /// once normalized, represents an axis of rotation.
        /// </param>
        /// <returns>New matrix.</returns>
        public static Matrix33 CreateRotationAroundAxis(Vector3 rot)
        {
            var matrix = new Matrix33();

            matrix.SetRotationAroundAxis(rot);

            return(matrix);
        }
예제 #3
0
        /// <summary>
        /// Creates new matrix that is set to represent rotation around given axis.
        /// </summary>
        /// <param name="c">   Cosine of angle of rotation.</param>
        /// <param name="s">   Sine of angle of rotation.</param>
        /// <param name="axis">Axis of rotation.</param>
        /// <returns>New matrix.</returns>
        public static Matrix33 CreateRotationAroundAxis(float c, float s, Vector3 axis)
        {
            var matrix = new Matrix33();

            matrix.SetRotationAroundAxis(c, s, axis);

            return(matrix);
        }