void Sphere::raycast(const Raycast& ray, RayHitList& reports) const { double a, b, c; params(ray, a, b, c); double discr = b*b - 4*a*c; if(discr > 0.0) { double disrcSqrt = glm::sqrt(discr); double t1 = (-b - disrcSqrt) / (2 * a); if(0.0 < t1 && t1 < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t1; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t1, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } double t2 = (-b + disrcSqrt) / (2 * a); if(0.0 < t2 && t2 < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t2; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t2, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } else if(discr == 0.0) { double t = -b / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t; glm::dvec3 n = glm::normalize(pt - _center); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } }
double SearchStructure::findNearestIntersection( const Raycast& raycast, RayHitReport& reportMin, RayHitList& rayHitList) const { Raycast ray(raycast); size_t minId = -1; size_t zId = 0; size_t zoneCount = _searchZones.size(); while(zId < zoneCount) { const SearchZone& zone = _searchZones[zId]; if(zone.bounds == StageZone::UNBOUNDED.get() || zone.bounds->intersects(ray, rayHitList)) { for(size_t s = zone.begSurf; s < zone.endSurf; ++s) { rayHitList.clear(); _searchSurfaces[s]->raycast(ray, rayHitList); RayHitReport* node = rayHitList.head; while(node != nullptr) { if(0.0 < node->length && node->length < ray.limit) { ray.limit = node->length; reportMin = *node; minId = s; } node = node->_next; } } ++zId; } else { zId = zone.endZone; } } if(!_isOptimized && reportMin.length != raycast.limit) { incrementCounter(_searchSurfaces[minId], ray.entropy); } return reportMin.length; }
void SurfaceAnd::raycast(const Raycast& ray, RayHitList& reports) const { size_t surfCount = _surfs.size(); for(size_t i=0; i < surfCount; ++i) { Surface* surf = _surfs[i].get(); RayHitReport* last = reports.head; surf->raycast(ray, reports); RayHitReport* node = reports.head; RayHitReport* parent = nullptr; while(node != last) { bool isIn = true; for(size_t j=0; j < surfCount; ++j) { if(i != j) { if(_surfs[j]->isIn(node->position) == EPointPosition::OUT) { isIn = false; break; } } } RayHitReport* next = node->_next; bool keep = isIn; if(keep) { // Keep ray hit parent = node; } else { // Dispose ray hit if(parent == nullptr) reports.head = next; else parent->_next = next; reports.dispose(node); } node = next; } } }
bool SearchStructure::intersectsScene( const Raycast& raycast, RayHitList& rayHitList, double incomingEntropy) const { rayHitList.clear(); size_t zId = 0; size_t zoneCount = _searchZones.size(); while(zId < zoneCount) { const SearchZone& zone = _searchZones[zId]; if(zone.bounds == StageZone::UNBOUNDED.get() || zone.bounds->intersects(raycast, rayHitList)) { for(size_t s = zone.begSurf; s < zone.endSurf; ++s) { if(_searchSurfaces[s]->intersects(raycast, rayHitList)) { if(!_isOptimized) incrementCounter(_searchSurfaces[s], incomingEntropy); return true; } } ++zId; } else { zId = zone.endZone; } } return false; }
void Disk::raycast(const Raycast& ray, RayHitList& reports) const { glm::dvec3 orig = glm::dvec3(_invTransform * glm::dvec4(ray.origin, 1.0)); glm::dvec3 dir = glm::dvec3(_invTransform * glm::dvec4(ray.direction, 0.0)); double dirDotNorm = glm::dot(_normal, dir); if(dirDotNorm != 0.0) { double t = -(glm::dot(_normal, orig) + _d) / dirDotNorm; if(0.0 < t && t < ray.limit) { if(glm::distance(orig + dir * t, _center) < _radius) { glm::dvec3 pt = ray.origin + ray.direction * t; reports.add(t, pt, _transformN, RayHitReport::NO_TEXCOORD, _coating.get(), _innerMat.get(), _outerMat.get()); } } } }
// ref : http://marctenbosch.com/photon/mbosch_intersection.pdf void Quadric::raycast(const Raycast& ray, RayHitList& reports) const { double a, b, c; params(ray, a, b, c); if(a != 0.0) { double dscr = b*b - 4*a*c; if(dscr > 0.0) { double dsrcSqrt = glm::sqrt(dscr); { double t = (-b - dsrcSqrt) / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt1 = ray.origin + ray.direction*t; glm::dvec3 n1 = computeNormal(_q, pt1); reports.add(t, ray, pt1, n1, RayHitReport::NO_TEXCOORD, _coating.get()); } } { double t = (-b + dsrcSqrt) / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt2 = ray.origin + ray.direction*t; glm::dvec3 n2 = computeNormal(_q, pt2); reports.add(t, ray, pt2, n2, RayHitReport::NO_TEXCOORD, _coating.get()); } } } else if (dscr == 0.0) { double t = -b / (2 * a); if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction*t; glm::dvec3 n = computeNormal(_q, pt); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } } else { if(b != 0.0) { double t = -c / b; if(0.0 < t && t < ray.limit) { glm::dvec3 pt = ray.origin + ray.direction * t; glm::dvec3 n = computeNormal(_q, pt); reports.add(t, ray, pt, n, RayHitReport::NO_TEXCOORD, _coating.get()); } } } }