unity中Game视图中实现和Scene视图中一样的摄像机操作

代码运行,是可行的,在github上找的,侵权请告知,忘记在哪下的了。

using UnityEngine;
using System.Collections;

public class CameraController : MonoBehaviour
{
    /// <summary>
    /// 视角类型.
    /// </summary>
    private enum ViewType
    {
        _2D = 0,
        _3D
    }

    /// <summary>
    /// 鼠标按键.
    /// </summary>
    private enum MouseButton
    {
        /// <summary>
        /// 鼠标左键.
        /// </summary>
        LEFT = 0,
        /// <summary>
        /// 鼠标右键.
        /// </summary> 
        RIGHT,
        /// <summary>
        /// 鼠标中键.
        /// </summary>
        MIDDLE
    }

    /// <summary>
    /// 指针样式.
    /// </summary>
    private enum CursorType
    {
        /// <summary>
        /// 默认样式.
        /// </summary>
        DEFAULT = 0,
        /// <summary>
        /// 小手.
        /// </summary>
        HAND,
        /// <summary>
        /// 眼睛.
        /// </summary>
        EYE,
        /// <summary>
        /// 放大镜.
        /// </summary>
        MAGNIFIER
    }

    #region 字段
    private const string MOUSESCROLLWHEEL = "Mouse ScrollWheel";        // 鼠标滚轮.
    private const string MOUSEX = "Mouse X";
    private const string MOUSEY = "Mouse Y";

    #region 输入

    private bool leftAltKeyDown;                                        // 左Alt键-按下.
    private bool rightAltKeyDown;                                       // 右Alt键-按下.
    private bool leftAltKey;                                            // 左Alt键-长按.
    private bool rightAltKey;                                           // 右Alt键-长按.
    private bool leftAltKeyUp;                                          // 左Alt键-抬起.
    private bool rightAltKeyUp;                                         // 右Alt键-抬起.
    private bool leftMouseButtonDown;                                   // 鼠标左键-按下.
    private bool rightMouseButtonDown;                                  // 鼠标右键-按下.
    private bool leftMouseButton;                                       // 鼠标左键-长按.
    private bool rightMouseButton;                                      // 鼠标右键-长按.
    private bool rightMouseButtonUp;                                    // 鼠标右键-抬起.
    private bool middleMouseButton;                                     // 鼠标中键-长按.
    private bool middleMouseButtonUp;                                   // 鼠标中键-抬起.

    #endregion

    private Camera m_Camera;                                            // 相机.
    private Texture2D handCursorTexture;                                // 小手.
    private Texture2D eyeCursorTexture;                                 // 眼睛.
    private Texture2D magnifierCursorTexture;                           // 放大镜.

    private Vector2 hotSpot = Vector2.zero;
    private CursorMode cursorMode = CursorMode.Auto;

    private float angle_X;                                              // 水平方向的角度值,绕Transform的y轴旋转(左右)
    private float angle_Y;                                              // 竖直方向的角度值,绕Transform的x轴旋转(上下)
    private float angle_Z;

    // 切换视角
    private Matrix4x4 defaultOrthProjMat;                               // 相机默认的正交投影矩阵.
    private Matrix4x4 defaultPersProjMat;                               // 相机默认的透视投影矩阵.
    private Matrix4x4 currentProjMat;                                   // 相机当前的投影矩阵.
    private bool isChangingViewType = false;                            // 正在切换视角.
    private float viewTypeLerpTime = 0f;                                // 插值时间.
    private ViewType viewType;                                          // 当前视角.

    [Header("Zoom")]
    // 相机拉近拉远 Zoom
    [SerializeField]
    private float distance = 20f;                      // 相机与lookAroudPos点的距离.
    [SerializeField, Range(1f, 20f)]
    private float zoomSpeed = 10f;                                      // 滚轮缩放速度.
    [SerializeField]
    private float maxDistance = 100f;                  // 相机最远距离.
    [SerializeField]
    private float minDistance = 1f;                    // 相机最近距离.

    [Header("360° Rotate")]
    // Alt+鼠标拖动, 360度观察
    [SerializeField, Range(2f, 10f)]
    private float rotateSensitivity = 5f;                               // 旋转灵敏度.
    private Vector3 lookAroundPos = Vector3.zero;

