@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
51 lines (41 loc) • 1.53 kB
JavaScript
import { assert } from "../assert.js";
/**
* Computes associated Legendre Polynomial P(l,m,x) at x
* Useful in Spherical Harmonics coefficient computation
* @param {number} l band
* @param {number} m
* @param {number} x must be between 0 and 1
* @returns {number}
*/
export function compute_legendre_polynomial(l, m, x) {
assert.lessThanOrEqual(x,1,'only valid for X <= 1');
// TODO we might be able to do better, see https://github.com/halueda/wavy-orbitals/blob/fe738b0f8de8783cb7886d2c6ee616c2befb363b/legendre.js#L16
// based on code from https://github.com/jan-van-bergen/SphericalHarmonicLighting/blob/2b214b3451859ded07ea4e41fb2aa8d2a44ab579/SphericalHarmonicsLighting/SphericalHarmonics.cpp#L61
// Apply rule 2; P m m
let pmm = 1.0;
if (m > 0) {
const somx2 = Math.sqrt((1.0 - x) * (1.0 + x));
let fact = 1.0;
for (let i = 1; i <= m; i++) {
pmm *= (-fact) * somx2;
fact += 2.0;
}
}
// If l is equal to m then P m m is already the right answer
if (l === m) {
return pmm;
}
// Use rule 3 once
let pmmp1 = x * (2.0 * m + 1.0) * pmm;
if (l === m + 1) {
return pmmp1;
}
// Iterate rule 1 until the right answer is found
let pll = 0.0;
for (let ll = m + 2; ll <= l; ll++) {
pll = ((2.0 * ll - 1.0) * x * pmmp1 - (ll + m - 1.0) * pmm) / (ll - m);
pmm = pmmp1;
pmmp1 = pll;
}
return pll;
}