REFLECT.C

Go to the documentation of this file.
00001 // file reflect.c
00002 
00003 #define MODULE_MIRRORS
00004 
00005 /* The functions in this file get surface colours for an reflection vector and */
00006 /* the generation of the ground reflection. ground reflection is done by using */
00007 /* a full Z screen buffer to record the identity of the faces that would be    */
00008 /* seen in the ground mirrors. Then when a ground pixel needs to get a         */
00009 /* reflection it is calculated from the reflection ray given that we know the  */
00010 /* id of the face involved. This is quicker that calculating a reflection image*/
00011 /* and using that as a map - I think.                                          */
00012 /* They also implement the Spotlight shadows - which is still NOT satisfactory */
00013 
00014 #include "render.h"
00015 
00016 static long IntersectMirror(long scanline, double v1x, double v1y,
00017                      double v2x, double v2y,  double *xi);
00018 static short ShadowMirrorLine(long scanline, double vx[3], double vy[3],
00019                       double *leftedge, double *rightedge,
00020                       double xmin, double xmax);
00021 static void UpdateShadowZbuffer(float *id,float *id2,
00022                                 long l, double xl, double xr,
00023                                 double d, double d2, vector en,
00024                                 double ec, double SBC);
00025 
00026 extern double spec_pow[16][max_spec+1],Rip_Freq;
00027 
00028 short mirror_ground=0;
00029 
00030 //#define US unsigned short
00031 #define US UNSIGNED
00032 #define UC unsigned char
00033 
00034 static UC     *grf_o;
00035 static US     *grf_f;
00036 static float  *grf_z;
00037 static long   shadow_buffer_size2;
00038 
00039 #ifdef _SUNSTYLE
00040 static long IntersectMirror(scanline,v1x,v1y,v2x,v2y,xi)
00041 long scanline; double v1x; double v1y; double v2x; double v2y; double *xi; {
00042 #else
00043 static long IntersectMirror(long scanline, double v1x, double v1y,
00044                      double v2x, double v2y,  double *xi){
00045 #endif
00046  double ddx,ddy,doff,ddxy;    /* scanline function for mirror */
00047  if((v1y < scanline)  && (v2y < scanline))return 0;
00048  if((v1y > scanline)  && (v2y > scanline))return 0;
00049  ddy = (v2y) - (v1y);
00050  if(fabs(ddy) < 0.0001)return 0;
00051  ddx = (v2x) - (v1x);
00052  doff=(double)scanline - v1y;
00053  ddxy=ddx*doff/ddy;
00054  *xi=(v1x)+ddxy;
00055  return 1;
00056 }
00057 
00058 #ifdef _SUNSTYLE
00059 static short ShadowMirrorLine(scanline,vx,vy,leftedge,rightedge,xmin,xmax)
00060 long scanline; double vx[3]; double vy[3]; double *leftedge;
00061 double *rightedge; double xmin; double xmax; {
00062 #else
00063 static short ShadowMirrorLine(long scanline, double vx[3], double vy[3],
00064                       double *leftedge, double *rightedge,
00065                       double xmin, double xmax){
00066 #endif
00067  long i1,i2,i3;                /* scanline function for mirror */
00068  double x1,x2,x3;
00069  i1=IntersectMirror(scanline,vx[0],vy[0],vx[1],vy[1],&x1);
00070  i2=IntersectMirror(scanline,vx[1],vy[1],vx[2],vy[2],&x2);
00071  i3=IntersectMirror(scanline,vx[2],vy[2],vx[0],vy[0],&x3);
00072  if((i1 == 1) && (i2 == 1) && (i3 == 1))
00073  {*leftedge = min(min(x1,x2),x3);
00074   *rightedge= max(max(x1,x2),x3);}
00075  else if((i2 == 1) && (i3 == 1))
00076  {*leftedge = min(x2,x3);
00077   *rightedge= max(x2,x3);}
00078  else if((i3 == 1) && (i1 == 1))
00079  {*leftedge = min(x3,x1);
00080   *rightedge= max(x3,x1);}
00081  else if((i1 == 1) && (i2 == 1))
00082  {*leftedge = min(x1,x2);
00083   *rightedge= max(x1,x2);}
00084  else return 0;
00085  if(*leftedge >= xmax)return 0;
00086  else *leftedge  = max(0,*leftedge);
00087  if(*rightedge < xmin)return 0;
00088  *rightedge = min(xmax-0.01,*rightedge);
00089  return 1;
00090 }
00091 
00092 static void UpdateZbuffer(long l, double xl, double xr, long id, long O,
00093                           double d2, vector en, double ec,
00094                           long Mxmax, long Mxcentre, double Mscalex){
00095  long i,ixl,ixr;               /* scanline function for mirror */
00096  double depth,bL,bR,aL,aR,dL,dR;
00097  xl += 0.01;
00098  xr -= 0.01;
00099  ixl = (long)xl;
00100  ixr = (long)xr;
00101  if(ixl == ixr){
00102    dL = xl - (double)Mxcentre; dL/=Mscalex;
00103    dR = xr - (double)Mxcentre; dR/=Mscalex;
00104    bL = en[0]*dL + en[2]*d2 + en[1];
00105    if(fabs(bL) < 1.e-30)aL=BIGP;
00106    else aL = ec/bL;
00107    bR = en[0]*dR + en[2]*d2 + en[1];
00108    if(fabs(bR) < 1.e-30)aR=BIGP;
00109    else aR = ec/bR;
00110    depth=min(aL,aR);
00111    if(depth > 1.000 && depth <= *(grf_z+l*(long)Mxmax+ixl)){
00112        *(grf_z+l*(long)Mxmax+ixl) = depth;
00113        *(grf_o+l*(long)Mxmax+ixl) = (UC)O;
00114        *(grf_f+l*(long)Mxmax+ixl) = (US)id;
00115    }
00116  }
00117  else{
00118    dL = xl - (double)Mxcentre; dL/=Mscalex;
00119    bL = en[0]*dL + en[2]*d2 + en[1];
00120    if(fabs(bL) < 1.e-30)aL=BIGP;
00121    else aL = (ec)/bL;
00122    bR = en[0]*DR[ixl] + en[2]*d2 + en[1];
00123    if(fabs(bR) < 1.e-30)aR=BIGP;
00124    else aR = ec/bR;
00125    depth=min(aL,aR);
00126    if(depth > 1.000 && depth <= *(grf_z+l*(long)Mxmax+ixl)){
00127      *(grf_z+l*(long)Mxmax+ixl) = depth;
00128      *(grf_o+l*(long)Mxmax+ixl) = (UC)O;
00129      *(grf_f+l*(long)Mxmax+ixl) = (US)id;
00130    }
00131    bL = en[0]*DL[ixr] + en[2]*d2 + en[1];
00132    if(fabs(bL) < 1.e-30)aL=BIGP;
00133    else aL = ec/bL;
00134    dR = xr - (double)Mxcentre; dR/=Mscalex;
00135    bR = en[0]*dR + en[2]*d2 + en[1];
00136    if(fabs(bR) < 1.e-30)aR=BIGP;
00137    else aR = (ec)/bR;
00138    depth=min(aR,aL);
00139    if(depth > 1.000 && depth <= *(grf_z+l*(long)Mxmax+ixr)){
00140      *(grf_z+l*(long)Mxmax+ixr) = depth;
00141      *(grf_o+l*(long)Mxmax+ixr) = (UC)O;
00142      *(grf_f+l*(long)Mxmax+ixr) = (US)id;
00143    }
00144    if(ixr-ixl  > 1)for(i=ixl+1;i<ixr;i++){
00145      bL = en[0]*DL[i] + en[2]*d2 + en[1];
00146      if(fabs(bL) < 1.e-30)aL=BIGP;
00147      else aL = ec/bL;
00148      bR = en[0]*DR[i] + en[2]*d2 + en[1];
00149      if(fabs(bL) < 1.e-30)aL=BIGP;
00150      else aR = ec/bR;
00151      depth=min(aL,aR);
00152      if(depth > 1.00 && depth <= *(grf_z+l*(long)Mxmax+i)){
00153        *(grf_z+l*(long)Mxmax+i) = depth;
00154        *(grf_o+l*(long)Mxmax+i) = (UC)O;
00155        *(grf_f+l*(long)Mxmax+i) = (US)id;
00156      }
00157    }
00158  }
00159 }
00160 
00161 void Free_Mirror_On_Ground(void){
00162  if(mirror_ground == 0)return;
00163  X__Free(grf_o); /* z buffer is X__Freed after it is used */
00164  X__Free(grf_f);
00165  mirror_ground=0;
00166 }
00167 
00168 short Mirror_In_Ground(void){       
00169  long i,j,l,fbc;
00170  long vi[3],screensize,Mxmax,Mymax,Mxcentre,Mycentre;
00171  face    *f;
00172  vertex  *v;
00173  vector p,pp[3],en;
00174  double dp,temp4,d2,ec,xx[3],yy[3],xxmin,xxmax,yymin,yymax,Mscalex,Mscaley;
00175  double itr[4][4],tr[4][4],t1[4][4],t2[4][4],t3[4][4],x,y,z,xg,yg,zg;
00176  Mscalex=scalex; Mscaley=scaley;
00177  if(full_mirror){
00178    Mxmax=XMAX; Mymax=YMAX;
00179  }
00180  else{
00181    Mxmax=ResolutionX; Mymax=ResolutionY;
00182    if(anti_alias == LOW)   {Mscalex /= 2;}
00183    if(anti_alias == MEDIUM){Mscalex /= 2; Mscaley /= 2;}
00184    if(anti_alias == HIGH)  {Mscalex /= 3; Mscaley /= 2;}
00185    if(anti_alias == ULTRA) {Mscalex /= 3; Mscaley /= 3;}
00186  }
00187  Mxcentre=Mxmax/2; Mycentre=Mymax/2;
00188  screensize = Mxmax*Mymax;
00189  if((grf_o = (UC *)X__Malloc(screensize*sizeof(UC))) == NULL){
00190    Render_Message(1,0,NULL); return FAIL;
00191  }
00192  if((grf_f = (US *)X__Malloc(screensize*sizeof(US))) == NULL){
00193    X__Free(grf_o);
00194    Render_Message(1,0,NULL); return FAIL;
00195  }
00196  if((grf_z = (float *)X__Malloc(screensize*sizeof(float))) == NULL){
00197    X__Free(grf_o);
00198    X__Free(grf_f);
00199    Render_Message(1,0,NULL); return FAIL;
00200  }
00201  mirror_ground=1;
00202  for(i=0;i<screensize;i++){
00203    *(grf_o + i) =  255;
00204    *(grf_f + i) =  65535;
00205    *(grf_z + i) =  BIGP;
00206  }
00207  R_roty(t1,CamTheta);   /* Get needed transformations          */
00208  R_rotx(t2,CamAlpha);
00209  R_m4by4(t2,t1,t3);
00210  R_rotz(t1,CamPhi);
00211  R_m4by4(t1,t3,t2);
00212  R_tram(t1,ViewPoint[0],ViewPoint[1],ViewPoint[2]);
00213  R_m4by4(t1,t2,itr);   /* ITR is inverse viewing transformation */
00214  R_tram(t2,-ViewPoint[0],-ViewPoint[1],-ViewPoint[2]);
00215  R_rotz(t3,-CamPhi);
00216  R_m4by4(t3,t2,t1);
00217  R_rotx(t2,-CamAlpha);
00218  R_m4by4(t2,t1,t3);
00219  R_roty(t1,-CamTheta);
00220  R_m4by4(t1,t3,tr);    /* TR is the viewing transformation      */
00221  R_m4by1(itr,Ground.p[0],Ground.p[1],Ground.p[2],&xg,&yg,&zg);
00222  for(i=0;i<Mxmax;i++) {
00223    DL[i]=(double)(i - Mxcentre);        DL[i]/=Mscalex;
00224    DR[i]=(double)(i+1-Mxcentre);        DR[i]/=Mscalex;
00225    D1[i]=(double)(i - Mxcentre) + 0.5;  D1[i]/=Mscalex;
00226  }
00227  for(i=0;i<ObjectCount;i++){
00228    if(!Object[i].in_use)continue;
00229    v=Object[i].Vbase;
00230    f=Object[i].Fbase;
00231    for(j=0;j<Object[i].NoFaces;j++){
00232      vi[0]=(f+j)->V[0];
00233      vi[1]=(f+j)->V[1];
00234      vi[2]=(f+j)->V[2];
00235      fbc=0;  /* count vertices below ground */
00236      for(l=0;l<3;l++){
00237        R_m4by1(itr,(v+vi[l])->p[0],(v+vi[l])->p[1],(v+vi[l])->p[2],&x,&y,&z);
00238        dp=z-zg;                    /* delta point and mirror plane */
00239        if(dp < 0.0){fbc++; z = zg;} /*  goto FACEBREAK;  point below plane*/
00240        else   z = zg-dp;
00241        R_m4by1(tr,x,y,z,&p[0],&p[1],&p[2]);
00242        veccopy(p,pp[l]);
00243        if(p[1] >= 1.000){  /* vertex in front of projection plane */
00244          temp4=(Mscalex*(p[0])/(p[1]));
00245          xx[l]=(double)Mxcentre + temp4;
00246          temp4=(Mscaley*(p[2])/(p[1]));
00247          yy[l]=(double)Mycentre - temp4;
00248        }
00249        else goto FACEBREAK;
00250      }
00251      if(fbc == 3)goto FACEBREAK; /* all vertices below ground */
00252      xxmin=min(xx[1],xx[2]);     xxmin=min(xx[0],xxmin);
00253      xxmax=max(xx[1],xx[2]);     xxmax=max(xx[0],xxmax);
00254      yymin=min(yy[1],yy[2]);     yymin=min(yy[0],yymin);
00255      yymax=max(yy[1],yy[2]);     yymax=max(yy[0],yymax);
00256      if((yymax > yymin) && (xxmax > xxmin)){
00257        VECSUB(pp[2],pp[0],pp[2])
00258        VECSUB(pp[1],pp[0],pp[1])
00259        cross(pp[1],pp[2],en);
00260        if(normalize(en) == 0){ /* only for good normals */
00261          ec=DOT(pp[0],en);
00262          if(ec > 0.0){
00263            VECSCALE((double)(-1.0),en,en)
00264            ec = -ec;
00265          }
00266          for(l=max(0,(long)yymin);l<=min((long)yymax,Mymax-1);l++){
00267            if(ShadowMirrorLine(l,xx,yy,&xxmin,&xxmax,
00268                                0.0,(double)Mxmax)){
00269              d2=(double)(Mycentre-l)/Mscaley;
00270              UpdateZbuffer(l,xxmin,xxmax,j,i,d2,en,ec,Mxmax,Mxcentre,Mscalex);
00271            }
00272          }
00273        }
00274      }
00275      FACEBREAK: continue;
00276    }
00277  }
00278  X__Free(grf_z); grf_z=NULL;
00279  return 1;
00280 }
00281 
00282 void Add_Ground_Mirror(long scanline, long col, vector p,
00283        unsigned char *R, unsigned char *G, unsigned char *B){
00284 /* p is vector to point on ground where reflection is */
00285  register long addr;
00286  int obj;
00287  face    *f;
00288  vertex  *v;
00289  double r1,pdotn,r=0.0,g=0.0,b=0.0;
00290  vector d;
00291 
00292  if(full_mirror)addr=XMAX*scanline+col;
00293  else addr=ResolutionX*(scanline/aaYstep)+col/aaXstep;
00294 
00295  obj=(int)(*(grf_o + addr));
00296  if( obj < 255){
00297    f = (Object + obj)->Fbase + (long)(*(grf_f + addr));
00298    v = (Object + obj)->Vbase;
00299    pdotn=DOT(p,Ground.n);
00300    VECSCALE(2*pdotn,Ground.n,d)
00301    VECSUB(p,d,d)                 /* vector in the reflected direction */
00302    GetSurfaceValue(obj,f,v,p,d,&r,&g,&b,0,0,0);
00303    r1=(1.0 - Ground.refl);
00304    *R = (unsigned char)
00305         ((double)*R * r1 + r*Ground.refl);
00306    *G = (unsigned char)
00307         ((double)*G * r1 + g*Ground.refl);
00308    *B = (unsigned char)
00309         ((double)*B * r1 + b*Ground.refl);
00310  }
00311  return;
00312 }
00313 
00314 void Free_Lights_Shadows(void){
00315  long i;
00316  for(i=0;i<Nlights;i++){
00317    if(Lights[i].shadow_buffer != NULL){
00318      X__Free(Lights[i].shadow_buffer);
00319      Lights[i].shadow_buffer=NULL;
00320    }
00321    if(Lights[i].object_buffer != NULL){
00322      X__Free(Lights[i].object_buffer);
00323      Lights[i].object_buffer=NULL;
00324    }
00325    if(Lights[i].face_buffer != NULL){
00326      X__Free(Lights[i].face_buffer);
00327      Lights[i].face_buffer=NULL;
00328    }
00329    if(Lights[i].atmospheric_shadow_buffer != NULL){
00330      X__Free(Lights[i].atmospheric_shadow_buffer);
00331      Lights[i].atmospheric_shadow_buffer=NULL;
00332    }
00333  }
00334 }
00335 
00336 void SetLightShadow(long id){  /* for light "id" */
00337  double itr[4][4],tr[4][4],t1[4][4],t2[4][4],t3[4][4],d,x,y,z,
00338         xx[3],yy[3],d2,ec,xxmin,xxmax,yymin,yymax;
00339  long i,j,l,vi[3];
00340  face   *f;
00341  vertex *v;
00342  vector en,pp[3],dr;
00343  float  d2f,*depth2=NULL;
00344  if(shadow_buffer_size == 0)return;
00345  if((Lights[id].shadow_buffer = (float *)X__Malloc((long)shadow_buffer_size*
00346      (long)shadow_buffer_size*(long)sizeof(float))) == NULL){
00347    Render_Message(2,0,NULL);
00348    return;
00349  }
00350  if((depth2 = (float *)X__Malloc((long)shadow_buffer_size*
00351      (long)shadow_buffer_size*(long)sizeof(float))) == NULL){
00352    X__Free(Lights[id].shadow_buffer);
00353    Lights[id].shadow_buffer=NULL;
00354    Render_Message(2,0,NULL);
00355    return;
00356  }
00357  else Render_Message(3,0,NULL);
00358  for(i=0;i< shadow_buffer_size*shadow_buffer_size; i++){
00359    *(Lights[id].shadow_buffer+i) = 1.0e30;
00360    *(depth2+i) = 1.e30;
00361  }
00362  R_roty(t1,CamTheta);
00363  R_rotx(t2,CamAlpha);
00364  R_m4by4(t2,t1,t3);
00365  R_rotz(t1,CamPhi);
00366  R_m4by4(t1,t3,t2);
00367  R_tram(t1,ViewPoint[0],ViewPoint[1],ViewPoint[2]);
00368  R_m4by4(t1,t2,itr);   /* ITR is inverse viewing transformation */
00369  R_m4by1(itr,Lights[id].p[0],Lights[id].p[1],Lights[id].p[2],&x,&y,&z);
00370  R_tram(t1,-x,-y,-z);
00371  R_rotz(t2,-Lights[id].dPhi*PI/180.0);
00372  R_m4by4(t2,t1,t3);
00373  R_rotx(t1,-Lights[id].dAlpha*PI/180.0);
00374  R_m4by4(t1,t3,t2);
00375  R_roty(t1,0.0);   /* no light bank dTheta*/
00376  R_m4by4(t1,t2,tr);  /* transform for light as viewing point */
00377  R_m4by4(tr,itr,Lights[id].shadow_transform); /* to move point to sh. buffer*/
00378  shadow_buffer_size2 = shadow_buffer_size/2.0;
00379  /* cone2 is 1/2 the cone angle + edge andle - radians */
00380  Lights[id].scale=d=(double)shadow_buffer_size2/tan(Lights[id].cone2);
00381  if(R_Nground > 0){ /* get ground depth */
00382    double c,b,mu;
00383    vector gp0,gp1,gp2,gn;
00384    R_m4by1(Lights[id].shadow_transform,
00385                Ground.p[0],Ground.p[1],Ground.p[2],&x,&y,&z);
00386    gp0[0]=x; gp0[1]=y; gp0[2]=z;
00387    R_m4by1(Lights[id].shadow_transform,
00388                Ground.x[0],Ground.x[1],Ground.x[2],&x,&y,&z);
00389    gp1[0]=x; gp1[1]=y; gp1[2]=z;
00390    R_m4by1(Lights[id].shadow_transform,
00391                Ground.y[0],Ground.y[1],Ground.y[2],&x,&y,&z);
00392    gp2[0]=x; gp2[1]=y; gp2[2]=z;
00393    vecsub(gp1,gp0,gp1);
00394    vecsub(gp2,gp0,gp2);
00395    cross(gp1,gp2,gn);
00396    normalize(gn);
00397    c=DOT(gp0,gn);
00398    for(i=0,l=0;i<shadow_buffer_size;i++){
00399      d2=(double)(shadow_buffer_size2-i);
00400      for(j=0;j<shadow_buffer_size;j++){ /* light points (0,1,0) */
00401 //       dr[0]=((double)j + 0.5); dr[1]=d; dr[2]=d2; // For direct distance
00402 //       normalize(dr); b=DOT(gn,dr);                // ""     ""
00403        b=gn[0]*((double)j + 0.5)+gn[1]*d+gn[2]*d2;
00404        if(fabs(b) > 1.e-4){
00405          mu=c/b;
00406          if(mu > 0.0){
00407            *(depth2+l) = mu*d;
00408 //           *(depth2+l) = mu;    // direct distance
00409          }
00410          l++;
00411        }
00412      }
00413    }
00414  }
00415  for(i=0;i<ObjectCount;i++){
00416    if(!Object[i].in_use)continue;
00417    v=Object[i].Vbase;
00418    f=Object[i].Fbase;
00419    if(!Object[i].cast_shadow)continue;
00420    for(j=0;j<Object[i].NoFaces;j++){
00421      vi[0]=(f+j)->V[0]; vi[1]=(f+j)->V[1]; vi[2]=(f+j)->V[2];
00422      for(l=0;l<3;l++){
00423        R_m4by1(Lights[id].shadow_transform,
00424                (v+vi[l])->p[0],(v+vi[l])->p[1],(v+vi[l])->p[2],
00425                &x,&y,&z);
00426        if(y > 0.0){  /* vertex in front of light */
00427          xx[l]=(double)shadow_buffer_size2 + d*x/y;
00428          yy[l]=(double)shadow_buffer_size2 - d*z/y;
00429          pp[l][0]=x; pp[l][1]=y; pp[l][2]=z;
00430        }
00431        else goto FACEBREAK;
00432      }
00433      xxmin=min(xx[1],xx[2]);     xxmin=min(xx[0],xxmin);
00434      xxmax=max(xx[1],xx[2]);     xxmax=max(xx[0],xxmax);
00435      yymin=min(yy[1],yy[2]);     yymin=min(yy[0],yymin);
00436      yymax=max(yy[1],yy[2]);     yymax=max(yy[0],yymax);
00437      if((yymax > yymin) && (xxmax > xxmin)){
00438        VECSUB(pp[2],pp[0],pp[2])
00439        VECSUB(pp[1],pp[0],pp[1])
00440        cross(pp[1],pp[2],en);
00441        if(normalize(en) == 0){
00442          ec=DOT(pp[0],en);
00443          for(l=max(0,(long)yymin);l<=min((long)yymax,shadow_buffer_size-1);l++){
00444            if(ShadowMirrorLine(l,xx,yy,&xxmin,&xxmax,0.0,
00445                                (double)shadow_buffer_size)){
00446              d2=(double)(shadow_buffer_size2-l);
00447              UpdateShadowZbuffer(Lights[id].shadow_buffer,depth2,
00448                                  l,xxmin,xxmax,d,d2,en,ec,
00449                                  (double)shadow_buffer_size2);
00450            }
00451          }
00452        }
00453      }
00454      FACEBREAK:;
00455    }
00456  }
00457  for(i=0;i< shadow_buffer_size*shadow_buffer_size; i++){
00458    d2f = *(Lights[id].shadow_buffer+i);
00459    if(*(depth2+i) < 1.e25 && d2f < 1.e25){
00460      *(Lights[id].shadow_buffer+i) = ( d2f + *(depth2+i) )*0.5;
00461    }
00462    else{
00463      *(Lights[id].shadow_buffer+i) += 1.e30;
00464    }
00465    *(depth2+i) = d2f;
00466  }
00467 // X__Free(depth2);
00468  Lights[id].atmospheric_shadow_buffer=depth2;
00469  return;
00470 }
00471 
00472 #define SBS shadow_buffer_size
00473 //#define TOLL1 1.0
00475 //#define TOLL2 200.0       // OK for atmospherics for atmospherics
00476 
00477 #define TOLL1 10.0
00478 #define TOLL2 0.0
00479 
00480 static void UpdateShadowZbuffer(float *id, float *iq,
00481                                 long l, double xl, double xr,
00482                                 double d, double d2, vector en, double ec,
00483                                 double SBC){
00484  long i,ixl,ixr;
00485  double depth,bL,bR,aL,aR,dL,dR;
00486  xl += 0.01;
00487  xr -= 0.01;
00488  ixl = (long)xl;
00489  ixr = (long)xr;
00490  if(ixl == ixr){
00491    dL = xl - SBC;
00492    dR = xr - SBC;
00493    bL = en[0]*dL + en[2]*d2 + en[1]*d ;
00494    if(fabs(bL) < 1.e-30)aL=BIGP;
00495    else aL = ec/bL;
00496    bR = en[0]*dR + en[2]*d2 + en[1]*d ;
00497    if(fabs(bR) < 1.e-30)aR=BIGP;
00498    else aR = ec/bR;
00499    depth=max(aL,aR)*d;
00500    if(fabs(depth - *(id+l*SBS+ixl)) < TOLL1){;}
00501    else if(depth > 0 && depth <= *(id+l*SBS+ixl)){
00502      if(*(id+l*SBS+ixl) <= *(iq+l*SBS+ixl)) *(iq+l*SBS+ixl) = *(id+l*SBS+ixl);
00503      *(id+l*SBS+ixl) = depth;
00504    }
00505    else if(depth > 0 && depth < *(iq+l*SBS+ixl)) *(iq+l*SBS+ixl) = depth;
00506  }
00507  else{
00508    dL = xl - SBC;
00509    bL = en[0]*dL + en[2]*d2 + en[1]*d ;
00510    if(fabs(bL) < 1.e-30)aL=BIGP;
00511    else aL = ec/bL; /* mu for vector {dL,d,d2} */
00512    bR = en[0]*(double)(ixl+1-SBC) + en[2]*d2 + en[1]*d ;
00513    if(fabs(bR) < 1.e-30)aR=BIGP;
00514    else aR = ec/bR; /* mu for vector {dL,d,d2} */
00515    depth=max(aL,aR)*d;
00516    if(fabs(depth - *(id+l*SBS+ixl)) < TOLL1){;}
00517    else if(depth > 0 && depth <= *(id+l*SBS+ixl)){
00518      if(*(id+l*SBS+ixl) <= *(iq+l*SBS+ixl)) *(iq+l*SBS+ixl) = *(id+l*SBS+ixl);
00519      *(id+l*SBS+ixl) = depth;
00520    }
00521    else if(depth > 0 && depth < *(iq+l*SBS+ixl)) *(iq+l*SBS+ixl) = depth;
00522    bL = en[0]*(double)(ixr-SBC) + en[2]*d2 + en[1]*d ;
00523    if(fabs(bL) < 1.e-30)aL=BIGP;
00524    else aL = ec/bL; /* mu for vector {dL,d,d2} */
00525    dR = xr - SBC;
00526    bR = en[0]*dR + en[2]*d2 + en[1]*d ;
00527    if(fabs(bR) < 1.e-30)aR=BIGP;
00528    else aR = ec/bR; /* mu for vector {dL,d,d2} */
00529    depth=max(aR,aL)*d;
00530    if(fabs(depth - *(id+l*SBS+ixr)) < TOLL1){;}
00531    else if(depth > 0 && depth <= *(id+l*SBS+ixr)){
00532      if(*(id+l*SBS+ixr) <= *(iq+l*SBS+ixr)) *(iq+l*SBS+ixr) = *(id+l*SBS+ixr);
00533      *(id+l*SBS+ixr) = depth;
00534    }
00535    else if(depth > 0 && depth < *(iq+l*SBS+ixr)) *(iq+l*SBS+ixr) = depth;
00536    if(ixr-ixl > 1)for(i=ixl+1;i<ixr;i++){
00537      bL = en[0]*(double)(i-SBC) + en[2]*d2 + en[1]*d ;
00538      if(fabs(bL) < 1.e-30)aL=BIGP;
00539      else aL = ec/bL;  /* mu for vector {dL,d,d2} */
00540      bR = en[0]*(double)(i+1-SBC) + en[2]*d2 + en[1]*d ;
00541      if(fabs(bR) < 1.e-30)aR=BIGP;
00542      else aR = ec/bR;  /* mu for vector {dL,d,d2} */
00543      depth=max(aL,aR)*d;
00544      if(fabs(depth - *(id+l*SBS+i)) < TOLL1){;}
00545      else if(depth > 0 && depth <= *(id+l*SBS+i)){
00546        if(*(id+l*SBS+i) <= *(iq+l*SBS+i)) *(iq+l*SBS+i) = *(id+l*SBS+i);
00547        *(id+l*SBS+i) = depth;
00548      }
00549      else if(depth > 0 && depth < *(iq+l*SBS+i)) *(iq+l*SBS+i) = depth;
00550    }
00551  }
00552 }
00553 
00554 #ifdef _SUNSTYLE
00555 void PointInShadow(p,id,intensity)
00556 vector p; long id; double *intensity; {
00557 #else
00558 void PointInShadow(vector p, long id, double *intensity){
00559 #endif
00560   double x,y,z,zz,dx,dy,i0,ix,iy,ii;
00561   long xx,yy,i,j,
00562 //  edge=0,
00563   edge=2,
00564   edge3,sum; /* double xx,yy; */
00565   R_m4by1(Lights[id].shadow_transform,p[0],p[1],p[2],&x,&y,&z);
00566   if(y > 0.0){  /* point in front of light */
00567     i0 = ix = iy = *intensity;
00568     dx=((double)shadow_buffer_size2 + Lights[id].scale*x/y);
00569     dy=((double)shadow_buffer_size2 - Lights[id].scale*z/y);
00570     xx=(long)dx; yy=(long)dy; sum=0; edge3=0;
00571     for(i=xx-edge;i<=xx+edge;i++)for(j=yy-edge;j<=yy+edge;j++){
00572       if(i >= 0 && i < SBS && j >= 0 && j < SBS){
00573         zz = *(Lights[id].shadow_buffer+j*SBS+i);
00574         if(zz < y)sum++; edge3++;
00575       }
00576     }
00577     if(edge3 > 0)i0 = i0 *
00578       (1.0 - (double)sum/(double)edge3*(1.0-shadow_density));
00579     xx++; sum=0; edge3=0;
00580     for(i=xx-edge;i<=xx+edge;i++)for(j=yy-edge;j<=yy+edge;j++){
00581       if(i >= 0 && i < SBS && j >= 0 && j < SBS){
00582         zz = *(Lights[id].shadow_buffer+j*SBS+i);
00583         if(zz < y)sum++; edge3++;
00584       }
00585     }
00586     if(edge3 > 0)ix = ix *
00587       (1.0 - (double)sum/(double)edge3*(1.0-shadow_density));
00588     yy++; xx--; sum=0; edge3=0;
00589     for(i=xx-edge;i<=xx+edge;i++)for(j=yy-edge;j<=yy+edge;j++){
00590       if(i >= 0 && i < SBS && j >= 0 && j < SBS){
00591         zz = *(Lights[id].shadow_buffer+j*SBS+i);
00592         if(zz < y)sum++; edge3++;
00593       }
00594     }
00595     if(edge3 > 0)iy = iy *
00596       (1.0 - (double)sum/(double)edge3*(1.0-shadow_density));
00597     yy--;
00598     dx -= (double)xx;
00599     dy -= (double)yy;
00600     ii = i0 + (ix - i0)*dx + (iy - i0)*dy;
00601     ii = min(ii,*intensity);
00602     *intensity = max(0.0,ii);
00603   }
00604   return;
00605 }
00606 
00607 #ifdef TRACER
00608 
00609 /* this function is nessary only if full trace of shadows etc. */
00610 
00611 #define TOL    1.e-6
00612 #define TOLE   1.e-4
00613 
00614 int R_intersect_face_old(vector p, vector d,
00615                      vector pf0, vector pf1, vector pf2, vector n,
00616                      double *depth, double tollerance){
00617 /* tollerance is to allow for no hit on origin face */
00618 /* p is origin of ray         d is (normalise ray direction */
00619 /* other params are for face being tested */
00620  vector v1,pi;
00621  double mu,mu1,det1,det2,det3,ve1,ve2,ve3,vp1,vp2,vp3,p1,p2,p3,a,b,dm,detmax;
00622  int k;
00623  mu1=DOT(d,n);
00624  if(fabs(mu1) < TOL)return 0;   /* parallel to face */
00625  VECSUB(pf0,p,v1)
00626  mu=DOT(n,v1)/mu1;
00627  if(mu < tollerance)return 0;          /* behind the ray   */
00628  VECSCALE(mu,d,v1)
00629  VECSUM(p,v1,pi)
00630  ve1=pf1[0]-pf0[0]; ve2=pf1[1]-pf0[1]; ve3=pf1[2]-pf0[2];
00631  vp1=pf2[0]-pf0[0]; vp2=pf2[1]-pf0[1]; vp3=pf2[2]-pf0[2];
00632  p1=pi[0]-pf0[0];
00633  p2=pi[1]-pf0[1];
00634  p3=pi[2]-pf0[2];
00635  det1=ve1*vp2-vp1*ve2;
00636  det2=ve1*vp3-vp1*ve3;
00637  det3=ve2*vp3-vp2*ve3;
00638  k=0; detmax=TOL;
00639  if((dm=fabs(det1)) > detmax){k=1; detmax=dm;}
00640  if((dm=fabs(det2)) > detmax){k=2; detmax=dm;}
00641  if((dm=fabs(det3)) > detmax){k=3; detmax=dm;}
00642  if(k == 0)return 0;
00643  else if(k == 1){
00644    a=( vp2*p1-vp1*p2)/det1;
00645    b=(-ve2*p1+ve1*p2)/det1;
00646  }
00647  else if(k == 2){
00648    a=( vp3*p1-vp1*p3)/det2;
00649    b=(-ve3*p1+ve1*p3)/det2;
00650  }
00651  else if(k == 3){
00652    a=( vp3*p2-vp2*p3)/det3;
00653    b=(-ve3*p2+ve2*p3)/det3;
00654  }
00655  if( a < -TOLE || a > 1.0+TOLE || b < -TOLE || b > 1.0+TOLE || (a+b) > 1.0+TOLE)return 0;
00656  *depth=mu;
00657  return 1;
00658 }
00659 
00660 #define TOLF 0.0001
00661 #define TOLP 0.025   // 0.01 = 89.4 degrees.
00662 #define TOLQ 100.0     // much smaller than face
00663 int R_intersect_face(vector p, vector d,
00664                      vector pf0, vector pf1, vector pf2, vector n,
00665                      double *depth, double tollerance){
00666 /* tollerance is to allow for no hit on origin face */
00667 /* p is origin of ray         d is (normalise ray direction */
00668 /* other params are for face being tested */
00669  vector v1,pi,w,u,v;
00670  double mu,a,b,de,uu,vv,wu,wv,uv; 
00671  mu=DOT(d,n);
00672  if(fabs(mu) < TOLP)return 0;   /* parallel to face */
00673  VECSUB(pf0,p,v1)
00674  mu=DOT(n,v1)/mu;
00675  if(mu < tollerance)return 0;   /* behind the ray origin  */
00676  VECSCALE(mu,d,v1)
00677  VECSUM(p,v1,pi)
00678  VECSUB(pi,pf0,w)
00679  VECSUB(pf1,pf0,u)
00680  VECSUB(pf2,pf0,v)
00681  uv=DOT(u,v);
00682  uu=DOT(u,u);
00683  vv=DOT(v,v);
00684  de=uu*vv-uv*uv;
00685  if(fabs(de) < TOLQ)return 0; 
00686  wu=DOT(w,u);
00687  wv=DOT(w,v);
00688  a=(wu*vv-wv*uv)/de; 
00689  b=(wv*uu-wu*uv)/de;
00690  if( a < -TOLF || a > 1.0+TOLF || b < -TOLF || b > 1.0+TOLF || (a+b) > 1.0+TOLF)return 0;
00691  *depth=mu;
00692  return 1;
00693 }
00694 
00695 
00696 
00697 
00698 #endif
00699 

Generated on Sun Apr 27 14:20:13 2014 for OpenFX by  doxygen 1.5.6