    // Alt+鼠标右键 放大缩小
    [Header("Field Of View")]
    private float minFov = 20f;                                         // 最小视角.
    private float maxFov = 135f;                                        // 最大视角.
    private Vector3 lastMousePosFov = Vector3.zero;
    [SerializeField, Range(0.01f, 0.1f)]
    private float fovSensitivity = 0.05f;                               // 视角灵敏度.

    // 选中物体聚焦
    private GameObject selectedObj = null;                              // 选中的物体.
    private float raycastMaxDistance = 1000f;
    private LayerMask raycastLayerMask;
    private RaycastHit raycastHit;

    [Header("Focus")]
    [SerializeField, Range(0.1f, 5f)]
    private float focusSpeed = 3.0f;                                    // 聚焦的速度.
    [SerializeField]
    private float focusDistance = 3f;                                   // 聚焦时与物体的距离.
    private bool isFocusing = false;                                    // 相机正看向物体中.
    private float focusTime = 0f;                                       // 聚焦时间.
    private Vector3 cameraInitForward;                                  // 相机最初的前方.
    private Vector3 focusTargetForward;                                 // 聚焦目标前方.
    private Vector3 focusInitPos;                                       // 聚焦前相机初始位置.
    private Vector3 focusTargetPos;                                     // 聚焦目标位置.
    #endregion

    #region Unity_Method

    private void Start()
    {
        Init();
    }
    private float mMoveSpeed = 0.2f;
    private void LateUpdate()
    {
        // 更新输入.
        UpdateInput();
        // 切换视角.
        SwitchViewType();
        // 拉近拉远.
        Zoom();
        // 拖动相机.
        Drag();
        // 360°查看.
        LookAround();
        // 放大缩小. 和切换视角共同使用时有Bug.
        Magnifier();
        // 聚焦.
        Focus();

        if (Input.GetKey(KeyCode.W))
        {
            m_Camera.transform.position += m_Camera.transform.forward * mMoveSpeed;
        }
        else if (Input.GetKey(KeyCode.S))
        {
            m_Camera.transform.position += -m_Camera.transform.forward * mMoveSpeed;
        }
        else if (Input.GetKey(KeyCode.A))
        {
            m_Camera.transform.position += -m_Camera.transform.right * mMoveSpeed;
        }
        else if (Input.GetKey(KeyCode.D))
        {
            m_Camera.transform.position += m_Camera.transform.right * mMoveSpeed;
        }

    }
    private void OnGUI()
    {
       

        //if (GUI.Button(new Rect(Vector2.zero, new Vector2(100, 50)), "正交"))
        //{
        //    SetViewType(ViewType._2D);
        //}

        //if (GUI.Button(new Rect(Vector2.up * 60, new Vector2(100, 50)), "透视"))
        //{
        //    SetViewType(ViewType._3D);
        //}

        //if (GUI.Button(new Rect(Vector2.up * 120, new Vector2(100, 50)), "正视图"))
        //{
        //    Front();
        //}

        //if (GUI.Button(new Rect(Vector2.up * 180, new Vector2(100, 50)), "后视图"))
        //{
        //    Back();
        //}

        //if (GUI.Button(new Rect(Vector2.up * 240, new Vector2(100, 50)), "左视图"))
        //{
        //    Left();
        //}

        //if (GUI.Button(new Rect(Vector2.up * 300, new Vector2(100, 50)), "右视图"))
        //{
        //    Right();
        //}

        //if (GUI.Button(new Rect(Vector2.up * 360, new Vector2(100, 50)), "上视图"))
        //{
        //    Top();
        //}

        //if (GUI.Button(new Rect(Vector2.up * 420, new Vector2(100, 50)), "下视图"))
        //{
        //    Down();
        //}
    }

    #endregion

    #region 初始化相关

    /// <summary>
    /// 初始化.
    /// </summary>
    private void Init()
    {
        m_Camera = GetComponent<Camera>();
        raycastLayerMask = 1 << LayerMask.NameToLayer("Default");

        RecalcDistance();
        CalculateProjMatrix();                  // 获取相机默认矩阵.
        ResetLookAroundPos();                   // 重置观察中心.
        LoadCursorTexture();                    // 加载鼠标图标.
    }

