Пример #1
0
INT	PolyPeIntersect(RAY *pr, ELEMENT *pe, IRECORD *hit)
	{
	INT	i;
	INT	*vindex;		/* Vertex index pointer.	     */
	INT	toright;		/* Counter.			     */
	INT	sh, nsh;		/* Sign holders.		     */
	REAL	Rd_dot_Pn;		/* Polygon normal dot ray direction. */
	REAL	Ro_dot_Pn;		/* Polygon normal dot ray origin.    */
	REAL	tval;			/* Intersection t distance value.    */
	REAL	x[MAX_VERTS + 1];	/* Projection list.		     */
	REAL	y[MAX_VERTS + 1];	/* Projection list.		     */
	REAL	ix, iy; 		/* Intersection projection point.    */
	REAL	dx, dy; 		/* Deltas between 2 vertices.	     */
	REAL	xint;			/* Intersection value.		     */
	VEC3	I;			/* Intersection point.		     */
	VEC3	*vlist, *vpos;		/* Vertex list pointer. 	     */
	POLY	*pp;			/* Ptr to polygon data. 	     */

	pp = (POLY *)pe->data;

	Rd_dot_Pn = VecDot(pp->norm, pr->D);

	if (ABS(Rd_dot_Pn) < RAYEPS)		/* Ray is parallel.	     */
		return (0);

	Ro_dot_Pn = VecDot(pp->norm, pr->P);

	tval = -(pp->d + Ro_dot_Pn)/Rd_dot_Pn;	/* Intersection distance.    */
	if (tval < RAYEPS)			/* Intersects behind ray.    */
		return (0);

	RayPoint(I, pr, tval);


	/* Polygon containment. */

	/* Project onto plane with greatest normal component. */

	vlist  = pp->vptr;
	vindex = pp->vindex;

	switch (pp->axis_proj)
		{
		case X_AXIS:
			for (i = 0; i < pp->nverts; i++)
				{
				vpos = vlist + (*vindex);
				x[i] = (*vpos)[1];
				y[i] = (*vpos)[2];
				vindex++;
				}

			ix = I[1];
			iy = I[2];
			break;

		case Y_AXIS:
			for (i = 0; i < pp->nverts; i++)
				{
				vpos = vlist + (*vindex);
				x[i] = (*vpos)[0];
				y[i] = (*vpos)[2];
				vindex++;
				}

			ix = I[0];
			iy = I[2];
			break;

		case Z_AXIS:
			for (i = 0; i < pp->nverts; i++)
				{
				vpos = vlist + (*vindex);
				x[i] = (*vpos)[0];
				y[i] = (*vpos)[1];
				vindex++;
				}

			ix = I[0];
			iy = I[1];
			break;
		}


	/* Translate to origin. */

	for (i = 0; i < pp->nverts; i++)
		{
		x[i] -= ix;
		y[i] -= iy;

		if (ABS(y[i]) < RAYEPS)
			y[i] = 0.0;
		}

	x[pp->nverts] = x[0];
	y[pp->nverts] = y[0];


	/*
	 *	If intersection point crosses an odd number of line segments,
	 *	the point is inside the polygon
	 */


	if (y[0] < 0.0)
		sh = 0;
	else
		sh = 1;

	toright = 0;

	for (i = 0; i < pp->nverts; i++)
		{
		/* Check if segment crosses in y. */

		if (y[i + 1] < 0.0)
			nsh = 0;
		else
			nsh = 1;

		if (nsh ^ sh)
			{
			dy = y[i + 1] - y[i];

			if (ABS(dy) >= RAYEPS)
				{
				dx   = x[i + 1] - x[i];
				xint = x[i] - y[i]*dx / dy;

				if (xint > 0.0)
					toright++;
				}
			}

		sh = nsh;
		}

	if (toright%2 == 1)
		{
		IsectAdd(hit, tval, pe);
		return (1);
		}
	else
		return (0);
	}
Пример #2
0
VOID	RayTrace(INT pid)
	{
	INT	j;
	INT	x, y;			/* Pixel address.		     */
	REAL	xx, yy;
	VEC3	N;			/* Normal at intersection.	     */
	VEC3	Ipoint; 		/* Intersection point.		     */
	COLOR	c;			/* Color for storing background.     */
	RAY	*ray;			/* Ray pointer. 		     */
	RAY	rmsg;			/* Ray message. 		     */
	RAYJOB	job;			/* Ray job from work pool.	     */
	OBJECT	*po;			/* Ptr to object.		     */
	BOOL	hit;			/* An object hit?		     */
	IRECORD hitrecord;		/* Intersection record. 	     */

	ray = &rmsg;

	while (GetJobs(&job, pid) != WPS_EMPTY)
		{
		while (GetRayJobFromBundle(&job, &x, &y))
			{
			/* Convert the ray job to the ray message format. */

			xx = (REAL)x;
			yy = (REAL)y;

			if (AntiAlias)
				for (j = 0; j < NumSubRays; j++)
					{
					ConvertPrimRayJobToRayMsg(ray, xx + frand(), yy + frand());
					PushRayTreeStack(ray, pid);
					}
			else
				{
				ConvertPrimRayJobToRayMsg(ray, xx, yy);
				PushRayTreeStack(ray, pid);
				}

			while (PopRayTreeStack(ray, pid) != RTS_EMPTY)
				{
				/* Find which object is closest along the ray. */

				switch (TraversalType)
					{
					case TT_LIST:
						hit = Intersect(ray, &hitrecord);
						break;

					case TT_HUG:
						hit = TraverseHierarchyUniform(ray, &hitrecord, pid);
						break;
					}

				/* Process the object ray hit. */

				if (hit)
					{
					/*
					 *  Get parent object to be able to access
					 *  object operations.
					 */

					po = hitrecord.pelem->parent;

					/* Calculate intersection point. */
					RayPoint(Ipoint, ray, hitrecord.t);

					/* Calculate normal at this point. */
					((void (*)(IRECORD *, VEC3, VEC3))(*po->procs->normal))(&hitrecord, Ipoint, N);

					/* Make sure normal is pointing toward ray origin. */
					if ((VecDot(ray->D, N)) >  0.0)
						VecNegate(N, N);

					/*
					 *  Compute shade at this point - will process
					 *  shadow rays and add secondary reflection
					 *  and refraction rays to ray tree stack
					 */

					Shade(Ipoint, N, ray, &hitrecord, pid);
					}
				else
					{
					/* Add background as pixel contribution. */

					VecCopy(c, View.bkg);
					VecScale(c, ray->weight, c);
					AddPixelColor(c, ray->x, ray->y);
					}
				}
			}
		}
	}