[net.graphics] arghhh

fritzz@net1.UCSD.EDU (Friedrich Knauss) (07/31/86)

Hiya!
requests fo the refraction fix have been overwhelming, so I decided to
post to the net. First of, it appears that some machines are having
problems with the routine scamult() in support.c. Removing the line
modifying xzl should fix the problem. (It isn't really needed).
Other problems that arise during initialization should work after this
refraction mod has been made.

Anyway, this routine does refraction properly: (kind of)
sin(theta incident)/sin(theta refracted) = ratio of indices of refraction.
for your information the refractive index for glass is about 1.5, the
refractive index for air is close to 1.
I am currently working on getting the amplitudes of refracted and
reflected light to be correct. It could be very ugly, and will also
include internal reflection. It may take a week or so, depending on how
eager I get. I may also start worrying about polarization (blech).
Now for the real thing...

changes you have to make:
1) in tracer.c:
right after the calculation of nob the is a loop that changes the value
bl[i].ior. It should be changed to:
bl[i].ior = bl[i].ior * bl[i].ior;

this saves time doing the multiplication every time you use it later on.

2) in shade.c:
delete the routine refract() and replace it with everything after the
dotted line down there.

That's it. I hope you enjoy playing with it, as it is far from a
finished project and has lots of opportunies for playing. Also, if
if you are impressed and desparately looking for new employees,
I'm currently in the market. ( =)/2 )
good luck and have fun...
f


------------------------------------------------------------------



int     refract (r, bll)
struct ray *r;
struct ball *bll;
{
    struct vector   new,
                    norm;
    struct mat  trans;
    double  l,
            refk ();
    struct sphere   ss;

    sv (&norm, &(r -> org), &(bll -> s.cent));
    vecl (&norm);
    vecl (&(r -> dir));
/* this is it!!*/

/* get the addition factor for the normal */
    scamult (refk (&(norm), &(r -> dir), bll -> ior), &norm);
    av (&(r -> dir), &(r -> dir), &norm);
/* find the point where the ray leaves the sphere. just like shade. */
    vexzl (&(r -> dir));
    vecl (&(r -> dir));
    mt (&(r -> dir), &trans);
    ss.rad = bll -> s.rad;
    sv (&ss.cent, &(bll -> s.cent), &(r -> org));
    l = findo (&trans, &(ss));
    mv (l * trans.x.x, l * trans.x.y, l * trans.x.z, &new);
    av (&(r -> org), &(r -> org), &new);
/* redirect the ray and continue tracing */
    sv (&norm, &(r -> org), &(bll -> s.cent));
    vecl (&norm);
    vecl (&(r -> dir));
    scamult (refk (&(norm), &(r -> dir), 1.0 / bll -> ior), &norm);
    av (&(r -> dir), &(r -> dir), &norm);

    return (shade (r));
}

double  refk (nrm, in, ior)
struct vector  *nrm,
               *in;
double  ior;
{
    double  dt,
            ln,
            li,
            ret;

    dt = dot (nrm, in);
    ln = nrm -> x * nrm -> x + nrm -> y * nrm -> y + nrm -> z * nrm -> z;
    li = in -> x * in -> x + in -> y * in -> y + in -> z * in -> z;
    if (dt < 0)
	ret = (-dt - sqrt (dt * dt - ln * li * (1 - ior))) / ln;
    else
	ret = (-dt + sqrt (dt * dt - ln * li * (1 - ior))) / ln;
    return (ret);
}