【Unity】Mathd系列(一)Double型Vector2

    由于Unity中的向量用的都是float型去存储,而float型的精度只有五位小数,导致了前段时间做项目的时候出现了精度上的问题。当时重新写了一个简单的类去解决它,过后觉得以后还有可能还会遇到类似的问题,于是系统的写了一下Unity中的几个结构体。

首先是Vector2d:

/// Vector2d.cs
/// 
/// The double type version of the Unity struct Vector2.
/// It can solve the problem that the float type may not be accurate enough.
/// 
/// Unity Vector2结构体的double版实现,以解决float型精度可能不够的问题。
/// 
/// Created by D子宇 on 2018.3.17 
/// 
/// Email: [email protected]
using System;
using UnityEngine;

namespace Mathd
{
    public struct Vector2d
    {
        #region public members

        public double x;
        public double y;

        #endregion

        #region constructor

        public Vector2d(double p_x,double p_y) {
            x = p_x;
            y = p_y;
        }

        #endregion

        #region public properties

        public double this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return x;
                    case 1:
                        return y;
                    default:
                        throw new IndexOutOfRangeException("Invalid Vector2d index!");
                }
            }
            set
            {
                switch (index)
                {
                    case 0:
                        x = value;
                        break;
                    case 1:
                        y = value;
                        break;
                    default:
                        throw new IndexOutOfRangeException("Invalid Vector2d index!");
                }
            }
        }

        public static Vector2d down
        {
            get
            {
                return new Vector2d(0, -1);
            }
        }
        public static Vector2d left
        {
            get
            {
                return new Vector2d(-1, 0);
            }
        }
        public static Vector2d one
        {
            get
            {
                return new Vector2d(1, 1);
            }
        }
        public static Vector2d right
        {
            get
            {
                return new Vector2d(1, 0);
            }
        }
        public static Vector2d up
        {
            get
            {
                return new Vector2d(0, 1);
            }
        }
        public static Vector2d zero
        {
            get
            {
                return new Vector2d(0, 0);

            }
        }
        public double magnitude
        {
            get
            {
                return Math.Sqrt(sqrMagnitude);
            }
        }
        public Vector2d normalized
        {
            get
            {
                Vector2d result = new Vector2d(x, y);
                result.Normalize();
                return result;
            }
        }
        public double sqrMagnitude
        {
            get
            {
                return x * x + y * y;
            }
        }

        #endregion

        #region public functions

        /// 
        /// 角度
        /// 
        /// 
        /// 
        /// 
        public static float Angle(Vector2d from, Vector2d to) {
            double cos = Dot(from.normalized, to.normalized);
            if (cos < -1)
            {
                cos = -1;
            }
            if (cos > 1)
            {
                cos = 1;
            }
            return (float)(Math.Acos(cos) * (180 / Math.PI));
        }
        /// 
        /// 限制距离
        /// 
        /// 
        /// 
        /// 
        public static Vector2d ClampMagnitude(Vector2d vector, double maxLength) {
            if (maxLength * maxLength >= vector.sqrMagnitude)
            {
                return vector;
            }
            return vector.normalized * maxLength;
        }
        /// 
        /// 距离
        /// 
        /// 
        /// 
        /// 
        public static double Distance(Vector2d a, Vector2d b) {
            return Math.Sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
        }
        /// 
        /// 点乘
        /// 
        /// 
        /// 
        /// 
        public static double Dot(Vector2d lhs, Vector2d rhs) {
            return lhs.x * rhs.x + lhs.y * rhs.y;
        }
        /// 
        /// 线性插值
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Vector2d Lerp(Vector2d a, Vector2d b, double t)
        {
            if (t <= 0)
            {
                return a;
            }
            else if (t >= 1)
            {
                return b;
            }
            return a + (b - a) * t;
        }
        /// 
        /// 线性插值(无限制)
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Vector2d LerpUnclamped(Vector2d a, Vector2d b, double t)
        {
            return a + (b - a) * t;
        }
        /// 
        /// 最大值(X,Y均取最大)
        /// 
        /// 
        /// 
        /// 
        public static Vector2d Max(Vector2d lhs, Vector2d rhs) {
            Vector2d temp = new Vector2d();
            temp.x = Math.Max(lhs.x, rhs.x);
            temp.y = Math.Max(lhs.y, rhs.y);
            return temp;
        }
        /// 
        /// 最小值(X,Y均取最小)
        /// 
        /// 
        /// 
        /// 
        public static Vector2d Min(Vector2d lhs, Vector2d rhs)
        {
            Vector2d temp = new Vector2d();
            temp.x = Math.Min(lhs.x, rhs.x);
            temp.y = Math.Min(lhs.y, rhs.y);
            return temp;
        }
        /// 
        /// 向目标点移动
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Vector2d MoveTowards(Vector2d current, Vector2d target, double maxDistanceDelta) {
            Vector2d vector2 = target - current;
            double single = vector2.magnitude;
            if (single <= maxDistanceDelta || single == 0f)
            {
                return target;
            }
            return current + ((vector2 / single) * maxDistanceDelta);
        }
        /// 
        /// 反射
        /// 
        /// 
        /// 
        /// 
        public static Vector2d Reflect(Vector2d inDirection, Vector2d inNormal) {
            return (-2f * Dot(inNormal, inDirection)) * inNormal + inDirection;
        }
        /// 
        /// 缩放
        /// 
        /// 
        /// 
        /// 
        public static Vector2d Scale(Vector2d a, Vector2d b) {
            Vector2d temp = new Vector2d();
            temp.x = a.x * b.x;
            temp.y = a.y * b.y;
            return temp;
        }
        /// 
        /// 平滑阻尼
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static Vector2d SmoothDamp(Vector2d current, Vector2d target, ref Vector2d currentVelocity, double smoothTime, double maxSpeed, double deltaTime) {
            smoothTime = Math.Max(0.0001, smoothTime);
            double num = 2 / smoothTime;
            double num2 = num * deltaTime;
            double d = 1f / (1f + num2 + 0.48f * num2 * num2 + 0.235f * num2 * num2 * num2);
            Vector2d vector = current - target;
            Vector2d vector2 = target;
            double maxLength = maxSpeed * smoothTime;
            vector = ClampMagnitude(vector, maxLength);
            target = current - vector;
            Vector2d vector3 = (currentVelocity + num * vector) * deltaTime;
            currentVelocity = (currentVelocity - num * vector3) * d;
            Vector2d vector4 = target + (vector + vector3) * d;
            if (Dot(vector2 - current, vector4 - vector2) > 0f)
            {
                vector4 = vector2;
                currentVelocity = (vector4 - vector2) / deltaTime;
            }
            return vector4;
        }
        /// 
        /// 模长平方
        /// 
        /// 
        /// 
        public static double SqrMagnitude(Vector2d a)
        {
            return a.sqrMagnitude;
        }
        /// 
        /// 单位化
        /// 
        public void Normalize() {
            if (this != zero)
            {
                double length = magnitude;
                x /= length;
                y /= length;
            }
        }
        /// 
        /// 缩放
        /// 
        /// 
        public void Scale(Vector2d scale) {
            x *= scale.x;
            y *= scale.y;
        }
        /// 
        /// 设置向量
        /// 
        /// 
        /// 
        public void Set(double newX, double newY) {
            x = newX;
            y = newY;
        }
        public double SqrMagnitude()
        {
            return sqrMagnitude;
        }
        public override string ToString() {
            return String.Format("({0}, {1})", x, y);
        }
        public override bool Equals(object other)
        {
            return this == (Vector2d)other;
        }
        public string ToString(string format) {
            return String.Format("({0}, {1})", x.ToString(format), y.ToString(format));
        }
        public override int GetHashCode()
        {
            return this.x.GetHashCode() ^ this.y.GetHashCode() << 2;
        }
        public Vector2d ToVector2()
        {
            return new Vector2d((float)x, (float)y);
        }

        #endregion

        #region operator

        public static Vector2d operator +(Vector2d a, Vector2d b)
        {
            return new Vector2d(a.x + b.x, a.y + b.y);
        }
        public static Vector2d operator -(Vector2d a)
        {
            return new Vector2d(-a.x, -a.y);
        }
        public static Vector2d operator -(Vector2d a, Vector2d b)
        {
            return new Vector2d(a.x - b.x, a.y - b.y);
        }
        public static Vector2d operator *(double d, Vector2d a)
        {
            return new Vector2d(a.x * d, a.y * d);
        }
        public static Vector2d operator *(Vector2d a, double d)
        {
            return new Vector2d(a.x * d, a.y * d);
        }
        public static Vector2d operator /(Vector2d a, double d)
        {
            return new Vector2d(a.x / d, a.y / d);
        }
        public static bool operator ==(Vector2d lhs, Vector2d rhs)
        {
            if (lhs.x == rhs.x && lhs.y == rhs.y)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        public static bool operator !=(Vector2d lhs, Vector2d rhs)
        {
            return !(lhs == rhs);
        }

        public static implicit operator Vector2d(Vector3d v)
        {
            return new Vector2d(v.x, v.y);
        }
        public static implicit operator Vector3d(Vector2d v)
        {
            return new Vector3d(v.x, v.y, 0);
        }
        public static implicit operator Vector2d(Vector2 v)
        {
            return new Vector2d(v.x, v.y);
        }
        public static implicit operator Vector2(Vector2d v)
        {
            return new Vector2((float)v.x, (float)v.y);
        }

        #endregion
    }
}
github地址: https://github.com/Darkziyu/Mathd/tree/develop

你可能感兴趣的:(Unity3D)