Spectrum FourierBSDF::f(const Vector3f &wo, const Vector3f &wi) const { // Find the zenith angle cosines and azimuth difference angle Float muI = CosTheta(-wi), muO = CosTheta(wo); Float cosPhi = CosDPhi(-wi, wo); // Compute Fourier coefficients $a_k$ for $(\mui, \muo)$ // Determine offsets and weights for $\mui$ and $\muo$ int offsetI, offsetO; Float weightsI[4], weightsO[4]; if (!bsdfTable.GetWeightsAndOffset(muI, &offsetI, weightsI) || !bsdfTable.GetWeightsAndOffset(muO, &offsetO, weightsO)) return Spectrum(0.f); // Allocate storage to accumulate _ak_ coefficients Float *ak = ALLOCA(Float, bsdfTable.mMax * bsdfTable.nChannels); memset(ak, 0, bsdfTable.mMax * bsdfTable.nChannels * sizeof(Float)); // Accumulate weighted sums of nearby $a_k$ coefficients int mMax = 0; for (int b = 0; b < 4; ++b) { for (int a = 0; a < 4; ++a) { // Add contribution of _(a, b)_ to $a_k$ values Float weight = weightsI[a] * weightsO[b]; if (weight != 0) { int m; const Float *ap = bsdfTable.GetAk(offsetI + a, offsetO + b, &m); mMax = std::max(mMax, m); for (int c = 0; c < bsdfTable.nChannels; ++c) for (int k = 0; k < m; ++k) ak[c * bsdfTable.mMax + k] += weight * ap[c * m + k]; } } } // Evaluate Fourier expansion for angle $\phi$ Float Y = std::max((Float)0, Fourier(ak, mMax, cosPhi)); Float scale = muI != 0 ? (1 / std::abs(muI)) : (Float)0; // Update _scale_ to account for adjoint light transport if (mode == TransportMode::Radiance && muI * muO > 0) { float eta = muI > 0 ? 1 / bsdfTable.eta : bsdfTable.eta; scale *= eta * eta; } if (bsdfTable.nChannels == 1) return Spectrum(Y * scale); else { // Compute and return RGB colors for tabulated BSDF Float R = Fourier(ak + 1 * bsdfTable.mMax, mMax, cosPhi); Float B = Fourier(ak + 2 * bsdfTable.mMax, mMax, cosPhi); Float G = 1.39829f * Y - 0.100913f * B - 0.297375f * R; Float rgb[3] = {R * scale, G * scale, B * scale}; return Spectrum::FromRGB(rgb).Clamp(); } }
vtkRectilinearGrid* avtFFTFilter::ComputeFFT(std::vector<double>* data, long nData, double dt) { debug5 <<"avtFFTFilter::ComputeFFT() - Entering" <<std::endl; // 1. Find the power of 2 greater than length of history data //We make a variable containing the value 2.0 //So that the windows compiler knows which "log" method we're trying to call double doubleTwo = 2.0; long nPwr2 = ceil(log((double)nData)/log(doubleTwo)); // 2) Get length of work array: nFFT = 2^nPwr2, nFFTdouble = 2*nFFT, nFFThalf = nFFT/2 long longTwo = 2; long nFFT = pow((long double)longTwo, (int)nPwr2); long nFFTdouble = 2 * nFFT; long nFFThalf = nFFT / 2; // 3) new double fftData[nFFTdouble], and zero-fill. double* fftData = new double[nFFTdouble]; for(long i = 0; i < nFFTdouble; i++) { fftData[i] = 0; } // 4) copy data over to fftData, with stride 2 for(long i = 0; i < nData; i++) { fftData[i * 2] = data->operator[](i); } // 5) perform the FFT, Fourier(fftData,nFFT,1) Fourier(fftData, nFFT, 1); // 6) compute complex amplitude, dB, and compress in array double oneENeg25 = pow((double)10, -25); for(int i = 0; i < nFFThalf; i++) { int jIndex = i * 2; fftData[i] = 10 * log10(std::max(oneENeg25, (pow(fftData[jIndex], 2) + pow(fftData[jIndex + 1], 2)))); } // 7) df = 1.0/(nFFT*dt) double df = 1.0/(nFFT * dt); // 8) get frequency axis: new freqs[nFFThalf], freq[i]=i*df std::vector<double> freqs; freqs.reserve(nFFThalf); for(long i = 0; i < nFFThalf; i++) { freqs.push_back(i * df); } // 9) Plot fftData[0:nFFThalf-1] vs. freqs. vtkRectilinearGrid* outGrid = PopulateRGrid(&freqs, fftData, nFFThalf); delete []fftData; debug5 <<"avtFFTFilter::ComputeFFT() - Returning" <<std::endl; return outGrid; }
void CLjz153View::OnFft() { // TODO: Add your command handler code here if (lpDIB_FFT) free(lpDIB_FFT); lpDIB_IFFT = NULL; Fourier(); Invalidate(); }
static void split (COMPLEX *in, int r, int m, COMPLEX *out) { register unsigned k, s, i, j; for (k = 0, j = 0; k < r; k++) for (s = 0, i = k; s < m; s++, i += r, j++) out [j] = in [i]; for (k = 0; k < r; k++, out += m, in += m) Fourier (out, m, in); }
rft ( COMPLEX *in, unsigned n, COMPLEX *out ) { if (W_init (n) == -1) return -1; Fourier (in, n, out); return 0; }
Float FourierBSDF::Pdf(const Vector3f &wo, const Vector3f &wi) const { // Find the zenith angle cosines and azimuth difference angle Float muI = CosTheta(-wi), muO = CosTheta(wo); Float cosPhi = CosDPhi(-wi, wo); // Compute luminance Fourier coefficients $a_k$ for $(\mui, \muo)$ int offsetI, offsetO; Float weightsI[4], weightsO[4]; if (!bsdfTable.GetWeightsAndOffset(muI, &offsetI, weightsI) || !bsdfTable.GetWeightsAndOffset(muO, &offsetO, weightsO)) return 0; Float *ak = ALLOCA(Float, bsdfTable.mMax * bsdfTable.nChannels); memset(ak, 0, bsdfTable.mMax * bsdfTable.nChannels * sizeof(Float)); int mMax = 0; for (int o = 0; o < 4; ++o) { for (int i = 0; i < 4; ++i) { Float weight = weightsI[i] * weightsO[o]; if (weight == 0) continue; int order; const Float *coeffs = bsdfTable.GetAk(offsetI + i, offsetO + o, &order); mMax = std::max(mMax, order); for (int k = 0; k < order; ++k) ak[k] += *coeffs++ * weight; } } // Evaluate probability of sampling _wi_ Float rho = 0; for (int o = 0; o < 4; ++o) { if (weightsO[o] == 0) continue; rho += weightsO[o] * bsdfTable.cdf[(offsetO + o) * bsdfTable.nMu + bsdfTable.nMu - 1] * (2 * Pi); } Float Y = Fourier(ak, mMax, cosPhi); return (rho > 0 && Y > 0) ? (Y / rho) : 0; }
int fft ( COMPLEX *in, unsigned n, COMPLEX *out ) { unsigned i; for (i = 0; i < n; i++) c_conj (in [i]); if (W_init (n) == -1) return -1; Fourier (in, n, out); for (i = 0; i < n; i++) { c_conj (out [i]); c_realdiv (out [i], n); } return 0; }
Spectrum FourierBSDF::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u, Float *pdf, BxDFType *sampledType) const { // Sample zenith angle component for _FourierBSDF_ Float muO = CosTheta(wo); Float pdfMu; Float muI = SampleCatmullRom2D(bsdfTable.nMu, bsdfTable.nMu, bsdfTable.mu, bsdfTable.mu, bsdfTable.avg, bsdfTable.cdf, muO, u[1], nullptr, &pdfMu); // Compute Fourier coefficients $a_k$ for $(\mui, \muo)$ // Determine offsets and weights for $\mui$ and $\muo$ int offsetI, offsetO; Float weightsI[4], weightsO[4]; if (!bsdfTable.GetWeightsAndOffset(muI, &offsetI, weightsI) || !bsdfTable.GetWeightsAndOffset(muO, &offsetO, weightsO)) return Spectrum(0.f); // Allocate storage to accumulate _ak_ coefficients Float *ak = ALLOCA(Float, bsdfTable.mMax * bsdfTable.nChannels); memset(ak, 0, bsdfTable.mMax * bsdfTable.nChannels * sizeof(Float)); // Accumulate weighted sums of nearby $a_k$ coefficients int mMax = 0; for (int b = 0; b < 4; ++b) { for (int a = 0; a < 4; ++a) { // Add contribution of _(a, b)_ to $a_k$ values Float weight = weightsI[a] * weightsO[b]; if (weight != 0) { int m; const Float *ap = bsdfTable.GetAk(offsetI + a, offsetO + b, &m); mMax = std::max(mMax, m); for (int c = 0; c < bsdfTable.nChannels; ++c) for (int k = 0; k < m; ++k) ak[c * bsdfTable.mMax + k] += weight * ap[c * m + k]; } } } // Importance sample the luminance Fourier expansion Float phi, pdfPhi; Float Y = SampleFourier(ak, bsdfTable.recip, mMax, u[0], &pdfPhi, &phi); *pdf = std::max((Float)0, pdfPhi * pdfMu); // Compute the scattered direction for _FourierBSDF_ Float sin2ThetaI = 1 - muI * muI; Float norm = std::sqrt(sin2ThetaI / Sin2Theta(wo)); Float sinPhi = std::sin(phi), cosPhi = std::cos(phi); *wi = -Vector3f(norm * (cosPhi * wo.x - sinPhi * wo.y), norm * (sinPhi * wo.x + cosPhi * wo.y), muI); // Evaluate remaining Fourier expansions for angle $\phi$ Float scale = muI != 0 ? (1 / std::abs(muI)) : (Float)0; if (mode == TransportMode::Radiance && muI * muO > 0) { float eta = muI > 0 ? 1 / bsdfTable.eta : bsdfTable.eta; scale *= eta * eta; } if (bsdfTable.nChannels == 1) return Spectrum(Y * scale); Float R = Fourier(ak + 1 * bsdfTable.mMax, mMax, cosPhi); Float B = Fourier(ak + 2 * bsdfTable.mMax, mMax, cosPhi); Float G = 1.39829f * Y - 0.100913f * B - 0.297375f * R; Float rgb[3] = {R * scale, G * scale, B * scale}; return Spectrum::FromRGB(rgb).Clamp(); }