home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * Copyright (c) 1988, David B. Wecker *
- * All Rights Reserved *
- * *
- * This file is part of DBW_uRAY *
- * *
- * DBW_uRAY 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_uRAY General Public *
- * License for full details. *
- * *
- * Everyone is granted permission to copy, modify and redistribute *
- * DBW_uRAY, but only under the conditions described in the *
- * DBW_uRAY General Public License. A copy of this license is *
- * supposed to have been given to you along with DBW_uRAY 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 881023 DBW - First released version *
- * V1.1 881110 DBW - Fixed scan coherence code *
- * V1.2 881125 DBW - Removed ALL scan coherence code (useless) *
- * added "fat" extent boxes *
- * *
- ************************************************************************/
-
- #include "uray.h"
-
- /************************************************************************/
- /**************** This module computes textures of objects **************/
- /************************************************************************/
-
- /* get the procedure texture */
- void gettex(n,intersect,normal,diffuse)
- NODE *n;
- VEC intersect,normal,diffuse;
- {
- int i,j,k;
- FLTDBL d;
-
- /* start with the default diffuse color */
- vcopy(n->att->color,diffuse);
- switch (n->att->tex) {
-
- /* no texture */
- case 0:
- break;
-
- /* checker board, p1 = alternate color, p2 = scale */
- case 1:
- for (i=j=0; i<3; i++) {
- if (n->att->p2[i] > 0.0) {
- k = (int)(intersect[i] / n->att->p2[i]);
- if (k < 0) j -= k;
- else j += k;
- }
- }
- if (j & 1) { vcopy(n->att->p1,diffuse); }
- break;
-
- /* random mottled texture, p1 = alternate color */
- case 2:
- for (i=0; i<3; i++) {
- diffuse[i] *= (d=rnd());
- diffuse[i] += (1.0-d) * n->att->p1[i];
- }
- break;
-
- /* blend textures */
- case 3: /* X axis blend, p1 = alternate color, p2 = coordinate */
- case 4: /* Y axis blend, p1 = alternate color, p2 = coordinate */
- case 5: /* Z axis blend, p1 = alternate color, p2 = coordinate */
- i = n->att->tex - 3;
- if (intersect[i] > n->att->p2[1]) d = n->att->p2[2] - n->att->p2[1];
- else d = n->att->p2[0] - n->att->p2[1];
-
- if (d == 0.0) break;
- d = (intersect[i] - n->att->p2[1]) / d;
-
- if (d > 1.0) d = 1.0;
- if (d < 0.0) d = 0.0;
-
- for (i=0; i<3; i++) {
- diffuse[i] *= d;
- diffuse[i] += (1.0-d) * n->att->p1[i];
- }
- break;
- }
- }
-
- /* return background value (computes sky and ground colors) */
- void getamb(frm, dir, retval)
- VEC frm, dir, retval;
- {
- FLTDBL v;
- int i;
-
- if (dir[1] < 0.0) {
- vcopy(GROUND,retval);
- return;
- }
- if (dir[2] < 0.0) v = 0.0;
- else {
- v = (1.0 - dir[1]) * dir[2];
- if (v > 1.0) v = 1.0;
- else v *= v;
- }
- for (i=0; i<3; i++) {
- retval[i] = NEAR[i] * (1.0 - v);
- retval[i] += FAR[i] * v;
- }
- }
-
- /* figure out ripple for current point inside of a wave surface */
- void calcripple(point,w,ripple)
- VEC point;
- int w;
- VEC ripple;
- {
- FLTDBL riprad,damper,tmp;
- int i,iriprad;
-
- riprad = 0.0;
- for (i=0; i<3; i++) {
- ripple[i] = tmp = waves[w].cen[i] - point[i];
- riprad += tmp * tmp;
- }
- /* unit vector pointing away from wave center */
- vunit(ripple,ripple);
-
- riprad = sqrt(riprad); /* distance from center to point */
- riprad += waves[w].phase * waves[w].length; /* move it */
-
- riprad /= waves[w].length; /* scale half-wave crest to 0..1 */
- if (waves[w].damp == 1.0) damper = 1.0;
- else damper = pow(waves[w].damp,riprad);
-
- iriprad = (int)riprad;
- if (iriprad & 1) {/* negate it */
- vscale(-1.0,ripple,ripple);
- }
- riprad -= (FLTDBL) 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 *= waves[w].amp;
- vscale(riprad,ripple,ripple); /* scale bend */
- }
-
- /* find surface normal for any object */
- FLTDBL findnormal(s,dir,intersect,normal,eflip)
- NODE *s;
- VEC dir,intersect,normal;
- int *eflip;
- {
- int i;
- FLTDBL d;
- VEC ripple,fuzzy;
-
- /* first get the standard normal */
- switch (s->typ) {
- case TYP_S: spherenormal(intersect,s,normal); break;
- default: planenormal(s,normal);
- }
-
- /* do any desired waves */
- if (s->att->wave != -1) { /* don't bother checking if there's no waves*/
- if (s->att->wave == -2) { /* fiddle with normal for all ripples */
- for (i = 0; i < nwaves; i++) {
- calcripple(intersect,i,ripple); /* calculate the wave perturbation */
- vadd(ripple,normal,normal); /* add ripple bend to normal */
- }
- }
-
- /* fiddle with normal for one ripple */
- else if (s->att->wave >= 0) {
- calcripple(intersect,s->att->wave,ripple); /* calc wave perturbation */
- vadd(ripple,normal,normal); /* add ripple bend to normal */
- }
- vunit(normal,normal); /* make sure it's a unit vector after all that */
- }
-
- /* Add any general normal perturbations */
- if (s->att->kf > 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 */
- vcomb(rnd() * s->att->kf,fuzzy,normal,normal);
- vunit(normal,normal); /* make sure it's a unit vector after all that */
- }
-
- /* make sure the normal is on the correct side of the surface */
- d = -vdot(dir,normal);
- *eflip = 0;
- if (d < 0.0) {
- vscale(-1.0, normal, normal);
- *eflip = 1;
- d = -d;
- }
-
- return d;
- }
-
-
-