Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }