#include "Ray.h" #include "Plane3.h" #include "VssRay.h" namespace GtpVisibilityPreprocessor { // ========================================================= // Ray .. static item used for generation of unique ID for // each instantiated ray // it has to start from 1, since 0 is default and for the first // ray initial value 0 will not work .. V.H. // The value 0 is reserved for particular purpose - the rays // that are converted to canonical space and thus the mailbox // rayID identification does not work for them! int Ray::genID = 1; void Ray::Init() { // if (mType == LOCAL_RAY) // intersections.reserve(1); // else // intersections.reserve(10); // apply the standard precomputation //Precompute(); // $$ JB precomputation will be applied only when the origin/dir valueas are set SetId(); } void Ray::Precompute() { // initialize inverted dir // invDir.SetValue(0.0, 0.0, 0.0); SetId(); ComputeInvertedDir(); } void Ray::SetLoc(const Vector3 &l) { loc = l; } // make such operation to slightly change the ray direction // in case any component of ray direction is zero. void Ray::CorrectZeroComponents() { const float eps = 1e-6f; // it does change the ray direction very slightly, // but the size direction vector is not practically changed if (fabs(dir.x) < eps) { if (dir.x < 0.0) dir.x = -eps; else dir.x = eps; } if (fabs(dir.y) < eps) { if (dir.y < 0.0) dir.y = -eps; else dir.y = eps; } if (fabs(dir.z) < eps) { if (dir.z < 0.0) dir.z = -eps; else dir.z = eps; } } void Ray::ComputeInvertedDir() const { // if ( (invDir.x != 0.0) || // (invDir.y != 0.0) || // (invDir.z != 0.0) ) // return; // has been already precomputed const float eps = 1e-6f; const float invEps = 1e6f; // it does change the ray direction very slightly, // but the size direction vector is not practically changed if (fabs(dir.x) < eps) { if (dir.x < 0.0) invDir.x = -invEps; else invDir.x = invEps; } else invDir.x = 1.0f / dir.x; if (fabs(dir.y) < eps) { if (dir.y < 0.0) invDir.y = -invEps; else invDir.y = invEps; } else invDir.y = 1.0f / dir.y; if (fabs(dir.z) < eps) { if (dir.z < 0.0f) invDir.z = -invEps; else invDir.z = invEps; } else invDir.z = 1.0f / dir.z; return; } void PassingRaySet::Reset() { for (int i=0; i < 3*Resolution*Resolution; i++) mDirectionalContributions[i] = 0; mRays = 0; mContributions = 0; } void PassingRaySet::AddRay(const Ray &ray, const int contributions) { int i = GetEntryIndex(ray.GetDir()); mRays++; mContributions += contributions; mDirectionalContributions[i] += contributions; } void PassingRaySet::AddRay2(const Ray &ray, const int objects, const int viewcells ) { int i = GetEntryIndex(ray.GetDir()); mRays++; mContributions += objects*viewcells; mDirectionalContributions[i] += objects*viewcells; } int PassingRaySet::GetEntryIndex(const Vector3 &direction) const { // get face int axis = direction.DrivingAxis(); Vector3 dir; float k = direction[axis]; if ( k < 0.0f) k = -k; dir = direction/k; float x, y; dir.ExtractVerts(&x, &y, axis); int ix = (int)((x + 1.0f)*0.5f*Resolution); int iy = (int)((y + 1.0f)*0.5f*Resolution); return Resolution*(Resolution*axis + iy) + ix; } int Ray::ClassifyPlane(const Plane3 &plane, const float minT, const float maxT, Vector3 &entP, Vector3 &extP) const { entP = Extrap(minT); extP = Extrap(maxT); const int entSide = plane.Side(entP); const int extSide = plane.Side(extP); if (entSide < 0) { if (extSide > 0) { return BACK_FRONT; } return BACK; } else if (entSide > 0) { if (extSide < 0) return FRONT_BACK; return FRONT; } else if (entSide == 0) { if (extSide > 0) return FRONT; else if (extSide < 0) return BACK; } return COINCIDENT; } ostream & operator<<(ostream &s, const PassingRaySet &set) { s<<"Ray Set #rays="<