OSG_BASE_DLLMAPPING bool intersect(const FrustumVolume &frustum, const Volume &vol, FrustumVolume::PlaneSet &inplanes) { Pnt3f min, max; vol.getBounds(min, max); const Plane *frust = frustum.getPlanes(); FrustumVolume::PlaneSet mask = 0x1; // check the box against the 6 planes, adjust the inplanes set // accordingly for(Int32 i = 0; i < 6; i++, mask <<= 1) { if((inplanes & mask) != 0) continue; if(frust[i].isOutHalfSpace(min, max)) return false; if(frust[i].isInHalfSpace(min, max)) inplanes |= mask; } return true; }
OSG_BASE_DLLMAPPING bool intersect(const SphereVolume &sphere, const FrustumVolume &frustum) { const Plane *frust = frustum.getPlanes(); //check the center of the sphere with each plane of the frustum for(Int32 i = 0; i < 6; i++) { if(frust[i].distance(sphere.getCenter()) < -sphere.getRadius()) return false; } return true; }
OSG_BASE_DLLMAPPING bool intersect(const CylinderVolume &cylinder, const FrustumVolume &frustum) { Pnt3f min, max; cylinder.getBounds(min, max); const Plane *frust = frustum.getPlanes(); // check each point of the box to the 6 planes for(Int32 i = 0; i < 6; i++) { if(frust[i].isOutHalfSpace(min, max)) return false; } return true; }
OSG_BEGIN_NAMESPACE OSG_BASE_DLLMAPPING bool operator ==(const FrustumVolume &lhs, const FrustumVolume &rhs) { return ((static_cast<const Volume &>(lhs) == rhs ) && (lhs.getPlanes()[0] == rhs.getPlanes()[0]) && (lhs.getPlanes()[1] == rhs.getPlanes()[1]) && (lhs.getPlanes()[2] == rhs.getPlanes()[2]) && (lhs.getPlanes()[3] == rhs.getPlanes()[3]) && (lhs.getPlanes()[4] == rhs.getPlanes()[4]) && (lhs.getPlanes()[5] == rhs.getPlanes()[5])); }
/*! Calculate the vertices (\a intVerts) and center (\a intCenter) of the intersection of \a fA and \a fB. */ void TrapezoidalShadowMapEngine::intersectFrusta( const FrustumVolume &fA, const FrustumVolume &fB, std::vector<Pnt3r> &intVerts, Pnt3r &intCenter) { const Plane *planes[12]; intVerts.clear ( ); intVerts.reserve(16); for(UInt32 i = 0; i < 6; ++i) { planes[i ] = &(fA.getPlanes()[i]); planes[6 + i] = &(fB.getPlanes()[i]); } // take all combinations of 3 planes -- but avoid choosing planes // we know to be parallel (i.e. near and far of the same frustum), or // that are known to intersect outside the frustum (i.e top/bottom, // left/right). for(UInt32 i = 0; i < 12; ++i) { // choose initial value of j such that it avoids near and far of fA for(UInt32 j = osgMax<UInt32>(2, i + 1); j < 12; ++j) { // near/far are parallel, // left/right always intersect outside the frustum, // top/bottom always intersect outside the frustum if((i == 6 && j == 7) || (i == 2 && j == 3) || (i == 8 && j == 9) || (i == 4 && j == 5) || (i == 10 && j == 11) ) continue; Line intLine; if(planes[i]->intersect(*planes[j], intLine) == false) continue; for(UInt32 k = j + 1; k < 12; ++k) { // near/far are parallel, // left/right always intersect outside the frustum, // top/bottom always intersect outside the frustum if((j == 6 && k == 7) || (j == 2 && k == 3) || (j == 8 && k == 9) || (j == 4 && k == 5) || (j == 10 && k == 11) ) continue; Pnt3r intPoint; if(planes[k]->intersectInfinite(intLine, intPoint) == false) continue; bool intPointValid = true; // check the intersection point against all planes to ensure // it is in both frusta for(UInt32 m = 0; m < 12; ++m) { // intPoint is the intersection of planes i, j, k, so // we don't have to test against those if(m == i || m == j || m == k) continue; if(planes[m]->isInHalfSpace(intPoint) == false) { intPointValid = false; break; } } if(intPointValid == true) { intCenter += intPoint.subZero(); intVerts.push_back(intPoint); } } } } intCenter /= intVerts.size(); }
bool Line::intersect(const FrustumVolume &frustum , Real &enter , Real &exit ) const { const Real inf = 2u << 16; Pnt3r enter_point = _pos + _dir * 0.f; Pnt3r exit_point = _pos + _dir * inf; face faces[6]; const Plane *planes = frustum.getPlanes(); Line lines[2]; //ln[0] - intersection of right and top planes planes[3].intersect(planes[4], lines[0]); //ln[1] - left and bottom planes[2].intersect(planes[5], lines[1]); Pnt3r pointA; Pnt3r pointB; if(!planes[0].intersectInfinite(lines[0],pointA)) std::cout << "This should never happen (A)!!!!"; if(!planes[1].intersectInfinite(lines[1],pointB)) std::cout << "This should never happen (B)!!!!"; faces[0].point = pointA; faces[0].inner_vector = pointB - pointA; faces[1].point = pointB; faces[1].inner_vector = pointA - pointB; faces[2].point = pointB; faces[2].inner_vector = pointA - pointB; faces[3].point = pointA; faces[3].inner_vector = pointB - pointA; faces[4].point = pointA; faces[4].inner_vector = pointB - pointA; faces[5].point = pointB; faces[5].inner_vector = pointA - pointB; for(Int32 i = 0; i < 6; i++) { faces[i].inner_normal=planes[i].getNormal(); if(faces[i].inner_normal.dot(faces[i].inner_vector) < 0.f) faces[i].inner_normal=-faces[i].inner_normal; Vec3r test_enp = enter_point - faces[i].point; Vec3r test_exp = exit_point - faces[i].point; Real value_enp = test_enp.dot(faces[i].inner_normal); Real value_exp = test_exp.dot(faces[i].inner_normal); if(value_enp < 0.f && value_exp < 0.f) return false; if(value_enp > 0.f && value_exp < 0.f) planes[i].intersect(*this, exit_point ); if(value_enp < 0.f && value_exp > 0.f) planes[i].intersect(*this, enter_point); } Real a; if((a = (enter_point - _pos).dot(_dir)) != 0.f) { enter = (enter_point - _pos).dot(enter_point - _pos) / a; } else { enter = 0.f; } if((a = (exit_point - _pos).dot(_dir)) != 0.f) { exit = (exit_point - _pos).dot(exit_point - _pos) / a; } else { enter = 0.f; } return true; }