INT SphPeIntersect(RAY *pr, ELEMENT *pe, IRECORD *hit) { INT nhits; /* Number of hits. */ REAL b, disc, t1, t2, vsq; /* Formula variables. */ SPHERE *ps; /* Ptr to sphere data. */ POINT V; /* C - P */ IRECORD *sphhit; ps = (SPHERE *)(pe->data); sphhit = hit; VecSub(V, ps->center, pr->P); /* Ray from origin to center.*/ vsq = VecDot(V, V); /* Length sq of V. */ b = VecDot(V, pr->D); /* Perpendicular scale of V. */ if (vsq > ps->rad2 && b < RAYEPS) /* Behind ray origin. */ return (0); disc = b*b - vsq + ps->rad2; /* Discriminate. */ if (disc < 0.0) /* Misses ray. */ return (0); disc = sqrt(disc); /* Find intersection param. */ t2 = b + disc; t1 = b - disc; if (t2 <= RAYEPS) /* Behind ray origin. */ return (0); nhits = 0; if (t1 > RAYEPS) /* Entering sphere. */ { IsectAdd(sphhit, t1, pe); sphhit++; nhits++; } IsectAdd(sphhit, t2, pe); /* Exiting sphere */ nhits++; return (nhits); }
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); }