鸟语天空
生成FOV裁剪面
post by:追风剑情 2019-10-22 19:54

一、工程截图

222.png

FOVPlane.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[DisallowMultipleComponent]
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class FOVPlane : MonoBehaviour
{
    [SerializeField]
    private Camera m_Camera;
    private Vector3 m_CameraPosition;
    private MeshFilter m_MeshFilter;
    private Vector3[] m_Corners;
    private Transform m_Transform;
    private bool m_Flip;//画面上下翻转

    void Awake()
    {
        if (m_Camera == null)
            m_Camera = Camera.main;
        if (m_Camera != null)
            m_CameraPosition = m_Camera.transform.position;
        m_MeshFilter = this.GetComponent<MeshFilter>();
        m_Transform = transform;
    }

    void Start()
    {
        MeshRectangle();

        m_Transform.position = Vector3.zero;
        m_Transform.rotation = Quaternion.identity;
        m_Transform.localScale = Vector3.one;
    }

    // 创建一个矩形
    void MeshRectangle()
    {
        float distance = transform.position.z - m_CameraPosition.z;
        m_Corners = GetCameraFovPositionByDistance(m_Camera, distance);

        //矩形的四个顶点坐标
        Vector3[] vertices = new Vector3[4];
        vertices[0] = m_Corners[0];
        vertices[1] = m_Corners[1];
        vertices[2] = m_Corners[2];
        vertices[3] = m_Corners[3];

        //三角形顶点索引
        int[] triangles = new int[6] { 0, 1, 2, 1, 3, 2 };

        //每个顶点的法线
        Vector3[] normals = new Vector3[4];
        normals[0] = Vector3.back;
        normals[1] = Vector3.back;
        normals[2] = Vector3.back;
        normals[3] = Vector3.back;

        //UV贴图坐标
        Vector2[] uvs = new Vector2[4];
        if (m_Flip)
        {
            uvs[0] = new Vector2(0, 1);
            uvs[1] = new Vector2(1, 1);
            uvs[2] = new Vector2(0, 0);
            uvs[3] = new Vector2(1, 0);
        }
        else
        {
            uvs[0] = new Vector2(0, 0);
            uvs[1] = new Vector2(1, 0);
            uvs[2] = new Vector2(0, 1);
            uvs[3] = new Vector2(1, 1);
        }

        //顶点颜色
        Color32[] colors32 = new Color32[4];
        colors32[0] = Color.white;
        colors32[1] = Color.white;
        colors32[2] = Color.white;
        colors32[3] = Color.white;

        Mesh mesh = new Mesh();
        mesh.hideFlags = HideFlags.DontSave;
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.colors32 = colors32;
        mesh.uv = uvs;
        mesh.normals = normals;

        m_MeshFilter.mesh = mesh;
    }

    /// <summary>
    /// 转载 https://www.cnblogs.com/shanksyi/p/5634060.html
    /// 获取指定距离下相机视口四个角的坐标
    /// </summary>
    /// <param name="cam"></param>
    /// <param name="distance">相对于相机的距离</param>
    /// <returns></returns>
    public Vector3[] GetCameraFovPositionByDistance(Camera cam, float distance)
    {
        Vector3[] corners = new Vector3[4];

        float halfFOV = (cam.fieldOfView * 0.5f) * Mathf.Deg2Rad;
        float aspect = cam.aspect;

        float height = distance * Mathf.Tan(halfFOV);
        float width = height * aspect;

        Transform tx = cam.transform;

        // 左上角
        corners[0] = tx.position - (tx.right * width);
        corners[0] += tx.up * height;
        corners[0] += tx.forward * distance;

        // 右上角
        corners[1] = tx.position + (tx.right * width);
        corners[1] += tx.up * height;
        corners[1] += tx.forward * distance;

        // 左下角
        corners[2] = tx.position - (tx.right * width);
        corners[2] -= tx.up * height;
        corners[2] += tx.forward * distance;

        // 右下角
        corners[3] = tx.position + (tx.right * width);
        corners[3] -= tx.up * height;
        corners[3] += tx.forward * distance;

        return corners;
    }

    void Update()
    {
        if (m_Corners == null)
            return;

        for (int i = 0; i < m_Corners.Length; i++)
        {
            Debug.DrawLine(m_CameraPosition, m_Corners[i], Color.red);
        }
    }
}


二、运行测试

1111.png

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容