better solid angle-weighted hemisphere sampling routine, code cleanups
parent
d53f7c9196
commit
825acab263
|
@ -28,8 +28,9 @@ MTS_NAMESPACE_BEGIN
|
|||
* \brief Three-dimensional normal data structure
|
||||
*
|
||||
* Internally represented using floating point numbers of the chosen
|
||||
* compile-time precision. The main difference in comparison to <tt>TVector3<Float></tt>
|
||||
* is in how instances of <tt>Normal</tt> are treated by linear transformations.
|
||||
* compile-time precision. The main difference of this data structure
|
||||
* when compared to \ref TVector3<Float> is in how instances of
|
||||
* \ref Normal are treated by linear transformations.
|
||||
*
|
||||
* \ingroup libcore
|
||||
* \ingroup libpython
|
||||
|
|
|
@ -68,8 +68,14 @@
|
|||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#define __OSX__
|
||||
#if !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#elif defined(__linux)
|
||||
#define __LINUX__
|
||||
#if !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#else
|
||||
#error Unknown OS
|
||||
#endif
|
||||
|
|
|
@ -50,7 +50,7 @@ template <typename T> struct TPoint2 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint2() { }
|
||||
#else
|
||||
TPoint2() { x = y = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TPoint2() { x = y = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
|
@ -243,7 +243,7 @@ template <typename T> struct TPoint3 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint3() { }
|
||||
#else
|
||||
TPoint3() { x = y = z = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TPoint3() { x = y = z = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
|
@ -440,7 +440,7 @@ template <typename T> struct TPoint4 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TPoint4() { }
|
||||
#else
|
||||
TPoint4() { x = y = z = w = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TPoint4() { x = y = z = w = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the point with the specified X, Y and Z components
|
||||
|
|
|
@ -87,11 +87,47 @@ namespace std {
|
|||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void sincos(float theta, float *sin, float *cos) {
|
||||
float sinValue = sinf(theta);
|
||||
*sin = sinValue;
|
||||
*cos = sqrtf(1.0f-sinValue*sinValue);
|
||||
}
|
||||
|
||||
inline void sincos(double theta, double *sin, double *cos) {
|
||||
double sinValue = sin(theta);
|
||||
*sin = sinValue;
|
||||
*cos = sqrt(1.0-sinValue*sinValue);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
using std::select2nd;
|
||||
using std::compose1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace std {
|
||||
#if defined(_GNU_SOURCE)
|
||||
inline void sincos(float theta, float *sin, float *cos) {
|
||||
::sincosf(theta, sin, cos);
|
||||
}
|
||||
|
||||
inline void sincos(double theta, double *sin, double *cos) {
|
||||
::sincos(theta, sin, cos);
|
||||
}
|
||||
#else
|
||||
inline void sincos(float theta, float *sin, float *cos) {
|
||||
float sinValue = sinf(theta);
|
||||
*sin = sinValue;
|
||||
*cos = sqrtf(1.0f-sinValue*sinValue);
|
||||
}
|
||||
|
||||
inline void sincos(double theta, double *sin, double *cos) {
|
||||
double sinValue = sin(theta);
|
||||
*sin = sinValue;
|
||||
*cos = sqrt(1.0-sinValue*sinValue);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(WIN32)
|
||||
inline bool mts_isnan(float f) {
|
||||
|
|
|
@ -49,7 +49,7 @@ template <typename T> struct TVector2 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TVector2() { }
|
||||
#else
|
||||
TVector2() { x = y = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TVector2() { x = y = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the vector with the specified X and Z components
|
||||
|
@ -241,7 +241,7 @@ template <typename T> struct TVector3 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TVector3() { }
|
||||
#else
|
||||
TVector3() { x = y = z = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TVector3() { x = y = z = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the vector with the specified X, Y and Z components
|
||||
|
@ -447,7 +447,7 @@ template <typename T> struct TVector4 {
|
|||
#if !defined(MTS_DEBUG_UNINITIALIZED)
|
||||
TVector4() { }
|
||||
#else
|
||||
TVector4() { x = y = z = w = std::numeric_limits<double>::quiet_NaN(); }
|
||||
TVector4() { x = y = z = w = std::numeric_limits<T>::quiet_NaN(); }
|
||||
#endif
|
||||
|
||||
/// Initialize the vector with the specified X, Y and Z components
|
||||
|
|
|
@ -586,60 +586,56 @@ void latinHypercube(Random *random, Float *dest, size_t nSamples, size_t nDim) {
|
|||
|
||||
|
||||
Vector sphericalDirection(Float theta, Float phi) {
|
||||
Float sinTheta = std::sin(theta);
|
||||
Float sinTheta, cosTheta, sinPhi, cosPhi;
|
||||
|
||||
std::sincos(theta, &sinTheta, &cosTheta);
|
||||
std::sincos(phi, &sinPhi, &cosPhi);
|
||||
|
||||
return Vector(
|
||||
sinTheta * std::cos(phi),
|
||||
sinTheta * std::sin(phi),
|
||||
std::cos(theta)
|
||||
sinTheta * cosPhi,
|
||||
sinTheta * sinPhi,
|
||||
cosTheta
|
||||
);
|
||||
}
|
||||
|
||||
Vector squareToSphere(const Point2 &sample) {
|
||||
Float z = 1.0f - 2.0f * sample.y;
|
||||
Float r = 1.0f - z * z;
|
||||
r = std::sqrt(std::max((Float) 0, r));
|
||||
Float phi = 2.0f * M_PI * sample.x;
|
||||
return Vector(r * std::cos(phi), r * std::sin(phi), z);
|
||||
Float r = std::sqrt(std::max((Float) 0.0f, 1.0f - z*z));
|
||||
Float sinPhi, cosPhi;
|
||||
std::sincos(2.0f * M_PI * sample.x, &sinPhi, &cosPhi);
|
||||
return Vector(r * cosPhi, r * sinPhi, z);
|
||||
}
|
||||
|
||||
Vector squareToHemisphere(const Point2 &sample) {
|
||||
Float phi = 2.0f * M_PI * sample.x;
|
||||
Float r2 = sample.y;
|
||||
Float tmp = std::sqrt(1-std::min((Float) 1, r2*r2));
|
||||
Float z = sample.y;
|
||||
Float tmp = std::sqrt(std::min((Float) 0, 1-z*z));
|
||||
|
||||
return Vector(
|
||||
std::cos(phi) * tmp,
|
||||
std::sin(phi) * tmp,
|
||||
r2
|
||||
);
|
||||
Float sinPhi, cosPhi;
|
||||
std::sincos(2.0f * M_PI * sample.x, &sinPhi, &cosPhi);
|
||||
|
||||
return Vector(cosPhi * tmp, sinPhi * tmp, z);
|
||||
}
|
||||
|
||||
Vector squareToHemispherePSA(const Point2 &sample) {
|
||||
Float r = std::sqrt(sample.x);
|
||||
Float phi = 2.0f * M_PI * sample.y;
|
||||
Float dirX = r * std::cos(phi);
|
||||
Float dirY = r * std::sin(phi);
|
||||
Float z = std::sqrt(1 - std::min((Float) 1, dirX*dirX + dirY*dirY));
|
||||
Point2 p = squareToDiskConcentric(sample);
|
||||
Float z = std::sqrt(std::max((Float) 0,
|
||||
1.0f - p.x*p.x - p.y*p.y));
|
||||
|
||||
if (EXPECT_NOT_TAKEN(z == 0)) {
|
||||
/* Guard against numerical imprecisions */
|
||||
return normalize(Vector(
|
||||
dirX, dirY, Epsilon));
|
||||
}
|
||||
/* Guard against numerical imprecisions */
|
||||
if (EXPECT_NOT_TAKEN(z == 0))
|
||||
z = 1e-10f;
|
||||
|
||||
return Vector(
|
||||
dirX, dirY, z
|
||||
);
|
||||
return Vector(p.x, p.y, z);
|
||||
}
|
||||
|
||||
Point2 squareToDisk(const Point2 &sample) {
|
||||
Float r = std::sqrt(sample.x);
|
||||
Float phi = 2.0f * M_PI * sample.y;
|
||||
Float dirX = r * std::cos(phi);
|
||||
Float dirY = r * std::sin(phi);
|
||||
Float sinPhi, cosPhi;
|
||||
std::sincos(2.0f * M_PI * sample.y, &sinPhi, &cosPhi);
|
||||
|
||||
return Point2(
|
||||
dirX, dirY
|
||||
cosPhi * r,
|
||||
sinPhi * r
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -687,10 +683,10 @@ Point2 squareToDiskConcentric(const Point2 &sample) {
|
|||
else
|
||||
coords = Point2(-r2, (M_PI/4.0f) * (6.0f - r1/r2));
|
||||
}
|
||||
return Point2(
|
||||
coords.x*std::cos(coords.y),
|
||||
coords.x*std::sin(coords.y)
|
||||
);
|
||||
|
||||
Point2 result;
|
||||
std::sincos(coords.y, &result.y, &result.x);
|
||||
return result*coords.x;
|
||||
}
|
||||
|
||||
Float squareToConePdf(Float cosCutoff) {
|
||||
|
@ -706,12 +702,11 @@ Vector squareToCone(Float cosCutoff, const Point2 &sample) {
|
|||
}
|
||||
|
||||
Point2 squareToStdNormal(const Point2 &sample) {
|
||||
Float tmp1 = std::sqrt(-2 * std::log(1-sample.x)),
|
||||
tmp2 = 2 * M_PI * sample.y;
|
||||
return Point2(
|
||||
tmp1 * std::cos(tmp2),
|
||||
tmp1 * std::sin(tmp2)
|
||||
);
|
||||
Float r = std::sqrt(-2 * std::log(1-sample.x)),
|
||||
phi = 2 * M_PI * sample.y;
|
||||
Point2 result;
|
||||
std::sincos(phi, &result.y, &result.x);
|
||||
return result * r;
|
||||
}
|
||||
|
||||
Float lanczosSinc(Float t, Float tau) {
|
||||
|
|
Loading…
Reference in New Issue