#include "RayCaster.h" #include "VssRay.h" #include "Ray.h" #include "Preprocessor.h" #include "ViewCellsManager.h" namespace GtpVisibilityPreprocessor { #define DEBUG_RAYCAST 0 #define EXACT_BOX_CLIPPING 0 RayCaster::RayCaster(const Preprocessor &preprocessor): mVssRayPool(), mPreprocessor(preprocessor) { } RayCaster::~RayCaster() { } VssRay *RayCaster::CastRay(const SimpleRay &simpleRay, const AxisAlignedBox3 &box, const bool castDoubleRay) { VssRayContainer rays; CastRay(simpleRay, rays, box, castDoubleRay, true); if (!rays.empty()) return rays.back(); else return NULL; } bool RayCaster::ClipToViewSpaceBox(const Vector3 &origin, const Vector3 &termination, Vector3 &clippedOrigin, Vector3 &clippedTermination) { Ray ray(origin, termination - origin, Ray::LINE_SEGMENT); ray.Precompute(); float tmin, tmax; if ((!mPreprocessor.mViewCellsManager-> GetViewSpaceBox().ComputeMinMaxT(ray, &tmin, &tmax)) || tmin>=tmax ) return false; if (tmin >= 1.0f || tmax <= 0.0f) return false; if (tmin > 0.0f) clippedOrigin = ray.Extrap(tmin); else clippedOrigin = origin; if (tmax < 1.0f) clippedTermination = ray.Extrap(tmax); else clippedTermination = termination; return true; } /** Checks if ray is valid (e.g., not in empty view space or outside the view space) */ bool RayCaster::ValidateRay(const Vector3 &origin, const Vector3 &direction, const AxisAlignedBox3 &box, Intersection &hit) { if (!hit.mObject) { // compute intersection with the scene bounding box #if EXACT_BOX_CLIPPING static Ray ray; mPreprocessor.SetupRay(ray, origin, direction); float tmin, tmax; if (box.ComputeMinMaxT(ray, &tmin, &tmax) && (tmin < tmax)) { hit.mPoint = ray.Extrap(tmax); } else { // cout<<" invalid hp "<= -Limits::Small) { hit.mObject = NULL; return false; } } } return true; } void RayCaster::SortRays(SimpleRayContainer &rays) { AxisAlignedBox3 box = mPreprocessor.mViewCellsManager->GetViewSpaceBox(); float b[12]={ box.Min().x, box.Min().y, box.Min().z, -1, -1, -1, box.Max().x, box.Max().y, box.Max().z, 1, 1, 1 }; #if 0 static vector pointerArray; if (pointerArray.size()!=rays.size()) { // realloc the pointerarray pointerArray.resize(rays.size()); } // init pointer array SimpleRay *p = &pointerArray[0]; for (i=0; i < rays.size(); i++, p++) pointerArray[i] = p; #endif _SortRays(rays, 0, (int)rays.size()-1, 0, b ); } void RayCaster::_SortRays(SimpleRayContainer &rays, const int l, const int r, const int depth, float box[12]) { // pick-up a pivot int axis; float maxDiff = -1.0f; // get the largest axis int offset = 0; int i; //const int batchsize = 16384; const int batchsize = 8192; //const int batchsize = 128; //if (r - l < 16*batchsize) // offset = 3; // if (depth%2==0) // offset = 3; for (i=offset; i < offset + 3; i++) { float diff = box[i + 6] - box[i]; if (diff > maxDiff) { maxDiff = diff; axis = i; } } // cout<mFlags |= VssRay::Valid; vssRay->mDistribution = simpleRay.mDistribution; vssRay->mGeneratorId = simpleRay.mGeneratorId; vssRays.push_back(vssRay); ++ hits; //cout << "vssray 1: " << *vssRay << " " << vssRay->mTermination - vssRay->mOrigin << endl; } #if DEBUG_RAYCAST Debug<<"PR3"<mFlags |= VssRay::Valid; vssRay->mDistribution = simpleRay.mDistribution; vssRay->mGeneratorId = simpleRay.mGeneratorId; vssRays.push_back(vssRay); ++ hits; //cout << "vssray 2: " << *vssRay << endl; } #if DEBUG_RAYCAST Debug<<"PR4"<