00001
00002 #ifndef Y_SAMPLEUTILS_H
00003 #define Y_SAMPLEUTILS_H
00004
00005 #include <core_api/ray.h>
00006 #include <algorithm>
00007 #include <string.h>
00008
00009 __BEGIN_YAFRAY
00010
00012
00013 vector3d_t inline SampleCosHemisphere(const vector3d_t &N,const vector3d_t &Ru,const vector3d_t &Rv, float s1, float s2)
00014 {
00015 PFLOAT z1 = s1;
00016 PFLOAT z2 = s2*M_2PI;
00017 return (Ru*fCos(z2) + Rv*fSin(z2))*fSqrt(1.0-z1) + N*fSqrt(z1);
00018 }
00019
00021
00022 vector3d_t inline SampleSphere(float s1, float s2)
00023 {
00024 vector3d_t dir;
00025 dir.z = 1.0f - 2.0f*s1;
00026 PFLOAT r = 1.0f - dir.z*dir.z;
00027 if(r>0.0f)
00028 {
00029 r = fSqrt(r);
00030 PFLOAT a = M_2PI * s2;
00031 dir.x = fCos(a) * r;
00032 dir.y = fSin(a) * r;
00033 }
00034 else
00035 {
00036 dir.x = 0.0f;
00037 dir.y = 0.0f;
00038 }
00039 return dir;
00040 }
00041
00043
00044 vector3d_t inline sampleCone(const vector3d_t &D, const vector3d_t &U, const vector3d_t &V, double maxCosAng, PFLOAT s1, PFLOAT s2)
00045 {
00046 double cosAng = 1.0 - (1.0-(double)maxCosAng) * (double)s2;
00047 double sinAng = fSqrt(1.0 - cosAng*cosAng);
00048 PFLOAT t1 = M_2PI*s1;
00049 return (U*fCos(t1) + V*fSin(t1))*(PFLOAT)sinAng + D*(PFLOAT)cosAng;
00050 }
00051
00052
00053 void inline CumulateStep1dDF(const float *f, int nSteps, float *integral, float *cdf)
00054 {
00055 int i;
00056 double c = 0.0, delta = 1.0/(double)nSteps;
00057 cdf[0] = 0.0;
00058 for (i = 1; i < nSteps+1; ++i)
00059 {
00060 c += (double)f[i-1] * delta;
00061 cdf[i] = float(c);
00062 }
00063 *integral = (float)c;
00064 for (i = 1; i < nSteps+1; ++i)
00065 cdf[i] /= *integral;
00066 }
00067
00073 class pdf1D_t
00074 {
00075 public:
00076 pdf1D_t() {}
00077 pdf1D_t(float *f, int n) {
00078 func = new float[n];
00079 cdf = new float[n+1];
00080 count = n;
00081 memcpy(func, f, n*sizeof(float));
00082 CumulateStep1dDF(func, n, &integral, cdf);
00083 invIntegral = 1.f / integral;
00084 invCount = 1.f / count;
00085 }
00086 ~pdf1D_t(){ delete[] func, delete[] cdf; }
00087 float Sample(float u, float *pdf)const
00088 {
00089
00090 float *ptr = std::lower_bound(cdf, cdf+count+1, u);
00091 int index = (int) (ptr-cdf-1);
00092
00093 float delta = (u - cdf[index]) / (cdf[index+1] - cdf[index]);
00094 if(pdf) *pdf = func[index] * invIntegral;
00095 return index + delta;
00096 }
00097
00098
00099 int DSample(float u, float *pdf)const
00100 {
00101 if(u == 0.f){ *pdf = func[0] * invIntegral; return 0; }
00102 float *ptr = std::lower_bound(cdf, cdf+count+1, u);
00103 int index = (int) (ptr-cdf-1);
00104 if(pdf) *pdf = func[index] * invIntegral;
00105 return index;
00106 }
00107
00108 float *func, *cdf;
00109 float integral, invIntegral, invCount;
00110 int count;
00111 };
00112
00113
00114
00115
00116
00117 void inline minRot(const vector3d_t &D, const vector3d_t &U,
00118 const vector3d_t &D2, vector3d_t &U2, vector3d_t &V2)
00119 {
00120 PFLOAT cosAlpha = D*D2;
00121 PFLOAT sinAlpha = fSqrt(1 - cosAlpha*cosAlpha);
00122 vector3d_t v = D^D2;
00123 U2 = cosAlpha*U + (1.f-cosAlpha) * (v*U) + sinAlpha * (v^U);
00124 V2 = D2^U2;
00125 }
00126
00127 inline vector3d_t reflect_plane(const vector3d_t &n,const vector3d_t &v)
00128 {
00129 const PFLOAT vn = v*n;
00130 return (2.f*vn)*n - v;
00131 }
00132
00134
00135 inline float addMod1(float a, float b)
00136 {
00137 float s = a+b;
00138 return s>1 ? s-1.f : s;
00139 }
00140
00141 __END_YAFRAY
00142
00143 #endif // Y_SAMPLEUTILS_H