#include "VssRay.h" #include "Beam.h" void Beam::Construct(const AxisAlignedBox3 &box, const AxisAlignedBox3 &dBox) { // the frustum is defined by set of negative halfspace described by mPlanes // construct Vector3 center = box.Center(); Vector3 dCenter = dBox.Center(); // "back plane" mPlanes.push_back(Plane3(-VssRay::GetDirection(dCenter.x, dCenter.y), center)); Vector3 directions[4]; directions[0] = VssRay::GetDirection(dBox.Min().x, dBox.Min().y); directions[1] = VssRay::GetDirection(dBox.Max().x, dBox.Min().y); directions[2] = VssRay::GetDirection(dBox.Max().x, dBox.Max().y); directions[3] = VssRay::GetDirection(dBox.Min().x, dBox.Max().y); // side planes mPlanes.push_back(Plane3(CrossProd(directions[0], directions[1]), center)); mPlanes.push_back(Plane3(CrossProd(directions[1], directions[2]), center)); mPlanes.push_back(Plane3(CrossProd(directions[2], directions[3]), center)); mPlanes.push_back(Plane3(CrossProd(directions[3], directions[0]), center)); // now make sure all planes contain the spatial box int i, j; for (i=0; i < mPlanes.size(); i++) { for (j=0; j < 8; j++) { float dist = mPlanes[i].Distance(box.GetVertex(j)); if (dist > 0) mPlanes[i].mD -= dist; } } mBox = box; mDirBox = dBox; SetValid(); } // conservative frustum box intersection // returns // 0 - box intersects the frustum // -1 - box intersects the frustum and is fully inside // 1 - box does not intersect the frustum int Beam::ComputeIntersection(const AxisAlignedBox3 &box) { int i; int result = -1; for (i=0; i < mPlanes.size(); i++) { int side = box.Side(mPlanes[i]); if (side == 1) return 1; if (side > result) result = side; } return result; } void Beam::ComputeFrustum(float &left, float &right, float &bottom, float &top, float &near, float &far, const AxisAlignedBox3 &sceneBBox) const { const float xDirRange = mDirBox.Max().x - mDirBox.Min().x; const float yDirRange = mDirBox.Max().y - mDirBox.Min().y; near = 0.1; // NOTE: what is the best value for near and far plane? far = 2.0f * Magnitude(sceneBBox.Diagonal()); left = near / tan(xDirRange * 0.5); right = near / tan(xDirRange * 0.5); bottom = near / tan(yDirRange * 0.5); top = near / tan(yDirRange * 0.5); } Vector3 Beam::GetMainDirection() const { Vector3 directions[4]; directions[0] = VssRay::GetDirection(dBox.Min().x, dBox.Min().y); directions[1] = VssRay::GetDirection(dBox.Max().x, dBox.Min().y); directions[2] = VssRay::GetDirection(dBox.Max().x, dBox.Max().y); directions[3] = VssRay::GetDirection(dBox.Min().x, dBox.Max().y); const Vector3 mainDir = directions[0] + directions[1] + directions[2] + directions[3]; return Normalize(mainDir); }