目前实现了两种方法:
1、将bound的点从世界坐标系转到摄像机视口坐标系vecA,其中摄像机所见视口坐标的范围是vecB(0-1,0-1,0-farClipPlane),比较vecA的xyz是否在vecB中即可
2、将bound的点从世界坐标系转到摄像机投影坐标系vecA,投影坐标系是vector4(x,y,z,w),投影坐标的xyz/w可得到NDC坐标系,摄像机可见的NDC坐标系范围是(-1~1,-1~1,-1~1),那么摄像机可见的投影坐标系范围是vecB(-w~w,-w~w,-w~w),比较vecA的xyz是否在vecB的中即可
两种方法大同小异,都是转换到某个容易得到摄像机范围的坐标系,然后进行比较
第二个方法比较优,比第一个方法少了几次坐标系转换
代码:
第一种方法:
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public static class TestExpand 6 { 7 /// <summary> 8 /// 检查一个世界坐标系下的点是否在摄像机可见范围内 9 /// </summary> 10 /// <param name="camera"></param> 11 /// <param name="worldPos"></param> 12 /// <returns></returns> 13 public static bool CheckPointIsInCamera(this Camera camera, Vector3 worldPos) 14 { 15 Vector3 viewPos = camera.WorldToViewportPoint(worldPos); 16 //Debug.Log(worldPos+" "+viewPos); 17 if(viewPos.x<0 || viewPos.x>1 || viewPos.y<0 || viewPos.y > 1 || viewPos.z<0 || viewPos.z>camera.farClipPlane) 18 { 19 return false; 20 } 21 return true; 22 } 23 24 /// <summary> 25 /// 检查bound某个点是否在摄像机可见范围内 26 /// </summary> 27 /// <param name="bound"></param> 28 /// <param name="camera"></param> 29 /// <returns></returns> 30 public static bool CheckBoundIsInCamera(this Bounds bound, Camera camera) 31 { 32 Vector4 worldPos = Vector4.one; 33 for (int i = -1; i <= 1; i += 2) 34 { 35 for (int j = -1; j <= 1; j += 2) 36 { 37 for (int k = -1; k <= 1; k += 2) 38 { 39 worldPos.x = bound.center.x + i * bound.extents.x; 40 worldPos.y = bound.center.y + j * bound.extents.y; 41 worldPos.z = bound.center.z + k * bound.extents.z; 42 if (camera.CheckPointIsInCamera(worldPos)) 43 { 44 return true; 45 } 46 47 } 48 } 49 } 50 return false; 51 } 52 }
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 6 public class Test : MonoBehaviour 7 { 8 private GameObject cube; 9 private Bounds bound; 10 private Camera mCamera; 11 12 void Start() 13 { 14 cube = GameObject.Find("Cube"); 15 bound = cube.GetComponent<MeshRenderer>().bounds; 16 mCamera = GetComponent<Camera>(); 17 } 18 19 void Update() 20 { 21 if (Input.GetKeyDown(KeyCode.Q)) 22 { 23 Debug.Log(bound.CheckBoundIsInCamera(mCamera)); 24 } 25 26 } 27 28 private void OnDrawGizmos() 29 { 30 bound.DrawBounds(Color.red); 31 } 32 }
第二种方法(和上面代码一样,只是判断点是否在摄像机内的方法改变)
1 public static bool CheckPointIsInCamera(this Camera camera, Vector4 worldPos) 2 { 3 Vector4 projectionPos = camera.projectionMatrix * camera.worldToCameraMatrix * worldPos; 4 if(projectionPos.x < -projectionPos.w || projectionPos.x > projectionPos.w || 5 projectionPos.y < -projectionPos.w || projectionPos.y > projectionPos.w || 6 projectionPos.z < -projectionPos.w || projectionPos.z > projectionPos.w) 7 { 8 return false; 9 } 10 return true; 11 }
内容来源于网络如有侵权请私信删除
- 还没有人评论,欢迎说说您的想法!