一种3D空间的柱状多边形检测实现
最近无意中拓展出这个东西,基于之前写的2D多边形检测:
http://www.cnblogs.com/hont/p/6105997.html
而判断两条线相交的方法替换成了我后来写的差乘判断:
http://www.cnblogs.com/hont/p/6106043.html
该功能在多边形选区与地形处理上应用较广泛
代码实现:
using UnityEngine; public class Test : MonoBehaviour { public Transform testComparePoint;//比较点 public Transform[] pointsArray;//比较多边形每个点 public float height = 4;//比较多边形高度 public bool IsInRange(Vector3 comparePoint) { Vector3 localComparePoint = transform.worldToLocalMatrix.MultiplyPoint3x4(comparePoint); //将比较点从世界转本地空间 bool flag = true; flag &= localComparePoint.y <= height; flag &= localComparePoint.y >= -height; flag &= IsConcaveContain2D(pointsArray, localComparePoint); if (flag) return true; return false; } public bool IsConcaveContain2D(Transform[] points, Vector3 compare) { const float kVirtualRaycastLen = 100000f; Vector3 comparePoint = (points[1].localPosition + points[0].localPosition) * 0.5f; Vector3 originPoint = compare; comparePoint += (comparePoint - originPoint).normalized * kVirtualRaycastLen; int count = 0; for (int i = 0; i < points.Length; i++) { Transform a = points[i % points.Length]; Transform b = points[(i + 1) % points.Length]; bool r = IsLineSegmentIntersection(a.localPosition, b.localPosition, originPoint, comparePoint); if (r) count++; } return count % 2 == 1; } //判断ab与cd线段是否相交 public bool IsLineSegmentIntersection(Vector3 a, Vector3 b, Vector3 c, Vector3 d) { float crossA = Vector3.Cross(d - c, a - c).y; float crossB = Vector3.Cross(d - c, b - c).y; if (!(crossA > 0f ^ crossB > 0f)) return false; float crossC = Vector3.Cross(b - a, c - a).y; float crossD = Vector3.Cross(b - a, d - a).y; if (!(crossC > 0f ^ crossD > 0f)) return false; return true; } private void OnDrawGizmos() { if (pointsArray == null) return; if (testComparePoint) { Vector3 comparePoint = testComparePoint.transform.position; if (IsInRange(comparePoint)) Gizmos.color = Color.red; } Gizmos.matrix = transform.localToWorldMatrix; for (int i = 0; i < pointsArray.Length; i++) { Transform a = pointsArray[i]; Transform b = pointsArray[(i + 1) % pointsArray.Length]; if (!a || !b) continue; Vector3 minA = a.localPosition; Vector3 minB = b.localPosition; Vector3 maxA = a.localPosition; Vector3 maxB = b.localPosition; minA.y = -height; minB.y = -height; maxA.y = height; maxB.y = height; Gizmos.DrawLine(minA, minB); Gizmos.DrawLine(maxA, maxB); Gizmos.DrawLine(minA, maxA); Gizmos.DrawLine(minB, maxB); } } }