1 |
greg |
1.3 |
{ RCSid $Id: fovsample.cal,v 1.2 2019/04/05 17:17:53 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 |
|
|
iDx, iDy, iDz = uniformly generated sampling vector |
15 |
|
|
|
16 |
|
|
Outputs: |
17 |
|
|
oDx, oDy, oDz = foveated sample direction (normalized) |
18 |
|
|
|
19 |
|
|
Other variables computed: |
20 |
|
|
iTheta = original angle to center (radians) |
21 |
greg |
1.2 |
oTheta = new angle to center (radians) |
22 |
greg |
1.1 |
} |
23 |
greg |
1.2 |
|
24 |
|
|
r : PI/360 * D; { half-angle of foveal region in radians } |
25 |
|
|
rp : M * r; { half-angle of mapped boundary } |
26 |
|
|
|
27 |
greg |
1.1 |
len(x,y,z) : sqrt(x*x + y*y + z*z); |
28 |
greg |
1.3 |
sq(x) : x*x; |
29 |
greg |
1.2 |
{ normalize central vector } |
30 |
greg |
1.1 |
Clen : len(Cx,Cy,Cz); |
31 |
|
|
nCx : Cx/Clen; |
32 |
|
|
nCy : Cy/Clen; |
33 |
|
|
nCz : Cz/Clen; |
34 |
greg |
1.2 |
{ normalize input direction } |
35 |
greg |
1.1 |
iDnf = 1/len(iDx,iDy,iDz); |
36 |
|
|
niDx = iDx*iDnf; |
37 |
|
|
niDy = iDy*iDnf; |
38 |
|
|
niDz = iDz*iDnf; |
39 |
greg |
1.2 |
{ check for degenerate case (center of fovea) } |
40 |
|
|
iDot = nCx*niDx + nCy*niDy + nCz*niDz; |
41 |
|
|
degen = iDot - cos(.05*PI/180); |
42 |
greg |
1.1 |
|
43 |
|
|
iTheta = acos(iDot); |
44 |
|
|
|
45 |
greg |
1.3 |
gamma = 1 + sq((iTheta-rp)/(PI-rp)) * (log(M)/(log(PI/(PI-r)) - log(M))); |
46 |
greg |
1.1 |
|
47 |
greg |
1.3 |
oTheta = if(rp-iTheta, iTheta/M, (PI-r)*(iTheta/(M*(PI-r)))^gamma); |
48 |
greg |
1.1 |
|
49 |
greg |
1.2 |
{ normalized "up" vector for rotation } |
50 |
|
|
Unf = 1/sqrt(1 - iDot*iDot); |
51 |
greg |
1.1 |
nUx = (nCy*niDz - nCz*niDy)*Unf; |
52 |
|
|
nUy = (nCz*niDx - nCx*niDz)*Unf; |
53 |
|
|
nUz = (nCx*niDy - nCy*niDx)*Unf; |
54 |
greg |
1.2 |
{ rotate central vector by oTheta to get new output } |
55 |
|
|
rcos = cos(oTheta); |
56 |
|
|
rsin = sqrt(1 - rcos*rcos); |
57 |
|
|
{ foveated sample direction } |
58 |
greg |
1.3 |
rDx = nCx*rcos + (nUy*nCz - nUz*nCy)*rsin; |
59 |
|
|
rDy = nCy*rcos + (nUz*nCx - nUx*nCz)*rsin; |
60 |
|
|
rDz = nCz*rcos + (nUx*nCy - nUy*nCx)*rsin; |
61 |
greg |
1.2 |
{ substitute approximation in degenerate case } |
62 |
greg |
1.1 |
oDx = if(degen, nCx+(niDx-nCx)/M, rDx); |
63 |
|
|
oDy = if(degen, nCy+(niDy-nCy)/M, rDy); |
64 |
|
|
oDz = if(degen, nCz+(niDz-nCz)/M, rDz); |