예제 #1
0
        /// <summary>
        /// http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static Quaterniond CreateFromTo(Vec3d from, Vec3d to)
        {
            // TODO
            // test implementation
            // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another

            if (!from.Unitize() || !to.Unitize())
            {
                return(Identity);
            }

            var ct = Vec3d.Dot(from, to);

            // parallel check
            if (1.0 - Math.Abs(ct) < SlurMath.ZeroTolerance)
            {
                //opposite check
                if (ct < 0.0)
                {
                    var perp = from.X < 1.0 ? from.CrossX() : from.CrossY();
                    var t    = 1.0 / perp.Length;
                    return(new Quaterniond(perp.X * t, perp.Y * t, perp.Z * t, 0.0));
                }

                return(Identity);
            }

            // can assume axis is valid
            var axis = Vec3d.Cross(from, to);
            var q    = new Quaterniond(axis.X, axis.Y, axis.Z, ct + 1);

            q.Unitize();

            return(q);
        }
예제 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static Quaterniond CreateFromTo(Vec3d from, Vec3d to)
        {
            // impl refs
            // https://stackoverflow.com/questions/1171849/finding-quaternion-representing-the-rotation-from-one-vector-to-another
            // http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors

            if (!from.Unitize() || !to.Unitize())
            {
                return(Identity);
            }

            var ca = Vec3d.Dot(from, to);

            // parallel check
            if (SlurMath.ApproxEquals(Math.Abs(ca), 1.0))
            {
                //opposite check
                if (ca < 0.0)
                {
                    var perp = from.X < 1.0 ? from.CrossX() : from.CrossY();
                    var t    = 1.0 / perp.Length;
                    return(new Quaterniond(perp.X * t, perp.Y * t, perp.Z * t, 0.0));
                }

                return(Identity);
            }

            // can assume axis is valid
            var axis = Vec3d.Cross(from, to);
            var q    = new Quaterniond(axis.X, axis.Y, axis.Z, ca + 1);

            q.Unitize();

            return(q);
        }
예제 #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static AxisAngle3d CreateFromTo(Vec3d from, Vec3d to)
        {
            if (!from.Unitize() || !to.Unitize())
            {
                return(Identity);
            }

            var ct = Vec3d.Dot(from, to);

            // parallel check
            if (1.0 - Math.Abs(ct) < SlurMath.ZeroTolerance)
            {
                // opposite check
                if (ct < 0.0)
                {
                    var perp = from.X < 1.0 ? from.CrossX() : from.CrossY();
                    return(new AxisAngle3d()
                    {
                        _axis = perp / perp.Length,
                        _angle = Math.PI,
                        _cosAngle = -1.0,
                        _sinAngle = 0.0
                    });
                }

                return(Identity);
            }

            // can assume axis is valid
            var axis = Vec3d.Cross(from, to);
            var st   = axis.Length;

            return(new AxisAngle3d()
            {
                _axis = axis / st,
                _angle = Math.Acos(ct),
                _sinAngle = st,
                _cosAngle = ct
            });
        }