ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/cal/fovsample.cal
Revision: 1.5
Committed: Tue Apr 9 00:52:55 2019 UTC (5 years, 1 month ago) by greg
Branch: MAIN
CVS Tags: rad5R4, rad5R3, HEAD
Changes since 1.4: +7 -6 lines
Log Message:
Added second degenerate case for vector opposite foveal direction

File Contents

# User Rev Content
1 greg 1.5 { RCSid $Id: fovsample.cal,v 1.4 2019/04/07 15:38:35 greg Exp $ }
2 greg 1.1 {
3     Foveated sampling based on central direction vector,
4     magnification factor at center, and central field of view.
5    
6     Greg Ward April 2019
7    
8 greg 1.2 Preset constants:
9 greg 1.1 Cx, Cy, Cz : central view direction
10 greg 1.2 M : central FOV magnification factor
11 greg 1.1 D : field of view (full angle in degrees)
12    
13     Inputs:
14 greg 1.4 forward = 1 if forward conversion, -1 if reverse
15     iDx, iDy, iDz = input sampling vector
16 greg 1.1
17     Outputs:
18 greg 1.4 oDx, oDy, oDz = output sample direction (normalized)
19 greg 1.1
20     Other variables computed:
21 greg 1.4 iTheta = input angle to center (radians)
22     oTheta = output angle to center (radians)
23 greg 1.1 }
24 greg 1.2
25     r : PI/360 * D; { half-angle of foveal region in radians }
26     rp : M * r; { half-angle of mapped boundary }
27    
28 greg 1.1 len(x,y,z) : sqrt(x*x + y*y + z*z);
29 greg 1.3 sq(x) : x*x;
30 greg 1.2 { normalize central vector }
31 greg 1.1 Clen : len(Cx,Cy,Cz);
32     nCx : Cx/Clen;
33     nCy : Cy/Clen;
34     nCz : Cz/Clen;
35 greg 1.2 { normalize input direction }
36 greg 1.1 iDnf = 1/len(iDx,iDy,iDz);
37     niDx = iDx*iDnf;
38     niDy = iDy*iDnf;
39     niDz = iDz*iDnf;
40 greg 1.5 { check for degenerate case (center of fovea or opposite) }
41 greg 1.2 iDot = nCx*niDx + nCy*niDy + nCz*niDz;
42 greg 1.5 degen0 = iDot - cos(.05*PI/180);
43     degen1 = cos(179.95*PI/180) - iDot;
44 greg 1.1
45     iTheta = acos(iDot);
46 greg 1.4 { quadratic function coefficients mate to linear ramp }
47     qa : (PI - PI/M)/sq(PI - rp);
48     qb : 1/M - 2*PI*r*(M - 1)/sq(PI - rp);
49     qc : (PI - PI/M)/sq(PI/rp - 1);
50    
51     oTheta = if (forward,
52     if(rp-iTheta, iTheta/M, qa*iTheta*iTheta + qb*iTheta + qc),
53     if(r-iTheta, iTheta*M, (sqrt(qb*qb - 4*qa*(qc - iTheta)) - qb)/(2*qa))
54     );
55 greg 1.2 { normalized "up" vector for rotation }
56     Unf = 1/sqrt(1 - iDot*iDot);
57 greg 1.1 nUx = (nCy*niDz - nCz*niDy)*Unf;
58     nUy = (nCz*niDx - nCx*niDz)*Unf;
59     nUz = (nCx*niDy - nCy*niDx)*Unf;
60 greg 1.2 { rotate central vector by oTheta to get new output }
61     rcos = cos(oTheta);
62     rsin = sqrt(1 - rcos*rcos);
63     { foveated sample direction }
64 greg 1.3 rDx = nCx*rcos + (nUy*nCz - nUz*nCy)*rsin;
65     rDy = nCy*rcos + (nUz*nCx - nUx*nCz)*rsin;
66     rDz = nCz*rcos + (nUx*nCy - nUy*nCx)*rsin;
67 greg 1.2 { substitute approximation in degenerate case }
68 greg 1.5 oDx = if(degen0, nCx+(niDx-nCx)*if(forward,1/M,M), if(degen1, niDx, rDx));
69     oDy = if(degen0, nCy+(niDy-nCy)*if(forward,1/M,M), if(degen1, niDy, rDy));
70     oDz = if(degen0, nCz+(niDz-nCz)*if(forward,1/M,M), if(degen1, niDz, rDz));