您的位置:首页 > 移动开发 > Unity3D

Unity3D正交相机包围盒计算方式

2020-12-01 15:35 1441 查看

Unity中的相机大家肯定都十分熟悉,主要有两种摄像机,即透视摄像机(Perspective)和正交摄像机(Orthographic)。
正交相机适用于做2D用途。正交相机有两个特别的属性Size和Aspect;

Size:正交摄像机显示高度
Aspect:摄像机显示区域的宽、高比

根据上面属性可以计算正交相机渲染画面的大小:

camera.height=camera.orthographicSize*2f

camera.width=camera.height*camera.aspect

包围盒算法是一种求离散点集最优包围空间的方法,基本思想就是用体积稍大且特性简单的几何体(包围盒)来近似地代替复杂的集合对象。
如下图,三个物体的包围盒。

计算方案:

  1. 求得物体(组)的正交投影范围;
  2. 移动正交相机到物体组上方的中心位置,并自动调整Size。

Unity中的包围盒用结构体——Bounds来表示

public GameObject obj;//要包围的物体
public Camera setCamera;//正交相机
public float ScreenScaleFactor;//占屏比例系数
private void Start()
{
var bound = GetBoundPointsByObj(obj);
var center = bound.center;
var extents = bound.extents;
setCamera.transform.position = new Vector3(center.x, center.y, center.z - 10);
SetOrthCameraSize(center.x - extents.x, center.x + extents.x, center.y - extents.y, center.y + extents.y);
}

计算所有物体包围盒:(求得最终包围盒的中心点,然后再从中心点开始逐步向外计算包围盒,bounds.Encapsulate(Bounds bounds)即为扩大包围盒函数。)

/// <summary>
/// 获取物体包围盒
/// </summary>
/// <param name="obj">父物体</param>
/// <returns>物体包围盒</returns>
private Bounds GetBoundPointsByObj(GameObject obj)
{
var bounds = new Bounds();
if (obj != null)
{
var renders = obj.GetComponentsInChildren<Renderer>();
if (renders != null)
{
var boundscenter = Vector3.zero;
foreach (var item in renders)
{
boundscenter += item.bounds.center;
}
if (obj.transform.childCount > 0)
boundscenter /= obj.transform.childCount;
bounds = new Bounds(boundscenter, Vector3.zero);
foreach (var item in renders)
{
bounds.Encapsulate(item.bounds);
}
}
}
return bounds;
}

相机若要在该物体组的中心点处:(下面为注释代码)

camera.position = new Vector3(bound.center.x, bound.center.y, bound.center.z+k);

设置正交相机的Size:

/// <summary>
/// 设置正交相机的Size
/// </summary>
/// <param name="xmin">包围盒x方向最小值</param>
/// <param name="xmax">包围盒x方向最大值</param>
/// <param name="ymin">包围盒y方向最小值</param>
/// <param name="ymax">包围盒y方向最大值</param>
private void SetOrthCameraSize(float xmin, float xmax, float ymin, float ymax)
{
float xDis = xmax - xmin;
float yDis = ymax - ymin;
float sizeX = xDis / ScreenScaleFactor / 2 / SetCamera.aspect;
float sizeY = yDis / ScreenScaleFactor / 2;
if (sizeX >= sizeY)
setCamera.orthographicSize = sizeX;
else
setCamera.orthographicSize = sizeY;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: