예제 #1
0
    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());
            }
        }
    }
예제 #2
0
    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;
    }
예제 #3
0
    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;
            }
        }
    }
예제 #4
0
    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;
    }
예제 #5
0
    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());
                }
            }
        }
    }
예제 #6
0
    // 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());
                }
            }
        }
    }