home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
015.lha
/
tracer_source
/
shade.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-10
|
6KB
|
322 lines
/*
* this subroutine does all the gritty work- it calculates
* what shade each pixel should be. I like recursion.
*/
#include <math.h>
#include <stdio.h>
#include "MyMath.h"
#include "rtd.h"
#include "macros.h"
#include "extern.h"
extern FFP big,
little;
int shade (r)
struct ray *r;
{
int i,
c,
refract ();
struct ray refr;
FFP lght,
z,
l,
k,
sanity,
find (), shadow ();
int sx,
sy;
FFP stupid;
struct vector new,
norm;
struct mat trans;
struct sphere ss;
if (++level <= LEVEL) {
c = -1;
l = ieee_to_ffp(1.0e37);
/* get vector length and xz component for mt() */
r -> dir.l = LEN (r -> dir);
r -> dir.xzl = XZL (r -> dir);
/*
make a transform matrix that rotates
something in space so that the ray will
be aligned with the x axis
*/
mt (&(r -> dir), &trans);
/* for starters we find out whether we hit anything. */
for (i = 0; i < nob; i++) {
ss.rad = bl[i] -> s.rad;
SV (ss.cent, bl[i] -> s.cent, r -> org);
k = find (&trans, &ss);
/*
if( SPTst( k ) > 0 )
printf("k = %f\n", ffp_to_ieee(k) );
*/
if (
( SPTst( k ) > 0 ) /* k>0.0 */
&&
( SPCmp(l, k) > 0 ) /* k<l */
) {
c = i;
l = k;
}
}
if (
c >= 0 &&
SPTst( SPAdd( SPMul(l, trans.x.y), r->org.y)) > 0
) {
/* WE HIT SOMETHING */
/*
printf("HIT: ball # %d, l = %f\n",
c, ffp_to_ieee(l) );
*/
MV (SPMul(l, trans.x.x),SPMul(l, trans.x.y),SPMul(l, trans.x.z),new );
/*
move the new orgin of the ray
to the intersection
*/
AV (refr.org, new, r -> org);
AV (r -> org, new, r -> org);
MV (r -> dir.x, r -> dir.y, r -> dir.z, refr.dir);
/* get a normal vector for the intersection point */
SV (norm, r -> org, bl[c] -> s.cent);
norm.l = LEN (norm);
/* ambient lighting */
lght = SPMul( SPFlt(200), bl[c] -> amb);
/*
shaded lighting (diffuse).
subroutine shadow is in find.c
*/
if ( SPTst( bl[c] -> dif) ) {
SV (new, ls.cent, r -> org);
new.l = LEN (new);
if( SPTst( (k=DOT(new, norm)) ) > 0)
lght = SPAdd(
SPDiv(
(norm.l),
SPDiv(
(new.l),
SPMul(
SPMul(
bl[c]->dif,
shadow( &(r -> org) )
),
k
)
)
),
lght
);
/*
lght += bl[c]->dif *
shadow( &(r -> org) ) *
k / (new.l) / (norm.l);
*/
}
/*reflection... easy */
if ( SPTst(bl[c] -> rfl) ) {
/* make the normal unit length */
norm.l = LEN (norm);
SCMLT ( SPDiv(norm.l, SPFlt(1) ), norm);
/*
get the length of the ray's
component in the normal direction
*/
stupid = SPMul(
SPFlt(2),
DOT (norm, r -> dir)
);
SCMLT (stupid, norm);
/*
subtract double the normal
component-!reflection!
*/
SV (r -> dir, r -> dir, norm);
lght = SPAdd(
lght,
SPMul(
bl[c] -> rfl,
SPFlt( shade (r) )
)
);
/*
lght += bl[c] -> rfl * (double) shade (r);
*/
}
/*
refraction. this is ugly as sin,
which is why I choose to deal with
it in it's own subroutine, which is
in it's own file now.
*/
if ( SPTst(bl[c] -> rfr) ) {
lght = SPAdd(
lght,
SPMul(
bl[c] -> rfr,
SPFlt( refract (&refr, bl[c] ) )
)
);
/*
lght += bl[c] -> rfr *
(double) refract (&refr, bl[c]);
*/
}
} else {
/* hit no objects... */
if (SPTst(r -> dir.y) < 0) {
/* crosses floor */
z = SPDiv(
(r -> dir.y),
SPNeg(r -> org.y)
);
(r -> org.x) = SPAdd(
(r -> org.x),
SPMul(
z,
(r -> dir.x)
)
);
(r -> org.z) = SPAdd(
(r -> org.z),
SPMul(
z,
(r -> dir.z)
)
);
/*
z = -(r -> org.y) / (r -> dir.y);
(r -> org.x) += z * (r -> dir.x);
(r -> org.z) += z * (r -> dir.z);
*/
(r -> org.y) = SPFlt(0);
/*
find out the mod of the value to
see where it hits susie. (ouch)
mess here if you only want the
pattern once.
*/
SV (new, ls.cent, r -> org);
new.l = LEN (new);
sx = SPFix(
SPDiv(
ieee_to_ffp(1.5),
r -> org.x
)
) % xsue;
if (sx < 0)
sx += xsue;
sy = -SPFix(
SPDiv(
ieee_to_ffp(1.5),
r -> org.z
)
) % ysue;
/*
sy = -(int) (r -> org.z / 1.5) % ysue;
*/
if (sy < 0)
sy += ysue;
/*
lght = (
sam *
suzie[sx][sy]+
1.0 - sam
) *
(0.8 * shadow (&(r -> org)) *
(new.y) / (new.l) + 40.0);
*/
sanity = SPMul(
sam,
SPAdd(
SPSub(
sam,
SPFlt(1)
),
SPDiv(
big,
SPSub(
little,
SPFlt(suzie[sx][sy])
)
)
)
);
lght = SPAdd(
SPFlt(40),
SPDiv(
(new.l),
SPMul(
(new.y),
SPMul(
ieee_to_ffp(0.8),
SPMul(
shadow ( &(r -> org) ),
sanity
)
)
)
)
);
} else {
/* check to see if it hit lightsource */
SV (ss.cent, ls.cent, r -> org);
ss.rad = ls.rad;
if (SPTst(find (&trans, &(ss.cent))) > 0)
lght = SPFlt(255);
else
lght = SPFlt(0);
}
}
}
/* too many levels return 0 cause it shouldn't matter */
else
lght = SPFlt(0);
level--;
if (SPTst(lght) < 0)
lght = SPFlt(0);
if (SPCmp(lght, SPFlt(255) ) > 0 )
lght = SPFlt(255);
return ( SPFix(lght) );
}