    /// <summary>
    /// 重置观察中心(观察中心在相机的前方).
    /// </summary>
    private void ResetLookAroundPos()
    {
        lookAroundPos = m_Camera.transform.position + m_Camera.transform.rotation * (Vector3.forward * distance);
    }

    /// <summary>
    /// 加载鼠标指针图标.
    /// </summary>
    private void LoadCursorTexture()
    {
        handCursorTexture = Resources.Load<Texture2D>("Textures/Hand");
        eyeCursorTexture = Resources.Load<Texture2D>("Textures/Eye");
        magnifierCursorTexture = Resources.Load<Texture2D>("Textures/Magnifier");
    }

    /// <summary>
    /// 设置鼠标样式.
    /// </summary>
    private void SetCursor(CursorType cursorType)
    {
        switch (cursorType)
        {
            case CursorType.DEFAULT:
                Cursor.SetCursor(null, hotSpot, cursorMode);
                break;
            case CursorType.HAND:
                Cursor.SetCursor(handCursorTexture, hotSpot, cursorMode);
                break;
            case CursorType.EYE:
                Cursor.SetCursor(eyeCursorTexture, hotSpot, cursorMode);
                break;
            case CursorType.MAGNIFIER:
                Cursor.SetCursor(magnifierCursorTexture, hotSpot, cursorMode);
                break;
            default:
                Debug.LogError("未知指针类型.");
                break;
        }
    }

    /// <summary>
    /// 更新输入.
    /// </summary>
    private void UpdateInput()
    {
        leftAltKeyDown = Input.GetKeyDown(KeyCode.LeftAlt);                            // 左Alt键-按下.
        rightAltKeyDown = Input.GetKeyDown(KeyCode.RightAlt);                          // 右Alt键-按下.
        leftAltKey = Input.GetKey(KeyCode.LeftAlt);                                    // 左Alt键-长按.
        rightAltKey = Input.GetKey(KeyCode.RightAlt);                                  // 右Alt键-长按.
        leftAltKeyUp = Input.GetKeyUp(KeyCode.LeftAlt);                                // 左Alt键-抬起.
        rightAltKeyUp = Input.GetKeyUp(KeyCode.RightAlt);                              // 右Alt键-抬起.
        rightMouseButtonDown = Input.GetMouseButtonDown((int)MouseButton.RIGHT);       // 鼠标右键-按下.
        leftMouseButtonDown = Input.GetMouseButtonDown((int)MouseButton.LEFT);         // 鼠标左键-按下.
        leftMouseButton = Input.GetMouseButton((int)MouseButton.LEFT);                 // 鼠标左键-长按.
        rightMouseButton = Input.GetMouseButton((int)MouseButton.RIGHT);               // 鼠标右键-长按.
        rightMouseButtonUp = Input.GetMouseButtonUp((int)MouseButton.RIGHT);           // 鼠标右键-抬起.

        middleMouseButton = Input.GetMouseButton((int)MouseButton.MIDDLE);             // 鼠标中键-按下.  
        middleMouseButtonUp = Input.GetMouseButtonUp((int)MouseButton.MIDDLE);         // 鼠标中键-抬起.
    }

    /// <summary>
    /// 计算距离.
    /// </summary>
    private void RecalcDistance()
    {
        Vector3 checkFarPos = m_Camera.transform.position + m_Camera.transform.rotation * (Vector3.forward * 1000);
        if (Physics.Linecast(m_Camera.transform.position, checkFarPos, out raycastHit))
        {
            // 如果相机中心有物体,则以物体到相机为距离
            distance = raycastHit.distance;
            if (selectedObj == null)
            {
                selectedObj = raycastHit.collider.gameObject;
            }
        }
    }

    #endregion

    #region 切换视角

