Back to index

radiance  4R0+20100331
dircode.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: dircode.c,v 2.7 2003/06/27 06:53:21 greg Exp $";
00003 #endif
00004 /*
00005  * Compute a 4-byte direction code (externals defined in rtmath.h).
00006  *
00007  * Mean accuracy is 0.0022 degrees, with a maximum error of 0.0058 degrees.
00008  */
00009 
00010 #include "rtmath.h"
00011 
00012 #define       DCSCALE              11585.2              /* (1<<13)*sqrt(2) */
00013 #define FXNEG        01
00014 #define FYNEG        02
00015 #define FZNEG        04
00016 #define F1X          010
00017 #define F2Z          020
00018 #define F1SFT        5
00019 #define F2SFT        18
00020 #define FMASK        0x1fff
00021 
00022 int32
00023 encodedir(dv)        /* encode a normalized direction vector */
00024 FVECT  dv;
00025 {
00026        register int32       dc = 0;
00027        int    cd[3], cm;
00028        register int  i;
00029 
00030        for (i = 0; i < 3; i++)
00031               if (dv[i] < 0.) {
00032                      cd[i] = (int)(dv[i] * -DCSCALE);
00033                      dc |= FXNEG<<i;
00034               } else
00035                      cd[i] = (int)(dv[i] * DCSCALE);
00036        if (!(cd[0] | cd[1] | cd[2]))
00037               return(0);           /* zero normal */
00038        if (cd[0] <= cd[1]) {
00039               dc |= F1X | cd[0] << F1SFT;
00040               cm = cd[1];
00041        } else {
00042               dc |= cd[1] << F1SFT;
00043               cm = cd[0];
00044        }
00045        if (cd[2] <= cm)
00046               dc |= F2Z | cd[2] << F2SFT;
00047        else
00048               dc |= cm << F2SFT;
00049        if (!dc)      /* don't generate 0 code normally */
00050               dc = F1X;
00051        return(dc);
00052 }
00053 
00054 
00055 void
00056 decodedir(dv, dc)    /* decode a normalized direction vector */
00057 register FVECT       dv;    /* returned */
00058 register int32       dc;
00059 {
00060        double d1, d2, der;
00061 
00062        if (!dc) {           /* special code for zero normal */
00063               dv[0] = dv[1] = dv[2] = 0.;
00064               return;
00065        }
00066        d1 = ((dc>>F1SFT & FMASK)+.5)*(1./DCSCALE);
00067        d2 = ((dc>>F2SFT & FMASK)+.5)*(1./DCSCALE);
00068        der = sqrt(1. - d1*d1 - d2*d2);
00069        if (dc & F1X) {
00070               dv[0] = d1;
00071               if (dc & F2Z) { dv[1] = der; dv[2] = d2; }
00072               else { dv[1] = d2; dv[2] = der; }
00073        } else {
00074               dv[1] = d1;
00075               if (dc & F2Z) { dv[0] = der; dv[2] = d2; }
00076               else { dv[0] = d2; dv[2] = der; }
00077        }
00078        if (dc & FXNEG) dv[0] = -dv[0];
00079        if (dc & FYNEG) dv[1] = -dv[1];
00080        if (dc & FZNEG) dv[2] = -dv[2];
00081 }
00082 
00083 
00084 double
00085 dir2diff(dc1, dc2)          /* approx. radians^2 between directions */
00086 int32  dc1, dc2;
00087 {
00088        FVECT  v1, v2;
00089 
00090        decodedir(v1, dc1);
00091        decodedir(v2, dc2);
00092 
00093        return(2. - 2.*DOT(v1,v2));
00094 }
00095 
00096 
00097 double
00098 fdir2diff(dc1, v2)          /* approx. radians^2 between directions */
00099 int32  dc1;
00100 register FVECT       v2;
00101 {
00102        FVECT  v1;
00103 
00104        decodedir(v1, dc1);
00105 
00106        return(2. - 2.*DOT(v1,v2));
00107 }