00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _LUXRAYS_SDL_MC_H
00023 #define _LUXRAYS_SDL_MC_H
00024
00025 #include <string.h>
00026
00027 #include "luxrays/luxrays.h"
00028
00029 namespace luxrays { namespace sdl {
00030
00031 template<class T> inline T Lerp(float t, T v1, T v2) {
00032 return (1.f - t) * v1 + t * v2;
00033 }
00034
00035 inline void LatLongMappingMap(float s, float t, Vector *wh, float *pdf) {
00036 const float theta = t * M_PI;
00037 const float sinTheta = sinf(theta);
00038
00039 if (wh) {
00040 const float phi = s * 2.f * M_PI;
00041 *wh = SphericalDirection(sinTheta, cosf(theta), phi);
00042 }
00043
00044 if (pdf)
00045 *pdf = INV_TWOPI * INV_PI / sinTheta;
00046 }
00047
00048 inline void ConcentricSampleDisk(const float u1, const float u2, float *dx, float *dy) {
00049 float r, theta;
00050
00051 float sx = 2.f * u1 - 1.f;
00052 float sy = 2.f * u2 - 1.f;
00053
00054
00055 if (sx == 0.f && sy == 0.f) {
00056 *dx = 0.f;
00057 *dy = 0.f;
00058 return;
00059 }
00060 if (sx >= -sy) {
00061 if (sx > sy) {
00062
00063 r = sx;
00064 if (sy > 0.f)
00065 theta = sy / r;
00066 else
00067 theta = 8.0f + sy / r;
00068 } else {
00069
00070 r = sy;
00071 theta = 2.0f - sx / r;
00072 }
00073 } else {
00074 if (sx <= sy) {
00075
00076 r = -sx;
00077 theta = 4.0f - sy / r;
00078 } else {
00079
00080 r = -sy;
00081 theta = 6.0f + sx / r;
00082 }
00083 }
00084 theta *= M_PI / 4.f;
00085 *dx = r * cosf(theta);
00086 *dy = r * sinf(theta);
00087 }
00088
00089 inline Vector UniformSampleSphere(const float u1, const float u2) {
00090 float z = 1.f - 2.f * u1;
00091 float r = sqrtf(Max(0.f, 1.f - z * z));
00092 float phi = 2.f * M_PI * u2;
00093 float x = r * cosf(phi);
00094 float y = r * sinf(phi);
00095
00096 return Vector(x, y, z);
00097 }
00098
00099 inline Vector CosineSampleHemisphere(const float u1, const float u2) {
00100 Vector ret;
00101 ConcentricSampleDisk(u1, u2, &ret.x, &ret.y);
00102 ret.z = sqrtf(Max(0.f, 1.f - ret.x * ret.x - ret.y * ret.y));
00103
00104 return ret;
00105 }
00106
00107 inline Vector UniformSampleCone(float u1, float u2, float costhetamax) {
00108 float costheta = Lerp(u1, costhetamax, 1.f);
00109 float sintheta = sqrtf(1.f - costheta*costheta);
00110 float phi = u2 * 2.f * M_PI;
00111 return Vector(cosf(phi) * sintheta,
00112 sinf(phi) * sintheta,
00113 costheta);
00114 }
00115
00116 inline Vector UniformSampleCone(float u1, float u2, float costhetamax,const Vector &x, const Vector &y, const Vector &z) {
00117 float costheta = Lerp(u1, costhetamax, 1.f);
00118 float sintheta = sqrtf(1.f - costheta*costheta);
00119 float phi = u2 * 2.f * M_PI;
00120 return cosf(phi) * sintheta * x + sinf(phi) * sintheta * y + costheta * z;
00121 }
00122
00123 inline float UniformConePdf(float costhetamax) {
00124 return 1.f / (2.f * M_PI * (1.f - costhetamax));
00125 }
00126
00127 inline void ComputeStep1dCDF(const float *f, unsigned int nSteps, float *c, float *cdf) {
00128
00129 cdf[0] = 0.f;
00130 for (unsigned int i = 1; i < nSteps + 1; ++i)
00131 cdf[i] = cdf[i - 1] + f[i - 1] / nSteps;
00132
00133 *c = cdf[nSteps];
00134 for (unsigned int i = 1; i < nSteps + 1; ++i)
00135 cdf[i] /= *c;
00136 }
00137
00138
00139 class Distribution1D {
00140 public:
00141
00150 Distribution1D(const float *f, unsigned int n) {
00151 func = new float[n];
00152 cdf = new float[n + 1];
00153 count = n;
00154 memcpy(func, f, n * sizeof (float));
00155
00156
00157 ComputeStep1dCDF(func, n, &funcInt, cdf);
00158 invFuncInt = 1.f / funcInt;
00159 invCount = 1.f / count;
00160 }
00161
00162 ~Distribution1D() {
00163 delete[] func;
00164 delete[] cdf;
00165 }
00166
00177 float SampleContinuous(float u, float *pdf, unsigned int *off = NULL) const {
00178
00179 float *ptr = std::lower_bound(cdf, cdf + count + 1, u);
00180 unsigned int offset = Max<int>(0, ptr - cdf - 1);
00181
00182
00183 const float du = (u - cdf[offset]) /
00184 (cdf[offset + 1] - cdf[offset]);
00185
00186
00187 *pdf = func[offset] * invFuncInt;
00188
00189
00190 if (off)
00191 *off = offset;
00192
00193
00194 return (offset + du) * invCount;
00195 }
00196
00207 unsigned int SampleDiscrete(float u, float *pdf, float *du = NULL) const {
00208
00209 float *ptr = std::lower_bound(cdf, cdf + count + 1, u);
00210 unsigned int offset = Max<int>(0, ptr - cdf - 1);
00211
00212
00213 if (du)
00214 *du = (u - cdf[offset]) /
00215 (cdf[offset + 1] - cdf[offset]);
00216
00217
00218 *pdf = func[offset] * invFuncInt * invCount;
00219 return offset;
00220 }
00221
00222 float Pdf(float u) const {
00223 return func[Offset(u)] * invFuncInt;
00224 }
00225
00226 float Average() const {
00227 return funcInt;
00228 }
00229
00230 unsigned int Offset(float u) const {
00231 return Min(count - 1, Floor2UInt(u * count));
00232 }
00233
00234 private:
00235
00236
00237
00238
00239 float *func, *cdf;
00244 float funcInt, invFuncInt, invCount;
00245
00246
00247
00248 unsigned int count;
00249 };
00250
00251 class Distribution2D {
00252 public:
00253 Distribution2D(const float *data, unsigned int nu, unsigned int nv) {
00254 pConditionalV.reserve(nv);
00255
00256 for (unsigned int v = 0; v < nv; ++v)
00257 pConditionalV.push_back(new Distribution1D(data + v * nu, nu));
00258
00259 std::vector<float> marginalFunc;
00260 marginalFunc.reserve(nv);
00261 for (unsigned int v = 0; v < nv; ++v)
00262 marginalFunc.push_back(pConditionalV[v]->Average());
00263 pMarginal = new Distribution1D(&marginalFunc[0], nv);
00264 }
00265
00266 ~Distribution2D() {
00267 delete pMarginal;
00268 for (unsigned int i = 0; i < pConditionalV.size(); ++i)
00269 delete pConditionalV[i];
00270 }
00271
00272 void SampleContinuous(float u0, float u1, float uv[2],
00273 float *pdf) const {
00274 float pdfs[2];
00275 unsigned int v;
00276 uv[1] = pMarginal->SampleContinuous(u1, &pdfs[1], &v);
00277 uv[0] = pConditionalV[v]->SampleContinuous(u0, &pdfs[0]);
00278 *pdf = pdfs[0] * pdfs[1];
00279 }
00280
00281 void SampleDiscrete(float u0, float u1, unsigned int uv[2], float *pdf) const {
00282 float pdfs[2];
00283 uv[1] = pMarginal->SampleDiscrete(u1, &pdf[1]);
00284 uv[0] = pConditionalV[uv[1]]->SampleDiscrete(u0, &pdf[0]);
00285 *pdf = pdfs[0] * pdfs[1];
00286 }
00287
00288 float Pdf(float u, float v) const {
00289 return pConditionalV[pMarginal->Offset(v)]->Pdf(u) *
00290 pMarginal->Pdf(v);
00291 }
00292
00293 float Average() const {
00294 return pMarginal->Average();
00295 }
00296
00297 private:
00298
00299 std::vector<Distribution1D *> pConditionalV;
00300 Distribution1D *pMarginal;
00301 };
00302
00303 } }
00304
00305 #endif
00306