Unity获取摄像机在某个平面上的视野范围

这是已知平面上的一个点和平面的法线的情况下,求摄像机在平面看到的视野范围,下图绿色的框框就是了。

效果:

代码:

  1 using UnityEngine;
  2 using System.Collections;
  3 using System;
  4
  5 public class CameraPlaneView : MonoBehaviour
  6 {
  7     #region for debug
  8     public Camera viewCamera;
  9
 10     void Update()
 11     {
 12         Vector3[] corners;
 13         if(GetPlaneCorners(Vector3.up, Vector3.zero, viewCamera, out corners))
 14         {
 15             Debug.DrawLine(corners[0], corners[1], Color.green);    // bottom
 16             Debug.DrawLine(corners[1], corners[2], Color.green);    // right
 17             Debug.DrawLine(corners[2], corners[3], Color.green);    // top
 18             Debug.DrawLine(corners[3], corners[0], Color.green);    // left
 19         }
 20     }
 21     #endregion
 22
 23
 24     /// <summary>
 25     /// 获取摄像机在平面上的视野范围的4个角的顶点
 26     /// </summary>
 27     /// <param name="normal">平面法线</param>
 28     /// <param name="planePoint">平面上的一点</param>
 29     /// <param name="camera">摄像机</param>
 30     /// <param name="corners">返回4个角的顺序:左下、右下、右上、左上</param>
 31     /// <returns>摄像机与平面是否完全相交</returns>
 32     public static bool GetPlaneCorners(Vector3 normal, Vector3 planePoint,Camera camera, out Vector3[] corners)
 33     {
 34         Plane plane = new Plane(normal, planePoint);
 35         return GetPlaneCorners(ref plane, camera, out corners);
 36     }
 37
 38     /// <summary>
 39     /// 获取摄像机在平面上的视野范围的4个角的顶点
 40     /// </summary>
 41     /// <param name="plane">平面结构体</param>
 42     /// <param name="camera">摄像机</param>
 43     /// <param name="corners">返回4个角的顺序:左下、右下、右上、左上</param>
 44     /// <returns>摄像机与平面是否完全相交</returns>
 45     public static bool GetPlaneCorners(ref Plane plane, Camera camera, out Vector3[] corners)
 46     {
 47         Ray rayBL = camera.ViewportPointToRay(new Vector3(0, 0, 1));     // bottom left
 48         Ray rayBR = camera.ViewportPointToRay(new Vector3(1, 0, 1));     // bottom right
 49         Ray rayTL = camera.ViewportPointToRay(new Vector3(0, 1, 1));     // top left
 50         Ray rayTR = camera.ViewportPointToRay(new Vector3(1, 1, 1));     // top right
 51
 52         corners = new Vector3[4];
 53         if (!GetRayPlaneIntersection(ref plane, rayBL, out corners[0])
 54             || !GetRayPlaneIntersection(ref plane, rayBR, out corners[1])
 55             || !GetRayPlaneIntersection(ref plane, rayTR, out corners[2])
 56             || !GetRayPlaneIntersection(ref plane, rayTL, out corners[3]))
 57         {
 58             return false;
 59         }
 60         else
 61         {
 62             return true;
 63         }
 64     }
 65
 66     /// <summary>
 67     /// 获取平面与射线的交点
 68     /// </summary>
 69     /// <param name="plane">平面结构体</param>
 70     /// <param name="ray">射线</param>
 71     /// <param name="intersection">返回交点</param>
 72     /// <returns>是否相交</returns>
 73     public static bool GetRayPlaneIntersection(ref Plane plane, Ray ray, out Vector3 intersection)
 74     {
 75         float enter;
 76         if(!plane.Raycast(ray, out enter))
 77         {
 78             intersection = Vector3.zero;
 79             return false;
 80         }
 81
 82         // 下面是获取t的公式
 83         // 注意,你需要先判断射线与平面是否平行,如果平面和射线平行,那么平面法线和射线方向的点积为0,即除数为0.
 84         //float t = (Vector3.Dot(normal, planePoint) - Vector3.Dot(normal, ray.origin)) / Vector3.Dot(normal, ray.direction.normalized);
 85         if (enter >= 0)
 86         {
 87             intersection = ray.origin + enter * ray.direction.normalized;
 88             return true;
 89         }
 90         else
 91         {
 92             intersection = Vector3.zero;
 93             return false;
 94         }
 95     }
 96
 97     /// <summary>
 98     /// 获取平面与射线的交点
 99     /// </summary>
100     /// <param name="normal">平面法线</param>
101     /// <param name="planePoint">平面上的一点</param>
102     /// <param name="ray">射线</param>
103     /// <param name="intersection">返回交点</param>
104     /// <returns>是否相交</returns>
105     public static bool GetRayPlaneIntersection(Vector3 normal, Vector3 planePoint, Ray ray, out Vector3 intersection)
106     {
107         Plane plane = new Plane(normal, planePoint);
108         return GetRayPlaneIntersection(ref plane, ray, out intersection);
109     }
110 }
时间: 2024-12-20 10:37:35