    /// <summary>
    /// 计算投影矩阵.
    /// </summary>
    private void CalculateProjMatrix()
    {
        currentProjMat = m_Camera.projectionMatrix;

        float aspect = m_Camera.aspect;
        float fov = m_Camera.fieldOfView;
        float size = m_Camera.orthographicSize;
        float far = m_Camera.farClipPlane;
        float near = m_Camera.nearClipPlane;
        float tan = Mathf.Tan(Mathf.Deg2Rad * fov * 0.5f);

        if (m_Camera.orthographic)
        {
            // 启动时相机是正交的
            viewType = ViewType._2D;
            fov = SetFovBySize(size);
        }
        else
        {
            // 启动时相机是透视的
            viewType = ViewType._3D;
            size = SetSizeByFov(fov);
        }

        // 透视投影矩阵.
        defaultPersProjMat = new Matrix4x4();
        //defaultPersProjMat = Matrix4x4.Perspective(fov, aspect, near, far);           // 透视矩阵也可直接调用这个来计算.
        defaultPersProjMat.SetRow(0, new Vector4(1.0f / (tan * aspect), 0, 0, 0));
        defaultPersProjMat.SetRow(1, new Vector4(0, 1.0f / tan, 0, 0));
        defaultPersProjMat.SetRow(2, new Vector4(0, 0, -(far + near) / (far - near), -2 * far * near / (far - near)));
        defaultPersProjMat.SetRow(3, new Vector4(0, 0, -1, 0));

        // 正交投影矩阵.
        defaultOrthProjMat = new Matrix4x4();
        defaultOrthProjMat.SetRow(0, new Vector4(1.0f / (aspect * size), 0, 0, 0));
        defaultOrthProjMat.SetRow(1, new Vector4(0, 1.0f / size, 0, 0));
        defaultOrthProjMat.SetRow(2, new Vector4(0, 0, -2f / (far - near), -(far + near) / (far - near)));
        defaultOrthProjMat.SetRow(3, new Vector4(0, 0, 0, 1));
    }

    /// <summary>
    /// 切换视角.
    /// </summary>
    private void SwitchViewType()
    {
        if (isChangingViewType)
        {
            viewTypeLerpTime += Time.deltaTime * 2.0f;
            if (viewType == ViewType._2D)
            {
                // 切换到正交视图.
                currentProjMat = Utils.Math.MatrixLerp(currentProjMat, defaultOrthProjMat, viewTypeLerpTime);
            }
            else
            {
                // 切换到透视视图.
                currentProjMat = Utils.Math.MatrixLerp(currentProjMat, defaultPersProjMat, viewTypeLerpTime);
            }
            m_Camera.projectionMatrix = currentProjMat;
            if (viewTypeLerpTime >= 1.0f)
            {
                isChangingViewType = false;
                viewTypeLerpTime = 0f;

                if (viewType == ViewType._2D)
                {
                    m_Camera.orthographic = true;
                }
                else
                {
                    m_Camera.orthographic = false;
                }
                m_Camera.ResetProjectionMatrix();
            }
        }
    }

    /// <summary>
    /// 设置将要切换的视角.
    /// </summary>
    /// <param name="targetViewType">目标视角.</param>
    private void SetViewType(ViewType targetViewType)
    {
        if (viewType != targetViewType)
        {
            viewType = targetViewType;
            isChangingViewType = true;
            viewTypeLerpTime = 0f;
        }
    }

    /// <summary>
    /// 根据正交相机的size设置对应透视相机的fov
    /// </summary>
    /// <param name="size">正交相机高度的一半,即orthographicSize</param>
    private float SetFovBySize(float size)
    {
        float fov = 2.0f * Mathf.Atan(size / distance) * Mathf.Rad2Deg;
        m_Camera.fieldOfView = fov;
        return fov;
    }

    /// <summary>
    /// 根据透视相机的fov设置对应正交相机的即orthographicSize
    /// </summary>
    /// <param name="fov">透视相机的fov</param>
    private float SetSizeByFov(float fov)
    {
        float size = distance * Mathf.Tan(fov * 0.5f * Mathf.Deg2Rad);
        m_Camera.orthographicSize = size;
        return size;
    }

    #endregion

    #region 拉近拉远

    /// <summary>
    /// 拉近拉远.
    /// </summary>
    /// <remarks>鼠标滚轮滚动,向上滚动拉近相机,向下滚动拉远相机</remarks>
    private void Zoom()
    {
        float scrollWheelValue = Input.GetAxis(MOUSESCROLLWHEEL);
        if (!Utils.Math.IsEqual(scrollWheelValue, 0f))
        {
            // scrollWheelValue:滚轮向上为+ 向下为-
            // 同时滚轮向上,拉近相机;滚轮向下,拉远相机
            distance -= scrollWheelValue * zoomSpeed;
            distance = Mathf.Clamp(distance, minDistance, maxDistance);

            m_Camera.transform.position = lookAroundPos - m_Camera.transform.rotation * (Vector3.forward * distance);

            // 相机距离改变后需同时修改fov或orthographicSize以及投影矩阵,保证正交/透视视图切换效果
            CalculateProjMatrix();
        }
    }

