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_CALC
- #include "ray.h"
-
- void spherenormal(center,p,n)
- vector center,p,n;
- {
- DIRECTION(center,p,n);
- }
-
- void planenormal(ve,vp,n)
- vector ve, vp, n;
- {
- cross(vp,ve,n);
- normalize(n);
- }
-
- void calcripple(point,w,ripple)
- vector point;
- int w;
- vector ripple;
- {
- float riprad,temp1,temp2,temp3,damper;
- int iriprad;
-
- direction(point,wave[w].center,ripple); /* unit vector pointing away from wave center */
-
- temp1 = wave[w].center[0] - point[0];
- temp2 = wave[w].center[1] - point[1];
- temp3 = wave[w].center[2] - point[2];
-
- temp1 = temp1 * temp1; /* square it */
- temp2 = temp2 * temp2; /* square it */
- temp3 = temp3 * temp3; /* square it */
-
- riprad = (float)sqrt(temp1 + temp2 + temp3); /* distance from center to point */
- riprad += wave[w].propagate * wave[w].wavelength; /* move it */
-
- riprad /= wave[w].wavelength; /* scale half-wave crest to 0..1 */
- if (wave[w].drag == 1.0)
- damper = 1.0;
- else
- damper = (float)pow(wave[w].drag,riprad); /* exponential damping */
-
- iriprad = (int) riprad;
- if (iriprad & 1)
- { /* negate it */
- ripple[0] = -ripple[0];
- ripple[1] = -ripple[1];
- ripple[2] = -ripple[2];
- }
- riprad -= (float) iriprad; /* just get fraction 0..1 */
- riprad -= 0.5; /* scale to -0.5 .. +0.5 */
- if (riprad < 0.0)
- riprad = -riprad; /* absolute value */
- riprad = 0.5 - riprad; /* invert */
- riprad *= damper;
- riprad *= wave[w].amplitude;
- vecscale(riprad,ripple,ripple); /* scale bend */
- }
-
- void noise3(point,total)
- vector point,
- total;
- {
- vector ripple;
- float s;
- int w;
-
- veczero(total);
- for (w = 0; w < numwaves; w++)
- {
- calcripple(point,w,ripple); /* calculate the wave perturbation */
- vecsum(ripple,total,total); /* sum the ripple bends */
- }
- s = NORM(total);
- if (s < 0.001)
- total[0] = 1.0;
- else
- {
- s = 1.0 / s;
- vecscale(s,total,total); /* Make it unit vector */
- }
- }
-
-
- float noise(point)
- vector point;
- {
- vector total;
- float s;
-
- noise3(point,total);
- s = total[0] + total[1] + total[2]; /* sum is between -sqrt(3)..+sqrt(3) */
- s += sqrt3; /* now between 0.0 and 2*sqrt(3) */
- s /= sqrt3times2; /* scale to range 0..1 */
-
- return( s );
- }
-
- float turbulence(point)
- vector point;
- {
- vector temp;
- float t,scale;
-
- if (numwaves > 0)
- {
- t = 0.0;
- scale = 1.0;
-
- while (scale < 64.0)
- {
- vecscale(scale,point,temp);
- t += fabs(noise(temp) / scale);
- scale *= 2.0;
- }
- }
- else
- {
- t = 1.5;
- }
-
- return( t );
- }
-
- void dodirection(val,eye2,d2,atten,amblits)
- vector val;
- vector eye2;
- vector d2;
- float atten;
- int amblits;
- {
- vector transparency,nextval,best_p,n,temp,q,eye,d;
-
- #ifdef MCH_AMIGA
- node *best_obj = 1L;
- #else
- node *best_obj = (node *)1L;
- #endif
-
- float best_t,qnorm,ddotn,n1,n2;
- int hitnext;
-
- /* make local modifyable copies */
- veccopy(eye2,eye);
- veccopy(d2,d);
- veczero(val);
- CV(1.0,1.0,1.0,transparency);
- all_intersects(eye,d,0);
-
- hitnext = 0;
- while ( best_obj &&
- (transparency[0] > 0.01 ||
- transparency[1] > 0.01 ||
- transparency[2] > 0.01 ) )
- {
- best_obj = get_next_intersection(hitnext,best_p,&best_t);
- if (best_obj)
- {
- getval(nextval,best_obj,best_p,d,atten,amblits);
- vecmul(transparency,nextval,nextval);
- vecsum(val,nextval,val);
- vecmul(best_obj->attr.tra,transparency,transparency);
-
- if (transparency[0] > 0.01 || /* Can some light get through? */
- transparency[1] > 0.01 ||
- transparency[2] > 0.01)
- if ((best_obj->attr.idx != idxref) || /* Is it refractive? */
- (best_obj->kind == SPHERE))
- { /* Is it a volume object? */
-
- /* apply refraction by changing ray direction and origin */
-
- findnormal(best_obj,best_p,n);
- ddotn = DOT(d,n);
-
- if (ddotn < 0.0)
- {
- n2 = best_obj->attr.idx;
- n1 = idxref;
- }
- else
- {
- n1 = best_obj->attr.idx;
- n2 = idxref;
- n[0] = -n[0]; /* Negate the normal */
- n[1] = -n[1];
- n[2] = -n[2];
- ddotn = -ddotn;
- }
-
- vecscale(ddotn,n,temp);
- vecsub(d,temp,temp);
- vecscale(n1 / n2,temp,q);
-
- qnorm = NORM(q); /* magnitude */
- if (qnorm >= 1.0)
- best_obj = NULL; /* past critical angle,no more light */
- else
- {
- vecscale(sqrt(1.0-(qnorm*qnorm)),n,temp);
- vecsub(q,temp,d);
- veccopy(best_p,eye);
- hitnext = -1; /* new direction vector,so re-depth-sort intersections */
- all_intersects(eye,d,0); /* Compute intersections with new ray */
- }
- }
- hitnext++;
- }
- }
- vecmul(backgroundval,transparency,nextval);
- vecsum(val,nextval,val);
- }
-