home *** CD-ROM | disk | FTP | other *** search
- /*
- Author: S.N.pattanaik
- Date : 24 March 1991.
-
- NOTE : The Quadrilateral must be CONVEX.
- */
-
- #include <stdio.h>
- #include <math.h>
- #include "GraphicsGems.h"
- #include "data_structure.h"
-
- double plane_intersect(ray_start,ray_direction,
- plane_normal,plane_constant)
- /*
- This routine returns the parameter of intersection
- of a ray defined as (ray_start+t.ray_direction) and
- a polygon.
- NOTE : No assumption of the vectors being normalised has been made.
- */
- Point3 *ray_start; /* Input */
- Vector3 *ray_direction,*plane_normal; /* Input */
- double plane_constant; /* Input */
- {
- double t = -1.0,product;
- if(fabs(product=V3Dot(ray_direction,plane_normal))>EPSILON){
- if(product<0.0)
- t = -(plane_constant+V3Dot(ray_start,plane_normal))/product;
- }
- return(t);
- }
-
- double ray_polygon(ray_start,ray_direction,plane_normal, plane_constant,dominant_axis,n,vlist)
- /*
- Adapted from "An Introduction to Ray Tracing" by Andrew Glassner.
-
- Project the polygon points on a co-ordinate plane.
- The projection does not preserve area but topology
- is preserved.
- Projection is simply throwing away that co-ordinate.
- Translate the polygon so that the intersection point is at origin.
- This simply means subtract the intersection point coordinate from
- each vertex of the polygon.
- Test each edge of the polygon against the +U axis. Count the total
- number of crosses. If the number is odd then the point is inside
- else outside.
- The algo has been given a winding number flavour. - Check -
- */
- Point3 *ray_start; /* Input */
- Vector3 *ray_direction; /* Input */
- Vector3 *plane_normal; /* Input */
- double plane_constant; /* Input */
- char dominant_axis; /* Input */
- int n; /* Input */
- Point3 *vlist; /* Input */
- {
- /*
- * Quadrants are defined as:
- * |
- * 1 | 0
- * |
- * -------c--------
- * |
- * 2 | 3
- * |
- */
- #define quadrant(p, c) ((p.x<c.x) ? ((p.y<c.y) ? 2 : 1) : ((p.y<c.y) ? 3 : 0))
-
-
- double t=plane_intersect(ray_start,ray_direction,
- plane_normal,plane_constant);
- if (t > EPSILON){ /* Check if point inside polygon or not */
- int i,num_of_crossings=0;
- Point2 C,last,cur;
- char lastquad,curquad;
-
- if (dominant_axis == 0){ /* X Axis */
- C.x = (*ray_start).y + t*(*ray_direction).y;
- C.y = (*ray_start).z + t*(*ray_direction).z;
- }
- else if (dominant_axis == 1){ /* Y Axis */
- C.x = (*ray_start).z + t*(*ray_direction).z;
- C.y = (*ray_start).x + t*(*ray_direction).x;
- }
- else{ /* Z Axis */
- C.x = (*ray_start).x + t*(*ray_direction).x;
- C.y = (*ray_start).y + t*(*ray_direction).y;
- }
- project_point(last,vlist[n-1],dominant_axis);
- lastquad = quadrant(last,C);
- for(i=0; i< n;i++,last=cur){
- project_point(cur,vlist[i],dominant_axis);
- curquad = quadrant(cur,C);
- if (curquad == lastquad) continue;
- if (((lastquad+1) & 3)==curquad) num_of_crossings++;
- else if (((curquad + 1) & 3) == lastquad) num_of_crossings--;
- else{
- /*
- * Find where edge crosses
- * center's X axis.
- */
- double right,left;
- right = last.x - cur.x;
- left = (last.y - cur.y) * (C.x - last.x);
- if (left + last.y * right > right * C.y)
- num_of_crossings+=2;
- else
- num_of_crossings-=2;
- }
- lastquad = curquad;
- }
- if (num_of_crossings != 0) return(t);
- }
- return(-1.);
- }
-
- double ray_quadrilateral(ray_start,ray_direction,
- plane_normal, plane_constant,
- Du0,Du1,Du2,Dux,Duy,
- Dv0,Dv1,Dv2,Dvx,Dvy,
- Qux,Quy,Qvx,Qvy,Na,Nb,Nc,
- pu,pv)
- /*
- This routine computes if
- the ray intersects the CONVEX quadrilateral.
- and
- returns the ray parameter t and
- surface parameters (u,v) of intersection.
- Because of the (u,v) requirement, the following method
- uses inverse mapping of the point of intersection
- of the ray with the plane to compute (u,v).
- For the point to be inside the quadrilateral the
- (u,v) will be in the range 0 to 1.
- So t > 0 and
- (u,v) are in the range 0 to 1 for a valid intersection.
-
- Source: "Essential Ray Tracing Algorithms" by Eric Haines in
- "An Introduction to RayTracing", page 59.
-
- NOTE : Assume that the Quadrilateral is CONVEX.
- */
- Point3 *ray_start; /* Input */
- Vector3 *ray_direction; /* Input */
- Vector3 *plane_normal; /* Input */
- double plane_constant; /* Input */
- double Du0,Du1,Du2,Dux,Duy,
- Dv0,Dv1,Dv2,Dvx,Dvy;
- Vector3 *Qux,*Quy,*Qvx,*Qvy;
- Vector3 *Na,*Nb,*Nc; /* Input. Precomputed according to the
- equations given in the Source. */
- double *pu, *pv; /* Output */
- {
- double t=plane_intersect(ray_start,ray_direction,
- plane_normal,plane_constant);
- if (t > EPSILON){
- Point3 R;
- R.x = (*ray_start).x + t*(*ray_direction).x;
- R.y = (*ray_start).y + t*(*ray_direction).y;
- R.z = (*ray_start).z + t*(*ray_direction).z;
- if (fabs(Du2) < EPSILON)
- *pu = (V3Dot(Nc,&R)-Du0)/(Du1-V3Dot(Na,&R));
- else{
- double Ka=Dux+V3Dot(Qux,&R),
- Kb=Duy+V3Dot(Quy,&R);
- double discriminant=sqrt(Ka*Ka-Kb);
- if (Ka < discriminant) *pu = Ka + discriminant;
- else *pu = Ka - discriminant;
- }
- if ( (*pu < 0.0) || (*pu > 1.0)) return(-1.0);
- if (fabs(Dv2) < EPSILON)
- *pv = (V3Dot(Nb,&R)-Dv0)/(Dv1-V3Dot(Na,&R));
- else{
- double Ka=Dvx+V3Dot(Qvx,&R),
- Kb=Dvy+V3Dot(Qvy,&R);
- double discriminant=sqrt(Ka*Ka-Kb);
- if (discriminant < 0.0) return(-1.0);
- if (Ka < discriminant) *pv = Ka + discriminant;
- else *pv = Ka - discriminant;
- }
- if ( (*pv < 0.0) || (*pv > 1.0)) return(-1.0);
- return(t);
- }
- return(-1.);
- }
-