设置相机朝向对象,并设置最佳观察的视野

Posted kingbook

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设置相机朝向对象,并设置最佳观察的视野相关的知识,希望对你有一定的参考价值。

LookToObject.cs绑定到Camera上

using UnityEngine;
/// <summary>
/// 设置相机朝向对象,并设置最佳观察的视野
/// </summary>
public class LookToObject:MonoBehaviour
    [Tooltip("相机所拍摄的对象")]
    public GameObject target;
    private MeshRenderer _targetMeshRenderer;
    private Camera _camera;

    private Vector3[] _points;
    private Vector3 _planeCenter;

    private void Start()
        _targetMeshRenderer=target.GetComponent<MeshRenderer>();
        _camera=GetComponent<Camera>();
    

    private void Update()
        //相机旋转朝向目标对象
        Bounds bounds=_targetMeshRenderer.bounds;
        Vector3 boundsCenter=bounds.center;
        _camera.transform.LookAt(boundsCenter);
        //包围盒角点
        Vector3[] points=getBoundsCorners(boundsCenter,bounds.extents);
        //所有角点投射到平面
        Vector3 planeNormal=boundsCenter-_camera.transform.position;
        worldPointsToPlane(points,points.Length,planeNormal);
        _points=points;
        //平面中心
        Vector3 planeCenter=Vector3.ProjectOnPlane(boundsCenter,planeNormal);
        _planeCenter=planeCenter;
        //取平面上各个点与平面中心的最大距离作为相机的视野矩形框大小
        float halfHeight=getMaxDistanceToPlaneCenter(points,points.Length,planeCenter);
        //相机与包围盒中心的距离(世界坐标为单位)
        float distance=Vector3.Distance(boundsCenter,_camera.transform.position);
        //得到视野大小
        _camera.fieldOfView=Mathf.Atan2(halfHeight,distance)*Mathf.Rad2Deg*2;  
    
    
    /// <summary>
    /// 返回包围盒的角点列表
    /// </summary>
    /// <param name="boundsCenter">包围盒的中心</param>
    /// <param name="boundsExtents">Bounds.extents</param>
    /// <returns></returns>
    private Vector3[] getBoundsCorners(Vector3 boundsCenter,Vector3 boundsExtents)
        Vector3[] vertices=new Vector3[8];
        //左下后
        vertices[0]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(-1,-1,-1));
        //左上后
        vertices[1]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(-1,1,-1));
        //右上后
        vertices[2]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(1,1,-1));
        //右下后
        vertices[3]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(1,-1,-1));

        //左下前
        vertices[4]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(-1,-1,1));
        //左上前
        vertices[5]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(-1,1,1));
        //右上前
        vertices[6]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(1,1,1));
        //右下前
        vertices[7]=boundsCenter+Vector3.Scale(boundsExtents,new Vector3(1,-1,1));
        return vertices;
    
    
    /// <summary>
    /// 将世界坐标点数组投射到以原点为中心的平面
    /// </summary>
    /// <param name="points">世界坐标点数组</param>
    /// <param name="pointCount">坐标点数量</param>
    /// <param name="planeNormal">平面法线</param>
    /// <returns></returns>
    private Vector3[] worldPointsToPlane(Vector3[] points,int pointCount,Vector3 planeNormal)
        for(int i=0;i<pointCount;i++)
            var vertex=points[i];
            points[i]=Vector3.ProjectOnPlane(vertex,planeNormal);
        
        return points;
    
    
    /// <summary>
    /// 返回平面上各个点与平面中心的最大距离
    /// </summary>
    /// <param name="points">平面上的各个点</param>
    /// <param name="pointCount">点数量</param>
    /// <param name="planeCenter">平面中心</param>
    /// <returns></returns>
    private float getMaxDistanceToPlaneCenter(Vector3[] points,int pointCount,Vector3 planeCenter)
        float maxDistance=float.MinValue;
        for(int i=0;i<pointCount;i++)
            var vertex=points[i];
            float distance=Vector3.Distance(vertex,planeCenter);
            if(distance>maxDistance)maxDistance=distance;
        
        return maxDistance;
    
    
    private void OnDrawGizmos()
        if(Application.isPlaying)
            if(_points!=null)
               drawPath(_points);
            
            drawPoint(_planeCenter,0.02f);
        
    
    
    /// <summary>
    /// 根据路径点数组画线
    /// </summary>
    /// <param name="vertices">路径点数组</param>
    private void drawPath(Vector3[] vertices)
        int len=vertices.Length;
        for (int i=0;i<len;i++)
            int nexti=(i+1)%len;
            Gizmos.DrawLine(vertices[i],vertices[nexti]);
        
    

    /// <summary>
    /// 用一个球体线框画一个点
    /// </summary>
    /// <param name="point">点位置</param>
    /// <param name="radius">球体线框半径</param>
    private void drawPoint(Vector3 point,float radius=0.02f)
        Gizmos.DrawWireSphere(point,radius);
    

    

以上是关于设置相机朝向对象,并设置最佳观察的视野的主要内容,如果未能解决你的问题,请参考以下文章

Android中的相机,如何获得最佳尺寸,预览尺寸,图片尺寸,视图尺寸,图像失真

设置可以注入的填充对象的最佳方法是啥?

js创建对象的最佳方式

iphone手机复制视频到电脑显示连接的设备没有发挥作用是怎么回事

为 UITableView 设置数据源和委托的最佳实践

使用opencv和覆盆子相机模块进行人脸检测的最佳算法是啥