コード例 #1
0
ファイル: lathe.cpp プロジェクト: neuroradiology/povray
bool Lathe::Intersect(const BasicRay& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int cnt;
    int found, j, n1, n2;
    DBL k, len, r, m, w, Dy2, r0, Dylen;
    DBL x1[7];
    DBL x2[3];
    DBL y1[6];
    DBL y2[2];
    DBL best;
    Vector3d P, D;
    LATHE_SPLINE_ENTRY *Entry;

    // Transform the ray into the lathe space.

    MInvTransPoint(P, ray.Origin, Trans);
    MInvTransDirection(D, ray.Direction, Trans);

    len = D.length();
    D /= len;

    Dylen = D[Y] * len; // TODO FIXME - why don't we do this *before* normalizing, saving us the multiplication by len?

#ifdef LATHE_EXTRA_STATS
    Thread->Stats()[Lathe_Bound_Tests]++;
#endif

    // Test if ray misses lathe's cylindrical bound.
    if(((D[Y] >= 0.0) && (P[Y] >  Height2)) ||
            ((D[Y] <= 0.0) && (P[Y] <  Height1)) ||
            ((D[X] >= 0.0) && (P[X] >  Radius2)) ||
            ((D[X] <= 0.0) && (P[X] < -Radius2)))
        return false;

    // Get distance r0 of the ray from rotation axis (i.e. y axis).
    r0 = fabs(P[X] * D[Z] - P[Z] * D[X]);
    r = D[X] * D[X] + D[Z] * D[Z];
    if(r > 0.0)
        r0 /= sqrt(r);

    // Test if ray misses lathe's cylindrical bound.
    if(r0 > Radius2)
        return false;

    // Intersect all cylindrical bounds.
    BCYL_INT *intervals = reinterpret_cast<BCYL_INT *>(Thread->BCyl_Intervals) ;
    BCYL_INT *rint = reinterpret_cast<BCYL_INT *>(Thread->BCyl_RInt) ;
    BCYL_INT *hint = reinterpret_cast<BCYL_INT *>(Thread->BCyl_HInt) ;

    if((cnt = Intersect_BCyl(Spline->BCyl, intervals, rint, hint, P, D)) == 0)
        return false;

#ifdef LATHE_EXTRA_STATS
    Thread->Stats()[Lathe_Bound_Tests_Succeeded]++;
#endif

    // Precalculate some constants that are ray-dependant only.
    m = D[X] * P[X] + D[Z] * P[Z];
    Dy2 = D[Y] * D[Y];

    // Step through the list of intersections.
    found = false;
    best = BOUND_HUGE;

    for(j = 0; j < cnt; j++)
    {
        // Get current segment.
        Entry = &Spline->Entry[intervals[j].n];

        // If we already have the best intersection we may exit.
        if(!(Type & IS_CHILD_OBJECT) && (intervals[j].d[0] > best))
            break;

        // Init number of roots found.
        n1 = 0;

        // Intersect segment.
        switch(Spline_Type)
        {
        // Linear spline
        case LINEAR_SPLINE:
            // Solve 2th order polynomial.
            x1[0] = Entry->C[Y] * Entry->C[Y] * r - Entry->C[X] * Entry->C[X] * Dy2;
            x1[1] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
            x1[2] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
            n1 = Solve_Polynomial(2, x1, y1, false, 0.0, Thread);
            break;
        // Quadratic spline
        case QUADRATIC_SPLINE:
            // Solve 4th order polynomial.
            x1[0] = Entry->B[Y] * Entry->B[Y] * r - Entry->B[X] * Entry->B[X] * Dy2;
            x1[1] = 2.0 * (Entry->B[Y] * Entry->C[Y] * r - Entry->B[X] * Entry->C[X] * Dy2);
            x1[2] = r * (2.0 * Entry->B[Y] * (Entry->D[Y] - P[Y]) + Entry->C[Y] * Entry->C[Y]) + 2.0 * Entry->B[Y] * D[Y] * m - (2.0 * Entry->B[X] * Entry->D[X] + Entry->C[X] * Entry->C[X]) * Dy2;
            x1[3] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
            x1[4] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
            n1 = Solve_Polynomial(4, x1, y1, Test_Flag(this, STURM_FLAG), 0.0, Thread);
            break;
        // Cubic spline
        case BEZIER_SPLINE:
        case CUBIC_SPLINE:
            // Solve 6th order polynomial.
            x1[0] = Entry->A[Y] * Entry->A[Y] * r - Entry->A[X] * Entry->A[X] * Dy2;
            x1[1] = 2.0 * (Entry->A[Y] * Entry->B[Y] * r - Entry->A[X] * Entry->B[X] * Dy2);
            x1[2] = (2.0 * Entry->A[Y] * Entry->C[Y] + Entry->B[Y] * Entry->B[Y]) * r - (2.0 * Entry->A[X] * Entry->C[X] + Entry->B[X] * Entry->B[X]) * Dy2;
            x1[3] = 2.0 * ((Entry->A[Y] * Entry->D[Y] + Entry->B[Y] * Entry->C[Y] - Entry->A[Y] * P[Y]) * r + Entry->A[Y] * D[Y] * m - (Entry->A[X] * Entry->D[X] + Entry->B[X] * Entry->C[X]) * Dy2);
            x1[4] = (2.0 * Entry->B[Y] * (Entry->D[Y] - P[Y]) + Entry->C[Y] * Entry->C[Y]) * r + 2.0 * Entry->B[Y] * D[Y] * m - (2.0 * Entry->B[X] * Entry->D[X] + Entry->C[X] * Entry->C[X]) * Dy2;
            x1[5] = 2.0 * (Entry->C[Y] * ((Entry->D[Y] - P[Y]) * r + D[Y] * m) - Entry->C[X] * Entry->D[X] * Dy2);
            x1[6] = (Entry->D[Y] - P[Y]) * ((Entry->D[Y] - P[Y]) * r + 2.0 * D[Y] * m) + Dy2 * (P[X] * P[X] + P[Z] * P[Z] - Entry->D[X] * Entry->D[X]);
            n1 = Solve_Polynomial(6, x1, y1, Test_Flag(this, STURM_FLAG), 0.0, Thread);
            break;
        }

        // Test roots for valid intersections.
        while(n1--)
        {
            w = y1[n1];
            if((w >= 0.0) && (w <= 1.0))
            {
                if(fabs(D[Y]) > EPSILON)
                {
                    k = (w * (w * (w * Entry->A[Y] + Entry->B[Y]) + Entry->C[Y]) + Entry->D[Y] - P[Y]);

                    if (test_hit(ray, Depth_Stack, k / Dylen, w, intervals[j].n, Thread))
                    {
                        found = true;
                        k /= D[Y];
                        if (k < best)
                            best = k;
                    }
                }
                else
                {
                    k = w * (w * (w * Entry->A[X] + Entry->B[X]) + Entry->C[X]) + Entry->D[X];

                    x2[0] = r;
                    x2[1] = 2.0 * m;
                    x2[2] = P[X] * P[X] + P[Z] * P[Z] - k * k;

                    n2 = Solve_Polynomial(2, x2, y2, false, 0.0, Thread);
                    while(n2--)
                    {
                        k = y2[n2];
                        if(test_hit(ray, Depth_Stack, k / len, w, intervals[j].n, Thread))
                        {
                            found = true;
                            if(k < best)
                                best = k;
                        }
                    }
                }
            }
        }
    }

    return found;
}
コード例 #2
0
ファイル: sor.cpp プロジェクト: SteveShaw/povray
bool Sor::Intersect(const BasicRay& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int cnt;
    int found, j, n;
    DBL a, b, k, h, len, u, v, r0;
    DBL x[4];
    DBL y[3];
    DBL best;
    Vector3d P, D;
    SOR_SPLINE_ENTRY *Entry;

    /* Transform the ray into the surface of revolution space. */

    MInvTransPoint(P, ray.Origin, Trans);

    MInvTransDirection(D, ray.Direction, Trans);

    len = D.length();

    D /= len;

    /* Test if ray misses object's bounds. */

#ifdef SOR_EXTRA_STATS
    Thread->Stats()[Sor_Bound_Tests]++;
#endif

    if (((D[Y] >= 0.0) && (P[Y] >  Height2)) ||
        ((D[Y] <= 0.0) && (P[Y] <  Height1)) ||
        ((D[X] >= 0.0) && (P[X] >  Radius2)) ||
        ((D[X] <= 0.0) && (P[X] < -Radius2)))
    {
        return(false);
    }

    /* Get distance of the ray from rotation axis (= y axis). */

    r0 = P[X] * D[Z] - P[Z] * D[X];

    if ((a = D[X] * D[X] + D[Z] * D[Z]) > 0.0)
    {
        r0 /= sqrt(a);
    }

    /* Test if ray misses object's bounds. */

    if (r0 > Radius2)
    {
        return(false);
    }

    /* Test base/cap plane. */

    found = false;

    best = BOUND_HUGE;

    if (Test_Flag(this, CLOSED_FLAG) && (fabs(D[Y]) > EPSILON))
    {
        /* Test base plane. */

        if (Base_Radius_Squared > DEPTH_TOLERANCE)
        {
            k = (Height1 - P[Y]) / D[Y];

            u = P[X] + k * D[X];
            v = P[Z] + k * D[Z];

            b = u * u + v * v;

            if (b <= Base_Radius_Squared)
            {
                if (test_hit(ray, Depth_Stack, k / len, k, BASE_PLANE, 0, Thread))
                {
                    found = true;

                    if (k < best)
                    {
                        best = k;
                    }
                }
            }
        }

        /* Test cap plane. */

        if (Cap_Radius_Squared > DEPTH_TOLERANCE)
        {
            k = (Height2 - P[Y]) / D[Y];

            u = P[X] + k * D[X];
            v = P[Z] + k * D[Z];

            b = u * u + v * v;

            if (b <= Cap_Radius_Squared)
            {
                if (test_hit(ray, Depth_Stack, k / len, k, CAP_PLANE, 0, Thread))
                {
                    found = true;

                    if (k < best)
                    {
                        best = k;
                    }
                }
            }
        }
    }

    /* Intersect all cylindrical bounds. */
    vector<BCYL_INT>& intervals = Thread->BCyl_Intervals;
    vector<BCYL_INT>& rint = Thread->BCyl_RInt;
    vector<BCYL_INT>& hint = Thread->BCyl_HInt;

    if ((cnt = Intersect_BCyl(Spline->BCyl, intervals, rint, hint, P, D)) == 0)
    {
#ifdef SOR_EXTRA_STATS
        if (found)
            Thread->Stats()[Sor_Bound_Tests_Succeeded]++;
#endif
        return(found);
    }

#ifdef SOR_EXTRA_STATS
    Thread->Stats()[Sor_Bound_Tests_Succeeded]++;
#endif

/* Step through the list of intersections. */

    for (j = 0; j < cnt; j++)
    {
        /* Get current segment. */

        Entry = &Spline->Entry[intervals[j].n];

        /* If we already have the best intersection we may exit. */

        if (!(Type & IS_CHILD_OBJECT) && (intervals[j].d[0] > best))
        {
            break;
        }

        /* Cubic curve. */

        x[0] = Entry->A * D[Y] * D[Y] * D[Y];

/*
        x[1] = D[Y] * D[Y] * (3.0 * Entry->A * P[Y] + Entry->B) - D[X] * D[X] - D[Z] * D[Z];
*/
        x[1] = D[Y] * D[Y] * (3.0 * Entry->A * P[Y] + Entry->B) - a;

        x[2] = D[Y] * (P[Y] * (3.0 * Entry->A * P[Y] + 2.0 * Entry->B) + Entry->C) - 2.0 * (P[X] * D[X] + P[Z] * D[Z]);

        x[3] = P[Y] * (P[Y] * (Entry->A * P[Y] + Entry->B) + Entry->C) + Entry->D - P[X] * P[X] - P[Z] * P[Z];

        n = Solve_Polynomial(3, x, y, Test_Flag(this, STURM_FLAG), 0.0, Thread);

        while (n--)
        {
            k = y[n];

            h = P[Y] + k * D[Y];

            if ((h >= Spline->BCyl->height[Spline->BCyl->entry[intervals[j].n].h1]) &&
                (h <= Spline->BCyl->height[Spline->BCyl->entry[intervals[j].n].h2]))
            {
                if (test_hit(ray, Depth_Stack, k / len, k, CURVE, intervals[j].n, Thread))
                {
                    found = true;

                    if (y[n] < best)
                    {
                        best = k;
                    }
                }
            }
        }
    }

    return(found);
}