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); }
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); }
// 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); }