    #endregion

    #region 拖动

    private bool isDraging = false;
    private Vector3 lastMousePos;

    /// <summary>
    /// 拖动.
    /// </summary>
    /// <remark>长按鼠标中键拖动</remark>
    private void Drag()
    {
        // 鼠标中键拖动相机.
        if (middleMouseButton)
        {
            if (isDraging == false)
            {
                isDraging = true;
                // 设置小手指针.
                SetCursor(CursorType.HAND);

                lastMousePos = Input.mousePosition;
            }
            else
            {
                Vector3 newMousePos = Input.mousePosition;
                Vector3 delta = newMousePos - lastMousePos;
                m_Camera.transform.position += CalcDragLength(m_Camera, delta, distance);
                lastMousePos = newMousePos;

                // 相机移动,重新设置目标位置.
                ResetLookAroundPos();
            }
        }
        if (middleMouseButtonUp)
        {
            isDraging = false;
            // 恢复默认指针.
            SetCursor(CursorType.DEFAULT);
        }
    }

    /// <summary>
    /// 计算拖拽距离.
    /// </summary>
    /// <param name="camera">相机</param>
    /// <param name="mouseDelta">鼠标移动距离</param>
    /// <param name="distance">相机距离观察物体的距离</param>
    private Vector3 CalcDragLength(Camera camera, Vector2 mouseDelta, float distance)
    {
        float rectHeight = -1;
        float rectWidth = -1;
        if (camera.orthographic)
        {
            rectHeight = 2 * camera.orthographicSize;
            //rectWidth = rectHeight / camera.aspect;
        }
        else
        {
            rectHeight = 2 * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
        }
        rectWidth = Screen.width * rectHeight / Screen.height;
        Vector3 moveDir = -rectWidth / Screen.width * mouseDelta.x * camera.transform.right - rectHeight / Screen.height * mouseDelta.y * camera.transform.up;

        return moveDir;
    }

    #endregion

    #region 360°旋转观察

    /// <summary>
    /// 360°旋转查看.
    /// </summary>
    /// <remark>Alt+鼠标左键 或 鼠标右键</remark>
    private void LookAround()
    {
        if (leftAltKeyDown || rightAltKeyDown || rightMouseButtonDown)
        {
            SetCursor(CursorType.EYE);

            angle_X = m_Camera.transform.eulerAngles.y;
            angle_Y = m_Camera.transform.eulerAngles.x;
            angle_Z = m_Camera.transform.eulerAngles.z;
        }

        if ((leftAltKey && leftMouseButton)
            || (rightAltKey && leftMouseButton)
            || (!leftAltKey && !rightAltKey && rightMouseButton))
        {
            float deltaX = Input.GetAxis(MOUSEX);
            float deltaY = Input.GetAxis(MOUSEY);

            // 相机朝前和朝后,与鼠标的滑动方向相反
            if ((angle_Y > 90f && angle_Y < 270f) || (angle_Y < -90 && angle_Y > -270f))
            {
                angle_X -= deltaX * rotateSensitivity;
            }
            else
            {
                angle_X += deltaX * rotateSensitivity;
            }
            angle_Y -= deltaY * rotateSensitivity;

            angle_X = Utils.Math.ClampAngle(angle_X, -365, 365);
            angle_Y = Utils.Math.ClampAngle(angle_Y, -365, 365);

            SetCameraPos();
        }

        if (leftAltKeyUp || rightAltKeyUp || rightMouseButtonUp)
        {
            SetCursor(CursorType.DEFAULT);
        }
    }

    private void SetCameraPos()
    {
        Quaternion rotation = Quaternion.Euler(angle_Y, angle_X, angle_Z);
        Vector3 dir = Vector3.forward * -distance;
        m_Camera.transform.rotation = rotation;
        m_Camera.transform.position = lookAroundPos + rotation * dir;
    }

    #endregion

    #region 聚焦选中物体

