コード例 #1
0
        public static OrientedBBox Create(Transform t)
        {
            OrientedBBox obb = new OrientedBBox();

            obb.center  = t.position;
            obb.right   = t.right;
            obb.up      = t.up;
            obb.extentX = 0.5f * t.localScale.x;
            obb.extentY = 0.5f * t.localScale.y;
            obb.extentZ = 0.5f * t.localScale.z;

            return(obb);
        }
コード例 #2
0
        public static OrientedBBox Create(Transform t)
        {
            OrientedBBox obb = new OrientedBBox();

            Vector3 vecX = t.localToWorldMatrix.GetColumn(0);
            Vector3 vecY = t.localToWorldMatrix.GetColumn(1);
            Vector3 vecZ = t.localToWorldMatrix.GetColumn(2);

            obb.center = t.position;
            obb.right  = vecX * (1.0f / vecX.magnitude);
            obb.up     = vecY * (1.0f / vecY.magnitude);

            obb.extentX = 0.5f * vecX.magnitude;
            obb.extentY = 0.5f * vecY.magnitude;
            obb.extentZ = 0.5f * vecZ.magnitude;

            return(obb);
        }
コード例 #3
0
        // Returns 'true' if the OBB intersects (or is inside) the frustum, 'false' otherwise.
        public static bool Overlap(OrientedBBox obb, Frustum frustum, int numPlanes, int numCorners)
        {
            bool overlap = true;

            // Test the OBB against frustum planes. Frustum planes are inward-facing.
            // The OBB is outside if it's entirely behind one of the frustum planes.
            // See "Real-Time Rendering", 3rd Edition, 16.10.2.
            for (int i = 0; overlap && i < numPlanes; i++)
            {
                Vector3 n = frustum.planes[i].normal;
                float   d = frustum.planes[i].distance;

                // Max projection of the half-diagonal onto the normal (always positive).
                float maxHalfDiagProj = obb.extentX * Mathf.Abs(Vector3.Dot(n, obb.right))
                                        + obb.extentY * Mathf.Abs(Vector3.Dot(n, obb.up))
                                        + obb.extentZ * Mathf.Abs(Vector3.Dot(n, obb.forward));

                // Positive distance -> center in front of the plane.
                // Negative distance -> center behind the plane (outside).
                float centerToPlaneDist = Vector3.Dot(n, obb.center) + d;

                // outside = maxHalfDiagProj < -centerToPlaneDist
                // outside = maxHalfDiagProj + centerToPlaneDist < 0
                // overlap = overlap && !outside
                overlap = overlap && (maxHalfDiagProj + centerToPlaneDist >= 0);
            }

            if (numCorners == 0)
            {
                return(overlap);
            }

            // Test the frustum corners against OBB planes. The OBB planes are outward-facing.
            // The frustum is outside if all of its corners are entirely in front of one of the OBB planes.
            // See "Correct Frustum Culling" by Inigo Quilez.
            // We can exploit the symmetry of the box by only testing against 3 planes rather than 6.
            Plane[] planes = new Plane[3];

            planes[0].normal   = obb.right;
            planes[0].distance = obb.extentX;
            planes[1].normal   = obb.up;
            planes[1].distance = obb.extentY;
            planes[2].normal   = obb.forward;
            planes[2].distance = obb.extentZ;

            for (int i = 0; overlap && i < 3; i++)
            {
                Plane plane = planes[i];

                // We need a separate counter for the "box fully inside frustum" case.
                bool outsidePos = true; // Positive normal
                bool outsideNeg = true; // Reversed normal

                // Merge 2 loops. Continue as long as all points are outside either plane.
                for (int j = 0; j < numCorners; j++)
                {
                    float proj = Vector3.Dot(plane.normal, frustum.corners[j] - obb.center);
                    outsidePos = outsidePos && (proj > plane.distance);
                    outsideNeg = outsideNeg && (-proj > plane.distance);
                }

                overlap = overlap && !(outsidePos || outsideNeg);
            }

            return(overlap);
        }