/// <summary>
        /// Retrieve index to the discrete PDF where its cumulative distribution matches the random variable x1 [0, 1].
        /// Uses binary search O(log n).
        /// </summary>
        public int Sample(double x1)
        {
            var range       = m_cdf.Length;
            var valueToFind = x1 * m_cdf[range - 1]; // x1 * sum -> CDF threshold to find

            var i0 = 0;

            // binary search
            while (range > 0)
            {
                var halfRange = range >> 1;
                var center    = i0 + halfRange;

                // check if value is left or right
                if (m_cdf[center] <= valueToFind)
                {
                    // right half
                    i0     = center + 1;
                    range -= halfRange + 1;
                }
                else
                {
                    // left half
                    range = halfRange;
                }
            }
            return(Fun.Clamp(i0 - 1, 0, m_cdf.Length - 2));
        }
Example #2
0
        /// <summary>
        /// Creates a quaternion representing a rotation from one
        /// vector into another.
        /// </summary>
        public __rot3t__(__v3t__ from, __v3t__ into)
        {
            var     a        = from.Normalized;
            var     b        = into.Normalized;
            var     angle    = Fun.Clamp(__v3t__.Dot(a, b), -1, 1).Acos();
            var     angleAbs = angle.Abs();
            __v3t__ axis;

            // some vectors do not normalize to 1.0 -> Vec.Dot = -0.99999999999999989 || -0.99999994f
            // acos => 3.1415926386886319 or 3.14124632f -> delta of 1e-7 or 1e-3
            if (angle < __rotIntoEps__)
            {
                axis  = a;
                angle = 0;
            }
            else if (__pi__ - angleAbs < __rotIntoEps__)
            {
                axis  = a.AxisAlignedNormal();
                angle = __pi__;
            }
            else
            {
                axis = __v3t__.Cross(a, b).Normalized;
            }

            this = new __rot3t__(axis, angle);
        }
Example #3
0
        /// <summary>
        /// Spherical linear interpolation.
        ///
        /// Assumes q1 and q2 are normalized and that t in [0,1].
        ///
        /// This method does interpolate along the shortest arc
        /// between q1 and q2.
        /// </summary>
        /// <param name="q1"></param>
        /// <param name="q2"></param>
        /// <param name="t">[0,1]</param>
        /// <returns>Interpolant</returns>
        public static Rot3f SlerpShortest(
            Rot3f q1, Rot3f q2, double t
            )
        {
            Rot3f q3       = q2;
            float cosomega = Fun.Clamp(Rot3f.Dot(q1, q3), -1, 1);

            if (cosomega < 0.0)
            {
                cosomega = -cosomega;
                q3      *= -1; //q3 = -q3;
            }

            if (cosomega >= 1.0)
            {
                // Special case: q1 and q2 are the same, so just return one of them.
                // This also catches the case where cosomega is very slightly > 1.0

                return(q1);
            }

            double sinomega = System.Math.Sqrt(1 - cosomega * cosomega);

            Rot3f result = new Rot3f();

            if (sinomega * double.MaxValue > 1)
            {
                double omega = System.Math.Acos(cosomega);
                float  s1    = (float)(System.Math.Sin((1.0 - t) * omega) / sinomega);
                float  s2    = (float)(System.Math.Sin(t * omega) / sinomega);

                result = s1 * q1 + s2 * q3;
            }
            else if (cosomega > 0)
            {
                // omega == 0

                float s1 = 1.0f - (float)t;
                float s2 = (float)t;

                result = s1 * q1 + s2 * q3;
            }
            else
            {
                // omega == -pi

                result.X = -q1.Y;
                result.Y = q1.X;
                result.Z = -q1.W;
                result.W = q1.Z;

                float s1 = (float)System.Math.Sin((0.5 - t) * System.Math.PI);
                float s2 = (float)System.Math.Sin(t * System.Math.PI);

                result = s1 * q1 + s2 * result;
            }

            return(result);
        }
        //# });
        #endregion

        #region LinCom

        //# foreach (var it in Meta.IntegerTypes) { var itn = it.Name;
        //# for (int tpc = 4; tpc < 7; tpc+=2) {
        //# foreach (var rt in Meta.RealTypes) { var rtn = rt.Name; var rtc = rt.Caps[0];
        public static __itn__ LinCom(
            /*# tpc.ForEach(i => { */ __itn__ p__i__ /*# }, comma); */, ref Tup__tpc__ <__rtn__> w)
        {
            return((__itn__)Fun.Clamp(/*# tpc.ForEach(i => { */ p__i__ * w.E__i__ /*# }, add); */, (__rtn__)__itn__.MinValue, (__rtn__)__itn__.MaxValue));
        }