Beispiel #1
0
static void Transform_Smooth_Triangle(OBJECT *Object, TRANSFORM *Trans)
{
  SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object;

  if (!Test_Flag(Object, DEGENERATE_FLAG))
  {
/*  BEG ROSE
    This is useless, because Compute_Triange recalculates this anyway:
    MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans);
    END ROSE */
    MTransPoint(Triangle->P1, Triangle->P1, Trans);
    MTransPoint(Triangle->P2, Triangle->P2, Trans);
    MTransPoint(Triangle->P3, Triangle->P3, Trans);
/*  BEG ROSE
    This code is definitely wrong:
    MTransPoint(Triangle->N1, Triangle->N1, Trans);
    MTransPoint(Triangle->N2, Triangle->N2, Trans);
    MTransPoint(Triangle->N3, Triangle->N3, Trans);
    Bug fix for this: */
    MTransNormal(Triangle->N1,Triangle->N1,Trans);
    MTransNormal(Triangle->N2,Triangle->N2,Trans);
    MTransNormal(Triangle->N3,Triangle->N3,Trans);
/*  END ROSE */

    Compute_Triangle((TRIANGLE *)Triangle, true);
  }
}
Beispiel #2
0
void Triangle::Transform(const TRANSFORM *tr)
{
    if(!Test_Flag(this, DEGENERATE_FLAG))
    {
        MTransPoint(P1, P1, tr);
        MTransPoint(P2, P2, tr);
        MTransPoint(P3, P3, tr);

        Compute_Triangle();
    }
}
Beispiel #3
0
void Camera::Transform(const TRANSFORM *Trans)
{
	MTransPoint(Location, Location, Trans);
	MTransDirection(Direction, Direction, Trans);
	MTransDirection(Up, Up, Trans);
	MTransDirection(Right, Right, Trans);
}
void Transform_Camera(CAMERA *Camera, TRANSFORM *Trans)
{
  MTransPoint(Camera->Location, Camera->Location, Trans);
  MTransDirection(Camera->Direction, Camera->Direction, Trans);
  MTransDirection(Camera->Up, Camera->Up, Trans);
  MTransDirection(Camera->Right, Camera->Right, Trans);
}
Beispiel #5
0
static void Transform_Triangle(OBJECT *Object, TRANSFORM *Trans)
{
  TRIANGLE *Triangle = (TRIANGLE *)Object;

  if (!Test_Flag(Object, DEGENERATE_FLAG))
  {
/*  ROSE BEG
    this is useless, because Compute_Triangle recalculates this anyway:
    MTransPoint(Triangle->Normal_Vector,Triangle->Normal_Vector, Trans);
    END ROSE */
    MTransPoint(Triangle->P1, Triangle->P1, Trans);
    MTransPoint(Triangle->P2, Triangle->P2, Trans);
    MTransPoint(Triangle->P3, Triangle->P3, Trans);

    Compute_Triangle(Triangle, false);
  }
}
Beispiel #6
0
void Sphere::Rotate(const Vector3d&, const TRANSFORM *tr)
{
    if(Trans == NULL)
    {
        MTransPoint(Center, Center, tr);

        Compute_BBox();
    }
    else
    {
        Transform(tr);
    }
}
Beispiel #7
0
void LightSource::Transform(const TRANSFORM *tr)
{
    DBL len;

    MTransPoint(Center, Center,    tr);
    MTransPoint(Points_At, Points_At, tr);
    MTransDirection(Axis1, Axis1,     tr);
    MTransDirection(Axis2, Axis2,     tr);

    MTransDirection(Direction, Direction, tr);

    /* Make sure direction has unit length. */

    len = Direction.length();

    if(len > EPSILON)
        Direction /= len;

    if(!children.empty())
        Transform_Object(children[0], tr);

    if(Projected_Through_Object != NULL)
        Transform_Object(Projected_Through_Object, tr);
}
Beispiel #8
0
void BicubicPatch::Transform(const TRANSFORM *tr)
{
    int i, j;

    for (i = 0; i < 4; i++)
    {
        for (j = 0; j < 4; j++)
        {
            MTransPoint(Control_Points[i][j], Control_Points[i][j], tr);
        }
    }

    Precompute_Patch_Values();

    Compute_BBox();
}
void Recompute_BBox(BBOX *bbox, TRANSFORM *trans)
{
  int i;
  VECTOR lower_left, lengths, corner;
  VECTOR mins, maxs;

  if (trans == NULL)
  {
    return;
  }

  Assign_BBox_Vect(lower_left, bbox->Lower_Left);
  Assign_BBox_Vect(lengths, bbox->Lengths);

  Make_Vector(mins, BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  Make_Vector(maxs, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);

  for (i = 1; i <= 8; i++)
  {
    Assign_Vector(corner, lower_left);

    corner[X] += ((i & 1) ? lengths[X] : 0.0);
    corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
    corner[Z] += ((i & 4) ? lengths[Z] : 0.0);

    MTransPoint(corner, corner, trans);

    if (corner[X] < mins[X]) { mins[X] = corner[X]; }
    if (corner[X] > maxs[X]) { maxs[X] = corner[X]; }
    if (corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
    if (corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
    if (corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
    if (corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
  }

  /* Clip bounding box at the largest allowed bounding box. */

  if (mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
  if (mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
  if (mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
  if (maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
  if (maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
  if (maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_HUGE / 2; }

  Make_BBox_from_min_max(*bbox, mins, maxs);
}
Beispiel #10
0
static void Transform_Bicubic_Patch(OBJECT *Object, TRANSFORM *Trans)
{
  int i, j;
  BICUBIC_PATCH *Patch = (BICUBIC_PATCH *) Object;
  
  for (i = 0; i < 4; i++)
  {
    for (j = 0; j < 4; j++)
    {
      MTransPoint(Patch->Control_Points[i][j], Patch->Control_Points[i][j], Trans);
    }
  }
  
  Precompute_Patch_Values(Patch);
  
  Compute_Bicubic_Patch_BBox(Patch);
}
Beispiel #11
0
static void Compute_Polygon_BBox(POLYGON *Polyg)
{
  int i;
  VECTOR p, Puv, Min, Max;

  Min[X] = Min[Y] = Min[Z] =  BOUND_HUGE;
  Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE;

  for (i = 0; i < Polyg->Data->Number; i++)
  {
    Puv[X] = Polyg->Data->Points[i][X];
    Puv[Y] = Polyg->Data->Points[i][Y];
    Puv[Z] = 0.0;

    MTransPoint(p, Puv, Polyg->Trans);

    Min[X] = min(Min[X], p[X]);
    Min[Y] = min(Min[Y], p[Y]);
    Min[Z] = min(Min[Z], p[Z]);
    Max[X] = max(Max[X], p[X]);
    Max[Y] = max(Max[Y], p[Y]);
    Max[Z] = max(Max[Z], p[Z]);
  }

  Make_BBox_from_min_max(Polyg->BBox, Min, Max);

  if (fabs(Polyg->BBox.Lengths[X]) < Small_Tolerance)
  {
    Polyg->BBox.Lower_Left[X] -= Small_Tolerance;
    Polyg->BBox.Lengths[X]    += 2.0 * Small_Tolerance;
  }

  if (fabs(Polyg->BBox.Lengths[Y]) < Small_Tolerance)
  {
    Polyg->BBox.Lower_Left[Y] -= Small_Tolerance;
    Polyg->BBox.Lengths[Y]    += 2.0 * Small_Tolerance;
  }

  if (fabs(Polyg->BBox.Lengths[Z]) < Small_Tolerance)
  {
    Polyg->BBox.Lower_Left[Z] -= Small_Tolerance;
    Polyg->BBox.Lengths[Z]    += 2.0 * Small_Tolerance;
  }
}
Beispiel #12
0
void Recompute_BBox(BoundingBox *bbox, const TRANSFORM *trans)
{
    int i;
    Vector3d lower_left, lengths, corner;
    Vector3d mins, maxs;

    if(trans == NULL)
        return;

    lower_left = Vector3d(bbox->lowerLeft);
    lengths    = Vector3d(bbox->size);

    mins = Vector3d(BOUND_HUGE);
    maxs = Vector3d(-BOUND_HUGE);

    for(i = 1; i <= 8; i++)
    {
        corner = lower_left;

        corner[X] += ((i & 1) ? lengths[X] : 0.0);
        corner[Y] += ((i & 2) ? lengths[Y] : 0.0);
        corner[Z] += ((i & 4) ? lengths[Z] : 0.0);

        MTransPoint(corner, corner, trans);

        if(corner[X] < mins[X]) { mins[X] = corner[X]; }
        if(corner[X] > maxs[X]) { maxs[X] = corner[X]; }
        if(corner[Y] < mins[Y]) { mins[Y] = corner[Y]; }
        if(corner[Y] > maxs[Y]) { maxs[Y] = corner[Y]; }
        if(corner[Z] < mins[Z]) { mins[Z] = corner[Z]; }
        if(corner[Z] > maxs[Z]) { maxs[Z] = corner[Z]; }
    }

    // Clip bounding box at the largest allowed bounding box.
    if(mins[X] < -BOUND_HUGE / 2) { mins[X] = -BOUND_HUGE / 2; }
    if(mins[Y] < -BOUND_HUGE / 2) { mins[Y] = -BOUND_HUGE / 2; }
    if(mins[Z] < -BOUND_HUGE / 2) { mins[Z] = -BOUND_HUGE / 2; }
    if(maxs[X] >  BOUND_HUGE / 2) { maxs[X] =  BOUND_HUGE / 2; }
    if(maxs[Y] >  BOUND_HUGE / 2) { maxs[Y] =  BOUND_HUGE / 2; }
    if(maxs[Z] >  BOUND_HUGE / 2) { maxs[Z] =  BOUND_HUGE / 2; }

    Make_BBox_from_min_max(*bbox, mins, maxs);
}
Beispiel #13
0
void Polygon::Compute_BBox()
{
    int i;
    Vector3d p, Puv, Min, Max;

    Min[X] = Min[Y] = Min[Z] =  BOUND_HUGE;
    Max[X] = Max[Y] = Max[Z] = -BOUND_HUGE;

    for (i = 0; i < Data->Number; i++)
    {
        Puv[X] = Data->Points[i][X];
        Puv[Y] = Data->Points[i][Y];
        Puv[Z] = 0.0;

        MTransPoint(p, Puv, Trans);

        Min = min(Min, p);
        Max = max(Max, p);
    }

    Make_BBox_from_min_max(BBox, Min, Max);

    if (fabs(BBox.size[X]) < SMALL_TOLERANCE)
    {
        BBox.lowerLeft[X] -= SMALL_TOLERANCE;
        BBox.size[X]    += 2.0 * SMALL_TOLERANCE;
    }

    if (fabs(BBox.size[Y]) < SMALL_TOLERANCE)
    {
        BBox.lowerLeft[Y] -= SMALL_TOLERANCE;
        BBox.size[Y]    += 2.0 * SMALL_TOLERANCE;
    }

    if (fabs(BBox.size[Z]) < SMALL_TOLERANCE)
    {
        BBox.lowerLeft[Z] -= SMALL_TOLERANCE;
        BBox.size[Z]    += 2.0 * SMALL_TOLERANCE;
    }
}
Beispiel #14
0
bool Ovus::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    bool Found = false;
    Vector3d Real_Normal, Real_Pt, INormal, IPoint;
    DBL Depth1, Depth2, Depth3, Depth4, Depth5, Depth6;
    DBL len, horizontal;
    Vector3d P,D;

    Thread->Stats()[Ray_Ovus_Tests]++;
    MInvTransPoint(P, ray.Origin, Trans);
    MInvTransDirection(D, ray.Direction, Trans);
    len = D.length();
    D /= len;

    Intersect_Ovus_Spheres(P, D, &Depth1, &Depth2, &Depth3,
                           &Depth4, &Depth5, &Depth6, Thread);
    if (Depth1 > EPSILON)
    {
        IPoint = P + Depth1 * D;
        if (IPoint[Y] < BottomVertical)
        {
            MTransPoint(Real_Pt, IPoint, Trans);
            if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
            {
                INormal = IPoint / BottomRadius;
                MTransNormal(Real_Normal, INormal, Trans);
                Real_Normal.normalize();
                Depth_Stack->push(Intersection(Depth1/len, Real_Pt, Real_Normal, this));
                Found = true;
            }
        }
    }

    if (Depth2 > EPSILON)
    {
        IPoint = P + Depth2 * D;

        if (IPoint[Y] < BottomVertical)
        {
            MTransPoint(Real_Pt, IPoint, Trans);
            if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
            {
                INormal = IPoint / BottomRadius;
                MTransNormal(Real_Normal, INormal, Trans);
                Real_Normal.normalize();
                Depth_Stack->push(Intersection(Depth2/len, Real_Pt, Real_Normal, this));
                Found = true;
            }
        }
    }

    if (Depth3 > EPSILON)
    {
        IPoint = P + Depth3 * D;

        if (IPoint[Y] > TopVertical)
        {
            MTransPoint(Real_Pt, IPoint, Trans);
            if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
            {
                INormal = IPoint;
                INormal[Y] -= BottomRadius;
                INormal /= TopRadius;
                MTransNormal(Real_Normal, INormal, Trans);
                Real_Normal.normalize();
                Depth_Stack->push(Intersection(Depth3/len, Real_Pt, Real_Normal, this));
                Found = true;
            }
        }
    }
    if (Depth4 > EPSILON)
    {
        IPoint = P + Depth4 * D;

        if (IPoint[Y] > TopVertical)
        {
            MTransPoint(Real_Pt, IPoint, Trans);
            if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
            {
                INormal = IPoint;
                INormal[Y] -= BottomRadius;
                INormal /= TopRadius;
                MTransNormal(Real_Normal, INormal, Trans);
                Real_Normal.normalize();
                Depth_Stack->push(Intersection(Depth4/len, Real_Pt, Real_Normal, this));
                Found = true;
            }
        }
    }

    if (Depth5 > EPSILON)
    {
        IPoint = P + Depth5 * D;
        MTransPoint(Real_Pt, IPoint, Trans);

        if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
        {
            INormal = IPoint;

            INormal[Y] -= VerticalPosition;
            horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z]));
            INormal[X] += (INormal[X] * HorizontalPosition / horizontal);
            INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal);
            INormal.normalize();
            MTransNormal(Real_Normal, INormal, Trans);
            Real_Normal.normalize();
            Depth_Stack->push(Intersection(Depth5/len, Real_Pt, Real_Normal, this));
            Found = true;
        }
    }
    if (Depth6 > EPSILON)
    {
        IPoint = P + Depth6 * D;
        MTransPoint(Real_Pt, IPoint, Trans);

        if (Clip.empty()||(Point_In_Clip(Real_Pt, Clip, Thread)))
        {
            INormal = IPoint;
            INormal[Y] -= VerticalPosition;
            horizontal = sqrt(Sqr(INormal[X]) + Sqr(INormal[Z]));
            INormal[X] += (INormal[X] * HorizontalPosition / horizontal);
            INormal[Z] += (INormal[Z] * HorizontalPosition / horizontal);
            INormal.normalize();
            MTransNormal(Real_Normal, INormal, Trans);
            Real_Normal.normalize();

            Depth_Stack->push(Intersection(Depth6/len, Real_Pt, Real_Normal, this));
            Found = true;
        }
    }
    if (Found)
    {
        Thread->Stats()[Ray_Ovus_Tests_Succeeded]++;
    }
    return (Found);
}
Beispiel #15
0
void Sphere::UVCoord(Vector2d& Result, const Intersection *Inter, TraceThreadData *Thread) const
{
    DBL len, phi, theta;
    DBL x,y,z;
    Vector3d New_Point, New_Center;

    /* Transform the point into the sphere's space */
    if (UV_Trans != NULL)
    {

        MInvTransPoint(New_Point, Inter->IPoint, UV_Trans);

        if (Trans != NULL)
            MTransPoint(New_Center, Center, Trans);
        else
            New_Center = Center;

        MInvTransPoint(New_Center, New_Center, UV_Trans);
    }
    else
    {
        New_Point = Inter->IPoint;
        New_Center = Center;
    }
    x = New_Point[X]-New_Center[X];
    y = New_Point[Y]-New_Center[Y];
    z = New_Point[Z]-New_Center[Z];

    len = sqrt(x * x + y * y + z * z);

    if (len == 0.0)
        return;
    else
    {
        x /= len;
        y /= len;
        z /= len;
    }

    /* Determine its angle from the x-z plane. */
    phi = 0.5 + asin(y) / M_PI; /* This will be from 0 to 1 */

    /* Determine its angle from the point (1, 0, 0) in the x-z plane. */
    len = x * x + z * z;

    if (len > EPSILON)
    {
        len = sqrt(len);
        if (z == 0.0)
        {
            if (x > 0)
                theta = 0.0;
            else
                theta = M_PI;
        }
        else
        {
            theta = acos(x / len);
            if (z < 0.0)
                theta = TWO_M_PI - theta;
        }

        theta /= TWO_M_PI;  /* This will be from 0 to 1 */
    }
    else
        /* This point is at one of the poles. Any value of xcoord will be ok... */
        theta = 0;

    Result[U] = theta;
    Result[V] = phi;
}
Beispiel #16
0
bool Fractal::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    bool Intersection_Found;
    bool LastIsInside = false;
    bool CurrentIsInside, NextIsInside;
    DBL Depth, Depth_Max;
    DBL Dist, Dist_Next, LenSqr, LenInv;

    Vector3d IPoint, Mid_Point, Next_Point, Real_Pt;
    Vector3d Real_Normal, F_Normal;
    Vector3d Direction;
    BasicRay New_Ray;

    Thread->Stats()[Ray_Fractal_Tests]++;

    Intersection_Found = false;

    /* Get into Fractal's world. */

    if (Trans != NULL)
    {
        MInvTransDirection(Direction, ray.Direction, Trans);
        LenSqr = Direction.lengthSqr();

        if (LenSqr == 0.0)
        {
            return (false);
        }

        if (LenSqr != 1.0)
        {
            LenInv = 1.0 / sqrt(LenSqr);
            Direction *= LenInv;
        }
        else
            LenInv = 1.0;

        New_Ray.Direction = Direction;
        MInvTransPoint(New_Ray.Origin, ray.Origin, Trans);
    }
    else
    {
        Direction = ray.Direction;
        New_Ray = ray;
        LenInv = 1.0;
    }

    /* Bound fractal. */

    if (!F_Bound(New_Ray, this, &Depth, &Depth_Max))
    {
        return (false);
    }

    if (Depth_Max < Fractal_Tolerance)
    {
        return (false);
    }

    if (Depth < Fractal_Tolerance)
    {
        Depth = Fractal_Tolerance;
    }

    /* Jump to starting point */

    Next_Point = New_Ray.Origin + Direction * Depth;

    CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack);

    /* Light ray starting inside ? */

    if (CurrentIsInside)
    {
        Next_Point += (2.0 * Fractal_Tolerance) * Direction;

        Depth += 2.0 * Fractal_Tolerance;

        if (Depth > Depth_Max)
        {
            return (false);
        }

        CurrentIsInside = D_Iteration(Next_Point, this, Direction, &Dist, Thread->Fractal_IStack);
    }

    /* Ok. Trace it */

    while (Depth < Depth_Max)
    {
        /*
         * Get close to the root: Advance with Next_Point, keeping track of last
         * position in IPoint...
         */

        while (1)
        {
            if (Dist < Precision)
                Dist = Precision;

            Depth += Dist;

            if (Depth > Depth_Max)
            {
                if (Intersection_Found)
                    Thread->Stats()[Ray_Fractal_Tests_Succeeded]++;
                return (Intersection_Found);
            }

            IPoint = Next_Point;
            Next_Point += Dist * Direction;

            NextIsInside = D_Iteration(Next_Point, this, Direction, &Dist_Next, Thread->Fractal_IStack);

            if (NextIsInside != CurrentIsInside)
            {
                /* Set surface was crossed... */

                Depth -= Dist;
                break;
            }
            else
            {
                Dist = Dist_Next; /* not reached */
            }
        }

        /* then, polish the root via bisection method... */

        while (Dist > Fractal_Tolerance)
        {
            Dist *= 0.5;
            Mid_Point = IPoint + Dist * Direction;

            LastIsInside = Iteration(Mid_Point, this, Thread->Fractal_IStack);

            if (LastIsInside == CurrentIsInside)
            {
                IPoint = Mid_Point;

                Depth += Dist;

                if (Depth > Depth_Max)
                {
                    if (Intersection_Found)
                        Thread->Stats()[Ray_Fractal_Tests_Succeeded]++;
                    return (Intersection_Found);
                }
            }
        }

        if (!CurrentIsInside) /* Mid_Point isn't inside the set */
        {
            IPoint += Dist * Direction;

            Depth += Dist;

            Iteration(IPoint, this, Thread->Fractal_IStack);
        }
        else
        {
            if (LastIsInside != CurrentIsInside)
            {
                Iteration(IPoint, this, Thread->Fractal_IStack);
            }
        }

        if (Trans != NULL)
        {
            MTransPoint(Real_Pt, IPoint, Trans);
            Normal_Calc(this, F_Normal, Thread->Fractal_IStack);
            MTransNormal(Real_Normal, F_Normal, Trans);
        }
        else
        {
            Real_Pt = IPoint;
            Normal_Calc(this, Real_Normal, Thread->Fractal_IStack);
        }

        if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread))
        {
            Real_Normal.normalize();
            Depth_Stack->push(Intersection(Depth * LenInv, Real_Pt, Real_Normal, this));
            Intersection_Found = true;

            /* If fractal isn't used with CSG we can exit now. */

            if (!(Type & IS_CHILD_OBJECT))
            {
                break;
            }
        }

        /* Start over where work was left */

        IPoint = Next_Point;
        Dist = Dist_Next;
        CurrentIsInside = NextIsInside;

    }

    if (Intersection_Found)
        Thread->Stats()[Ray_Fractal_Tests_Succeeded]++;
    return (Intersection_Found);
}
Beispiel #17
0
bool Sphere::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    Thread->Stats()[Ray_Sphere_Tests]++;

    if(Do_Ellipsoid)
    {
        register int Intersection_Found;
        DBL Depth1, Depth2, len;
        Vector3d IPoint;
        BasicRay New_Ray;

        // Transform the ray into the ellipsoid's space

        MInvTransRay(New_Ray, ray, Trans);

        len = New_Ray.Direction.length();
        New_Ray.Direction /= len;

        Intersection_Found = false;

        if(Intersect(New_Ray, Center, Sqr(Radius), &Depth1, &Depth2))
        {
            Thread->Stats()[Ray_Sphere_Tests_Succeeded]++;
            if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE))
            {
                IPoint = New_Ray.Evaluate(Depth1);
                MTransPoint(IPoint, IPoint, Trans);

                if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    Depth_Stack->push(Intersection(Depth1 / len, IPoint, this));
                    Intersection_Found = true;
                }
            }

            if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE))
            {
                IPoint = New_Ray.Evaluate(Depth2);
                MTransPoint(IPoint, IPoint, Trans);

                if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    Depth_Stack->push(Intersection(Depth2 / len, IPoint, this));
                    Intersection_Found = true;
                }
            }
        }

        return(Intersection_Found);
    }
    else
    {
        register int Intersection_Found;
        DBL Depth1, Depth2;
        Vector3d IPoint;

        Intersection_Found = false;

        if(Intersect(ray, Center, Sqr(Radius), &Depth1, &Depth2))
        {
            Thread->Stats()[Ray_Sphere_Tests_Succeeded]++;
            if((Depth1 > DEPTH_TOLERANCE) && (Depth1 < MAX_DISTANCE))
            {
                IPoint = ray.Evaluate(Depth1);

                if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    Depth_Stack->push(Intersection(Depth1, IPoint, this));
                    Intersection_Found = true;
                }
            }

            if((Depth2 > DEPTH_TOLERANCE) && (Depth2 < MAX_DISTANCE))
            {
                IPoint = ray.Evaluate(Depth2);

                if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    Depth_Stack->push(Intersection(Depth2, IPoint, this));
                    Intersection_Found = true;
                }
            }
        }

        return(Intersection_Found);
    }
}