예제 #1
0
int BicubicPatch::bezier_subpatch_intersect(const BasicRay &ray, const ControlPoints *Patch, DBL u0, DBL  u1, DBL  v0, DBL  v1, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int cnt = 0;
    TripleVector3d V1;
    DBL u, v, Depth;
    DBL uu[3], vv[3];
    Vector3d P, N;
    Vector2d UV;
    Vector2d uv_point, tpoint;

    V1[0] = (*Patch)[0][0];
    V1[1] = (*Patch)[0][3];
    V1[2] = (*Patch)[3][3];

    uu[0] = u0; uu[1] = u0; uu[2] = u1;
    vv[0] = v0; vv[1] = v1; vv[2] = v1;

    if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
    {
        if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
        {
            /* transform current point from uv space to texture space */
            uv_point[0] = v;
            uv_point[1] = u;
            Compute_Texture_UV(uv_point, ST, tpoint);

            UV[U] = tpoint[0];
            UV[V] = tpoint[1];
            Depth_Stack->push(Intersection(Depth, P, N, UV, this));

            cnt++;
        }
    }

    V1[1] = V1[2];
    V1[2] = (*Patch)[3][0];

    uu[1] = uu[2]; uu[2] = u1;
    vv[1] = vv[2]; vv[2] = v0;

    if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
    {
        if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
        {
            /* transform current point from uv space to texture space */
            uv_point[0] = v;
            uv_point[1] = u;
            Compute_Texture_UV(uv_point, ST, tpoint);

            UV[U] = tpoint[0];
            UV[V] = tpoint[1];
            Depth_Stack->push(Intersection(Depth, P, N, UV, this));

            cnt++;
        }
    }

    return (cnt);
}
예제 #2
0
static int All_Cone_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
{
  int Intersection_Found, cnt, i;
  VECTOR IPoint;
  CONE_INT I[4];

  Intersection_Found = false;

  if ((cnt = intersect_cone(Ray, (CONE *)Object, I)) != 0)
  {
    for (i = 0; i < cnt; i++)
    {
      VEvaluateRay(IPoint, Ray->Initial, I[i].d, Ray->Direction);

      if (Point_In_Clip(IPoint, Object->Clip))
      {
        push_entry_i1(I[i].d,IPoint,Object,I[i].t,Depth_Stack);

        Intersection_Found = true;
      }
    }
  }

  return (Intersection_Found);
}
예제 #3
0
파일: torus.cpp 프로젝트: Degot/povray
bool Torus::All_Intersections(const Ray& ray, IStack& Depth_Stack, SceneThreadData *Thread)
{
	int i, max_i, Found;
	DBL Depth[4];
	VECTOR IPoint;

	Found = false;

	if ((max_i = Intersect(ray, Depth, Thread)) > 0)
	{
		for (i = 0; i < max_i; i++)
		{
			if ((Depth[i] > DEPTH_TOLERANCE) && (Depth[i] < MAX_DISTANCE))
			{
				VEvaluateRay(IPoint, ray.Origin, Depth[i], ray.Direction);

				if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
				{
					Depth_Stack->push(Intersection(Depth[i], IPoint, this));

					Found = true;
				}
			}
		}
	}

	return(Found);
}
예제 #4
0
static int All_Box_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
{
  int Intersection_Found;
  int Side1, Side2;
  DBL Depth1, Depth2;
  VECTOR IPoint;

  Increase_Counter(stats[Ray_Box_Tests]);

  Intersection_Found = false;

  if (Intersect_Box(Ray, ((BOX *)Object)->Trans, ((BOX *)Object)->bounds[0], ((BOX *)Object)->bounds[1], &Depth1, &Depth2, &Side1, &Side2))
  {
    if (Depth1 > DEPTH_TOLERANCE)
    {
      VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);

      if (Point_In_Clip(IPoint, Object->Clip))
      {
        push_entry_i1(Depth1,IPoint,Object,Side1,Depth_Stack);

        Intersection_Found = true;
      }
    }

    VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);

    if (Point_In_Clip(IPoint, Object->Clip))
    {
      push_entry_i1(Depth2,IPoint,Object,Side2,Depth_Stack);

      Intersection_Found = true;
    }
  }

  if (Intersection_Found)
  {
    Increase_Counter(stats[Ray_Box_Tests_Succeeded]);
  }

  return (Intersection_Found);
}
예제 #5
0
static int All_Quadric_Intersections(OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
{
  DBL Depth1, Depth2;
  VECTOR IPoint;
  register int Intersection_Found;

  Intersection_Found = false;

  if (Intersect_Quadric(Ray, (QUADRIC *)Object, &Depth1, &Depth2))
  {
    if ((Depth1 > Small_Tolerance) && (Depth1 < Max_Distance))
    {
      VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);

      if (Point_In_Clip(IPoint, Object->Clip))
      {
        push_entry(Depth1, IPoint, Object, Depth_Stack);

        Intersection_Found = true;
      }
    }

    if ((Depth2 > Small_Tolerance) && (Depth2 < Max_Distance))
    {
      VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);

      if (Point_In_Clip(IPoint, Object->Clip))
      {
        push_entry(Depth2, IPoint, Object, Depth_Stack);

        Intersection_Found = true;
      }
    }
  }

  return(Intersection_Found);
}
예제 #6
0
bool Plane::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    DBL Depth;
    Vector3d IPoint;

    if (Intersect(ray, &Depth, Thread))
    {
        IPoint = ray.Evaluate(Depth);

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

    return(false);
}
예제 #7
0
파일: planes.cpp 프로젝트: Degot/povray
bool Plane::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
	DBL Depth;
	VECTOR IPoint;

	if (Intersect(ray, &Depth, Thread))
	{
		VEvaluateRay(IPoint, ray.Origin, Depth, ray.Direction);

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

	return(false);
}
예제 #8
0
파일: super.cpp 프로젝트: UberPOV/UberPOV
bool Superellipsoid::insert_hit(const BasicRay &ray, DBL Depth, IStack& Depth_Stack, TraceThreadData *Thread)
{
    Vector3d IPoint;

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

        if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
        {
            Depth_Stack->push(Intersection(Depth, IPoint, this));

            return(true);
        }
    }

    return(false);
}
예제 #9
0
bool Lathe::test_hit(const BasicRay &ray, IStack& Depth_Stack, DBL d, DBL w, int n, TraceThreadData *Thread)
{
    Vector3d IPoint;

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

        if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
        {
            Depth_Stack->push(Intersection(d, IPoint, this, n, w));

            return(true);
        }
    }

    return(false);
}
예제 #10
0
static int All_Plane_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
{
  DBL Depth;
  VECTOR IPoint;

  if (Intersect_Plane(Ray, (PLANE *)Object, &Depth))
  {
    VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);

    if (Point_In_Clip(IPoint, Object->Clip))
    {
      push_entry(Depth,IPoint,Object,Depth_Stack);

      return(true);
    }
  }

  return(false);
}
예제 #11
0
파일: sor.cpp 프로젝트: SteveShaw/povray
bool Sor::test_hit(const BasicRay &ray, IStack& Depth_Stack, DBL d, DBL k, int t, int n, TraceThreadData *Thread)
{
    Vector3d IPoint;

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

        if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
        {
            /* is the extra copy of d redundant? */
            Depth_Stack->push(Intersection(d, IPoint, this, t, n, k));

            return(true);
        }
    }

    return(false);
}
예제 #12
0
파일: lemon.cpp 프로젝트: atlaste/povray
bool Lemon::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    bool Intersection_Found;
    int cnt, i;
    Vector3d Real_Normal;
    Vector3d Real_Pt,INormal;
    LEMON_INT I[4];
    Vector3d P,D;
    DBL len;

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

    Intersection_Found = false;

    if ((cnt = Intersect(P, D, I, Thread)) != 0)
    {
        for (i = 0; i < cnt; i++)
        {
            Real_Pt = ray.Origin + I[i].d/len * ray.Direction;

            if (Clip.empty() || Point_In_Clip(Real_Pt, Clip, Thread))
            {
                INormal = I[i].n;
                MTransNormal(Real_Normal, INormal, Trans);
                Real_Normal.normalize();

                Depth_Stack->push(Intersection(I[i].d/len,Real_Pt,Real_Normal,this));
                Intersection_Found = true;
            }
        }
    }
    if(Intersection_Found)
    {
        Thread->Stats()[Ray_Lemon_Tests_Succeeded]++;
    }
    return (Intersection_Found);
}
예제 #13
0
bool Triangle::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    DBL Depth;
    Vector3d IPoint;

    Thread->Stats()[Ray_Triangle_Tests]++;
    if (Intersect(ray, &Depth))
    {
        Thread->Stats()[Ray_Triangle_Tests_Succeeded]++;
        IPoint = ray.Evaluate(Depth);

        if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
        {
            Depth_Stack->push(Intersection(Depth,IPoint,this));

            return(true);
        }
    }

    return(false);
}
예제 #14
0
static int All_Disc_Intersections (OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack)
{
  int Intersection_Found;
  DBL Depth;
  VECTOR IPoint;

  Intersection_Found = false;

  if (Intersect_Disc (Ray, (DISC *)Object, &Depth))
  {
    VEvaluateRay(IPoint, Ray->Initial, Depth, Ray->Direction);

    if (Point_In_Clip (IPoint, Object->Clip))
    {
      push_entry(Depth,IPoint,Object,Depth_Stack);
      Intersection_Found = true;
    }
  }

  return (Intersection_Found);
}
예제 #15
0
파일: torus.cpp 프로젝트: hjw3001/povray
bool SpindleTorus::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int i, max_i, Found;
    DBL Depth[4];
    Vector3d IPoint;

    Found = false;

    if ((max_i = Intersect(ray, Depth, Thread)) > 0)
    {
        for (i = 0; i < max_i; i++)
        {
            if ((Depth[i] > DEPTH_TOLERANCE) && (Depth[i] < MAX_DISTANCE))
            {
                IPoint = ray.Evaluate(Depth[i]);

                if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    // To test whether the point is on the spindle,
                    // we test whether it is inside a sphere around the origin going through the spindle's tips.

                    Vector3d P;
                    MInvTransPoint(P, IPoint, Trans);
                    bool onSpindle = (P.lengthSqr() < mSpindleTipYSqr);

                    bool validIntersection = (onSpindle ? (mSpindleMode & SpindleVisible)
                                                        : (mSpindleMode & NonSpindleVisible));

                    if (validIntersection)
                    {
                        Depth_Stack->push(Intersection(Depth[i], IPoint, this, P, onSpindle));
                        Found = true;
                    }
                }
            }
        }
    }

    return(Found);
}
예제 #16
0
파일: disc.cpp 프로젝트: wfpokorny/povray
bool Disc::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int Intersection_Found;
    DBL Depth;
    Vector3d IPoint;

    Intersection_Found = false;

    Thread->Stats()[Ray_Disc_Tests]++;
    if (Intersect(ray, &Depth))
    {
        Thread->Stats()[Ray_Disc_Tests_Succeeded]++;
        IPoint = ray.Evaluate(Depth);

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

    return (Intersection_Found);
}
예제 #17
0
파일: cone.cpp 프로젝트: hjw3001/povray
bool Cone::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int Intersection_Found, cnt, i;
    Vector3d IPoint;
    CONE_INT I[4];

    Intersection_Found = false;

    if ((cnt = Intersect(ray, I, Thread)) != 0)
    {
        for (i = 0; i < cnt; i++)
        {
            IPoint = ray.Evaluate(I[i].d);

            if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
            {
                Depth_Stack->push(Intersection(I[i].d,IPoint,this,I[i].t));
                Intersection_Found = true;
            }
        }
    }

    return (Intersection_Found);
}
예제 #18
0
파일: fractal.cpp 프로젝트: hjw3001/povray
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);
}
예제 #19
0
파일: fpmetric.cpp 프로젝트: fourks/povray
bool Parametric::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
	VECTOR P, D, IPoint;
	UV_VECT low_vect, hi_vect, uv;
	Ray New_Ray;
	DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen;
	DBL Depth1, Depth2, temp, Len, TResult = HUGE_VAL;
	DBL low, hi, len;
	int MaxPrecompX, MaxPrecompY, MaxPrecompZ;
	int split, i = 0, Side1, Side2;
	int parX, parY;
	int i_flg;
	DBL Intervals_Low[2][32];
	DBL Intervals_Hi[2][32];
	int SectorNum[32];

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

	if(container_shape)
	{
		if(Trans != NULL)
		{
			MInvTransPoint(New_Ray.Origin, ray.Origin, Trans);
			MInvTransDirection(New_Ray.Direction, ray.Direction, Trans);
			VLength(len, New_Ray.Direction);
			VInverseScaleEq(New_Ray.Direction, len);
			i_flg = Sphere::Intersect(New_Ray, container.sphere.center,
			                          (container.sphere.radius) * (container.sphere.radius),
			                          &Depth1, &Depth2);
			Depth1 = Depth1 / len;
			Depth2 = Depth2 / len;
		}
		else
		{
			i_flg = Sphere::Intersect(ray, container.sphere.center,
			                          (container.sphere.radius) * (container.sphere.radius), &Depth1, &Depth2);
		}
		Thread->Stats()[Ray_Sphere_Tests]--;
		if(i_flg)
			Thread->Stats()[Ray_Sphere_Tests_Succeeded]--;
	}
	else
	{
		i_flg = Box::Intersect(ray, Trans, container.box.corner1, container.box.corner2,
		                       &Depth1, &Depth2, &Side1, &Side2);
	}

	if(!i_flg)
		return false;

	Thread->Stats()[Ray_Par_Bound_Tests_Succeeded]++;
	Thread->Stats()[Ray_Parametric_Tests]++;

	if (Trans != NULL)
	{
		MInvTransPoint(P, ray.Origin, Trans);
		MInvTransDirection(D, ray.Direction, Trans);
	}
	else
	{
		P[X] = ray.Origin[X];
		P[Y] = ray.Origin[Y];
		P[Z] = ray.Origin[Z];
		D[X] = ray.Direction[X];
		D[Y] = ray.Direction[Y];
		D[Z] = ray.Direction[Z];
	}

	if (Depth1 == Depth2)
		Depth1 = 0;

	if ((Depth1 += 4 * accuracy) > Depth2)
		return false;

	Intervals_Low[INDEX_U][0] = umin;
	Intervals_Hi[INDEX_U][0] = umax;

	Intervals_Low[INDEX_V][0] = vmin;
	Intervals_Hi[INDEX_V][0] = vmax;
	/* Fri 09-27-1996 0. */
	SectorNum[0] = 1;

	MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0;
	if (PData != NULL)
	{
		if (((PData->flags) & OK_X) != 0)
			MaxPrecompX = 1 << (PData->depth);
		if (((PData->flags) & OK_Y) != 0)
			MaxPrecompY = 1 << (PData->depth);
		if (((PData->flags) & OK_Z) != 0)
			MaxPrecompZ = 1 << (PData->depth);
	}
	/* 0 */
	while (i >= 0)
	{
		low_vect[U] = Intervals_Low[INDEX_U][i];
		hi_vect[U] = Intervals_Hi[INDEX_U][i];
		Len = hi_vect[U] - low_vect[U];
		split = INDEX_U;

		low_vect[V] = Intervals_Low[INDEX_V][i];
		hi_vect[V] = Intervals_Hi[INDEX_V][i];
		temp = hi_vect[V] - low_vect[V];
		if (temp > Len)
		{
			Len = temp;
			split = INDEX_V;
		}
		parX = parY = 0;
		TLen = 0;

		/* X */
		if (SectorNum[i] < MaxPrecompX)
		{
			low = PData->Low[0][SectorNum[i]];
			hi = PData->Hi[0][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[0]), accuracy, low_vect, hi_vect, max_gradient, low, hi);
		/* fabs(D[X] *(T2-T1)) is not OK with new method */

		if (close(D[0], 0))
		{
			parX = 1;
			if ((hi < P[0]) || (low > P[0]))
			{
				i--;
				continue;
			}
		}
		else
		{
			XRayMin = (hi - P[0]) / D[0];
			XRayMax = (low - P[0]) / D[0];
			if (XRayMin > XRayMax)
			{
				temp = XRayMin;
				XRayMin = XRayMax;
				XRayMax = temp;
			}

			if ((XRayMin > Depth2) || (XRayMax < Depth1))
			{
				i--;
				continue;
			}

			if ((TPotRes = XRayMin) > TResult)
			{
				i--;
				continue;
			}

			TLen = XRayMax - XRayMin;
		}

		/* Y */
		if (SectorNum[i] < MaxPrecompY)
		{
			low = PData->Low[1][SectorNum[i]];
			hi = PData->Hi[1][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[1]), accuracy, low_vect, hi_vect, max_gradient, low, hi);

		if (close(D[1], 0))
		{
			parY = 1;
			if ((hi < P[1]) || (low > P[1]))
			{
				i--;
				continue;
			}
		}
		else
		{
			YRayMin = (hi - P[1]) / D[1];
			YRayMax = (low - P[1]) / D[1];
			if (YRayMin > YRayMax)
			{
				temp = YRayMin;
				YRayMin = YRayMax;
				YRayMax = temp;
			}
			if ((YRayMin > Depth2) || (YRayMax < Depth1))
			{
				i--;
				continue;
			}
			if ((TPotRes = YRayMin) > TResult)
			{
				i--;
				continue;
			}
			if (parX == 0)
			{
				if ((YRayMin > XRayMax) || (YRayMax < XRayMin))
				{
					i--;
					continue;
				}
			}
			if ((temp = YRayMax - YRayMin) > TLen)
				TLen = temp;
		}

		/* Z */
		if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i]))
		{
			low = PData->Low[2][SectorNum[i]];
			hi = PData->Hi[2][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(Thread->functionContext, *(Function[2]), accuracy, low_vect, hi_vect, max_gradient, low, hi);

		if (close(D[2], 0))
		{
			if ((hi < P[2]) || (low > P[2]))
			{
				i--;
				continue;
			}
		}
		else
		{
			ZRayMin = (hi - P[2]) / D[2];
			ZRayMax = (low - P[2]) / D[2];
			if (ZRayMin > ZRayMax)
			{
				temp = ZRayMin;
				ZRayMin = ZRayMax;
				ZRayMax = temp;
			}
			if ((ZRayMin > Depth2) || (ZRayMax < Depth1))
			{
				i--;
				continue;
			}
			if ((TPotRes = ZRayMin) > TResult)
			{
				i--;
				continue;
			}
			if (parX == 0)
			{
				if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin))
				{
					i--;
					continue;
				}
			}
			if (parY == 0)
			{
				if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin))
				{
					i--;
					continue;
				}
			}
			if ((temp = ZRayMax - ZRayMin) > TLen)
				TLen = temp;
		}

		if (Len > TLen)
			Len = TLen;
		if (Len < accuracy)
		{
			if ((TResult > TPotRes) && (TPotRes > Depth1))
			{
				TResult = TPotRes;
				Assign_UV_Vect(uv, low_vect);
			}
			i--;
		}
		else
		{
			/* 1 copy */
			if ((SectorNum[i] *= 2) >= Max_intNumber)
				SectorNum[i] = Max_intNumber;
			SectorNum[i + 1] = SectorNum[i];
			SectorNum[i]++;
			i++;
			Intervals_Low[INDEX_U][i] = low_vect[U];
			Intervals_Hi[INDEX_U][i] = hi_vect[U];

			Intervals_Low[INDEX_V][i] = low_vect[V];
			Intervals_Hi[INDEX_V][i] = hi_vect[V];

			/* 2 split */
			temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0;
			Intervals_Hi[split][i] = temp;
			Intervals_Low[split][i - 1] = temp;
		}
	}

	if (TResult < Depth2)
	{
		Thread->Stats()[Ray_Parametric_Tests_Succeeded]++;
		VScale(IPoint, ray.Direction, TResult);
		VAddEq(IPoint, ray.Origin);

		if (Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
		{
			/*
			  compute_param_normal( Par, UResult, VResult , &N); 
			  push_normal_entry( TResult ,IPoint, N, (ObjectPtr ) Object, Depth_Stack);
			*/
			Depth_Stack->push(Intersection(TResult, IPoint, uv, this));

			return true;
		}
	}

	return false;
}
예제 #20
0
bool IsoSurface::All_Intersections(const Ray& ray, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int Side1 = 0, Side2 = 0, itrace = 0;
    DBL Depth1 = 0.0, Depth2 = 0.0;
    BasicRay New_Ray;
    Vector3d IPoint;
    Vector3d Plocal, Dlocal;
    DBL tmax = 0.0, tmin = 0.0, tmp = 0.0;
    DBL maxg = max_gradient;
    int i = 0 ; /* count of intervals in stack - 1      */
    int IFound = false;
    int begin = 0, end = 0;
    bool in_shadow_test = false;
    Vector3d VTmp;

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

    if(container->Intersect(ray, Trans, Depth1, Depth2, Side1, Side2)) /* IsoSurface_Bound_Tests */
    {
        Thread->Stats()[Ray_IsoSurface_Bound_Tests_Succeeded]++;

        in_shadow_test = ray.IsShadowTestRay();

        if(Depth1 < 0.0)
            Depth1 = 0.0;

        if(Trans != NULL)
        {
            MInvTransPoint(Plocal, ray.Origin, Trans);
            MInvTransDirection(Dlocal, ray.Direction, Trans);
        }
        else
        {
            Plocal = ray.Origin;
            Dlocal = ray.Direction;
        }

        Thread->isosurfaceData->Inv3 = 1;

        if(closed != false)
        {
            VTmp = Plocal + Depth1 * Dlocal;
            tmp = Vector_Function(Thread->functionContext, VTmp);
            if(Depth1 > accuracy)
            {
                if(tmp < 0.0)                   /* The ray hits the bounding shape */
                {
                    IPoint = ray.Evaluate(Depth1);
                    if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                    {
                        Depth_Stack->push(Intersection(Depth1, IPoint, this, 1, Side1));
                        IFound = true;
                        itrace++;
                        Thread->isosurfaceData->Inv3 *= -1;
                    }
                }
            }
            else
            {
                if(tmp < (maxg * accuracy * 4.0))
                {
                    Depth1 = accuracy * 5.0;
                    VTmp = Plocal + Depth1 * Dlocal;
                    if(Vector_Function(Thread->functionContext, VTmp) < 0)
                        Thread->isosurfaceData->Inv3 = -1;
                    /* Change the sign of the function (IPoint is in the bounding shpae.)*/
                }
                VTmp = Plocal + Depth2 * Dlocal;
                if(Vector_Function(Thread->functionContext, VTmp) < 0.0)
                {
                    IPoint = ray.Evaluate(Depth2);
                    if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                    {
                        Depth_Stack->push(Intersection(Depth2, IPoint, this, 1, Side2));
                        IFound = true;
                    }
                }
            }
        }

        /*  METHOD 2   by R. Suzuki */
        tmax = Depth2 = min(Depth2, BOUND_HUGE);
        tmin = Depth1 = min(Depth2, Depth1);
        if((tmax - tmin) < accuracy)
        {
            if (IFound)
                Depth_Stack->pop(); // we added an intersection already, so we need to undo that
            return (false);
        }
        Thread->Stats()[Ray_IsoSurface_Tests]++;
        if((Depth1 < accuracy) && (Thread->isosurfaceData->Inv3 == 1))
        {
            /* IPoint is on the isosurface */
            VTmp = Plocal + tmin * Dlocal;
            if(fabs(Vector_Function(Thread->functionContext, VTmp)) < (maxg * accuracy * 4.0))
            {
                tmin = accuracy * 5.0;
                VTmp = Plocal + tmin * Dlocal;
                if(Vector_Function(Thread->functionContext, VTmp) < 0)
                    Thread->isosurfaceData->Inv3 = -1;
                /* change the sign and go into the isosurface */
            }
        }

        Thread->isosurfaceData->ctx = Thread->functionContext;

        for (; itrace < max_trace; itrace++)
        {
            if(Function_Find_Root(*(Thread->isosurfaceData), Plocal, Dlocal, &tmin, &tmax, maxg, in_shadow_test, Thread) == false)
                break;
            else
            {
                IPoint = ray.Evaluate(tmin);
                if(Clip.empty() || Point_In_Clip(IPoint, Clip, Thread))
                {
                    Depth_Stack->push(Intersection(tmin, IPoint, this, 0, 0 /*Side1*/));
                    IFound = true;
                }
            }
            tmin += accuracy * 5.0;
            if((tmax - tmin) < accuracy)
                break;
            Thread->isosurfaceData->Inv3 *= -1;
        }

        if(IFound)
            Thread->Stats()[Ray_IsoSurface_Tests_Succeeded]++;
    }

    if(eval == true)
    {
        DBL temp_max_gradient = max_gradient; // TODO FIXME - works around nasty gcc (found using 4.0.1) bug failing to honor casting away of volatile on pass by value on template argument lookup [trf]
        max_gradient = max((DBL)temp_max_gradient, maxg); // TODO FIXME - This is not thread-safe but should be!!! [trf]
    }

    return (IFound);
}
예제 #21
0
int All_Parametric_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack)
{
	PARAMETRIC * Par = (PARAMETRIC *)Object;
	PRECOMP_PAR_DATA * PData = ((PARAMETRIC *)Object)->PData;
	VECTOR P, D, IPoint;
	UV_VECT low_vect, hi_vect;
	RAY New_Ray;
	DBL XRayMin, XRayMax, YRayMin, YRayMax, ZRayMin, ZRayMax, TPotRes, TLen;
	DBL Depth1, Depth2, temp, Len, UResult, VResult, TResult = HUGE_VAL;
	DBL low, hi, len;
	int MaxPrecompX, MaxPrecompY, MaxPrecompZ;
	int split, i = 0, Side1, Side2;
	int parX, parY;
	int i_flg;

	Increase_Counter(stats[Ray_Par_Bound_Tests]);

	if(Par->container_shape)
	{
		if(Par->Trans != NULL)
		{
			MInvTransPoint(New_Ray.Initial, Ray->Initial, Par->Trans);
			MInvTransDirection(New_Ray.Direction, Ray->Direction, Par->Trans);
			VLength(len, New_Ray.Direction);
			VInverseScaleEq(New_Ray.Direction, len);
			i_flg = Intersect_Sphere(&New_Ray, Par->container.sphere.center, 
			                         (Par->container.sphere.radius) * (Par->container.sphere.radius),
			                         &Depth1, &Depth2);
			Depth1 = Depth1 / len;
			Depth2 = Depth2 / len;
		}
		else
		{
			i_flg = Intersect_Sphere(Ray, Par->container.sphere.center, 
			                         (Par->container.sphere.radius) * (Par->container.sphere.radius), &Depth1, &Depth2);
		}
		Decrease_Counter(stats[Ray_Sphere_Tests]);
		if(i_flg)
			Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]);
	}
	else
	{
		i_flg = Intersect_Box(Ray, Par->Trans, Par->container.box.corner1, Par->container.box.corner2,
		                      &Depth1, &Depth2, &Side1, &Side2);
	}

	if(!i_flg)
		return false;

	Increase_Counter(stats[Ray_Par_Bound_Tests_Succeeded]);
	Increase_Counter(stats[Ray_Parametric_Tests]);

	if (Par->Trans != NULL)
	{
		MInvTransPoint(P, Ray->Initial, Par->Trans);
		MInvTransDirection(D, Ray->Direction, Par->Trans);
	}
	else
	{
		P[X] = Ray->Initial[X];
		P[Y] = Ray->Initial[Y];
		P[Z] = Ray->Initial[Z];
		D[X] = Ray->Direction[X];
		D[Y] = Ray->Direction[Y];
		D[Z] = Ray->Direction[Z];
	}

	if (Depth1 == Depth2)
		Depth1 = 0;

	if ((Depth1 += 4 * Par->accuracy) > Depth2)
		return false;

	Intervals_Low[INDEX_U][0] = Par->umin;
	Intervals_Hi[INDEX_U][0] = Par->umax;

	Intervals_Low[INDEX_V][0] = Par->vmin;
	Intervals_Hi[INDEX_V][0] = Par->vmax;
	/* Fri 09-27-1996 0. */
	SectorNum[0] = 1;

	MaxPrecompX = MaxPrecompY = MaxPrecompZ = 0;
	if (PData != NULL)
	{
		if (((PData->flags) & OK_X) != 0)
			MaxPrecompX = 1 << (PData->depth);
		if (((PData->flags) & OK_Y) != 0)
			MaxPrecompY = 1 << (PData->depth);
		if (((PData->flags) & OK_Z) != 0)
			MaxPrecompZ = 1 << (PData->depth);
	}
	/* 0 */
	while (i >= 0)
	{
		low_vect[U] = Intervals_Low[INDEX_U][i];
		hi_vect[U] = Intervals_Hi[INDEX_U][i];
		Len = hi_vect[U] - low_vect[U];
		split = INDEX_U;

		low_vect[V] = Intervals_Low[INDEX_V][i];
		hi_vect[V] = Intervals_Hi[INDEX_V][i];
		temp = hi_vect[V] - low_vect[V];
		if (temp > Len)
		{
			Len = temp;
			split = INDEX_V;
		}
		parX = parY = 0;
		TLen = 0;

		/* X */
		if (SectorNum[i] < MaxPrecompX)
		{
			low = PData->Low[0][SectorNum[i]];
			hi = PData->Hi[0][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(*(Par->Function[0]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi);
		/* fabs(D[X] *(T2-T1)) is not OK with new method */

		if (close(D[0], 0))
		{
			parX = 1;
			if ((hi < P[0]) || (low > P[0]))
			{
				i--;
				continue;
			}
		}
		else
		{
			XRayMin = (hi - P[0]) / D[0];
			XRayMax = (low - P[0]) / D[0];
			if (XRayMin > XRayMax)
			{
				temp = XRayMin;
				XRayMin = XRayMax;
				XRayMax = temp;
			}

			if ((XRayMin > Depth2) || (XRayMax < Depth1))
			{
				i--;
				continue;
			}

			if ((TPotRes = XRayMin) > TResult)
			{
				i--;
				continue;
			}

			TLen = XRayMax - XRayMin;
		}

		/* Y */
		if (SectorNum[i] < MaxPrecompY)
		{
			low = PData->Low[1][SectorNum[i]];
			hi = PData->Hi[1][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(*(Par->Function[1]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi);

		if (close(D[1], 0))
		{
			parY = 1;
			if ((hi < P[1]) || (low > P[1]))
			{
				i--;
				continue;
			}
		}
		else
		{
			YRayMin = (hi - P[1]) / D[1];
			YRayMax = (low - P[1]) / D[1];
			if (YRayMin > YRayMax)
			{
				temp = YRayMin;
				YRayMin = YRayMax;
				YRayMax = temp;
			}
			if ((YRayMin > Depth2) || (YRayMax < Depth1))
			{
				i--;
				continue;
			}
			if ((TPotRes = YRayMin) > TResult)
			{
				i--;
				continue;
			}
			if (parX == 0)
			{
				if ((YRayMin > XRayMax) || (YRayMax < XRayMin))
				{
					i--;
					continue;
				}
			}
			if ((temp = YRayMax - YRayMin) > TLen)
				TLen = temp;
		}

		/* Z */
		if ((SectorNum[i] < MaxPrecompZ) && (0 < SectorNum[i]))
		{
			low = PData->Low[2][SectorNum[i]];
			hi = PData->Hi[2][SectorNum[i]];
		}
		else
			Evaluate_Function_Interval_UV(*(Par->Function[2]), Par->accuracy, low_vect, hi_vect, Par->max_gradient, low, hi);

		if (close(D[2], 0))
		{
			if ((hi < P[2]) || (low > P[2]))
			{
				i--;
				continue;
			}
		}
		else
		{
			ZRayMin = (hi - P[2]) / D[2];
			ZRayMax = (low - P[2]) / D[2];
			if (ZRayMin > ZRayMax)
			{
				temp = ZRayMin;
				ZRayMin = ZRayMax;
				ZRayMax = temp;
			}
			if ((ZRayMin > Depth2) || (ZRayMax < Depth1))
			{
				i--;
				continue;
			}
			if ((TPotRes = ZRayMin) > TResult)
			{
				i--;
				continue;
			}
			if (parX == 0)
			{
				if ((ZRayMin > XRayMax) || (ZRayMax < XRayMin))
				{
					i--;
					continue;
				}
			}
			if (parY == 0)
			{
				if ((ZRayMin > YRayMax) || (ZRayMax < YRayMin))
				{
					i--;
					continue;
				}
			}
			if ((temp = ZRayMax - ZRayMin) > TLen)
				TLen = temp;
		}

		if (Len > TLen)
			Len = TLen;
		if (Len < Par->accuracy)
		{
			if ((TResult > TPotRes) && (TPotRes > Depth1))
			{
				TResult = TPotRes;
				Par->last_u = UResult = low_vect[U];
				Par->last_v = VResult = low_vect[V];
			}
			i--;
		}
		else
		{
			/* 1 copy */
			if ((SectorNum[i] *= 2) >= Max_intNumber)
				SectorNum[i] = Max_intNumber;
			SectorNum[i + 1] = SectorNum[i];
			SectorNum[i]++;
			i++;
			Intervals_Low[INDEX_U][i] = low_vect[U];
			Intervals_Hi[INDEX_U][i] = hi_vect[U];

			Intervals_Low[INDEX_V][i] = low_vect[V];
			Intervals_Hi[INDEX_V][i] = hi_vect[V];

			/* 2 split */
			temp = (Intervals_Hi[split][i] + Intervals_Low[split][i]) / 2.0;
			Intervals_Hi[split][i] = temp;
			Intervals_Low[split][i - 1] = temp;
		}
	}

	if (TResult < Depth2)
	{
		Increase_Counter(stats[Ray_Parametric_Tests_Succeeded]);
		VScale(IPoint, Ray->Direction, TResult);
		VAddEq(IPoint, Ray->Initial);

		if (Point_In_Clip(IPoint, Par->Clip))
		{
			/*
			  compute_param_normal( Par, UResult, VResult , &N); 
			  push_normal_entry( TResult ,IPoint, N, (OBJECT *) Object, Depth_Stack);
			*/
//			UV_VECT uv;
//			Make_UV_Vector(uv, UResult, VResult);
//			push_uv_entry(TResult, IPoint, uv, (OBJECT *)Object, Depth_Stack);
			push_entry(TResult, IPoint, (OBJECT *)Object, Depth_Stack);

			return true;
		}
	}

	return false;
}
예제 #22
0
int BicubicPatch::bezier_tree_walker(const BasicRay &ray, const BEZIER_NODE *Node, IStack& Depth_Stack, TraceThreadData *Thread)
{
    int i, cnt = 0;
    DBL Depth, u, v;
    DBL uu[3], vv[3];
    Vector3d N, P;
    TripleVector3d V1;
    Vector2d UV;
    Vector2d uv_point, tpoint;
    const BEZIER_CHILDREN *Children;
    const BEZIER_VERTICES *Vertices;

    /*
     * Make sure the ray passes through a sphere bounding
     * the control points of the patch.
     */

    if (!spherical_bounds_check(ray, Node->Center, Node->Radius_Squared))
    {
        return (0);
    }

    /*
     * If this is an interior node then continue the descent,
     * else do a check against the vertices.
     */

    if (Node->Node_Type == BEZIER_INTERIOR_NODE)
    {
        Children = reinterpret_cast<const BEZIER_CHILDREN *>(Node->Data_Ptr);

        for (i = 0; i < Node->Count; i++)
        {
            cnt += bezier_tree_walker(ray, Children->Children[i], Depth_Stack, Thread);
        }
    }
    else if (Node->Node_Type == BEZIER_LEAF_NODE)
    {
        Vertices = reinterpret_cast<const BEZIER_VERTICES *>(Node->Data_Ptr);

        V1[0] = Vertices->Vertices[0];
        V1[1] = Vertices->Vertices[1];
        V1[2] = Vertices->Vertices[2];

        uu[0] = Vertices->uvbnds[0];
        uu[1] = Vertices->uvbnds[0];
        uu[2] = Vertices->uvbnds[1];
        vv[0] = Vertices->uvbnds[2];
        vv[1] = Vertices->uvbnds[3];
        vv[2] = Vertices->uvbnds[3];

        /*
         * Triangulate this subpatch, then check for
         * intersections in the triangles.
         */

        if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
        {
            if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
            {
                /* transform current point from uv space to texture space */
                uv_point[0] = v;
                uv_point[1] = u;
                Compute_Texture_UV(uv_point, ST, tpoint);

                UV[U] = tpoint[0];
                UV[V] = tpoint[1];
                Depth_Stack->push(Intersection(Depth, P, N, UV, this));

                cnt++;
            }
        }

        V1[1] = V1[2];
        V1[2] = Vertices->Vertices[3];

        uu[1] = uu[2]; uu[2] = Vertices->uvbnds[1];
        vv[1] = vv[2]; vv[2] = Vertices->uvbnds[2];

        if (intersect_subpatch(ray, V1, uu, vv, &Depth, P, N, &u, &v))
        {
            if (Clip.empty() || Point_In_Clip(P, Clip, Thread))
            {
                /* transform current point from object space to texture space */
                uv_point[0] = v;
                uv_point[1] = u;
                Compute_Texture_UV(uv_point, ST, tpoint);

                UV[U] = tpoint[0];
                UV[V] = tpoint[1];
                Depth_Stack->push(Intersection(Depth, P, N, UV, this));

                cnt++;
            }
        }
    }
    else
    {
        throw POV_EXCEPTION_STRING("Bad Node type in bezier_tree_walker().");
    }

    return (cnt);
}
예제 #23
0
static int All_IsoSurface_Intersections(OBJECT* Object, RAY* Ray, ISTACK* Depth_Stack)
{
	ISOSURFACE * Isosrf = (ISOSURFACE *)Object;
	int Side1 = 0, Side2 = 0, itrace = 0, i_flg = 0;
	DBL Depth1 = 0.0, Depth2 = 0.0, len = 0.0;
	RAY New_Ray;
	VECTOR IPoint;
	VECTOR P, D;
	DBL tmax = 0.0, tmin = 0.0, tmp = 0.0;
	int i = 0 ; /* count of intervals in stack - 1      */
	int IFound = false;
	int begin = 0, end = 0;
	bool in_shadow_test = false;
	VECTOR VTmp;

	Increase_Counter(stats[Ray_IsoSurface_Bound_Tests]);

	in_shadow_test = ((Ray->Optimisiation_Flags & OPTIMISE_SHADOW_TEST) == OPTIMISE_SHADOW_TEST);

	if(Isosrf->container_shape)
	{
		if(Isosrf->Trans != NULL)
		{
			MInvTransPoint(New_Ray.Initial, Ray->Initial, Isosrf->Trans);
			MInvTransDirection(New_Ray.Direction, Ray->Direction, Isosrf->Trans);
			VLength(len, New_Ray.Direction);
			VInverseScaleEq(New_Ray.Direction, len);
			i_flg = Intersect_Sphere(&New_Ray, Isosrf->container.sphere.center, 
			                         (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius),
			                         &Depth1, &Depth2);
			Depth1 = Depth1 / len;
			Depth2 = Depth2 / len;
		}
		else
		{
			i_flg = Intersect_Sphere(Ray, Isosrf->container.sphere.center, 
			                         (Isosrf->container.sphere.radius) * (Isosrf->container.sphere.radius), &Depth1, &Depth2);
		}
		Decrease_Counter(stats[Ray_Sphere_Tests]);
		if(i_flg)
			Decrease_Counter(stats[Ray_Sphere_Tests_Succeeded]);
	}
	else
	{
		i_flg = Intersect_Box(Ray, Isosrf->Trans, Isosrf->container.box.corner1, Isosrf->container.box.corner2,
		                      &Depth1, &Depth2, &Side1, &Side2);
	}

	if(Depth1 < 0.0)
		Depth1 = 0.0;

	if(i_flg)									/* IsoSurface_Bound_Tests */
	{
		Increase_Counter(stats[Ray_IsoSurface_Bound_Tests_Succeeded]);
		if(Isosrf->Trans != NULL)
		{
			MInvTransPoint(P, Ray->Initial, Isosrf->Trans);
			MInvTransDirection(D, Ray->Direction, Isosrf->Trans);
		}
		else
		{
			Assign_Vector(P, Ray->Initial);
			Assign_Vector(D, Ray->Direction);
		}
		Isosrf->Inv3 = 1;

		if(Isosrf->closed != false)
		{
			VEvaluateRay(VTmp, P, Depth1, D);
			tmp = Vector_IsoSurface_Function(Isosrf, VTmp);
			if(Depth1 > Isosrf->accuracy)
			{
				if(tmp < 0.0)					/* The ray hits the bounding shape */
				{
					VEvaluateRay(IPoint, Ray->Initial, Depth1, Ray->Direction);
					if(Point_In_Clip(IPoint, Object->Clip))
					{
						push_entry_i1(Depth1, IPoint, Object, Side1, Depth_Stack);
						IFound = true;
						itrace++;
						Isosrf->Inv3 *= -1;
					}
				}
			}
			else
			{
				if(tmp < (Isosrf->max_gradient * Isosrf->accuracy * 4.0))
				{
					Depth1 = Isosrf->accuracy * 5.0;
					VEvaluateRay(VTmp, P, Depth1, D);
					if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0)
						Isosrf->Inv3 = -1;
					/* Change the sign of the function (IPoint is in the bounding shpae.)*/
				}
				VEvaluateRay(VTmp, P, Depth2, D);
				if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0.0)
				{
					VEvaluateRay(IPoint, Ray->Initial, Depth2, Ray->Direction);
					if(Point_In_Clip(IPoint, Object->Clip))
					{
						push_entry_i1(Depth2, IPoint, Object, Side2, Depth_Stack);
						IFound = true;
					}
				}
			}
		}

		/*  METHOD 2   by R. Suzuki */
		tmax = Depth2 = min(Depth2, BOUND_HUGE);
		tmin = Depth1 = min(Depth2, Depth1);
		if((tmax - tmin) < Isosrf->accuracy)
			return (false);
		Increase_Counter(stats[Ray_IsoSurface_Tests]);
		if((Depth1 < Isosrf->accuracy) && (Isosrf->Inv3 == 1))
		{
			/* IPoint is on the isosurface */
			VEvaluateRay(VTmp, P, tmin, D);
			if(fabs(Vector_IsoSurface_Function(Isosrf, VTmp)) < (Isosrf->max_gradient * Isosrf->accuracy * 4.0))
			{
				tmin = Isosrf->accuracy * 5.0;
				VEvaluateRay(VTmp, P, tmin, D);
				if(Vector_IsoSurface_Function(Isosrf, VTmp) < 0)
					Isosrf->Inv3 = -1;
				/* change the sign and go into the isosurface */
			}
		}

		for (; itrace < Isosrf->max_trace; itrace++)
		{
			if(IsoSurface_Function_Find_Root(Isosrf, P, D, &tmin, &tmax, in_shadow_test) == false)
				break;
			else
			{
				VEvaluateRay(IPoint, Ray->Initial, tmin, Ray->Direction);
				if(Point_In_Clip(IPoint, Object->Clip))
				{
					push_entry_i1(tmin, IPoint, Object, 0 /*Side1*/, Depth_Stack);
					IFound = true;
				}
			}
			tmin += Isosrf->accuracy * 5.0;
			if((tmax - tmin) < Isosrf->accuracy)
				break;
			Isosrf->Inv3 *= -1;
		}

		if(IFound)
			Increase_Counter(stats[Ray_IsoSurface_Tests_Succeeded]);
	}

	return (IFound);
}
예제 #24
0
파일: sphere.cpp 프로젝트: SteveShaw/povray
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);
    }
}
예제 #25
0
파일: ovus.cpp 프로젝트: jwmynhier/povray
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);
}