/// <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)); }
/// <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); }
/// <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)); }