public void TestAbs1() { var expr = MathS.Abs(x) + 4; var func = expr.Compile(x); Assert.Equal(4, func.Call(0)); }
public void TestAbs3() { var expr = MathS.Abs(x) + 4; var func = expr.Compile(x); Assert.Equal(9, func.Call(new Complex(3, 4))); }
public Vector3 ToVector3() { if (MathS.Abs(w) <= Threshold) { return(new Vector3(x, y, z)); } else { return(new Vector3(x / w, y / w, z / w)); } }
private IVertexOutputData[] ClipPolygon(IVertexOutputData[] polygon) { for (int planeIndex = 0; planeIndex < 6; planeIndex++) { List <IVertexOutputData> vdatas = new List <IVertexOutputData>(); int vi = planeIndex / 2; int sign = planeIndex % 2 == 0 ? 1 : -1; for (int pointIndex = 0; pointIndex < polygon.Length; pointIndex++) { int index0 = pointIndex; int index1 = pointIndex == polygon.Length - 1 ? 0 : pointIndex + 1; IVertexOutputData v0 = polygon[index0]; IVertexOutputData v1 = polygon[index1]; Vector4 p0 = v0.clip; Vector4 p1 = v1.clip; Vector3 n0 = v0.viewNormal; Vector3 n1 = v1.viewNormal; float d0 = (p0[vi] + p0.w * sign) * p0.w; float d1 = (p1[vi] + p1.w * sign) * p1.w; float ds = d0 * d1; if (ds < 0) { // 边与裁剪面相交 float u = d0 / (d0 - d1); Vector4 p = p0 + (p1 - p0) * u; Vector3 n = n0 + (n1 - n0) * u; if (sign * d0 > 0) { vdatas.Add(v0); } IVertexOutputData data = new VertexOutputData(); data.clip = p; data.viewNormal = n; vdatas.Add(data); } else if (MathS.Abs(d0) < Threshold) { // p0点在裁剪面上 vdatas.Add(v0); } else if (sign * d0 > 0 && sign * d1 >= 0) { // 边完全位于裁剪面之内 vdatas.Add(v0); } } polygon = vdatas.ToArray(); } return(polygon); }
public IVertexOutputData Triangle(IVertexOutputData[] clips, Vector2[] screens, int[] pixel) { Vector2 center = new Vector2(pixel[0], pixel[1]); float a = MathS.Abs(Vector2.Cross(screens[1] - screens[0], screens[2] - screens[0]) * 0.5f); // 重心法求插值系数 float a0 = MathS.Abs(Vector2.Cross(screens[1] - screens[0], center - screens[0]) * 0.5f) / a; float a1 = MathS.Abs(Vector2.Cross(screens[2] - screens[1], center - screens[1]) * 0.5f) / a; float a2 = MathS.Abs(Vector2.Cross(screens[0] - screens[2], center - screens[2]) * 0.5f) / a; // 插值 IVertexOutputData lerp = new VertexOutputData(); lerp.clip = a0 * clips[0].clip + a1 * clips[1].clip + a2 * clips[2].clip; lerp.viewNormal = a0 * clips[0].viewNormal + a1 * clips[1].viewNormal + a2 * clips[2].viewNormal; return(lerp); }
public Vector3 Perpendicular() { float ax = MathS.Abs(x); float ay = MathS.Abs(y); float az = MathS.Abs(z); if (ax < ay && ax < az) { return(new Vector3(0, -z, y)); } else if (ay < ax && ay < az) { return(new Vector3(-z, 0, x)); } else { return(new Vector3(-y, x, 0)); } }
/// <summary> /// 旋转单位向量From到另外一个单位向量To /// </summary> /// <param name="from">单位向量</param> /// <param name="to">单位向量</param> /// <returns>单位四元数</returns> public static Quaternion FromTo(Vector3 from, Vector3 to) { Quaternion uq = Quaternion.identity; float squar = 2 * (1 + Vector3.Dot(from, to)); if (MathS.Abs(squar) <= Threshold) { Vector3 perp = from.Perpendicular().normalized; uq = new Quaternion(perp.x, perp.y, perp.z, 0); } else { float root = MathS.Sqrt(squar); Vector3 imag = from.Cross(to) / root; float real = root * 0.5f; uq = new Quaternion(imag.x, imag.y, imag.z, real); } return(uq); }
/// <summary> /// 旋转轴和旋转角(单位四元数有效) /// </summary> /// <param name="angle"></param> /// <param name="axisNormal"></param> public void ToAngleAxis(out float angle, out Vector3 axisNormal) { Vector3 axis = new Vector3( MathS.Abs(x) <= Threshold ? 0f : x, MathS.Abs(y) <= Threshold ? 0f : y, MathS.Abs(z) <= Threshold ? 0f : z ); if (axis == Vector3.zero) { angle = 0; axisNormal = Vector3.zero; } else { float length = axis.magnitude; angle = MathS.Atan2(length, w) * 2 * MathS.RadToDeg; axisNormal = axis / length; } }
/// <summary> /// 欧拉角(单位四元数有效) /// </summary> /// <returns></returns> public Vector3 ToEulers() { Vector3 euler = Vector3.zero; Matrix m = ToMatrix(); if (MathS.Abs(m[1, 0]) <= Threshold && MathS.Abs(m[1, 1]) <= Threshold) { euler.x = m[1, 2] <= 0 ? 90 : -90; euler.y = 0; euler.z = MathS.Atan2(-m[0, 1], m[0, 0]) * MathS.RadToDeg; } else { euler.x = MathS.Asin(-m[1, 2]); euler.y = MathS.Atan2(m[0, 2], m[2, 2]); euler.z = MathS.Atan2(m[1, 0], m[1, 1]); euler *= MathS.RadToDeg; } return(euler); }
[Fact] public void Abs() => Test(@"\left|x\right|", MathS.Abs(x));
public float Distance(Vector3 point) { return(MathS.Abs(point.Dot(mNormal) - md)); }