home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright (c) 1987, David B. Wecker *
- * All Rights Reserved *
- * *
- * This file is part of DBW_Render *
- * *
- * DBW_Render is distributed in the hope that it will be useful, but *
- * WITHOUT ANY WARRANTY. No author or distributor accepts *
- * responsibility to anyone for the consequences of using it or for *
- * whether it serves any particular purpose or works at all, unless *
- * he says so in writing. Refer to the DBW_Render General Public *
- * License for full details. *
- * *
- * Everyone is granted permission to copy, modify and redistribute *
- * DBW_Render, but only under the conditions described in the *
- * DBW_Render General Public License. A copy of this license is *
- * supposed to have been given to you along with DBW_Render so you *
- * can know your rights and responsibilities. It should be in a file *
- * named COPYING. Among other things, the copyright notice and this *
- * notice must be preserved on all copies. *
- ************************************************************************
- * *
- * Authors: *
- * DBW - David B. Wecker *
- * *
- * Versions: *
- * V1.0 870125 DBW - First released version *
- * *
- ************************************************************************/
-
- #define MODULE_HIT
- #include "ray.h"
-
- void findnormal(np,p,n)
- node *np;
- vector p,
- n;
- {
- vector ripple,fuzzy,bevelx,bevely,bevelz,tmp;
- float t;
- int w,j,it;
-
- switch (np->kind)
- {
- case SPHERE :
- SPHERENORMAL(sptr(np)->center,p,n);
- break;
- case TRIANGLE :
- PLANENORMAL(tptr(np)->ve,tptr(np)->vp,n);
- break;
- case QUAD :
- PLANENORMAL(qptr(np)->ve,qptr(np)->vp,n);
- break;
- case RING :
- PLANENORMAL(rptr(np)->ve,rptr(np)->vp,n);
- break;
- }
-
- if (np->attr.tex != 0)
- { /* don't bother checking if there's no texture */
- if (np->attr.tex == 4)
- { /* fiddle with normal for all ripples */
- for (w = 0; w < numwaves; w++)
- {
- calcripple(p,w,ripple); /* calculate the wave perturbation */
- vecsum(ripple,n,n); /* add ripple bend to normal */
- }
- normalize(n); /* make sure it's a unit vector after all that */
- }
-
- /* fiddle with normal for one ripple */
- else if (np->attr.tex >= 10 && np->attr.tex <= 19)
- {
- calcripple(p,np->attr.tex - 10,ripple); /* calc wave perturbation */
- vecsum(ripple,n,n); /* add ripple bend to normal */
- normalize(n); /* make sure it's still a unit vector */
- }
-
- /* check for rough pebbly surface */
- else if (np->attr.tex >= 90 && np->attr.tex <= 99)
- {
- j = np->attr.tex - 90; /* select the desired pebble finish */
- vecscale(pebble[j].zoom,p,tmp);
- fuzzy[0] = turbulence(tmp);
- vecscale(1.5,tmp,tmp);
- fuzzy[1] = turbulence(tmp);
- vecscale(1.5,tmp,tmp);
- fuzzy[2] = turbulence(tmp);
- if (fuzzy[0] > 0.7)
- fuzzy[0] = 0.7;
- if (fuzzy[1] > 0.7)
- fuzzy[1] = 0.7;
- if (fuzzy[2] > 0.7)
- fuzzy[2] = 0.7;
- if (rnd() < 0.5)
- fuzzy[0] = -fuzzy[0];
- if (rnd() < 0.5)
- fuzzy[1] = -fuzzy[1];
- if (rnd() < 0.5)
- fuzzy[2] = -fuzzy[2];
- vecscale(pebble[j].scale,fuzzy,fuzzy);
- vecsum(n,fuzzy,n);
- normalize(n);
- }
- }
-
- /*---------------------------------------------------------------------*/
- /* Add any general normal perturbations */
-
- if (np->attr.fuz > 0.0)
- {
- /* Perturb the normal randomly to produce fuzzy surfaces */
- fuzzy[0] = rnd(); /* 0..1 */
- fuzzy[1] = rnd();
- fuzzy[2] = rnd();
- if (rnd() < 0.5)
- fuzzy[0] = -fuzzy[0];
- if (rnd() < 0.5)
- fuzzy[1] = -fuzzy[1];
- if (rnd() < 0.5)
- fuzzy[2] = -fuzzy[2];
-
- /* 'fuzzy' is now approximately a random unit vector */
- vecscale(rnd() * np->attr.fuz,fuzzy,fuzzy);
- vecsum(fuzzy,n,n); /* vector addition of fuzz compunent to true normal */
- normalize(n); /* Make sure it's still a unit vector */
- }
- }
-
- int hitcylinder(cp,eye,d,p,t)
- cylinder *cp; /* the cylinder */
- vector eye; /* source ray origin */
- vector d; /* source ray */
- vector p;
- float *t;
- {
- float aa,bb,cc,radical,a2,b2,c2,dist1,dist2;
- vector otop,oeye,p1,p2,opoint1,opoint2;
-
- /*
- * translate bottom of cylinder to 0,0,0
- * get translated eyepoint and cylinder top
- */
-
- VECSUB(eye, cp->bottom, oeye);
- VECSUB(cp->top,cp->bottom, otop); /* ? */
-
-
- a2 = cp->a*cp->a;
- b2 = cp->b*cp->b;
- c2 = cp->c*cp->c;
-
- if (a2 < SMALL) return( FALSE );
- if (b2 < SMALL) return( FALSE );
- if (c2 < SMALL) return( FALSE );
-
-
- aa = d[0]*d[0] / a2;
- aa += d[2]*d[2] / b2;
- aa -= d[1]*d[1] / c2;
-
- bb = d[0]*oeye[0] / a2;
- bb += d[2]*oeye[2] / b2;
- bb -= d[1]*oeye[1] / c2;
-
- cc = oeye[0]*oeye[0] / a2;
- cc += oeye[2]*oeye[2] / b2;
- cc -= oeye[1]*oeye[1] / c2;
-
- /*
- * descriminate < 0, ray misses cylinder
- * descriminate == 0, ray grazes cylinder
- */
-
- if ((radical = (bb*bb) - (4.0*aa*cc)) < 0.0)
- return( FALSE );
-
- radical = sqrt(radical);
-
- aa = 2.0 * aa;
-
- if ( aa < SMALL )
- return( FALSE );
-
- /* the roots of the quadratic */
-
- dist1 = (-bb + radical) / aa;
- dist2 = (-bb - radical) / aa;
-
-
- VECSCALE(dist1,d,p1);
- VECSUM(p1,oeye,p1);
- VECSCALE(dist2,d,p2);
- VECSUM(p2,oeye,p2);
- VECSUB(oeye,p1,opoint1);
- VECSUB(oeye,p2,opoint2);
- dist1 = NORM(opoint1);
- dist2 = NORM(opoint2);
-
- if (dist1 < dist2)
- {
- VECCOPY(p1,p);
- *t = dist1;
- }
- else
- {
- VECCOPY(p2,p);
- *t = dist2;
- }
-
- return( TRUE );
- }
-
- int hitsphere(center,radius,eye,d,p,t)
- vector center; /* where it is */
- vector eye; /* where we are */
- vector d;
- vector p;
- float radius; /* how big it is */
- float *t;
- {
- float r_r,d_r,t2,radical;
- vector r;
-
- VECSUB(center,eye,r);
- r_r = DOT(r,r);
- d_r = DOT(d,r);
-
- if ((radical = (d_r*d_r) + (radius*radius) - r_r) < 0.0)
- return( FALSE );
-
- radical = sqrt(radical);
-
- if (d_r < radical)
- {
- *t = d_r + radical;
- t2 = d_r - radical;
- }
- else
- {
- *t = d_r - radical;
- t2 = d_r + radical;
- }
-
- if (fabs(*t) < SMALL)
- *t = t2;
-
- if (*t <= 0)
- return( FALSE );
-
- VECSCALE((*t),d,p);
- VECSUM(p,eye,p);
- return( TRUE );
- }
-
- int hitplane(p,ve,vp,eye,d,sfs,inter)
- vector p,
- ve,
- vp,
- eye,
- d,
- sfs,
- inter;
- {
- vector h;
- float det;
-
- det = ve[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
- det -= vp[0] * ((ve[1] * d[2]) - (ve[2] * d[1]));
- det += d[0] * ((ve[1] * vp[2])- (ve[2] * vp[1]));
-
- if (det == 0.0)
- return FALSE;
-
- vecsub(eye,p,h);
-
- sfs[2] = h[0] * ((ve[1] * vp[2]) - (ve[2] * vp[1]));
- sfs[2] -= h[1] * ((ve[0] * vp[2]) - (ve[2] * vp[0]));
- sfs[2] += h[2] * ((ve[0] * vp[1]) - (ve[1] * vp[0]));
- sfs[2] /= det;
- sfs[2] = -sfs[2];
-
- if (sfs[2] < SMALL)
- return FALSE;
-
- sfs[0] = h[0] * ((vp[1] * d[2]) - (vp[2] * d[1]));
- sfs[0] -= h[1] * ((vp[0] * d[2]) - (vp[2] * d[0]));
- sfs[0] += h[2] * ((vp[0] * d[1]) - (vp[1] * d[0]));
- sfs[0] /= det;
-
- sfs[1] = h[0] * ((ve[2] * d[1]) - (ve[1] * d[2]));
- sfs[1] += h[1] * ((ve[0] * d[2]) - (ve[2] * d[0]));
- sfs[1] -= h[2] * ((ve[0] * d[1]) - (ve[1] * d[0]));
- sfs[1] /= det;
-
- VECCOPY(d,inter);
- VECSCALE(sfs[2],inter,inter);
- VECSUM(inter,eye,inter);
-
- return TRUE;
- }
-
- int hittriangle(tp,eye,d,p,t)
- triangle *tp;
- vector eye,
- d,
- p;
- float *t;
- {
- vector sfs;
- int hit;
-
- hit = hitplane(tp->position,tp->ve,tp->vp,eye,d,sfs,p) &&
- sfs[0] > 0.0 && sfs[1] > 0.0 && sfs[0] + sfs[1] <= 1.0;
- *t = sfs[2];
-
- return hit;
- }
-
- int hitquad(qp,eye,d,p,t)
- quad *qp;
- vector eye,
- d,
- p;
- float *t;
- {
- vector sfs;
- int hit = FALSE;
-
- if (hitplane(qp->position,qp->ve,qp->vp,eye,d,sfs,p))
- hit = sfs[0] > 0.0 && sfs[1] > 0.0 && sfs[0] <= 1.0 && sfs[1] <= 1.0;
- *t = sfs[2];
- return hit;
- }
-
- int hitring(rp,eye,d,p,t)
- ring *rp;
- vector eye,
- d,
- p;
- float *t;
- {
- vector sfs;
- float r;
- int hit;
-
- hit = hitplane(rp->position,rp->ve,rp->vp,eye,d,sfs,p) &&
- (r = sfs[0] * sfs[0] + sfs[1] * sfs[1]) <= rp->maxrad &&
- r >= rp->minrad;
- *t = sfs[2];
- return( hit );
- }
-
- void shell(v,v1,v2,n)
- float v[];
- vector v1[];
- node *v2[];
- int n;
- {
- int gap,i,j;
- node *temp2;
- vector temp1;
- float temp;
-
- sorts++; /* Keep statistics */
- sort_size += n;
-
- for (gap = n/2; gap > 0; gap /=2)
- for (i = gap; i < n; i++)
- for (j = i-gap; j>=0 && v[j] > v[j+gap]; j -= gap)
- {
- temp = v[j];
- v[j] = v[j+gap];
- v[j+gap] = temp;
-
- VECCOPY(v1[j],temp1);
- VECCOPY(v1[j+gap],v1[j]);
- VECCOPY(temp1,v1[j+gap]);
-
- temp2 = v2[j];
- v2[j] = v2[j+gap];
- v2[j+gap] = temp2;
- }
- }
-
-