public static void GetCullingPlanesAndSphere(out SPlanes planes, out AABB aabb, Matrix4x4 frustumMatrix, Matrix4x4 objTrans) { // From the objects that we are rendering from this camera. // Cull it further to the objects that overlap with the Projector frustum Matrix4x4 finalMatrix = frustumMatrix * objTrans; planes = ExtractProjectionPlanes(finalMatrix); aabb = ExtracetProjectionAABB(finalMatrix); }
static SPlanes ExtractProjectionPlanes(Matrix4x4 finalMatrix) { //https://www.zhihu.com/question/46377273/answer/101213293 SPlanes outPlanes = new SPlanes(); const int kPlaneFrustumLeft = 0; const int kPlaneFrustumRight = 1; const int kPlaneFrustumBottom = 2; const int kPlaneFrustumTop = 3; const int kPlaneFrustumNear = 4; const int kPlaneFrustumFar = 5; //const int kPlaneFrustumNum = 6; Vector4 tmpVec = new Vector4(); Vector4 otherVec = new Vector4(); tmpVec[0] = finalMatrix[3, 0]; tmpVec[1] = finalMatrix[3, 1]; tmpVec[2] = finalMatrix[3, 2]; tmpVec[3] = finalMatrix[3, 3]; otherVec[0] = finalMatrix[0, 0]; otherVec[1] = finalMatrix[0, 1]; otherVec[2] = finalMatrix[0, 2]; otherVec[3] = finalMatrix[0, 3]; // left & right outPlanes[kPlaneFrustumLeft] = NormalizeUnsafe(new Vector3(otherVec[0] + tmpVec[0], otherVec[1] + tmpVec[1], otherVec[2] + tmpVec[2]), otherVec[3] + tmpVec[3]); outPlanes[kPlaneFrustumRight] = NormalizeUnsafe(new Vector3(-otherVec[0] + tmpVec[0], -otherVec[1] + tmpVec[1], -otherVec[2] + tmpVec[2]), -otherVec[3] + tmpVec[3]); // bottom & top otherVec[0] = finalMatrix[1, 0]; otherVec[1] = finalMatrix[1, 1]; otherVec[2] = finalMatrix[1, 2]; otherVec[3] = finalMatrix[1, 3]; outPlanes[kPlaneFrustumBottom] = NormalizeUnsafe(new Vector3(otherVec[0] + tmpVec[0], otherVec[1] + tmpVec[1], otherVec[2] + tmpVec[2]), otherVec[3] + tmpVec[3]); outPlanes[kPlaneFrustumTop] = NormalizeUnsafe(new Vector3(-otherVec[0] + tmpVec[0], -otherVec[1] + tmpVec[1], -otherVec[2] + tmpVec[2]), -otherVec[3] + tmpVec[3]); otherVec[0] = finalMatrix[2, 0]; otherVec[1] = finalMatrix[2, 1]; otherVec[2] = finalMatrix[2, 2]; otherVec[3] = finalMatrix[2, 3]; // near & far outPlanes[kPlaneFrustumNear] = NormalizeUnsafe(new Vector3(otherVec[0] + tmpVec[0], otherVec[1] + tmpVec[1], otherVec[2] + tmpVec[2]), otherVec[3] + tmpVec[3]); outPlanes[kPlaneFrustumFar] = NormalizeUnsafe(new Vector3(-otherVec[0] + tmpVec[0], -otherVec[1] + tmpVec[1], -otherVec[2] + tmpVec[2]), -otherVec[3] + tmpVec[3]); return(outPlanes); }
bool IntersectAABBPlaneBounds(AABB a, SPlanes ps) { Vector3 m = a.m; // GetCenter(a.Min, a.Max);// a.GetCenter();// center of AABB Vector3 extent = a.extent; // GetExtent(a.Min, a.Max);//a.GetExtent();// half-diagonal for (int i = 0; i < 6; ++i) { Plane p = ps[i]; Vector3 normal = p.normal; float dist = p.GetDistanceToPoint(m); float radius = Vector3.Dot(extent, new Vector3(Mathf.Abs(normal.x), Mathf.Abs(normal.y), Mathf.Abs(normal.z))); if (dist + radius <= 0) { return(false); // behind clip plane } } return(true); // AABB intersects space bounded by planes }
bool RightParallelepipedInFrustum(Vector4 Min, Vector4 Max, SPlanes frustum_planes) { bool inside = true; //试视锥体的6个平面。 for (int i = 0; i < 6; i++) { //从8点找到最靠近平面的那个点,然后测试它是否在平面之后。 //如果是的话 - 那么对象不在视锥体的内部。 float d = Mathf.Max(Min.x * frustum_planes[i].normal.x, Max.x * frustum_planes[i].normal.x) + Mathf.Max(Min.y * frustum_planes[i].normal.y, Max.y * frustum_planes[i].normal.y) + Mathf.Max(Min.z * frustum_planes[i].normal.z, Max.z * frustum_planes[i].normal.z) + frustum_planes[i].distance; inside &= d > 0; //return false; //with flag works faster } return(inside); }