Commit f1c3d4ddbe054fcc883fcbcc680dae0d406f3453

Authored by David Mayerich
1 parent 5795a81c

added spherical harmonics evaluation header file

Showing 1 changed file with 72 additions and 0 deletions   Show diff stats
programming/random/cpp/sh.h 0 → 100644
  1 +/* Solving the associated legendre polynomials iteratively. Most of this code was taken from
  2 + * the work described by Robin Green from Sony Computer Entertainment America:
  3 + *
  4 + * R. Green, Spherical Harmonic Lighting: The Gritty Details, Sony Computer Entertainment America, 2003
  5 + * http://www.research.scea.com/gdc2003/spherical-harmonic-lighting.pdf
  6 + */
  7 +
  8 +
  9 +/// This function computes the factorial n!
  10 +/// where n! = n * (n-1) * (n-2) * (n-3) * ...... * 2 * 1
  11 +unsigned long factorial(unsigned int n)
  12 +{
  13 + if (n == 0) //the standard definition of a factorial specifies that 0! = 1
  14 + return 1;
  15 + return n * factorial(n - 1); //recursively call this function
  16 +}
  17 +
  18 +/// Evaluate an Associated Legendre Polynomial P(l,m,x) at x
  19 +/// This implements evaluation of the associated Legendre polynomials using
  20 +/// a recursive method with the following rules:
  21 +///
  22 +/// 1) (l - m)P(l, m) = x(2l-1)P(l-1, m) - (l + m - 1)P(l-2, m)
  23 +/// 2) P(m, m) = (-1)^m (2m - 1)!! (1 - x^2)^{m/2}
  24 +/// 3) P(m+1, m) = x (2m + 1)P(m, m)
  25 +double P(int l,int m,double x)
  26 +{
  27 +
  28 + double pmm = 1.0; //first iteration, P(0, 0) = 1
  29 + if(m>0) { //solve for positive values of m
  30 + double somx2 = sqrt((1.0-x)*(1.0+x));
  31 + double fact = 1.0;
  32 + for(int i=1; i<=m; i++) {
  33 + pmm *= (-fact) * somx2;
  34 + fact += 2.0;
  35 + }
  36 + }
  37 + if(l==m) return pmm; //if the degree equals the order, the solution is found above
  38 + double pmmp1 = x * (2.0*m+1.0) * pmm;
  39 + if(l==m+1) return pmmp1;
  40 + double pll = 0.0;
  41 + for(int ll=m+2; ll<=l; ++ll) {
  42 + pll = ( (2.0*ll-1.0)*x*pmmp1-(ll+m-1.0)*pmm ) / (ll-m);
  43 + pmm = pmmp1;
  44 + pmmp1 = pll;
  45 + }
  46 + return pll;
  47 +}
  48 +
  49 +/// Calculate the scaling factor for a normalized Legendre polynomial
  50 +/// l is the degree, ranging from [0..N]
  51 +/// m is the order in the range [-l..l]
  52 +double K(int l, int m)
  53 +{
  54 + static const double K_PI = 3.14159;
  55 + // renormalisation constant for SH function
  56 + double temp = ((2.0*l+1.0)*factorial(l-m)) / (4.0*K_PI*factorial(l+m));
  57 + return sqrt(temp);
  58 +}
  59 +
  60 +/// return a point sample of a Spherical Harmonic basis function
  61 +/// l is the degree, range [0..N]
  62 +/// m is the order in the range [-l..l]
  63 +/// theta in the range [0..Pi]
  64 +/// phi in the range [0..2*Pi]
  65 +double SH(int l, int m, double theta, double phi){
  66 +
  67 + const double sqrt2 = sqrt(2.0);
  68 + if(m==0) return K(l,0)*P(l,m,cos(theta));
  69 + else if(m>0) return sqrt2*K(l,m)*cos(m*phi)*P(l,m,cos(theta));
  70 + else return sqrt2*K(l,-m)*sin(-m*phi)*P(l,-m,cos(theta));
  71 +}
  72 +