    /// <summary>
    /// 聚焦选中物体.
    /// </summary>
    private void Focus()
    {
        if (leftMouseButtonDown)
        {
            Ray ray = m_Camera.ScreenPointToRay(Input.mousePosition);

            // Scene视图绘制射线方便测试.
            //Debug.DrawLine(ray.origin, ray.origin + ray.direction * raycastMaxDistance, Color.red, 3f);

            if (Physics.Raycast(ray, out raycastHit, raycastMaxDistance, raycastLayerMask))
            {
                selectedObj = raycastHit.collider.gameObject;
            }
            else
            {
                selectedObj = null;
                ResetLookAroundPos();
            }
        }

        if (selectedObj != null)
        {
            if (Input.GetKeyDown(KeyCode.F))
            {
                isFocusing = true;
                focusTime = 0f;
                cameraInitForward = m_Camera.transform.forward;
                focusTargetForward = Vector3.Normalize(selectedObj.transform.position - m_Camera.transform.position);

                focusInitPos = m_Camera.transform.position;
                distance = focusDistance;
                focusTargetPos = selectedObj.transform.position - focusTargetForward * distance;
            }
        }

        if (isFocusing)
        {
            focusTime += Time.deltaTime * focusSpeed;
            Vector3 forward = Vector3.Lerp(cameraInitForward, focusTargetForward, focusTime);
            m_Camera.transform.rotation = Quaternion.LookRotation(forward);

            m_Camera.transform.position = Vector3.Lerp(focusInitPos, focusTargetPos, focusTime);

            if (focusTime >= 1f)
            {
                // 聚焦完毕.
                focusTime = 0f;
                isFocusing = false;
                m_Camera.transform.rotation = Quaternion.LookRotation(focusTargetForward);
                m_Camera.transform.position = focusTargetPos;

                // 设置观察中心.
                lookAroundPos = selectedObj.transform.position;
            }
        }
    }

    #endregion

    #region 各种视图

    /// <summary>
    /// 正视图.
    /// </summary>
    private void Front()
    {
        angle_X = 180;
        angle_Y = 0;

        SetCameraPos();
    }

    /// <summary>
    /// 后视图.
    /// </summary>
    private void Back()
    {
        angle_X = 0;
        angle_Y = 0;

        SetCameraPos();
    }

    /// <summary>
    /// 右视图.
    /// </summary>
    private void Right()
    {
        angle_X = -90;
        angle_Y = 0;

        SetCameraPos();
    }

    /// <summary>
    /// 左视图.
    /// </summary>
    private void Left()
    {
        angle_X = 90;
        angle_Y = 0;

        SetCameraPos();
    }

    /// <summary>
    /// 上视图(俯视图).
    /// </summary>
    private void Top()
    {
        angle_X = 0;
        angle_Y = 90;

        SetCameraPos();
    }

    /// <summary>
    /// 下视图.
    /// </summary>
    private void Down()
    {
        angle_X = 0;
        angle_Y = -90;

        SetCameraPos();
    }

    #endregion

    #region 放大/缩小

    /// <summary>
    /// 放大缩小.
    /// </summary>
    private void Magnifier()
    {
        if ((leftAltKey || rightAltKey) && rightMouseButton)
        {
            if (lastMousePosFov.Equals(Vector3.zero))
            {
                lastMousePosFov = Input.mousePosition;
                SetCursor(CursorType.MAGNIFIER);
            }

            float deltaX = lastMousePosFov.x - Input.mousePosition.x;

            if (viewType == ViewType._2D)
            {
                // 透视视图改size
                float size = m_Camera.orthographicSize + deltaX * 0.01f;
                size = Mathf.Clamp(size, 1.0f, 8f);
                m_Camera.orthographicSize = size;

                // 调节size需同时修改相机透视模式下的fov
                SetFovBySize(size);
            }
            else
            {
                // 透视视图改fov
                float fov = m_Camera.fieldOfView + deltaX * fovSensitivity;
                fov = Mathf.Clamp(fov, minFov, maxFov);
                m_Camera.fieldOfView = fov;

                // 调节了fov需同时修改相机正交模式下的size
                SetSizeByFov(fov);
            }

            lastMousePosFov = Input.mousePosition;
        }

        if (rightMouseButtonUp)
        {
            SetCursor(CursorType.DEFAULT);
            lastMousePosFov = Vector3.zero;

            // 重新计算投影矩阵.
            CalculateProjMatrix();
        }
    }

    #endregion
}


  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值