目前实现了两种方法:

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 }
View Code
 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 }
View Code

 

第二种方法(和上面代码一样,只是判断点是否在摄像机内的方法改变)

 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     }
View Code

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!