| 1 |
greg |
1.1 |
#ifndef lint
|
| 2 |
greg |
2.2 |
static const char RCSid[] = "$Id$";
|
| 3 |
greg |
1.1 |
#endif
|
| 4 |
|
|
/*
|
| 5 |
|
|
* o_cone.c - routine to determine ray intersection with cones.
|
| 6 |
greg |
2.2 |
*/
|
| 7 |
|
|
|
| 8 |
greg |
2.3 |
#include "copyright.h"
|
| 9 |
greg |
1.1 |
|
| 10 |
|
|
#include "ray.h"
|
| 11 |
|
|
|
| 12 |
|
|
#include "otypes.h"
|
| 13 |
|
|
|
| 14 |
|
|
#include "cone.h"
|
| 15 |
|
|
|
| 16 |
|
|
|
| 17 |
|
|
o_cone(o, r) /* intersect ray with cone */
|
| 18 |
|
|
OBJREC *o;
|
| 19 |
|
|
register RAY *r;
|
| 20 |
|
|
{
|
| 21 |
|
|
FVECT rox, rdx;
|
| 22 |
|
|
double a, b, c;
|
| 23 |
|
|
double root[2];
|
| 24 |
|
|
int nroots, rn;
|
| 25 |
|
|
register CONE *co;
|
| 26 |
|
|
register int i;
|
| 27 |
|
|
|
| 28 |
|
|
/* get cone structure */
|
| 29 |
|
|
co = getcone(o, 1);
|
| 30 |
|
|
|
| 31 |
|
|
/*
|
| 32 |
|
|
* To intersect a ray with a cone, we transform the
|
| 33 |
|
|
* ray into the cone's normalized space. This greatly
|
| 34 |
|
|
* simplifies the computation.
|
| 35 |
|
|
* For a cone or cup, normalization results in the
|
| 36 |
|
|
* equation:
|
| 37 |
|
|
*
|
| 38 |
|
|
* x*x + y*y - z*z == 0
|
| 39 |
|
|
*
|
| 40 |
|
|
* For a cylinder or tube, the normalized equation is:
|
| 41 |
|
|
*
|
| 42 |
|
|
* x*x + y*y - r*r == 0
|
| 43 |
|
|
*
|
| 44 |
|
|
* A normalized ring obeys the following set of equations:
|
| 45 |
|
|
*
|
| 46 |
|
|
* z == 0 &&
|
| 47 |
|
|
* x*x + y*y >= r0*r0 &&
|
| 48 |
|
|
* x*x + y*y <= r1*r1
|
| 49 |
|
|
*/
|
| 50 |
|
|
|
| 51 |
|
|
/* transform ray */
|
| 52 |
|
|
multp3(rox, r->rorg, co->tm);
|
| 53 |
|
|
multv3(rdx, r->rdir, co->tm);
|
| 54 |
|
|
/* compute intersection */
|
| 55 |
|
|
|
| 56 |
|
|
if (o->otype == OBJ_CONE || o->otype == OBJ_CUP) {
|
| 57 |
|
|
|
| 58 |
|
|
a = rdx[0]*rdx[0] + rdx[1]*rdx[1] - rdx[2]*rdx[2];
|
| 59 |
|
|
b = 2.0*(rdx[0]*rox[0] + rdx[1]*rox[1] - rdx[2]*rox[2]);
|
| 60 |
|
|
c = rox[0]*rox[0] + rox[1]*rox[1] - rox[2]*rox[2];
|
| 61 |
|
|
|
| 62 |
|
|
} else if (o->otype == OBJ_CYLINDER || o->otype == OBJ_TUBE) {
|
| 63 |
|
|
|
| 64 |
|
|
a = rdx[0]*rdx[0] + rdx[1]*rdx[1];
|
| 65 |
|
|
b = 2.0*(rdx[0]*rox[0] + rdx[1]*rox[1]);
|
| 66 |
|
|
c = rox[0]*rox[0] + rox[1]*rox[1] - CO_R0(co)*CO_R0(co);
|
| 67 |
|
|
|
| 68 |
|
|
} else { /* OBJ_RING */
|
| 69 |
|
|
|
| 70 |
|
|
if (rdx[2] <= FTINY && rdx[2] >= -FTINY)
|
| 71 |
|
|
return(0); /* parallel */
|
| 72 |
|
|
root[0] = -rox[2]/rdx[2];
|
| 73 |
|
|
if (root[0] <= FTINY || root[0] >= r->rot)
|
| 74 |
|
|
return(0); /* distance check */
|
| 75 |
|
|
b = root[0]*rdx[0] + rox[0];
|
| 76 |
|
|
c = root[0]*rdx[1] + rox[1];
|
| 77 |
|
|
a = b*b + c*c;
|
| 78 |
|
|
if (a < CO_R0(co)*CO_R0(co) || a > CO_R1(co)*CO_R1(co))
|
| 79 |
|
|
return(0); /* outside radii */
|
| 80 |
|
|
r->ro = o;
|
| 81 |
|
|
r->rot = root[0];
|
| 82 |
|
|
for (i = 0; i < 3; i++)
|
| 83 |
|
|
r->rop[i] = r->rorg[i] + r->rdir[i]*r->rot;
|
| 84 |
|
|
VCOPY(r->ron, co->ad);
|
| 85 |
|
|
r->rod = -rdx[2];
|
| 86 |
greg |
1.3 |
r->rox = NULL;
|
| 87 |
greg |
1.1 |
return(1); /* good */
|
| 88 |
|
|
}
|
| 89 |
|
|
/* roots for cone, cup, cyl., tube */
|
| 90 |
|
|
nroots = quadratic(root, a, b, c);
|
| 91 |
|
|
|
| 92 |
|
|
for (rn = 0; rn < nroots; rn++) { /* check real roots */
|
| 93 |
|
|
if (root[rn] <= FTINY)
|
| 94 |
|
|
continue; /* too small */
|
| 95 |
|
|
if (root[rn] >= r->rot)
|
| 96 |
|
|
break; /* too big */
|
| 97 |
|
|
/* check endpoints */
|
| 98 |
|
|
for (i = 0; i < 3; i++) {
|
| 99 |
|
|
rox[i] = r->rorg[i] + root[rn]*r->rdir[i];
|
| 100 |
|
|
rdx[i] = rox[i] - CO_P0(co)[i];
|
| 101 |
|
|
}
|
| 102 |
|
|
b = DOT(rdx, co->ad);
|
| 103 |
|
|
if (b < 0.0)
|
| 104 |
|
|
continue; /* before p0 */
|
| 105 |
|
|
if (b > co->al)
|
| 106 |
|
|
continue; /* after p1 */
|
| 107 |
|
|
r->ro = o;
|
| 108 |
|
|
r->rot = root[rn];
|
| 109 |
|
|
VCOPY(r->rop, rox);
|
| 110 |
|
|
/* get normal */
|
| 111 |
|
|
if (o->otype == OBJ_CYLINDER)
|
| 112 |
|
|
a = CO_R0(co);
|
| 113 |
|
|
else if (o->otype == OBJ_TUBE)
|
| 114 |
|
|
a = -CO_R0(co);
|
| 115 |
|
|
else { /* OBJ_CONE || OBJ_CUP */
|
| 116 |
|
|
c = CO_R1(co) - CO_R0(co);
|
| 117 |
|
|
a = CO_R0(co) + b*c/co->al;
|
| 118 |
|
|
if (o->otype == OBJ_CUP) {
|
| 119 |
|
|
c = -c;
|
| 120 |
|
|
a = -a;
|
| 121 |
|
|
}
|
| 122 |
|
|
}
|
| 123 |
|
|
for (i = 0; i < 3; i++)
|
| 124 |
|
|
r->ron[i] = (rdx[i] - b*co->ad[i])/a;
|
| 125 |
|
|
if (o->otype == OBJ_CONE || o->otype == OBJ_CUP)
|
| 126 |
|
|
for (i = 0; i < 3; i++)
|
| 127 |
|
|
r->ron[i] = (co->al*r->ron[i] - c*co->ad[i])
|
| 128 |
|
|
/co->sl;
|
| 129 |
|
|
r->rod = -DOT(r->rdir, r->ron);
|
| 130 |
greg |
1.3 |
r->rox = NULL;
|
| 131 |
greg |
1.1 |
return(1); /* good */
|
| 132 |
|
|
}
|
| 133 |
|
|
return(0);
|
| 134 |
|
|
}
|