Unity获取摄像机在某个平面上的视野范围的相关文章

[Unity菜鸟] 摄像机

1.摄像机围绕物体旋转 using UnityEngine; using System.Collections; public class CameraVirtual : MonoBehaviour { //旋转的物体 public GameObject building; //用来记录鼠标的位置,以便计算旋转幅度 Vector2 p1, p2; // Update is called once per frame void Update() { if (Input.GetMouseButton

threejs 限制物件只能在指定平面上拖拽

threejs提供有 DragController.js的例子来辅助拖拽 该例子可以在基于当前屏幕的x和y轴上拖拽物体,但是它不能影响z轴. 查看代码,可以在touchStart\mousedown下找到下述代码: _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _worldPosition.setFromMatrixPosition( _selected.matrixWorld

Problem A: 平面上的点——Point类 (III)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法,输出各Point对象的构造和析构次序.实现showPoint()函数. 接口描述: showPoint()函数按输出格式输出Point对象,调用Point::show()方法实现. Point::show()方法:按输出格式输出Point对象. I

Unity 获取网络北京时间

最近在做的单机,由于需要获得网络时间,搜了很多Unity获取网络服务器的代码,大多数不是接口已经失效就是代码过于繁琐.(心中满满的吐槽)直接放代码 获取网页内容后是 0=跟一个15位时间戳.需要自己转换成时间格式.

POJ C程序设计进阶 编程题#4:寻找平面上的极大点

编程题#4:寻找平面上的极大点 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 在一个平面上,如果有两个点(x,y),(a,b),如果说(x,y)支配了(a,b),这是指x>=a,y>=b; 用图形来看就是(a,b)坐落在以(x,y)为右上角的一个无限的区域内. 给定n个点的集合,一定存在若干个点,它们不会被集合中的任何一点所支配,这些点叫做极大值点. 编程找出所有的极大

Problem E: 平面上的点——Point类 (II)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法,输出各Point对象的构造和析构次序. 接口描述: Point::show()方法:按输出格式输出Point对象. Input 输入多行,每行为一组坐标"x,y",表示点的x坐标和y坐标,x和y的值都在double数据范围内.

Problem A: 平面上的点和线——Point类、Line类 (I)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定,两点确定一条线段.现在我们封装一个"Point类"和"Line类"来实现平面上的点的操作. 根据"append.cc",完成Point类和Line类的构造方法和show()方法. 接口描述: Point::show()方法:按格式输出Point对象. Line::show()方法:按格式输出Line对象. Input 输入的第一行为N,表示后面有N行测试样例

Problem D: 平面上的点——Point类 (I)

Description 在数学上,平面直角坐标系上的点用X轴和Y轴上的两个坐标值唯一确定.现在我们封装一个"Point类"来实现平面上的点的操作. 根据"append.cc",完成Point类的构造方法和show()方法. 接口描述: Point::show()方法:按输出格式输出Point对象. Input 输入多行,每行为一组坐标"x,y",表示点的x坐标和y坐标,x和y的值都在double数据范围内. Output 输出为多行,每行为一个点

uva10245-The Closest Pair Problem(平面上的点分治)

解析:平面上的点分治,先递归得到左右子区间的最小值d,再处理改区间,肯定不会考虑哪些距离已经大于d的点对,对y坐标归并排序,然后从小到大开始枚举更新d,对于某个点,x轴方向只用考虑[x-d,x+d](x是分的中轴线),y轴方向只用考虑[y-d,y](y是这个点的y值),因为d值一直在变小,所以这个矩形包含的点数很少. 代码 #include<cstdio> #include<cstring> #include<string> #include<vector>