Exemple #1
0
object * newtri(void * tex, vector v0, vector v1, vector v2) {
  tri * t;
  vector edge1, edge2, edge3;

  VSub(&v1, &v0, &edge1);
  VSub(&v2, &v0, &edge2);
  VSub(&v2, &v1, &edge3);

  /* check to see if this will be a degenerate triangle before creation */
  if ((VLength(&edge1) >= EPSILON) && 
      (VLength(&edge2) >= EPSILON) && 
      (VLength(&edge3) >= EPSILON)) {

    t=(tri *) rt_getmem(sizeof(tri));

    t->nextobj = NULL;
    t->methods = &tri_methods;

    t->tex = (texture *)tex;
    t->v0 = v0;
    t->edge1 = edge1;
    t->edge2 = edge2;
 
    return (object *) t;
  }
  
  return NULL; /* was a degenerate triangle */
}
Exemple #2
0
int
All_Torus_Intersections(void)
{
  double len;
  VECTOR D;
  VLength(len, D);
  VLength(len, D);
  return 0;
}
void Compute_Cylinder_Data(OBJECT *Object)
{
  DBL tmpf;
  VECTOR axis;
  CONE *Cone = (CONE *)Object;

  VSub(axis, Cone->apex, Cone->base);

  VLength(tmpf, axis);

  if (tmpf < EPSILON)
  {
    Error("Degenerate cylinder, base point = apex point.");
  }
  else
  {
    VInverseScaleEq(axis, tmpf);

    Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf);
  }

  Cone->dist = 0.0;

  /* Recalculate the bounds */

  Compute_Cone_BBox(Cone);
}
Exemple #4
0
static void waves (const VECTOR EPoint, const TNORMAL *Tnormal, VECTOR normal, const TraceThreadData *Thread)
{
	register unsigned int i;
	register DBL length, scalar, index, sinValue ;
	VECTOR point;

	for (i = 0 ; i < Thread->numberOfWaves ; i++)
	{
		VSub (point, EPoint, *Thread->waveSources[i]);

		VLength (length, point);

		if (length == 0.0)
		{
			length = 1.0;
		}

		index = length * Tnormal->Frequency * Thread->waveFrequencies[i] + Tnormal->Phase;

		sinValue = cycloidal(index);

		scalar = sinValue * Tnormal->Amount / Thread->waveFrequencies[i];

		VAddScaledEq(normal, scalar / (length * (DBL)Thread->numberOfWaves), point);
	}
}
Exemple #5
0
static void Scale_Smooth_Triangle(OBJECT *Object, VECTOR Vector, TRANSFORM * /*Trans*/)
{
  DBL Length;
  SMOOTH_TRIANGLE *Triangle = (SMOOTH_TRIANGLE *)Object;

  if (!Test_Flag(Object, DEGENERATE_FLAG))
  {
/*  BEG ROSE
    this is useless, because Compute_Triange recalculates this anyway:
    Triangle->Normal_Vector[X] = Triangle->Normal_Vector[X] / Vector[X];
    Triangle->Normal_Vector[Y] = Triangle->Normal_Vector[Y] / Vector[Y];
    Triangle->Normal_Vector[Z] = Triangle->Normal_Vector[Z] / Vector[Z];

    VLength(Length, Triangle->Normal_Vector);
    VScaleEq(Triangle->Normal_Vector, 1.0 / Length);
    Triangle->Distance /= Length;
    END ROSE */

    VEvaluateEq(Triangle->P1, Vector);
    VEvaluateEq(Triangle->P2, Vector);
    VEvaluateEq(Triangle->P3, Vector);

/*  BEG ROSE
    The normal vectors also have to be transformed (BUG fix): */
    Triangle->N1[X] /= Vector[X];
    Triangle->N1[Y] /= Vector[Y];
    Triangle->N1[Z] /= Vector[Z];
    VLength(Length,Triangle->N1);
    VScaleEq(Triangle->N1,1.0/Length);
    Triangle->N2[X] /= Vector[X];
    Triangle->N2[Y] /= Vector[Y];
    Triangle->N2[Z] /= Vector[Z];
    VLength(Length,Triangle->N2);
    VScaleEq(Triangle->N2,1.0/Length);
    Triangle->N3[X] /= Vector[X];
    Triangle->N3[Y] /= Vector[Y];
    Triangle->N3[Z] /= Vector[Z];
    VLength(Length,Triangle->N3);
    VScaleEq(Triangle->N3,1.0/Length);
/*  END ROSE */

    Compute_Triangle((TRIANGLE *)Triangle,true);
  }
}
Exemple #6
0
static int intersect_poylgon(RAY *Ray, POLYGON *Polyg, DBL *Depth)
{
  DBL x, y, len;
  VECTOR p, d;

  /* Don't test degenerate polygons. */

  if (Test_Flag(Polyg, DEGENERATE_FLAG))
  {
    return(false);
  }

  Increase_Counter(stats[Ray_Polygon_Tests]);

  /* Transform the ray into the polygon space. */

  MInvTransPoint(p, Ray->Initial, Polyg->Trans);

  MInvTransDirection(d, Ray->Direction, Polyg->Trans);

  VLength(len, d);

  VInverseScaleEq(d, len);

  /* Intersect ray with the plane in which the polygon lies. */

  if (fabs(d[Z]) < ZERO_TOLERANCE)
  {
    return(false);
  }

  *Depth = -p[Z] / d[Z];

  if ((*Depth < DEPTH_TOLERANCE) || (*Depth > Max_Distance))
  {
    return(false);
  }

  /* Does the intersection point lie inside the polygon? */

  x = p[X] + *Depth * d[X];
  y = p[Y] + *Depth * d[Y];

  if (in_polygon(Polyg->Data->Number, Polyg->Data->Points, x, y))
  {
    Increase_Counter(stats[Ray_Polygon_Tests_Succeeded]);

    *Depth /= len;

    return (true);
  }
  else
  {
    return (false);
  }
}
Exemple #7
0
static DBL point_plane_distance(VECTOR p, VECTOR  n, DBL *d)
{
  DBL temp1, temp2;

  VDot(temp1, p, n);

  temp1 += *d;

  VLength(temp2, n);

  if (fabs(temp2) < EPSILON)
  {
    return (0.0);
  }

  temp1 /= temp2;

  return (temp1);
}
static int Intersect_Disc (RAY *Ray, DISC *disc, DBL *Depth)
{
  DBL t, u, v, r2, len;
  VECTOR P, D;

  Increase_Counter(stats[Ray_Disc_Tests]);

  /* Transform the point into the discs space */

  MInvTransPoint(P, Ray->Initial, disc->Trans);
  MInvTransDirection(D, Ray->Direction, disc->Trans);

  VLength(len, D);
  VInverseScaleEq(D, len);

  if (fabs(D[Z]) > EPSILON)
  {
    t = -P[Z] / D[Z];

    if (t >= 0.0)
    {
      u = P[X] + t * D[X];
      v = P[Y] + t * D[Y];

      r2 = Sqr(u) + Sqr(v);

      if ((r2 >= disc->iradius2) && (r2 <= disc->oradius2))
      {
        *Depth = t / len;

        if ((*Depth > Small_Tolerance) && (*Depth < Max_Distance))
        {
          Increase_Counter(stats[Ray_Disc_Tests_Succeeded]);

          return (true);
        }
      }
    }
  }

  return (false);
}
Exemple #9
0
void Plane::Scale(const VECTOR Vector, const TRANSFORM *tr)
{
	DBL Length;

	if(Trans == NULL)
	{
		VDivEq(Normal_Vector, Vector);

		VLength(Length, Normal_Vector);

		VInverseScaleEq(Normal_Vector, Length);

		Distance /= Length;

		Compute_BBox();
	}
	else
	{
		Transform(tr);
	}
}
Exemple #10
0
static void merge_spheres(VECTOR C, DBL *r, VECTOR  C1, DBL  r1, VECTOR  C2, DBL  r2)
{
	DBL l, r1r, r2r, k1, k2;
	VECTOR D;

	VSub(D, C1, C2);

	VLength(l, D);

	/* Check if one sphere encloses the other. */

	r1r = sqrt(r1);
	r2r = sqrt(r2);

	if (l + r1r <= r2r)
	{
		Assign_Vector(C, C2);

		*r = r2;

		return;
	}

	if (l + r2r <= r1r)
	{
		Assign_Vector(C, C1);

		*r = r1;

		return;
	}

	k1 = (1.0 + (r1r - r2r) / l) / 2.0;
	k2 = (1.0 + (r2r - r1r) / l) / 2.0;

	VLinComb2(C, k1, C1, k2, C2);

	*r = Sqr((l + r1r + r2r) / 2.0);
}
static void Scale_Plane (OBJECT *Object, VECTOR Vector, TRANSFORM *Trans)
{
  DBL Length;
  PLANE *Plane = (PLANE  *) Object;

  if (Plane->Trans == NULL)
  {
    VDivEq(Plane->Normal_Vector, Vector);

    VLength(Length, ((PLANE *)Object)->Normal_Vector);

    VInverseScaleEq (((PLANE *)Object)->Normal_Vector, Length);

    ((PLANE *)Object)->Distance /= Length;

    Compute_Plane_BBox(Plane);
  }
  else
  {
    Transform_Plane (Object, Trans);
  }
}
Exemple #12
0
static void Quadric_Normal(VECTOR Result, OBJECT *Object, INTERSECTION *Inter)
{
  QUADRIC *Quadric = (QUADRIC *) Object;
  DBL Len;

  /* This is faster and shorter. [DB 7/94] */

  Result[X] = 2.0 * QA * Inter->IPoint[X] +
                    QB * Inter->IPoint[Y] +
                    QC * Inter->IPoint[Z] +
                    QD;

  Result[Y] =       QB * Inter->IPoint[X] +
              2.0 * QE * Inter->IPoint[Y] +
                    QF * Inter->IPoint[Z] +
                    QG;

  Result[Z] =       QC * Inter->IPoint[X] +
                    QF * Inter->IPoint[Y] +
              2.0 * QH * Inter->IPoint[Z] +
                    QI;

  VLength(Len, Result);

  if (Len == 0.0)
  {
    /* The normal is not defined at this point of the surface. */
    /* Set it to any arbitrary direction. */

    Make_Vector(Result, 1.0, 0.0, 0.0);
  }
  else
  {
    VInverseScaleEq(Result, Len);
  }
}
void bump_map(VECTOR EPoint, TNORMAL *Tnormal, VECTOR normal)
{
  DBL xcoor = 0.0, ycoor = 0.0;
  int index, index2, index3;
  COLOUR colour1, colour2, colour3;
  VECTOR p1, p2, p3;
  VECTOR bump_normal;
  VECTOR xprime, yprime, zprime, Temp;
  DBL Length;
  DBL Amount = Tnormal->Amount;
  IMAGE *Image = Tnormal->Vals.Image;

  Make_ColourA(colour1, 0.0, 0.0, 0.0, 0.0, 0.0);
  Make_ColourA(colour2, 0.0, 0.0, 0.0, 0.0, 0.0);
  Make_ColourA(colour3, 0.0, 0.0, 0.0, 0.0, 0.0);

  /* going to have to change this */
  /* need to know if bump point is off of image for all 3 points */

  if (map(EPoint, (TPATTERN *) Tnormal, &xcoor, &ycoor))
  {
    return;
  }
  else
  {
    image_colour_at(Image, xcoor, ycoor, colour1, &index);
  }

  xcoor--;
  ycoor++;

  if (xcoor < 0.0)
  {
    xcoor += (DBL)Image->iwidth;
  }
  else
  {
    if (xcoor >= Image->iwidth)
    {
      xcoor -= (DBL)Image->iwidth;
    }
  }

  if (ycoor < 0.0)
  {
    ycoor += (DBL)Image->iheight;
  }
  else
  {
    if (ycoor >= (DBL)Image->iheight)
    {
      ycoor -= (DBL)Image->iheight;
    }
  }

  image_colour_at(Image, xcoor, ycoor, colour2, &index2);

  xcoor += 2.0;

  if (xcoor < 0.0)
  {
    xcoor += (DBL)Image->iwidth;
  }
  else
  {
    if (xcoor >= Image->iwidth)
    {
      xcoor -= (DBL)Image->iwidth;
    }
  }

  image_colour_at(Image, xcoor, ycoor, colour3, &index3);

  if (Image->Colour_Map == NULL || Image->Use_Colour_Flag)
  {
    p1[X] = 0;
    p1[Y] = Amount * (GREY_SCALE( colour1 ));
    p1[Z] = 0;

    p2[X] = -1;
    p2[Y] = Amount * (GREY_SCALE( colour2 ));
    p2[Z] = 1;

    p3[X] = 1;
    p3[Y] = Amount * (GREY_SCALE( colour3 ));
    p3[Z] = 1;
  }
  else
  {
    p1[X] = 0;
    p1[Y] = Amount * index;
    p1[Z] = 0;

    p2[X] = -1;
    p2[Y] = Amount * index2;
    p2[Z] = 1;

    p3[X] = 1;
    p3[Y] = Amount * index3;
    p3[Z] = 1;
  }

  /* we have points 1,2,3 for a triangle now we need the surface normal for it */

  VSub(xprime, p1, p2);
  VSub(yprime, p3, p2);
  VCross(bump_normal, yprime, xprime);
  VNormalize(bump_normal, bump_normal);

  Assign_Vector(yprime, normal);
  Make_Vector(Temp, 0.0, 1.0, 0.0);
  VCross(xprime, yprime, Temp);
  VLength(Length, xprime);

  if (Length < EPSILON)
  {
    if (fabs(normal[Y] - 1.0) < Small_Tolerance)
    {
      Make_Vector(yprime, 0.0, 1.0, 0.0);
      Make_Vector(xprime, 1.0, 0.0, 0.0);
      Length = 1.0;
    }
    else
    {
      Make_Vector(yprime, 0.0, -1.0, 0.0);
      Make_Vector(xprime, 1.0, 0.0, 0.0);
      Length = 1.0;
    }
  }

  VScaleEq(xprime, 1.0 / Length);
  VCross(zprime, xprime, yprime);
  VNormalizeEq(zprime);
  VScaleEq(xprime, bump_normal[X]);
  VScaleEq(yprime, bump_normal[Y]);
  VScaleEq(zprime, bump_normal[Z]);
  VAdd(Temp, xprime, yprime);
  VScaleEq(zprime, -1);
  VAdd(normal, Temp, zprime);
}
Exemple #14
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;
}
Exemple #15
0
int Torus::Intersect(const Ray& ray, DBL *Depth, SceneThreadData *Thread) const
{
	int i, n;
	DBL len, R2, Py2, Dy2, PDy2, k1, k2;
	DBL y1, y2, r1, r2;
	DBL c[5];
	DBL r[4];
	VECTOR P, D;
	DBL DistanceP;            // Distance from P to torus center (origo).
	DBL BoundingSphereRadius; // Sphere fully (amply) enclosing torus.
	DBL Closer;               // P is moved Closer*D closer to torus.

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

	/* Transform the ray into the torus space. */

	MInvTransPoint(P, ray.Origin, Trans);

	MInvTransDirection(D, ray.Direction, Trans);

	VLength(len, D);

	VInverseScaleEq(D, len);

	i = 0;

	y1 = -MinorRadius;
	y2 =  MinorRadius;
	r1 = Sqr(MajorRadius - MinorRadius);

	if ( MajorRadius < MinorRadius )
		r1 = 0;

	r2 = Sqr(MajorRadius + MinorRadius);

#ifdef TORUS_EXTRA_STATS
	Thread->Stats()[Torus_Bound_Tests]++;
#endif

	if (Test_Thick_Cylinder(P, D, y1, y2, r1, r2))
	{
#ifdef TORUS_EXTRA_STATS
		Thread->Stats()[Torus_Bound_Tests_Succeeded]++;
#endif

		// Move P close to bounding sphere to have more precise root calculation.
		// Bounding sphere radius is R + r, we add r once more to ensure
		// that P is safely outside sphere.
		BoundingSphereRadius = MajorRadius + MinorRadius + MinorRadius;
		DistanceP = VSumSqr(P); // Distance is currently squared.
		Closer = 0.0;
		if (DistanceP > Sqr(BoundingSphereRadius))
		{
			DistanceP = sqrt(DistanceP); // Now real distance.
			Closer = DistanceP - BoundingSphereRadius;
			VAddScaledEq(P, Closer, D);
		}

		R2   = Sqr(MajorRadius);
		r2   = Sqr(MinorRadius);

		Py2  = P[Y] * P[Y];
		Dy2  = D[Y] * D[Y];
		PDy2 = P[Y] * D[Y];

		k1   = P[X] * P[X] + P[Z] * P[Z] + Py2 - R2 - r2;
		k2   = P[X] * D[X] + P[Z] * D[Z] + PDy2;

		c[0] = 1.0;

		c[1] = 4.0 * k2;

		c[2] = 2.0 * (k1 + 2.0 * (k2 * k2 + R2 * Dy2));

		c[3] = 4.0 * (k2 * k1 + 2.0 * R2 * PDy2);

		c[4] = k1 * k1 + 4.0 * R2 * (Py2 - r2);

		n = Solve_Polynomial(4, c, r, Test_Flag(this, STURM_FLAG), ROOT_TOLERANCE, Thread);

		while(n--)
			Depth[i++] = (r[n] + Closer) / len;
	}

	if (i)
		Thread->Stats()[Ray_Torus_Tests_Succeeded]++;

	return(i);
}
static int intersect_cone(RAY *Ray, CONE *Cone, CONE_INT *Intersection)
{
  int i = 0;
  DBL a, b, c, z, t1, t2, len;
  DBL d;
  VECTOR P, D;

  Increase_Counter(stats[Ray_Cone_Tests]);

  /* Transform the ray into the cones space */

  MInvTransPoint(P, Ray->Initial, Cone->Trans);
  MInvTransDirection(D, Ray->Direction, Cone->Trans);

  VLength(len, D);
  VInverseScaleEq(D, len);

  if (Test_Flag(Cone, CYLINDER_FLAG))
  {
    /* Solve intersections with a cylinder */

    a = D[X] * D[X] + D[Y] * D[Y];

    if (a > EPSILON)
    {
      b = P[X] * D[X] + P[Y] * D[Y];

      c = P[X] * P[X] + P[Y] * P[Y] - 1.0;

      d = b * b - a * c;

      if (d >= 0.0)
      {
        d = sqrt(d);

        t1 = (-b + d) / a;
        t2 = (-b - d) / a;

        z = P[Z] + t1 * D[Z];

        if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
        {
          Intersection[i].d   = t1 / len;
          Intersection[i++].t = SIDE_HIT;
        }

        z = P[Z] + t2 * D[Z];

        if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= 0.0) && (z <= 1.0))
        {
          Intersection[i].d   = t2 / len;
          Intersection[i++].t = SIDE_HIT;
        }
      }
    }
  }
  else
  {
    /* Solve intersections with a cone */

    a = D[X] * D[X] + D[Y] * D[Y] - D[Z] * D[Z];

    b = D[X] * P[X] + D[Y] * P[Y] - D[Z] * P[Z];

    c = P[X] * P[X] + P[Y] * P[Y] - P[Z] * P[Z];

    if (fabs(a) < EPSILON)
    {
      if (fabs(b) > EPSILON)
      {
        /* One intersection */

        t1 = -0.5 * c / b;

        z = P[Z] + t1 * D[Z];

        if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
        {
          Intersection[i].d   = t1 / len;
          Intersection[i++].t = SIDE_HIT;
        }
      }
    }
    else
    {
      /* Check hits against the side of the cone */

      d = b * b - a * c;

      if (d >= 0.0)
      {
        d = sqrt(d);

        t1 = (-b - d) / a;
        t2 = (-b + d) / a;

        z = P[Z] + t1 * D[Z];

        if ((t1 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
        {
          Intersection[i].d   = t1 / len;
          Intersection[i++].t = SIDE_HIT;
        }

        z = P[Z] + t2 * D[Z];

        if ((t2 > Cone_Tolerance) && (t1 < Max_Distance) && (z >= Cone->dist) && (z <= 1.0))
        {
          Intersection[i].d   = t2 / len;
          Intersection[i++].t = SIDE_HIT;
        }
      }
    }
  }

  if (Test_Flag(Cone, CLOSED_FLAG) && (fabs(D[Z]) > EPSILON))
  {
    d = (1.0 - P[Z]) / D[Z];

    a = (P[X] + d * D[X]);

    b = (P[Y] + d * D[Y]);

    if (((Sqr(a) + Sqr(b)) <= 1.0) && (d > Cone_Tolerance) && (d < Max_Distance))
    {
      Intersection[i].d   = d / len;
      Intersection[i++].t = CAP_HIT;
    }

    d = (Cone->dist - P[Z]) / D[Z];

    a = (P[X] + d * D[X]);

    b = (P[Y] + d * D[Y]);

    if ((Sqr(a) + Sqr(b)) <= (Test_Flag(Cone, CYLINDER_FLAG) ? 1.0 : Sqr(Cone->dist))
      && (d > Cone_Tolerance) && (d < Max_Distance))
    {
      Intersection[i].d   = d / len;
      Intersection[i++].t = BASE_HIT;
    }
  }

  if (i)
  {
    Increase_Counter(stats[Ray_Cone_Tests_Succeeded]);
  }

  return (i);
}
Exemple #17
0
int IsoSurface_Function_Find_Root(ISOSURFACE* ISOSRF, VECTOR P, VECTOR D, DBL* Depth1, DBL* Depth2, bool in_shadow_test)
{
	DBL dt, t21, l_b, l_e, oldmg;
	ISO_Pair EP1, EP2;
	VECTOR VTmp;

	Increase_Counter(stats[Ray_IsoSurface_Find_Root]);

	VLength(ISOSRF->Vlength, D);

	if(ISOSRF->cache)
	{
		Increase_Counter(stats[Ray_IsoSurface_Cache]);
		VEvaluateRay(VTmp, P, *Depth1, D);
		VSubEq(VTmp, ISOSRF->P);
		VLength(l_b, VTmp);
		VEvaluateRay(VTmp, P, *Depth2, D);
		VSubEq(VTmp, ISOSRF->D);
		VLength(l_e, VTmp);
		if((ISOSRF->fmax - ISOSRF->max_gradient * max(l_b, l_e)) > 0.0)
		{
			Increase_Counter(stats[Ray_IsoSurface_Cache_Succeeded]);
			return false;
		}
	}

	Assign_Vector(ISOSRF->P, P);
	Assign_Vector(ISOSRF->D, D);

	ISOSRF->cache = false;
	EP1.t = *Depth1;
	EP1.f = Float_IsoSurface_Function(ISOSRF, Depth1);
	ISOSRF->fmax = EP1.f;
	if((ISOSRF->closed == false) && (EP1.f < 0.0))
	{
		ISOSRF->Inv3 *= -1;
		EP1.f *= -1;
	}

	EP2.t = *Depth2;
	EP2.f = Float_IsoSurface_Function(ISOSRF, Depth2);
	ISOSRF->fmax = min(EP2.f, ISOSRF->fmax);

	oldmg = ISOSRF->max_gradient;
	t21 = (*Depth2 - *Depth1);
	if((ISOSRF->eval == true) && (ISOSRF->max_gradient > ISOSRF->eval_param[0]))
		ISOSRF->max_gradient *= ISOSRF->eval_param[2];
	dt = ISOSRF->max_gradient * ISOSRF->Vlength * t21;
	if(IsoSurface_Function_Find_Root_R(ISOSRF, &EP1, &EP2, dt, t21, 1.0 / (ISOSRF->Vlength * t21), in_shadow_test))
	{
		if(ISOSRF->eval == true)
		{
			DBL curvar = fabs(ISOSRF->max_gradient - oldmg);

			if(curvar > ISOSRF->mginfo->eval_var)
				ISOSRF->mginfo->eval_var = curvar;

			ISOSRF->mginfo->eval_cnt++;
			ISOSRF->mginfo->eval_gradient_sum += ISOSRF->max_gradient;

			if(ISOSRF->max_gradient > ISOSRF->mginfo->eval_max)
				ISOSRF->mginfo->eval_max = ISOSRF->max_gradient;
		}

		*Depth1 = ISOSRF->tl;

		return true;
	}
	else if(!in_shadow_test)
	{
		ISOSRF->cache = true;
		VEvaluateRay(ISOSRF->P, P, EP1.t, D);
		VEvaluateRay(ISOSRF->D, P, EP2.t, D);

		return false;
	}

	return false;
}
Exemple #18
0
static void IsoSurface_Normal(VECTOR Result, OBJECT* Object, INTERSECTION* Inter)
{
	VECTOR New_Point, TPoint;
	ISOSURFACE *Isosrf = (ISOSURFACE *)Object;
	FUNCTION Function = *(((ISOSURFACE *)Object)->Function);
	DBL funct;

	switch (Inter->i1)
	{
		case SIDE_X_0:
			Make_Vector(Result, -1.0, 0.0, 0.0);
			break;
		case SIDE_X_1:
			Make_Vector(Result, 1.0, 0.0, 0.0);
			break;
		case SIDE_Y_0:
			Make_Vector(Result, 0.0, -1.0, 0.0);
			break;
		case SIDE_Y_1:
			Make_Vector(Result, 0.0, 1.0, 0.0);
			break;
		case SIDE_Z_0:
			Make_Vector(Result, 0.0, 0.0, -1.0);
			break;
		case SIDE_Z_1:
			Make_Vector(Result, 0.0, 0.0, 1.0);
			break;

		default:

			/* Transform the point into the isosurface space */
			if(((ISOSURFACE *)Object)->Trans != NULL)
				MInvTransPoint(New_Point, Inter->IPoint, Isosrf->Trans);
			else
				Assign_Vector(New_Point, Inter->IPoint);

			if(Isosrf->container_shape)
			{
				VSub(Result, New_Point, Isosrf->container.sphere.center);
				VLength(funct, Result);
				if(fabs(funct - Isosrf->container.sphere.radius) < EPSILON)
				{
					VInverseScaleEq(Result, Isosrf->container.sphere.radius);
					break;
				}
			}

			Assign_Vector(TPoint, New_Point);
			funct = Evaluate_Function(Function, TPoint);
			Assign_Vector(TPoint, New_Point);
			TPoint[X] += Isosrf->accuracy;
			Result[X] = Evaluate_Function(Function, TPoint) - funct;
			Assign_Vector(TPoint, New_Point);
			TPoint[Y] += Isosrf->accuracy;
			Result[Y] = Evaluate_Function(Function, TPoint) - funct;
			Assign_Vector(TPoint, New_Point);
			TPoint[Z] += Isosrf->accuracy;
			Result[Z] = Evaluate_Function(Function, TPoint) - funct;

			if((Result[X] == 0) && (Result[Y] == 0) && (Result[Z] == 0))
				Result[X] = 1.0;
			VNormalize(Result, Result);
	}


	/* Transform the point into the boxes space. */

	if(((ISOSURFACE *)Object)->Trans != NULL)
	{
		MTransNormal(Result, Result, ((ISOSURFACE *)Object)->Trans);

		VNormalize(Result, Result);
	}
}
Exemple #19
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);
}
Exemple #20
0
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;
}
Exemple #21
0
int Compute_Triangle(TRIANGLE *Triangle,int Smooth)
{
  int swap,degn;
  VECTOR V1, V2, Temp;
  DBL Length;

  VSub(V1, Triangle->P1, Triangle->P2);
  VSub(V2, Triangle->P3, Triangle->P2);

  VCross(Triangle->Normal_Vector, V1, V2);

  VLength(Length, Triangle->Normal_Vector);

  /* Set up a flag so we can ignore degenerate triangles */

  if (Length == 0.0)
  {
    Set_Flag(Triangle, DEGENERATE_FLAG);

    return(false);
  }

  /* Normalize the normal vector. */

  VInverseScaleEq(Triangle->Normal_Vector, Length);

  VDot(Triangle->Distance, Triangle->Normal_Vector, Triangle->P1);

  Triangle->Distance *= -1.0;

  find_triangle_dominant_axis(Triangle);

  swap = false;

  switch (Triangle->Dominant_Axis)
  {
    case X:

      if ((Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[Z] - Triangle->P1[Z]) <
          (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[Y] - Triangle->P1[Y]))
      {
        swap = true;
      }

      break;

    case Y:

      if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Z] - Triangle->P1[Z]) <
          (Triangle->P2[Z] - Triangle->P3[Z])*(Triangle->P2[X] - Triangle->P1[X]))
      {
        swap = true;
      }

      break;

    case Z:

      if ((Triangle->P2[X] - Triangle->P3[X])*(Triangle->P2[Y] - Triangle->P1[Y]) <
          (Triangle->P2[Y] - Triangle->P3[Y])*(Triangle->P2[X] - Triangle->P1[X]))
      {
        swap = true;
      }

      break;
  }

  if (swap)
  {
    Assign_Vector(Temp, Triangle->P2);
    Assign_Vector(Triangle->P2, Triangle->P1);
    Assign_Vector(Triangle->P1, Temp);

    if (Smooth)
    {
      Assign_Vector(Temp, ((SMOOTH_TRIANGLE *)Triangle)->N2);
      Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N2, ((SMOOTH_TRIANGLE *)Triangle)->N1);
      Assign_Vector(((SMOOTH_TRIANGLE *)Triangle)->N1, Temp);
    }
  }
  
  degn=true;

  if (Smooth)
  {
    degn=compute_smooth_triangle((SMOOTH_TRIANGLE *)Triangle);
  }

  /* Build the bounding information from the vertices. */

  Compute_Triangle_BBox(Triangle);

  return(degn);
}
void Compute_Cone_Data(OBJECT *Object)
{
  DBL tlen, len, tmpf;
  VECTOR tmpv, axis, origin;
  CONE *Cone = (CONE *)Object;

  /* Process the primitive specific information */

  if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON)
  {
    /* What we are dealing with here is really a cylinder */

    Set_Flag(Cone, CYLINDER_FLAG);

    Compute_Cylinder_Data(Object);

    return;
  }

  if (Cone->apex_radius < Cone->base_radius)
  {
    /* Want the bigger end at the top */

    Assign_Vector(tmpv,Cone->base);
    Assign_Vector(Cone->base,Cone->apex);
    Assign_Vector(Cone->apex,tmpv);

    tmpf = Cone->base_radius;
    Cone->base_radius = Cone->apex_radius;
    Cone->apex_radius = tmpf;
  }

  /* Find the axis and axis length */

  VSub(axis, Cone->apex, Cone->base);

  VLength(len, axis);

  if (len < EPSILON)
  {
    Error("Degenerate cone/cylinder.");
  }
  else
  {
    VInverseScaleEq(axis, len);
  }

  /* Determine alignment */

  tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius);

  VScale(origin, axis, tmpf);

  VSub(origin, Cone->base, origin);

  tlen = tmpf + len;

  Cone->dist = tmpf / tlen;

  Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen);

  /* Recalculate the bounds */

  Compute_Cone_BBox(Cone);
}
Exemple #23
0
void Warp_EPoint (VECTOR TPoint, VECTOR EPoint, TPATTERN *TPat)
{
   VECTOR PTurbulence,RP;
   int Axis,i,temp_rand;
   int blockX = 0, blockY = 0, blockZ = 0 ;
   SNGL BlkNum;
   DBL  Length;
   DBL  Strength;
   WARP *Warp=TPat->Warps;
   TURB *Turb;
   TRANS *Tr;
   REPEAT *Repeat;
   BLACK_HOLE *Black_Hole;
   VECTOR Delta, Center;

   Assign_Vector(TPoint, EPoint);

   while (Warp != NULL)
   {
      switch(Warp->Warp_Type)
      {
        case CLASSIC_TURB_WARP:
          if ((TPat->Type == MARBLE_PATTERN) ||
              (TPat->Type == NO_PATTERN)     ||
              (TPat->Type == WOOD_PATTERN))
          {
             break;
          }
        /* If not a special type, fall through to next case */

        case EXTRA_TURB_WARP:
          Turb=(TURB *)Warp;
          DTurbulence (PTurbulence, TPoint, Turb);
          TPoint[X] += PTurbulence[X] * Turb->Turbulence[X];
          TPoint[Y] += PTurbulence[Y] * Turb->Turbulence[Y];
          TPoint[Z] += PTurbulence[Z] * Turb->Turbulence[Z];
          break;

        case NO_WARP:
          break;

        case TRANSFORM_WARP:
          Tr=(TRANS *)Warp;
          MInvTransPoint(TPoint, TPoint, &(Tr->Trans));
          break;

        case REPEAT_WARP:
          Repeat=(REPEAT *)Warp;
          Assign_Vector(RP,TPoint);
          Axis=Repeat->Axis;
          BlkNum=(SNGL)floor(TPoint[Axis]/Repeat->Width);
          
          RP[Axis]=TPoint[Axis]-BlkNum*Repeat->Width;
          
          if (((int)BlkNum) & 1)
          {          
             VEvaluateEq(RP,Repeat->Flip);
             if ( Repeat->Flip[Axis] < 0 ) 
             {
                RP[Axis] = Repeat->Width+RP[Axis];
             }
          }

          VAddScaledEq(RP,BlkNum,Repeat->Offset);
          Assign_Vector(TPoint,RP);
          break;

        case BLACK_HOLE_WARP:
          Black_Hole = (BLACK_HOLE *) Warp ;
          Assign_Vector (Center, Black_Hole->Center) ;

          if (Black_Hole->Repeat)
          {
            /* first, get the block number we're in for each dimension  */
            /* block numbers are (currently) calculated relative to 0   */
            /* we use floor () since it correctly returns -1 for the
               first block below 0 in each axis                         */
            /* one final point - we could run into overflow problems if
               the repeat vector was small and the scene very large.    */
            if (Black_Hole->Repeat_Vector [X] >= Small_Tolerance)
              blockX = (int) floor (TPoint [X] / Black_Hole->Repeat_Vector [X]) ;

            if (Black_Hole->Repeat_Vector [Y] >= Small_Tolerance)
              blockY = (int) floor (TPoint [Y] / Black_Hole->Repeat_Vector [Y]) ;

            if (Black_Hole->Repeat_Vector [Z] >= Small_Tolerance)
              blockZ = (int) floor (TPoint [Z] / Black_Hole->Repeat_Vector [Z]) ;

            if (Black_Hole->Uncertain)
            {
              /* if the position is uncertain calculate the new one first */
              /* this will allow the same numbers to be returned by frand */
              
              temp_rand = POV_GET_OLD_RAND(); /*protect seed*/
  
              POV_SRAND (Hash3d (blockX, blockY, blockZ)) ;
              Center [X] += FRAND () * Black_Hole->Uncertainty_Vector [X] ;
              Center [Y] += FRAND () * Black_Hole->Uncertainty_Vector [Y] ;
              Center [Z] += FRAND () * Black_Hole->Uncertainty_Vector [Z] ;
              POV_SRAND (temp_rand) ;  /*restore*/
            }

            Center [X] += Black_Hole->Repeat_Vector [X] * blockX ;
            Center [Y] += Black_Hole->Repeat_Vector [Y] * blockY ;
            Center [Z] += Black_Hole->Repeat_Vector [Z] * blockZ ;
          }

          VSub (Delta, TPoint, Center) ;
          VLength (Length, Delta) ;

          /* Length is the distance from the centre of the black hole */
          if (Length >= Black_Hole->Radius) break ;

          if (Black_Hole->Type == 0)
          {
            /* now convert the length to a proportion (0 to 1) that the point
               is from the edge of the black hole. a point on the perimeter
               of the black hole will be 0.0 ; a point at the centre will be
               1.0 ; a point exactly halfway will be 0.5, and so forth. */
            Length = (Black_Hole->Radius - Length) / Black_Hole->Radius ;

            /* Strength is the magnitude of the transformation effect. firstly,
               apply the Power variable to Length. this is meant to provide a
               means of controlling how fast the power of the Black Hole falls
               off from its centre. if Power is 2.0, then the effect is inverse
               square. increasing power will cause the Black Hole to be a lot
               weaker in its effect towards its perimeter. 
               
               finally we multiply Strength with the Black Hole's Strength
               variable. if the resultant value exceeds 1.0 we clip it to 1.0.
               this means a point will never be transformed by more than its
               original distance from the centre. the result of this clipping
               is that you will have an 'exclusion' area near the centre of
               the black hole where all points whose final value exceeded or
               equalled 1.0 were moved by a fixed amount. this only happens
               if the Strength value of the Black Hole was greater than one. */

            Strength = pow (Length, Black_Hole->Power) * Black_Hole->Strength ;
            if (Strength > 1.0) Strength = 1.0 ;
            
            /* if the Black Hole is inverted, it gives the impression of 'push-
               ing' the pattern away from its centre. otherwise it sucks. */
            VScaleEq (Delta, Black_Hole->Inverted ? -Strength : Strength) ;

            /* add the scaled Delta to the input point to end up with TPoint. */
            VAddEq (TPoint, Delta) ;
          }
          break;
          
        /* 10/23/1998 Talious added SPherical Cylindrical and toroidal
        warps */

        case CYLINDRICAL_WARP:
          warp_cylindrical(TPoint, (CYLW *)Warp);
          break;

        case PLANAR_WARP:
          warp_planar(TPoint, (PLANARW *)Warp);
          break;
      
        case SPHERICAL_WARP:
          warp_spherical(TPoint, (SPHEREW *)Warp);
          break;

        case TOROIDAL_WARP:
          warp_toroidal(TPoint, (TOROIDAL *) Warp);
          break;
          
        default:
          Error("Warp type %d not yet implemented",Warp->Warp_Type);
      }
      Warp=Warp->Next_Warp;
   }

   for (i=X; i<=Z; i++)
     if (TPoint[i] > COORDINATE_LIMIT)
       TPoint[i]= COORDINATE_LIMIT;
     else
       if (TPoint[i] < -COORDINATE_LIMIT)
         TPoint[i] = -COORDINATE_LIMIT;

}
Exemple #24
0
static DBL determine_subpatch_flatness(VECTOR (*Patch)[4][4])
{
  int i, j;
  DBL d, dist, temp1;
  VECTOR n, TempV;
  VECTOR vertices[4];

  Assign_Vector(vertices[0], (*Patch)[0][0]);
  Assign_Vector(vertices[1], (*Patch)[0][3]);

  VSub(TempV, vertices[0], vertices[1]);

  VLength(temp1, TempV);

  if (fabs(temp1) < EPSILON)
  {
    /*
     * Degenerate in the V direction for U = 0. This is ok if the other
     * two corners are distinct from the lower left corner - I'm sure there
     * are cases where the corners coincide and the middle has good values,
     * but that is somewhat pathalogical and won't be considered.
     */

    Assign_Vector(vertices[1], (*Patch)[3][3]);

    VSub(TempV, vertices[0], vertices[1]);

    VLength(temp1, TempV);

    if (fabs(temp1) < EPSILON)
    {
      return (-1.0);
    }

    Assign_Vector(vertices[2], (*Patch)[3][0]);

    VSub(TempV, vertices[0], vertices[1]);

    VLength(temp1, TempV);

    if (fabs(temp1) < EPSILON)
    {
      return (-1.0);
    }

    VSub(TempV, vertices[1], vertices[2]);

    VLength(temp1, TempV);

    if (fabs(temp1) < EPSILON)
    {
      return (-1.0);
    }
  }
  else
  {
    Assign_Vector(vertices[2], (*Patch)[3][0]);

    VSub(TempV, vertices[0], vertices[1]);

    VLength(temp1, TempV);

    if (fabs(temp1) < EPSILON)
    {
      Assign_Vector(vertices[2], (*Patch)[3][3]);

      VSub(TempV, vertices[0], vertices[2]);

      VLength(temp1, TempV);

      if (fabs(temp1) < EPSILON)
      {
        return (-1.0);
      }

      VSub(TempV, vertices[1], vertices[2]);

      VLength(temp1, TempV);

      if (fabs(temp1) < EPSILON)
      {
        return (-1.0);
      }
    }
    else
    {
      VSub(TempV, vertices[1], vertices[2]);

      VLength(temp1, TempV);

      if (fabs(temp1) < EPSILON)
      {
        return (-1.0);
      }
    }
  }

  /*
   * Now that a good set of candidate points has been found,
   * find the plane equations for the patch.
   */

  if (subpatch_normal(vertices[0], vertices[1], vertices[2], n, &d))
  {
    /*
     * Step through all vertices and see what the maximum
     * distance from the plane happens to be.
     */

    dist = 0.0;

    for (i = 0; i < 4; i++)
    {
      for (j = 0; j < 4; j++)
      {
        temp1 = fabs(point_plane_distance(((*Patch)[i][j]), n, &d));

        if (temp1 > dist)
        {
          dist = temp1;
        }
      }
    }

    return (dist);
  }
  else
  {
/*
    Debug_Info("Subpatch normal failed in determine_subpatch_flatness\n");
*/

    return (-1.0);
  }
}