new 'math' namespace, some minor reorganization, added erf()/erfinv() functions
parent
152cfa4b26
commit
76766fb10c
|
@ -135,7 +135,7 @@ struct Frame {
|
|||
Float sinTheta = Frame::sinTheta(v);
|
||||
if (sinTheta == 0.0f)
|
||||
return 1.0f;
|
||||
return clamp(v.y / sinTheta, (Float) -1.0f, (Float) 1.0f);
|
||||
return math::clamp(v.y / sinTheta, (Float) -1.0f, (Float) 1.0f);
|
||||
}
|
||||
|
||||
/** \brief Assuming that the given direction is in the local coordinate
|
||||
|
@ -144,21 +144,21 @@ struct Frame {
|
|||
Float sinTheta = Frame::sinTheta(v);
|
||||
if (sinTheta == 0.0f)
|
||||
return 1.0f;
|
||||
return clamp(v.x / sinTheta, (Float) -1.0f, (Float) 1.0f);
|
||||
return math::clamp(v.x / sinTheta, (Float) -1.0f, (Float) 1.0f);
|
||||
}
|
||||
|
||||
/** \brief Assuming that the given direction is in the local coordinate
|
||||
* system, return the squared sine of the phi parameter in spherical
|
||||
* coordinates */
|
||||
inline static Float sinPhi2(const Vector &v) {
|
||||
return clamp(v.y * v.y / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
|
||||
return math::clamp(v.y * v.y / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
|
||||
}
|
||||
|
||||
/** \brief Assuming that the given direction is in the local coordinate
|
||||
* system, return the squared cosine of the phi parameter in spherical
|
||||
* coordinates */
|
||||
inline static Float cosPhi2(const Vector &v) {
|
||||
return clamp(v.x * v.x / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
|
||||
return math::clamp(v.x * v.x / sinTheta2(v), (Float) 0.0f, (Float) 1.0f);
|
||||
}
|
||||
|
||||
/// Equality test
|
||||
|
|
|
@ -23,7 +23,143 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* Contains elementary 1D math functions that were either not provided by the standard,
|
||||
* or which are not consistently provided on all platforms/compilers
|
||||
*/
|
||||
namespace math {
|
||||
|
||||
/// Cross-platform implementation of the error function
|
||||
extern MTS_EXPORT_CORE Float erf(Float x);
|
||||
|
||||
/// Cross-platform implementation of the inverse error function
|
||||
extern MTS_EXPORT_CORE Float erfinv(Float x);
|
||||
|
||||
/// sqrt(a^2 + b^2) without range issues (like 'hypot' on compilers that support C99, single precision)
|
||||
extern MTS_EXPORT_CORE float hypot2(float a, float b);
|
||||
|
||||
/// sqrt(a^2 + b^2) without range issues (like 'hypot' on compilers that support C99, double precision)
|
||||
extern MTS_EXPORT_CORE double hypot2(double a, double b);
|
||||
|
||||
/// Base-2 logarithm (single precision)
|
||||
extern MTS_EXPORT_CORE float log2(float value);
|
||||
|
||||
/// Base-2 logarithm (double precision)
|
||||
extern MTS_EXPORT_CORE double log2(double value);
|
||||
|
||||
/// Generic clamping function
|
||||
template <typename Scalar> inline Scalar clamp(Scalar value, Scalar min, Scalar max) {
|
||||
return std::min(max, std::max(min, value));
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two values
|
||||
template <typename Scalar> inline Scalar lerp(Scalar t, Scalar v1, Scalar v2) {
|
||||
return ((Scalar) 1 - t) * v1 + t * v2;
|
||||
}
|
||||
|
||||
/// S-shaped smoothly varying interpolation between two values
|
||||
template <typename Scalar> inline Scalar smoothStep(Scalar min, Scalar max, Scalar value) {
|
||||
Scalar v = clamp((value - min) / (max - min), (Scalar) 0, (Scalar) 1);
|
||||
return v * v * (-2 * v + 3);
|
||||
}
|
||||
|
||||
/// Always-positive modulo function (assumes b > 0)
|
||||
inline int32_t modulo(int32_t a, int32_t b) {
|
||||
int32_t r = a % b;
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Always-positive modulo function (assumes b > 0)
|
||||
inline int64_t modulo(int64_t a, int64_t b) {
|
||||
int64_t r = a % b;
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline ssize_t modulo(ssize_t a, ssize_t b) {
|
||||
if (sizeof(ssize_t) == 8)
|
||||
return modulo((int64_t) a, (int64_t) b);
|
||||
else
|
||||
return modulo((int32_t) a, (int32_t) b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Always-positive modulo function, single precision version (assumes b > 0)
|
||||
inline float modulo(float a, float b) {
|
||||
float r = std::fmod(a, b);
|
||||
return (r < 0.0f) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Always-positive modulo function, double precision version (assumes b > 0)
|
||||
inline double modulo(double a, double b) {
|
||||
double r = std::fmod(a, b);
|
||||
return (r < 0.0) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Integer floor function (single precision)
|
||||
template <typename Scalar> inline int floorToInt(Scalar value) { return (int) std::floor(value); }
|
||||
|
||||
/// Integer ceil function (single precision)
|
||||
template <typename Scalar> inline int ceilToInt(Scalar value) { return (int) std::ceil(value); }
|
||||
|
||||
/// Integer round function (single precision)
|
||||
inline int roundToInt(float value) { return (int) ::roundf(value); }
|
||||
|
||||
/// Integer round function (double precision)
|
||||
inline int roundToInt(double value) { return (int) ::round(value); }
|
||||
|
||||
/// Base-2 logarithm (32-bit integer version)
|
||||
extern MTS_EXPORT_CORE int log2i(uint32_t value);
|
||||
|
||||
/// Base-2 logarithm (64-bit integer version)
|
||||
extern MTS_EXPORT_CORE int log2i(uint64_t value);
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline int log2i(size_t value) {
|
||||
if (sizeof(size_t) == 8)
|
||||
return log2i((uint64_t) value);
|
||||
else
|
||||
return log2i((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Check if an integer is a power of two (unsigned 32 bit version)
|
||||
inline bool isPowerOfTwo(uint32_t i) { return (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (signed 32 bit version)
|
||||
inline bool isPowerOfTwo(int32_t i) { return i > 0 && (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (64 bit version)
|
||||
inline bool isPowerOfTwo(uint64_t i) { return (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (signed 64 bit version)
|
||||
inline bool isPowerOfTwo(int64_t i) { return i > 0 && (i & (i-1)) == 0; }
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline bool isPowerOfTwo(size_t value) {
|
||||
if (sizeof(size_t) == 8) /// will be optimized away
|
||||
return isPowerOfTwo((uint64_t) value);
|
||||
else
|
||||
return isPowerOfTwo((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Round an integer to the next power of two
|
||||
extern MTS_EXPORT_CORE uint32_t roundToPowerOfTwo(uint32_t i);
|
||||
|
||||
/// Round an integer to the next power of two (64 bit version)
|
||||
extern MTS_EXPORT_CORE uint64_t roundToPowerOfTwo(uint64_t i);
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
/// Round an integer to the next power of two
|
||||
inline size_t roundToPowerOfTwo(size_t value) {
|
||||
if (sizeof(size_t) == 8) /// will be optimized away
|
||||
return (size_t) roundToPowerOfTwo((uint64_t) value);
|
||||
else
|
||||
return (size_t) roundToPowerOfTwo((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__LINUX__) && defined(__x86_64__)
|
||||
/*
|
||||
The Linux/x86_64 single precision implementations of 'exp'
|
||||
|
|
|
@ -341,7 +341,7 @@ template <int M, int N, typename T> void
|
|||
// Compute implicit shift
|
||||
T g = d[l];
|
||||
T p = (d[l + 1] - g) / (2.0f * e[l]);
|
||||
T r = hypot2(1, p);
|
||||
T r = math::hypot2((T) 1, p);
|
||||
|
||||
if (p < 0)
|
||||
r = -r;
|
||||
|
@ -368,7 +368,7 @@ template <int M, int N, typename T> void
|
|||
s2 = s;
|
||||
g = c * e[i];
|
||||
h = c * p;
|
||||
r = hypot2(p, e[i]);
|
||||
r = math::hypot2(p, e[i]);
|
||||
e[i + 1] = s * r;
|
||||
s = e[i] / r;
|
||||
c = p / r;
|
||||
|
|
|
@ -367,7 +367,7 @@ template <typename T> inline TQuaternion<T> slerp(const TQuaternion<T> &q1,
|
|||
// Revert to plain linear interpolation
|
||||
return normalize(q1 * (1.0f - t) + q2 * t);
|
||||
} else {
|
||||
Float theta = math::safe_acos(clamp(cosTheta, (Float) -1.0f, (Float) 1.0f));
|
||||
Float theta = math::safe_acos(math::clamp(cosTheta, (Float) -1.0f, (Float) 1.0f));
|
||||
Float thetap = theta * t;
|
||||
TQuaternion<T> qperp = normalize(q2 - q1 * cosTheta);
|
||||
return q1 * std::cos(thetap) + qperp * std::sin(thetap);
|
||||
|
|
|
@ -133,7 +133,7 @@ template <typename Scalar> struct Resampler {
|
|||
filterRadius *= scale;
|
||||
}
|
||||
|
||||
m_taps = ceilToInt(filterRadius * 2);
|
||||
m_taps = math::ceilToInt(filterRadius * 2);
|
||||
if (sourceRes == targetRes && (m_taps % 2) != 1)
|
||||
--m_taps;
|
||||
m_halfTaps = m_taps / 2;
|
||||
|
@ -149,7 +149,7 @@ template <typename Scalar> struct Resampler {
|
|||
Float center = (i + (Float) 0.5f) / targetRes * sourceRes;
|
||||
|
||||
/* Determine the index of the first original sample that might contribute */
|
||||
m_start[i] = floorToInt(center - filterRadius + (Float) 0.5f);
|
||||
m_start[i] = math::floorToInt(center - filterRadius + (Float) 0.5f);
|
||||
|
||||
/* Determine the size of center region, on which to run fast non condition-aware code */
|
||||
if (m_start[i] < 0)
|
||||
|
@ -438,13 +438,13 @@ private:
|
|||
if (EXPECT_NOT_TAKEN(pos < 0 || pos >= m_sourceRes)) {
|
||||
switch (m_bc) {
|
||||
case ReconstructionFilter::EClamp:
|
||||
pos = clamp(pos, 0, m_sourceRes - 1);
|
||||
pos = math::clamp(pos, 0, m_sourceRes - 1);
|
||||
break;
|
||||
case ReconstructionFilter::ERepeat:
|
||||
pos = modulo(pos, m_sourceRes);
|
||||
pos = math::modulo(pos, m_sourceRes);
|
||||
break;
|
||||
case ReconstructionFilter::EMirror:
|
||||
pos = modulo(pos, 2*m_sourceRes);
|
||||
pos = math::modulo(pos, 2*m_sourceRes);
|
||||
if (pos >= m_sourceRes)
|
||||
pos = 2*m_sourceRes - pos - 1;
|
||||
break;
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace math {
|
|||
* holds column 1 of the original matrix, and so on.
|
||||
* \author Intel Intrinsics Guide for AVX2
|
||||
*/
|
||||
FINLINE void transpose(__m128& row0, __m128& row1,
|
||||
FINLINE void transpose_ps(__m128& row0, __m128& row1,
|
||||
__m128& row2, __m128& row3) {
|
||||
__m128 tmp3, tmp2, tmp1, tmp0;
|
||||
tmp0 = _mm_unpacklo_ps(row0, row1);
|
||||
|
@ -96,12 +96,12 @@ namespace math {
|
|||
}
|
||||
|
||||
/// Component-wise clamp: <tt>max(min(x, maxVal), minVal)</tt>
|
||||
inline __m128 clamp(__m128 x, __m128 minVal, __m128 maxVal) {
|
||||
inline __m128 clamp_ps(__m128 x, __m128 minVal, __m128 maxVal) {
|
||||
return _mm_max_ps(_mm_min_ps(x, maxVal), minVal);
|
||||
}
|
||||
|
||||
/// Sum of all elements in the vector
|
||||
inline float hsum(__m128 vec) {
|
||||
inline float hsum_ps(__m128 vec) {
|
||||
__m128 tmp = _mm_shuffle_ps(vec, vec, _MM_SHUFFLE(1,0,3,2));
|
||||
__m128 sum_tmp = _mm_add_ps(vec, tmp);
|
||||
tmp = _mm_shuffle_ps(sum_tmp, sum_tmp, _MM_SHUFFLE(2,3,0,1));
|
||||
|
@ -110,7 +110,7 @@ namespace math {
|
|||
}
|
||||
|
||||
/// Maximum across all the elements of a vector
|
||||
inline float hmax(__m128 vec) {
|
||||
inline float hmax_ps(__m128 vec) {
|
||||
__m128 tmp = _mm_shuffle_ps(vec, vec, _MM_SHUFFLE(1,0,3,2));
|
||||
__m128 tmp_max = _mm_max_ps(vec, tmp);
|
||||
tmp = _mm_shuffle_ps(tmp_max, tmp_max, _MM_SHUFFLE(2,3,0,1));
|
||||
|
@ -119,7 +119,7 @@ namespace math {
|
|||
}
|
||||
|
||||
/// Minimum across all the elements of a vector
|
||||
inline float hmin(__m128 vec) {
|
||||
inline float hmin_ps(__m128 vec) {
|
||||
__m128 tmp = _mm_shuffle_ps(vec, vec, _MM_SHUFFLE(1,0,3,2));
|
||||
__m128 tmp_min = _mm_min_ps(vec, tmp);
|
||||
tmp = _mm_shuffle_ps(tmp_min, tmp_min, _MM_SHUFFLE(2,3,0,1));
|
||||
|
|
|
@ -477,7 +477,7 @@ FINLINE void transpose(SSEVector4f& row0, SSEVector4f& row1,
|
|||
row3 = _mm_movehl_ps(tmp3, tmp1);
|
||||
}
|
||||
|
||||
} // namespace math
|
||||
} // namespace sse
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
||||
|
|
|
@ -271,121 +271,6 @@ template <typename DataType, typename IndexType> void permute_inplace(
|
|||
//! @{ \name Numerical utility functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/// sqrt(a^2 + b^2) without underflow (like 'hypot' on compilers that support C99)
|
||||
extern MTS_EXPORT_CORE Float hypot2(Float a, Float b);
|
||||
|
||||
/// Base-2 logarithm
|
||||
extern MTS_EXPORT_CORE Float log2(Float value);
|
||||
|
||||
/// Always-positive modulo function (assumes b > 0)
|
||||
inline int32_t modulo(int32_t a, int32_t b) {
|
||||
int32_t r = a % b;
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Always-positive modulo function (assumes b > 0)
|
||||
inline int64_t modulo(int64_t a, int64_t b) {
|
||||
int64_t r = a % b;
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline ssize_t modulo(ssize_t a, ssize_t b) {
|
||||
if (sizeof(ssize_t) == 8)
|
||||
return modulo((int64_t) a, (int64_t) b);
|
||||
else
|
||||
return modulo((int32_t) a, (int32_t) b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Always-positive modulo function, float version (assumes b > 0)
|
||||
inline Float modulo(Float a, Float b) {
|
||||
Float r = std::fmod(a, b);
|
||||
return (r < 0) ? r+b : r;
|
||||
}
|
||||
|
||||
/// Compute the signum (a.k.a. "sign") function
|
||||
inline Float signum(Float value) {
|
||||
if (value < 0)
|
||||
return -1;
|
||||
else if (value > 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Compute the signum (a.k.a. "sign") function, and return an integer value
|
||||
inline int signumToInt(Float value) {
|
||||
if (value < 0)
|
||||
return -1;
|
||||
else if (value > 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Integer floor function
|
||||
inline int floorToInt(Float value) {
|
||||
return (int) std::floor(value);
|
||||
}
|
||||
|
||||
/// Integer ceil function
|
||||
inline int ceilToInt(Float value) {
|
||||
return (int) std::ceil(value);
|
||||
}
|
||||
|
||||
/// Base-2 logarithm (32-bit integer version)
|
||||
extern MTS_EXPORT_CORE int log2i(uint32_t value);
|
||||
|
||||
/// Base-2 logarithm (64-bit integer version)
|
||||
extern MTS_EXPORT_CORE int log2i(uint64_t value);
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline int log2i(size_t value) {
|
||||
if (sizeof(size_t) == 8)
|
||||
return log2i((uint64_t) value);
|
||||
else
|
||||
return log2i((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Check if an integer is a power of two (unsigned 32 bit version)
|
||||
inline bool isPowerOfTwo(uint32_t i) { return (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (signed 32 bit version)
|
||||
inline bool isPowerOfTwo(int32_t i) { return i > 0 && (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (64 bit version)
|
||||
inline bool isPowerOfTwo(uint64_t i) { return (i & (i-1)) == 0; }
|
||||
|
||||
/// Check if an integer is a power of two (signed 64 bit version)
|
||||
inline bool isPowerOfTwo(int64_t i) { return i > 0 && (i & (i-1)) == 0; }
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
inline bool isPowerOfTwo(size_t value) {
|
||||
if (sizeof(size_t) == 8) /// will be optimized away
|
||||
return isPowerOfTwo((uint64_t) value);
|
||||
else
|
||||
return isPowerOfTwo((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Round an integer to the next power of two
|
||||
extern MTS_EXPORT_CORE uint32_t roundToPowerOfTwo(uint32_t i);
|
||||
|
||||
/// Round an integer to the next power of two (64 bit version)
|
||||
extern MTS_EXPORT_CORE uint64_t roundToPowerOfTwo(uint64_t i);
|
||||
|
||||
#if defined(MTS_AMBIGUOUS_SIZE_T)
|
||||
/// Round an integer to the next power of two
|
||||
inline size_t roundToPowerOfTwo(size_t value) {
|
||||
if (sizeof(size_t) == 8) /// will be optimized away
|
||||
return (size_t) roundToPowerOfTwo((uint64_t) value);
|
||||
else
|
||||
return (size_t) roundToPowerOfTwo((uint32_t) value);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Solve a quadratic equation of the form a*x^2 + b*x + c = 0.
|
||||
* \return \c true if a solution could be found
|
||||
|
@ -407,22 +292,6 @@ inline Float radToDeg(Float value) { return value * (180.0f / M_PI); }
|
|||
/// Convert degrees to radians
|
||||
inline Float degToRad(Float value) { return value * (M_PI / 180.0f); }
|
||||
|
||||
/// Generic clamping function
|
||||
template <typename Scalar> inline Scalar clamp(Scalar value, Scalar min, Scalar max) {
|
||||
return std::min(max, std::max(min, value));
|
||||
}
|
||||
|
||||
/// Linearly interpolate between two values
|
||||
inline Float lerp(Float t, Float v1, Float v2) {
|
||||
return ((Float) 1 - t) * v1 + t * v2;
|
||||
}
|
||||
|
||||
/// S-shaped smoothly varying interpolation between two values
|
||||
inline Float smoothStep(Float min, Float max, Float value) {
|
||||
Float v = clamp((value - min) / (max - min), (Float) 0, (Float) 1);
|
||||
return v * v * (-2 * v + 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Numerically well-behaved routine for computing the angle
|
||||
* between two unit direction vectors
|
||||
|
|
|
@ -31,29 +31,28 @@ MTS_NAMESPACE_BEGIN
|
|||
* The main application of this class is to generate uniformly
|
||||
* distributed or weighted point sets in certain common target domains.
|
||||
*/
|
||||
class MTS_EXPORT_CORE Warp {
|
||||
public:
|
||||
namespace warp {
|
||||
// =============================================================
|
||||
//! @{ \name Warping techniques related to spheres and subsets
|
||||
// =============================================================
|
||||
|
||||
/// Uniformly sample a vector on the unit sphere with respect to solid angles
|
||||
static Vector squareToUniformSphere(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Vector squareToUniformSphere(const Point2 &sample);
|
||||
|
||||
/// Density of \ref squareToUniformSphere() with respect to solid angles
|
||||
static inline Float squareToUniformSpherePdf() { return INV_FOURPI; }
|
||||
extern MTS_EXPORT_CORE inline Float squareToUniformSpherePdf() { return INV_FOURPI; }
|
||||
|
||||
/// Uniformly sample a vector on the unit hemisphere with respect to solid angles
|
||||
static Vector squareToUniformHemisphere(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Vector squareToUniformHemisphere(const Point2 &sample);
|
||||
|
||||
/// Density of \ref squareToUniformHemisphere() with respect to solid angles
|
||||
static inline Float squareToUniformHemispherePdf() { return INV_TWOPI; }
|
||||
extern MTS_EXPORT_CORE inline Float squareToUniformHemispherePdf() { return INV_TWOPI; }
|
||||
|
||||
/// Sample a cosine-weighted vector on the unit hemisphere with respect to solid angles
|
||||
static Vector squareToCosineHemisphere(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Vector squareToCosineHemisphere(const Point2 &sample);
|
||||
|
||||
/// Density of \ref squareToCosineHemisphere() with respect to solid angles
|
||||
static inline Float squareToCosineHemispherePdf(const Vector &d)
|
||||
extern MTS_EXPORT_CORE inline Float squareToCosineHemispherePdf(const Vector &d)
|
||||
{ return INV_PI * Frame::cosTheta(d); }
|
||||
|
||||
/**
|
||||
|
@ -63,7 +62,7 @@ public:
|
|||
* \param cosCutoff Cosine of the cutoff angle
|
||||
* \param sample A uniformly distributed sample on \f$[0,1]^2\f$
|
||||
*/
|
||||
static Vector squareToUniformCone(Float cosCutoff, const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Vector squareToUniformCone(Float cosCutoff, const Point2 &sample);
|
||||
|
||||
/**
|
||||
* \brief Uniformly sample a vector that lies within a given
|
||||
|
@ -72,7 +71,7 @@ public:
|
|||
* \param cosCutoff Cosine of the cutoff angle
|
||||
* \param sample A uniformly distributed sample on \f$[0,1]^2\f$
|
||||
*/
|
||||
static inline Float squareToUniformConePdf(Float cosCutoff) {
|
||||
extern MTS_EXPORT_CORE inline Float squareToUniformConePdf(Float cosCutoff) {
|
||||
return INV_TWOPI / (1-cosCutoff);
|
||||
}
|
||||
|
||||
|
@ -84,41 +83,41 @@ public:
|
|||
// =============================================================
|
||||
|
||||
/// Uniformly sample a vector on a 2D disk
|
||||
static Point2 squareToUniformDisk(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Point2 squareToUniformDisk(const Point2 &sample);
|
||||
|
||||
/// Density of \ref squareToUniformDisk per unit area
|
||||
static inline Float squareToUniformDiskPdf() { return INV_PI; }
|
||||
extern MTS_EXPORT_CORE inline Float squareToUniformDiskPdf() { return INV_PI; }
|
||||
|
||||
/// Low-distortion concentric square to disk mapping by Peter Shirley (PDF: 1/PI)
|
||||
static Point2 squareToUniformDiskConcentric(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Point2 squareToUniformDiskConcentric(const Point2 &sample);
|
||||
|
||||
/// Inverse of the mapping \ref squareToUniformDiskConcentric
|
||||
static Point2 uniformDiskToSquareConcentric(const Point2 &p);
|
||||
extern MTS_EXPORT_CORE Point2 uniformDiskToSquareConcentric(const Point2 &p);
|
||||
|
||||
/// Density of \ref squareToUniformDisk per unit area
|
||||
static inline Float squareToUniformDiskConcentricPdf() { return INV_PI; }
|
||||
extern MTS_EXPORT_CORE inline Float squareToUniformDiskConcentricPdf() { return INV_PI; }
|
||||
|
||||
/// Convert an uniformly distributed square sample into barycentric coordinates
|
||||
static Point2 squareToUniformTriangle(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Point2 squareToUniformTriangle(const Point2 &sample);
|
||||
|
||||
/**
|
||||
* \brief Sample a point on a 2D standard normal distribution
|
||||
*
|
||||
* Internally uses the Box-Muller transformation
|
||||
*/
|
||||
static Point2 squareToStdNormal(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Point2 squareToStdNormal(const Point2 &sample);
|
||||
|
||||
/// Density of \ref squareToStdNormal per unit area
|
||||
static Float squareToStdNormalPdf(const Point2 &pos);
|
||||
extern MTS_EXPORT_CORE Float squareToStdNormalPdf(const Point2 &pos);
|
||||
|
||||
/// Warp a uniformly distributed square sample to a 2D tent distribution
|
||||
static Point2 squareToTent(const Point2 &sample);
|
||||
extern MTS_EXPORT_CORE Point2 squareToTent(const Point2 &sample);
|
||||
|
||||
/**
|
||||
* \brief Warp a uniformly distributed sample on [0, 1] to a nonuniform
|
||||
* tent distribution with nodes <tt>{a, b, c}</tt>
|
||||
*/
|
||||
static Float intervalToNonuniformTent(Float a, Float b, Float c, Float sample);
|
||||
extern MTS_EXPORT_CORE Float intervalToNonuniformTent(Float a, Float b, Float c, Float sample);
|
||||
|
||||
//! @}
|
||||
// =============================================================
|
||||
|
|
|
@ -978,7 +978,7 @@ protected:
|
|||
|
||||
/* Establish an ad-hoc depth cutoff value (Formula from PBRT) */
|
||||
if (m_maxDepth == 0)
|
||||
m_maxDepth = (int) (8 + 1.3f * log2i(primCount));
|
||||
m_maxDepth = (int) (8 + 1.3f * math::log2i(primCount));
|
||||
m_maxDepth = std::min(m_maxDepth, (SizeType) MTS_KD_MAXDEPTH);
|
||||
|
||||
KDLog(m_logLevel, "Creating a preliminary index list (%s)",
|
||||
|
|
|
@ -508,15 +508,15 @@ public:
|
|||
switch (m_bcu) {
|
||||
case ReconstructionFilter::ERepeat:
|
||||
// Assume that the input repeats in a periodic fashion
|
||||
x = modulo(x, size.x);
|
||||
x = math::modulo(x, size.x);
|
||||
break;
|
||||
case ReconstructionFilter::EClamp:
|
||||
// Clamp to the outermost sample position
|
||||
x = clamp(x, 0, size.x - 1);
|
||||
x = math::clamp(x, 0, size.x - 1);
|
||||
break;
|
||||
case ReconstructionFilter::EMirror:
|
||||
// Assume that the input is mirrored along the boundary
|
||||
x = modulo(x, 2*size.x);
|
||||
x = math::modulo(x, 2*size.x);
|
||||
if (x >= size.x)
|
||||
x = 2*size.x - x - 1;
|
||||
break;
|
||||
|
@ -536,15 +536,15 @@ public:
|
|||
switch (m_bcv) {
|
||||
case ReconstructionFilter::ERepeat:
|
||||
// Assume that the input repeats in a periodic fashion
|
||||
y = modulo(y, size.y);
|
||||
y = math::modulo(y, size.y);
|
||||
break;
|
||||
case ReconstructionFilter::EClamp:
|
||||
// Clamp to the outermost sample position
|
||||
y = clamp(y, 0, size.y - 1);
|
||||
y = math::clamp(y, 0, size.y - 1);
|
||||
break;
|
||||
case ReconstructionFilter::EMirror:
|
||||
// Assume that the input is mirrored along the boundary
|
||||
y = modulo(y, 2*size.y);
|
||||
y = math::modulo(y, 2*size.y);
|
||||
if (y >= size.y)
|
||||
y = 2*size.y - y - 1;
|
||||
break;
|
||||
|
@ -565,7 +565,7 @@ public:
|
|||
/// Evaluate the texture at the given resolution using a box filter
|
||||
inline Value evalBox(int level, const Point2 &uv) const {
|
||||
const Vector2i &size = m_pyramid[level].getSize();
|
||||
return evalTexel(level, floorToInt(uv.x*size.x), floorToInt(uv.y*size.y));
|
||||
return evalTexel(level, math::floorToInt(uv.x*size.x), math::floorToInt(uv.y*size.y));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -585,7 +585,7 @@ public:
|
|||
const Vector2i &size = m_pyramid[level].getSize();
|
||||
Float u = uv.x * size.x - 0.5f, v = uv.y * size.y - 0.5f;
|
||||
|
||||
int xPos = floorToInt(u), yPos = floorToInt(v);
|
||||
int xPos = math::floorToInt(u), yPos = math::floorToInt(v);
|
||||
Float dx1 = u - xPos, dx2 = 1.0f - dx1,
|
||||
dy1 = v - yPos, dy2 = 1.0f - dy1;
|
||||
|
||||
|
@ -612,7 +612,7 @@ public:
|
|||
const Vector2i &size = m_pyramid[level].getSize();
|
||||
Float u = uv.x * size.x - 0.5f, v = uv.y * size.y - 0.5f;
|
||||
|
||||
int xPos = floorToInt(u), yPos = floorToInt(v);
|
||||
int xPos = math::floorToInt(u), yPos = math::floorToInt(v);
|
||||
Float dx = u - xPos, dy = v - yPos;
|
||||
|
||||
const Value p00 = evalTexel(level, xPos, yPos);
|
||||
|
@ -645,7 +645,7 @@ public:
|
|||
F = A*C - B*B*0.25f;
|
||||
|
||||
/* Compute the major and minor radii */
|
||||
Float root = hypot2(A-C, B),
|
||||
Float root = math::hypot2(A-C, B),
|
||||
Aprime = 0.5f * (A + C - root),
|
||||
Cprime = 0.5f * (A + C + root),
|
||||
majorRadius = Aprime != 0 ? std::sqrt(F / Aprime) : 0,
|
||||
|
@ -654,8 +654,8 @@ public:
|
|||
if (m_filterType == ETrilinear || !(minorRadius > 0) || !(majorRadius > 0) || F < 0) {
|
||||
/* Determine a suitable mip map level, while preferring
|
||||
blurring over aliasing */
|
||||
Float level = log2(std::max(majorRadius, Epsilon));
|
||||
int ilevel = floorToInt(level);
|
||||
Float level = math::log2(std::max(majorRadius, Epsilon));
|
||||
int ilevel = math::floorToInt(level);
|
||||
|
||||
if (ilevel < 0) {
|
||||
/* Bilinear interpolation (lookup is smaller than 1 pixel) */
|
||||
|
@ -701,7 +701,7 @@ public:
|
|||
|
||||
/* Determine a suitable MIP map level, such that the filter
|
||||
covers a reasonable amount of pixels */
|
||||
Float level = std::max((Float) 0.0f, log2(minorRadius));
|
||||
Float level = std::max((Float) 0.0f, math::log2(minorRadius));
|
||||
int ilevel = (int) level;
|
||||
Float a = level - ilevel;
|
||||
|
||||
|
@ -786,8 +786,8 @@ protected:
|
|||
Float invDet = 1.0f / (-B*B + 4.0f*A*C),
|
||||
deltaU = 2.0f * std::sqrt(C * invDet),
|
||||
deltaV = 2.0f * std::sqrt(A * invDet);
|
||||
int u0 = ceilToInt(u - deltaU), u1 = floorToInt(u + deltaU);
|
||||
int v0 = ceilToInt(v - deltaV), v1 = floorToInt(v + deltaV);
|
||||
int u0 = math::ceilToInt(u - deltaU), u1 = math::floorToInt(u + deltaU);
|
||||
int v0 = math::ceilToInt(v - deltaV), v1 = math::floorToInt(v + deltaV);
|
||||
|
||||
/* Scale the coefficients by the size of the Gaussian lookup table */
|
||||
Float As = A * MTS_MIPMAP_LUT_SIZE,
|
||||
|
|
|
@ -518,8 +518,8 @@ public:
|
|||
for (int i=0; i<nRays; ++i) {
|
||||
Point2 sample1(random->nextFloat(), random->nextFloat()),
|
||||
sample2(random->nextFloat(), random->nextFloat());
|
||||
Point p1 = bsphere.center + Warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + Warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Point p1 = bsphere.center + warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Ray ray(p1, normalize(p2-p1), 0.0f);
|
||||
Float mint, maxt, t;
|
||||
if (m_aabb.rayIntersect(ray, mint, maxt)) {
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &sample) const {
|
||||
if (!(bRec.typeMask & EDiffuseTransmission))
|
||||
return Spectrum(0.0f);
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
if (Frame::cosTheta(bRec.wi) > 0)
|
||||
bRec.wo.z *= -1;
|
||||
bRec.eta = 1.0f;
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
Spectrum sample(BSDFSamplingRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||
if (!(bRec.typeMask & m_combinedType))
|
||||
return Spectrum(0.0f);
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
if (Frame::cosTheta(bRec.wi) > 0)
|
||||
bRec.wo.z *= -1;
|
||||
bRec.eta = 1.0f;
|
||||
|
|
|
@ -123,14 +123,14 @@ public:
|
|||
|| Frame::cosTheta(bRec.wo) <= 0)
|
||||
return 0.0f;
|
||||
|
||||
return Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &sample) const {
|
||||
if (!(bRec.typeMask & EDiffuseReflection) || Frame::cosTheta(bRec.wi) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
|
@ -141,11 +141,11 @@ public:
|
|||
if (!(bRec.typeMask & EDiffuseReflection) || Frame::cosTheta(bRec.wi) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
pdf = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
pdf = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return m_reflectance->eval(bRec.its);
|
||||
}
|
||||
|
||||
|
|
|
@ -155,8 +155,8 @@ public:
|
|||
Spectrum result(0.0f);
|
||||
m_initialization = true;
|
||||
for (size_t i=0; i<nSamples; ++i) {
|
||||
bRec.wi = Warp::squareToCosineHemisphere(Point2(random->nextFloat(), random->nextFloat()));
|
||||
bRec.wo = Warp::squareToCosineHemisphere(Point2(random->nextFloat(), random->nextFloat()));
|
||||
bRec.wi = warp::squareToCosineHemisphere(Point2(random->nextFloat(), random->nextFloat()));
|
||||
bRec.wo = warp::squareToCosineHemisphere(Point2(random->nextFloat(), random->nextFloat()));
|
||||
its.uv = Point2(random->nextFloat(), random->nextFloat());
|
||||
|
||||
result += eval(bRec, ESolidAngle) / Frame::cosTheta(bRec.wo);
|
||||
|
@ -177,8 +177,8 @@ public:
|
|||
(1 - its.uv.y) * m_repeatV);
|
||||
Point2 xy(uv.x * m_pattern.tileWidth, uv.y * m_pattern.tileHeight);
|
||||
Point2i lookup(
|
||||
modulo((int) xy.x, m_pattern.tileWidth),
|
||||
modulo((int) xy.y, m_pattern.tileHeight));
|
||||
math::modulo((int) xy.x, m_pattern.tileWidth),
|
||||
math::modulo((int) xy.y, m_pattern.tileHeight));
|
||||
int yarnID = m_pattern.pattern[lookup.x + lookup.y * m_pattern.tileWidth] - 1;
|
||||
const Yarn &yarn = m_pattern.yarns.at(yarnID);
|
||||
|
||||
|
@ -203,8 +203,8 @@ public:
|
|||
Point2 xy(uv.x * m_pattern.tileWidth, uv.y * m_pattern.tileHeight);
|
||||
|
||||
Point2i lookup(
|
||||
modulo((int) xy.x, m_pattern.tileWidth),
|
||||
modulo((int) xy.y, m_pattern.tileHeight));
|
||||
math::modulo((int) xy.x, m_pattern.tileWidth),
|
||||
math::modulo((int) xy.y, m_pattern.tileHeight));
|
||||
|
||||
int yarnID = m_pattern.pattern[lookup.x + lookup.y * m_pattern.tileWidth] - 1;
|
||||
|
||||
|
@ -330,7 +330,7 @@ public:
|
|||
measure != ESolidAngle)
|
||||
return 0.0f;
|
||||
|
||||
return Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &sample) const {
|
||||
|
@ -344,7 +344,7 @@ public:
|
|||
return Spectrum(0.0f);
|
||||
|
||||
/* Lacking a better sampling method, generate cosine-weighted directions */
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EGlossyReflection;
|
||||
|
@ -362,11 +362,11 @@ public:
|
|||
return Spectrum(0.0f);
|
||||
|
||||
/* Lacking a better sampling method, generate cosine-weighted directions */
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EGlossyReflection;
|
||||
pdf = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
pdf = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return eval(bRec, ESolidAngle) / pdf;
|
||||
}
|
||||
|
||||
|
@ -437,7 +437,7 @@ public:
|
|||
if (ss == 0.0f)
|
||||
As = A;
|
||||
else
|
||||
As = A * (1.0f - smoothStep(0, 1, (std::abs(u_of_v)
|
||||
As = A * (1.0f - math::smoothStep((Float) 0, (Float) 1, (std::abs(u_of_v)
|
||||
- (1.0f - ss) * umax) / (ss * umax)));
|
||||
|
||||
// fs is scattering function.
|
||||
|
|
|
@ -159,7 +159,7 @@ public:
|
|||
Float diffuseProb = 0.0f, specProb = 0.0f;
|
||||
|
||||
if (hasDiffuse)
|
||||
diffuseProb = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
diffuseProb = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
|
||||
if (hasSpecular) {
|
||||
Float alpha = dot(bRec.wo, reflect(bRec.wi)),
|
||||
|
@ -225,7 +225,7 @@ public:
|
|||
if (Frame::cosTheta(bRec.wo) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
} else {
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ public:
|
|||
else
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
return diff * (Warp::squareToCosineHemispherePdf(bRec.wo)
|
||||
return diff * (warp::squareToCosineHemispherePdf(bRec.wo)
|
||||
* m_invEta2 * (1-Fi) * (1-Fo));
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ public:
|
|||
if (std::abs(dot(reflect(bRec.wi), bRec.wo)-1) < DeltaEpsilon)
|
||||
return probSpecular;
|
||||
} else if (hasDiffuse && measure == ESolidAngle) {
|
||||
return Warp::squareToCosineHemispherePdf(bRec.wo) * (1-probSpecular);
|
||||
return warp::squareToCosineHemispherePdf(bRec.wo) * (1-probSpecular);
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
|
@ -334,7 +334,7 @@ public:
|
|||
} else {
|
||||
bRec.sampledComponent = 1;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
bRec.wo = Warp::squareToCosineHemisphere(Point2(
|
||||
bRec.wo = warp::squareToCosineHemisphere(Point2(
|
||||
(sample.x - probSpecular) / (1 - probSpecular),
|
||||
sample.y
|
||||
));
|
||||
|
@ -356,7 +356,7 @@ public:
|
|||
} else {
|
||||
bRec.sampledComponent = 1;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
Float Fo = fresnelDielectricExt(Frame::cosTheta(bRec.wo), m_eta);
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->eval(bRec.its);
|
||||
|
@ -398,7 +398,7 @@ public:
|
|||
} else {
|
||||
bRec.sampledComponent = 1;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
bRec.wo = Warp::squareToCosineHemisphere(Point2(
|
||||
bRec.wo = warp::squareToCosineHemisphere(Point2(
|
||||
(sample.x - probSpecular) / (1 - probSpecular),
|
||||
sample.y
|
||||
));
|
||||
|
@ -411,7 +411,7 @@ public:
|
|||
diff /= 1 - m_fdrInt;
|
||||
|
||||
pdf = (1-probSpecular) *
|
||||
Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
|
||||
return diff * (m_invEta2 * (1-Fi) * (1-Fo) / (1-probSpecular));
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ public:
|
|||
} else {
|
||||
bRec.sampledComponent = 1;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
Float Fo = fresnelDielectricExt(Frame::cosTheta(bRec.wo), m_eta);
|
||||
|
||||
Spectrum diff = m_diffuseReflectance->eval(bRec.its);
|
||||
|
@ -433,7 +433,7 @@ public:
|
|||
else
|
||||
diff /= 1 - m_fdrInt;
|
||||
|
||||
pdf = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
pdf = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
|
||||
return diff * (m_invEta2 * (1-Fi) * (1-Fo));
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ public:
|
|||
if (hasSpecular && Frame::cosTheta(bRec.wo) * Frame::cosTheta(bRec.wi) > 0) {
|
||||
/* Calculate the reflection half-vector */
|
||||
const Vector H = normalize(bRec.wo+bRec.wi)
|
||||
* signum(Frame::cosTheta(bRec.wo));
|
||||
* math::signum(Frame::cosTheta(bRec.wo));
|
||||
|
||||
/* Evaluate the microsurface normal distribution */
|
||||
const Float D = m_distribution.eval(H, alphaT);
|
||||
|
@ -317,7 +317,7 @@ public:
|
|||
|
||||
/* Calculate the reflection half-vector */
|
||||
const Vector H = normalize(bRec.wo+bRec.wi)
|
||||
* signum(Frame::cosTheta(bRec.wo));
|
||||
* math::signum(Frame::cosTheta(bRec.wo));
|
||||
|
||||
/* Evaluate the roughness texture */
|
||||
Float alpha = m_alpha->eval(bRec.its).average();
|
||||
|
|
|
@ -223,30 +223,30 @@ public:
|
|||
|| Frame::cosTheta(bRec.wo) <= 0)
|
||||
return 0.0f;
|
||||
|
||||
return Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFSamplingRecord &bRec, const Point2 &sample) const {
|
||||
if (!(bRec.typeMask & EGlossyReflection) || Frame::cosTheta(bRec.wi) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EGlossyReflection;
|
||||
return eval(bRec, ESolidAngle) /
|
||||
Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
}
|
||||
|
||||
Spectrum sample(BSDFSamplingRecord &bRec, Float &pdf, const Point2 &sample) const {
|
||||
if (!(bRec.typeMask & EGlossyReflection) || Frame::cosTheta(bRec.wi) <= 0)
|
||||
return Spectrum(0.0f);
|
||||
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.eta = 1.0f;
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EGlossyReflection;
|
||||
pdf = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
pdf = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
return eval(bRec, ESolidAngle) / pdf;
|
||||
}
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ public:
|
|||
}
|
||||
|
||||
if (hasDiffuse)
|
||||
result += probDiffuse * Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
result += probDiffuse * warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ public:
|
|||
} else {
|
||||
bRec.sampledComponent = 1;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
}
|
||||
bRec.eta = 1.0f;
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ public:
|
|||
}
|
||||
|
||||
if (hasDiffuse)
|
||||
diffuseProb = Warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
diffuseProb = warp::squareToCosineHemispherePdf(bRec.wo);
|
||||
|
||||
if (hasDiffuse && hasSpecular)
|
||||
return m_specularSamplingWeight * specProb +
|
||||
|
@ -311,7 +311,7 @@ public:
|
|||
if (Frame::cosTheta(bRec.wo) <= 0.0f)
|
||||
return Spectrum(0.0f);
|
||||
} else {
|
||||
bRec.wo = Warp::squareToCosineHemisphere(sample);
|
||||
bRec.wo = warp::squareToCosineHemisphere(sample);
|
||||
bRec.sampledComponent = 0;
|
||||
bRec.sampledType = EDiffuseReflection;
|
||||
}
|
||||
|
|
|
@ -115,9 +115,9 @@ public:
|
|||
Spectrum sampleDirection(DirectionSamplingRecord &dRec,
|
||||
PositionSamplingRecord &pRec,
|
||||
const Point2 &sample, const Point2 *extra) const {
|
||||
Vector local = Warp::squareToCosineHemisphere(sample);
|
||||
Vector local = warp::squareToCosineHemisphere(sample);
|
||||
dRec.d = Frame(pRec.n).toWorld(local);
|
||||
dRec.pdf = Warp::squareToCosineHemispherePdf(local);
|
||||
dRec.pdf = warp::squareToCosineHemispherePdf(local);
|
||||
dRec.measure = ESolidAngle;
|
||||
return Spectrum(1.0f);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ public:
|
|||
Float time) const {
|
||||
PositionSamplingRecord pRec(time);
|
||||
m_shape->samplePosition(pRec, spatialSample);
|
||||
Vector local = Warp::squareToCosineHemisphere(directionalSample);
|
||||
Vector local = warp::squareToCosineHemisphere(directionalSample);
|
||||
ray.setTime(time);
|
||||
ray.setOrigin(pRec.p);
|
||||
ray.setDirection(Frame(pRec.n).toWorld(local));
|
||||
|
|
|
@ -108,7 +108,7 @@ public:
|
|||
|
||||
Spectrum samplePosition(PositionSamplingRecord &pRec,
|
||||
const Point2 &sample, const Point2 *extra) const {
|
||||
Vector d = Warp::squareToUniformSphere(sample);
|
||||
Vector d = warp::squareToUniformSphere(sample);
|
||||
|
||||
pRec.p = m_sceneBSphere.center + d * m_sceneBSphere.radius;
|
||||
pRec.n = -d;
|
||||
|
@ -129,9 +129,9 @@ public:
|
|||
Spectrum sampleDirection(DirectionSamplingRecord &dRec,
|
||||
PositionSamplingRecord &pRec,
|
||||
const Point2 &sample, const Point2 *extra) const {
|
||||
Vector local = Warp::squareToCosineHemisphere(sample);
|
||||
Vector local = warp::squareToCosineHemisphere(sample);
|
||||
dRec.d = Frame(pRec.n).toWorld(local);
|
||||
dRec.pdf = Warp::squareToCosineHemispherePdf(local);
|
||||
dRec.pdf = warp::squareToCosineHemispherePdf(local);
|
||||
dRec.measure = ESolidAngle;
|
||||
return Spectrum(1.0f);
|
||||
}
|
||||
|
@ -160,8 +160,8 @@ public:
|
|||
const Point2 &spatialSample,
|
||||
const Point2 &directionalSample,
|
||||
Float time) const {
|
||||
Vector v0 = Warp::squareToUniformSphere(spatialSample);
|
||||
Vector v1 = Warp::squareToCosineHemisphere(directionalSample);
|
||||
Vector v0 = warp::squareToUniformSphere(spatialSample);
|
||||
Vector v1 = warp::squareToCosineHemisphere(directionalSample);
|
||||
|
||||
ray.setOrigin(m_geoBSphere.center + v0 * m_geoBSphere.radius);
|
||||
ray.setDirection(Frame(-v0).toWorld(v1));
|
||||
|
@ -176,12 +176,12 @@ public:
|
|||
Float pdf;
|
||||
|
||||
if (!dRec.refN.isZero()) {
|
||||
d = Warp::squareToCosineHemisphere(sample);
|
||||
pdf = Warp::squareToCosineHemispherePdf(d);
|
||||
d = warp::squareToCosineHemisphere(sample);
|
||||
pdf = warp::squareToCosineHemispherePdf(d);
|
||||
d = Frame(dRec.refN).toWorld(d);
|
||||
} else {
|
||||
d = Warp::squareToUniformSphere(sample);
|
||||
pdf = Warp::squareToUniformSpherePdf();
|
||||
d = warp::squareToUniformSphere(sample);
|
||||
pdf = warp::squareToUniformSpherePdf();
|
||||
}
|
||||
|
||||
/* Intersect against the bounding sphere. This is not really
|
||||
|
@ -220,7 +220,7 @@ public:
|
|||
if (!dRec.refN.isZero())
|
||||
pdfSA = INV_PI * std::max((Float) 0.0f, dot(dRec.d, dRec.refN));
|
||||
else
|
||||
pdfSA = Warp::squareToUniformSpherePdf();
|
||||
pdfSA = warp::squareToUniformSpherePdf();
|
||||
|
||||
if (dRec.measure == ESolidAngle)
|
||||
return pdfSA;
|
||||
|
|
|
@ -103,7 +103,7 @@ public:
|
|||
Spectrum samplePosition(PositionSamplingRecord &pRec, const Point2 &sample, const Point2 *extra) const {
|
||||
const Transform &trafo = m_worldTransform->eval(pRec.time);
|
||||
|
||||
Point2 p = Warp::squareToUniformDiskConcentric(sample);
|
||||
Point2 p = warp::squareToUniformDiskConcentric(sample);
|
||||
|
||||
Vector perpOffset = trafo(Vector(p.x, p.y, 0) * m_bsphere.radius);
|
||||
Vector d = trafo(Vector(0, 0, 1));
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
const Point2 &directionalSample,
|
||||
Float time) const {
|
||||
const Transform &trafo = m_worldTransform->eval(time);
|
||||
Point2 p = Warp::squareToUniformDiskConcentric(spatialSample);
|
||||
Point2 p = warp::squareToUniformDiskConcentric(spatialSample);
|
||||
Vector perpOffset = trafo(Vector(p.x, p.y, 0) * m_bsphere.radius);
|
||||
Vector d = trafo(Vector(0, 0, 1));
|
||||
ray.setOrigin(m_bsphere.center - d*m_bsphere.radius + perpOffset);
|
||||
|
|
|
@ -411,7 +411,7 @@ public:
|
|||
|
||||
Spectrum samplePosition(PositionSamplingRecord &pRec, const Point2 &sample,
|
||||
const Point2 *extra) const {
|
||||
Vector d = Warp::squareToUniformSphere(sample);
|
||||
Vector d = warp::squareToUniformSphere(sample);
|
||||
|
||||
pRec.p = m_sceneBSphere.center + d * m_sceneBSphere.radius;
|
||||
pRec.n = -d;
|
||||
|
@ -503,7 +503,7 @@ public:
|
|||
Vector d; Spectrum value; Float pdf;
|
||||
internalSampleDirection(directionalSample, d, value, pdf);
|
||||
d = -trafo(d);
|
||||
Point2 offset = Warp::squareToUniformDiskConcentric(spatialSample);
|
||||
Point2 offset = warp::squareToUniformDiskConcentric(spatialSample);
|
||||
Vector perpOffset = Frame(d).toWorld(Vector(offset.x, offset.y, 0));
|
||||
|
||||
ray.setOrigin(m_geoBSphere.center + (perpOffset - d) * m_geoBSphere.radius);
|
||||
|
@ -572,10 +572,10 @@ public:
|
|||
/* Using the remaining bits of precision to shift the sample by an offset
|
||||
drawn from a tent function. This effectively creates a sampling strategy
|
||||
for a linearly interpolated environment map */
|
||||
Point2 pos = Point2((Float) col, (Float) row) + Warp::squareToTent(sample);
|
||||
Point2 pos = Point2((Float) col, (Float) row) + warp::squareToTent(sample);
|
||||
|
||||
/* Bilinearly interpolate colors from the adjacent four neighbors */
|
||||
int xPos = floorToInt(pos.x), yPos = floorToInt(pos.y);
|
||||
int xPos = math::floorToInt(pos.x), yPos = math::floorToInt(pos.y);
|
||||
Float dx1 = pos.x - xPos, dx2 = 1.0f - dx1,
|
||||
dy1 = pos.y - yPos, dy2 = 1.0f - dy1;
|
||||
|
||||
|
@ -587,8 +587,8 @@ public:
|
|||
|
||||
/* Compute the final color and probability density of the sample */
|
||||
value = (value1 + value2) * m_scale;
|
||||
pdf = (value1.getLuminance() * m_rowWeights[clamp(yPos, 0, m_size.y-1)] +
|
||||
value2.getLuminance() * m_rowWeights[clamp(yPos+1, 0, m_size.y-1)]) * m_normalization;
|
||||
pdf = (value1.getLuminance() * m_rowWeights[math::clamp(yPos, 0, m_size.y-1)] +
|
||||
value2.getLuminance() * m_rowWeights[math::clamp(yPos+1, 0, m_size.y-1)]) * m_normalization;
|
||||
|
||||
/* Turn into a proper direction on the sphere */
|
||||
Float sinPhi, cosPhi, sinTheta, cosTheta;
|
||||
|
@ -616,7 +616,7 @@ public:
|
|||
Float u = uv.x * m_size.x - 0.5f, v = uv.y * m_size.y - 0.5f;
|
||||
|
||||
/* Bilinearly interpolate colors from the adjacent four neighbors */
|
||||
int xPos = floorToInt(u), yPos = floorToInt(v);
|
||||
int xPos = math::floorToInt(u), yPos = math::floorToInt(v);
|
||||
Float dx1 = u - xPos, dx2 = 1.0f - dx1,
|
||||
dy1 = v - yPos, dy2 = 1.0f - dy1;
|
||||
|
||||
|
@ -627,8 +627,8 @@ public:
|
|||
stats::filteredLookups.incrementBase();
|
||||
|
||||
Float sinTheta = math::safe_sqrt(1-d.y*d.y);
|
||||
return (value1.getLuminance() * m_rowWeights[clamp(yPos, 0, m_size.y-1)] +
|
||||
value2.getLuminance() * m_rowWeights[clamp(yPos+1, 0, m_size.y-1)])
|
||||
return (value1.getLuminance() * m_rowWeights[math::clamp(yPos, 0, m_size.y-1)] +
|
||||
value2.getLuminance() * m_rowWeights[math::clamp(yPos+1, 0, m_size.y-1)])
|
||||
* m_normalization / std::max(std::abs(sinTheta), Epsilon);
|
||||
}
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ public:
|
|||
PositionSamplingRecord &pRec,
|
||||
const Point2 &sample,
|
||||
const Point2 *extra) const {
|
||||
dRec.d = Warp::squareToUniformSphere(sample);
|
||||
dRec.d = warp::squareToUniformSphere(sample);
|
||||
dRec.pdf = INV_FOURPI;
|
||||
dRec.measure = ESolidAngle;
|
||||
return Spectrum(1.0f);
|
||||
|
@ -124,7 +124,7 @@ public:
|
|||
const Transform &trafo = m_worldTransform->eval(time);
|
||||
ray.setTime(time);
|
||||
ray.setOrigin(trafo(Point(0.0f)));
|
||||
ray.setDirection(Warp::squareToUniformSphere(directionalSample));
|
||||
ray.setDirection(warp::squareToUniformSphere(directionalSample));
|
||||
return m_intensity * (4 * M_PI);
|
||||
}
|
||||
|
||||
|
|
|
@ -442,7 +442,7 @@ protected:
|
|||
result.clampNegative();
|
||||
|
||||
if (m_extend)
|
||||
result *= smoothStep(0, 1, 2 - 2*coords.elevation*INV_PI);
|
||||
result *= math::smoothStep((Float) 0, (Float) 1, 2 - 2*coords.elevation*INV_PI);
|
||||
|
||||
return result * m_scale;
|
||||
}
|
||||
|
|
|
@ -147,16 +147,16 @@ public:
|
|||
const Point2 &sample,
|
||||
const Point2 *extra) const {
|
||||
const Transform &trafo = m_worldTransform->eval(pRec.time);
|
||||
Vector d = Warp::squareToUniformCone(m_cosCutoffAngle, sample);
|
||||
Vector d = warp::squareToUniformCone(m_cosCutoffAngle, sample);
|
||||
dRec.d = trafo(d);
|
||||
dRec.pdf = Warp::squareToUniformConePdf(m_cosCutoffAngle);
|
||||
dRec.pdf = warp::squareToUniformConePdf(m_cosCutoffAngle);
|
||||
dRec.measure = ESolidAngle;
|
||||
return evalDirection(dRec, pRec)/dRec.pdf;
|
||||
}
|
||||
|
||||
Float pdfDirection(const DirectionSamplingRecord &dRec,
|
||||
const PositionSamplingRecord &pRec) const {
|
||||
return (dRec.measure == ESolidAngle) ? Warp::squareToUniformConePdf(m_cosCutoffAngle) : 0.0f;
|
||||
return (dRec.measure == ESolidAngle) ? warp::squareToUniformConePdf(m_cosCutoffAngle) : 0.0f;
|
||||
}
|
||||
|
||||
Spectrum evalDirection(const DirectionSamplingRecord &dRec,
|
||||
|
@ -172,12 +172,12 @@ public:
|
|||
Float time) const {
|
||||
const Transform &trafo = m_worldTransform->eval(time);
|
||||
|
||||
Vector local = Warp::squareToUniformCone(
|
||||
Vector local = warp::squareToUniformCone(
|
||||
m_cosCutoffAngle, directionalSample);
|
||||
ray.setTime(time);
|
||||
ray.setOrigin(trafo.transformAffine(Point(0.0f)));
|
||||
ray.setDirection(trafo(local));
|
||||
Float dirPdf = Warp::squareToUniformConePdf(m_cosCutoffAngle);
|
||||
Float dirPdf = warp::squareToUniformConePdf(m_cosCutoffAngle);
|
||||
return m_intensity * falloffCurve(local) / dirPdf;
|
||||
}
|
||||
|
||||
|
|
|
@ -203,7 +203,7 @@ public:
|
|||
|
||||
for (size_t i=0; i<nSamples; ++i) {
|
||||
Vector dir = frame.toWorld(
|
||||
Warp::squareToUniformCone(cosTheta, sample02(i)));
|
||||
warp::squareToUniformCone(cosTheta, sample02(i)));
|
||||
|
||||
Float sinTheta = math::safe_sqrt(1-dir.y*dir.y);
|
||||
SphericalCoordinates sphCoords = fromSphere(dir);
|
||||
|
|
|
@ -201,7 +201,7 @@ public:
|
|||
|
||||
for (size_t i=0; i<nSamples; ++i) {
|
||||
Vector dir = sunFrame.toWorld(
|
||||
Warp::squareToUniformCone(cosTheta, sample02(i)));
|
||||
warp::squareToUniformCone(cosTheta, sample02(i)));
|
||||
|
||||
Float sinTheta = math::safe_sqrt(1-dir.y*dir.y);
|
||||
SphericalCoordinates sphCoords = fromSphere(dir);
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
|
||||
const Intersection &its = rRec.its;
|
||||
for (size_t i=0; i<numShadingSamples; ++i) {
|
||||
Vector d = its.toWorld(Warp::squareToCosineHemisphere(sampleArray[i]));
|
||||
Vector d = its.toWorld(warp::squareToCosineHemisphere(sampleArray[i]));
|
||||
|
||||
Ray shadowRay(its.p, d, Epsilon, m_rayLength, ray.time);
|
||||
if (!rRec.scene->rayIntersect(shadowRay))
|
||||
|
|
|
@ -440,7 +440,7 @@ bool ManifoldPerturbation::sampleMutation(
|
|||
|
||||
cosTheta = dot(wo_old, n_old);
|
||||
|
||||
Float dTheta = Warp::squareToStdNormal(m_sampler->next2D()).x
|
||||
Float dTheta = warp::squareToStdNormal(m_sampler->next2D()).x
|
||||
* 0.5f * M_PI / m_probFactor;
|
||||
math::sincos(dTheta, &sinPhi, &cosPhi);
|
||||
|
||||
|
|
|
@ -383,7 +383,7 @@ int PathVertex::sampleSensor(const Scene *scene, Sampler *sampler,
|
|||
}
|
||||
|
||||
bool PathVertex::perturbPosition(const Scene *scene, Sampler *sampler, Float stddev) {
|
||||
Point2 step = Warp::squareToStdNormal(sampler->next2D()) * stddev;
|
||||
Point2 step = warp::squareToStdNormal(sampler->next2D()) * stddev;
|
||||
EVertexType type = (EVertexType) this->type;
|
||||
Ray ray;
|
||||
|
||||
|
@ -462,7 +462,7 @@ Float PathVertex::perturbPositionPdf(const PathVertex *target, Float stddev) con
|
|||
Vector rel = itsOld.geoFrame.toLocal(itsOld.p - itsNew.p);
|
||||
Point2 rel2 = Point2(rel.x, rel.y) / stddev;
|
||||
|
||||
return Warp::squareToStdNormalPdf(rel2) * absDot(itsOld.geoFrame.n, itsNew.geoFrame.n) / (stddev*stddev);
|
||||
return warp::squareToStdNormalPdf(rel2) * absDot(itsOld.geoFrame.n, itsNew.geoFrame.n) / (stddev*stddev);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -473,7 +473,7 @@ Float PathVertex::perturbPositionPdf(const PathVertex *target, Float stddev) con
|
|||
Vector rel = Frame(prOld.n).toLocal(prOld.p - prNew.p);
|
||||
Point2 rel2 = Point2(rel.x, rel.y) / stddev;
|
||||
|
||||
return Warp::squareToStdNormalPdf(rel2) * absDot(prOld.n, prNew.n) / (stddev*stddev);
|
||||
return warp::squareToStdNormalPdf(rel2) * absDot(prOld.n, prNew.n) / (stddev*stddev);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ libcore_objects = [
|
|||
'class.cpp', 'object.cpp', 'statistics.cpp', 'thread.cpp', 'brent.cpp',
|
||||
'logger.cpp', 'appender.cpp', 'formatter.cpp', 'lock.cpp', 'qmc.cpp',
|
||||
'random.cpp', 'timer.cpp', 'util.cpp', 'properties.cpp', 'half.cpp',
|
||||
'transform.cpp', 'spectrum.cpp', 'aabb.cpp', 'stream.cpp',
|
||||
'transform.cpp', 'spectrum.cpp', 'aabb.cpp', 'stream.cpp', 'math.cpp',
|
||||
'fstream.cpp', 'plugin.cpp', 'triangle.cpp', 'bitmap.cpp',
|
||||
'fmtconv.cpp', 'serialization.cpp', 'sstream.cpp', 'cstream.cpp',
|
||||
'mstream.cpp', 'sched.cpp', 'sched_remote.cpp', 'sshstream.cpp',
|
||||
|
|
|
@ -813,9 +813,9 @@ void Bitmap::convolve(const Bitmap *_kernel) {
|
|||
/* Copy and zero-pad the convolution kernel in a wraparound fashion */
|
||||
if (ch < channelCountKernel) {
|
||||
for (size_t y=0; y<kernelSize; ++y) {
|
||||
ssize_t wrappedY = modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
ssize_t wrappedY = math::modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
for (size_t x=0; x<kernelSize; ++x) {
|
||||
ssize_t wrappedX = modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
ssize_t wrappedX = math::modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
kernel[wrappedX+wrappedY*paddedWidth] = _kernel->getFloat16Data()[(x+y*kernelSize)*channelCountKernel+ch];
|
||||
}
|
||||
}
|
||||
|
@ -831,9 +831,9 @@ void Bitmap::convolve(const Bitmap *_kernel) {
|
|||
/* Copy and zero-pad the convolution kernel in a wraparound fashion */
|
||||
if (ch < channelCountKernel) {
|
||||
for (size_t y=0; y<kernelSize; ++y) {
|
||||
ssize_t wrappedY = modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
ssize_t wrappedY = math::modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
for (size_t x=0; x<kernelSize; ++x) {
|
||||
ssize_t wrappedX = modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
ssize_t wrappedX = math::modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
kernel[wrappedX+wrappedY*paddedWidth] = _kernel->getFloat32Data()[(x+y*kernelSize)*channelCountKernel+ch];
|
||||
}
|
||||
}
|
||||
|
@ -849,9 +849,9 @@ void Bitmap::convolve(const Bitmap *_kernel) {
|
|||
/* Copy and zero-pad the convolution kernel in a wraparound fashion */
|
||||
if (ch < channelCountKernel) {
|
||||
for (size_t y=0; y<kernelSize; ++y) {
|
||||
ssize_t wrappedY = modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
ssize_t wrappedY = math::modulo(hKernelSize - (ssize_t) y, (ssize_t) paddedHeight);
|
||||
for (size_t x=0; x<kernelSize; ++x) {
|
||||
ssize_t wrappedX = modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
ssize_t wrappedX = math::modulo(hKernelSize - (ssize_t) x, (ssize_t) paddedWidth);
|
||||
kernel[wrappedX+wrappedY*paddedWidth] = _kernel->getFloat64Data()[(x+y*kernelSize)*channelCountKernel+ch];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,9 +105,9 @@ void ChiSquare::fill(
|
|||
Point2 sphCoords = toSphericalCoordinates(boost::get<0>(sample));
|
||||
|
||||
int thetaBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.x * factor.x)), m_thetaBins-1);
|
||||
math::floorToInt(sphCoords.x * factor.x)), m_thetaBins-1);
|
||||
int phiBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.y * factor.y)), m_phiBins-1);
|
||||
math::floorToInt(sphCoords.y * factor.y)), m_phiBins-1);
|
||||
m_table[thetaBin * m_phiBins + phiBin] += boost::get<1>(sample);
|
||||
if (boost::get<1>(sample) > 0 && boost::get<2>(sample) == EDiscrete)
|
||||
discreteDirections.insert(boost::get<0>(sample));
|
||||
|
@ -123,9 +123,9 @@ void ChiSquare::fill(
|
|||
Float pdf = pdfFn(direction, EDiscrete);
|
||||
|
||||
int thetaBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.x * factor.x)), m_thetaBins-1);
|
||||
math::floorToInt(sphCoords.x * factor.x)), m_thetaBins-1);
|
||||
int phiBin = std::min(std::max(0,
|
||||
floorToInt(sphCoords.y * factor.y)), m_phiBins-1);
|
||||
math::floorToInt(sphCoords.y * factor.y)), m_phiBins-1);
|
||||
|
||||
m_refTable[thetaBin * m_phiBins + phiBin] += pdf * m_sampleCount;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
This file is part of Mitsuba, a physically based rendering system.
|
||||
|
||||
Copyright (c) 2007-2012 by Wenzel Jakob and others.
|
||||
|
||||
Mitsuba is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License Version 3
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
Mitsuba is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <mitsuba/mitsuba.h>
|
||||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
namespace math {
|
||||
|
||||
Float erfinv(Float x) {
|
||||
// Based on "Approximating the erfinv function" by Mark Giles
|
||||
Float w = -math::fastlog(((Float) 1 - x)*((Float) 1 + x));
|
||||
Float p;
|
||||
if (w < (Float) 5) {
|
||||
w = w - (Float) 2.5;
|
||||
p = (Float) 2.81022636e-08;
|
||||
p = (Float) 3.43273939e-07 + p*w;
|
||||
p = (Float) -3.5233877e-06 + p*w;
|
||||
p = (Float) -4.39150654e-06 + p*w;
|
||||
p = (Float) 0.00021858087 + p*w;
|
||||
p = (Float) -0.00125372503 + p*w;
|
||||
p = (Float) -0.00417768164 + p*w;
|
||||
p = (Float) 0.246640727 + p*w;
|
||||
p = (Float) 1.50140941 + p*w;
|
||||
} else {
|
||||
w = std::sqrt(w) - (Float) 3;
|
||||
p = (Float) -0.000200214257;
|
||||
p = (Float) 0.000100950558 + p*w;
|
||||
p = (Float) 0.00134934322 + p*w;
|
||||
p = (Float) -0.00367342844 + p*w;
|
||||
p = (Float) 0.00573950773 + p*w;
|
||||
p = (Float) -0.0076224613 + p*w;
|
||||
p = (Float) 0.00943887047 + p*w;
|
||||
p = (Float) 1.00167406 + p*w;
|
||||
p = (Float) 2.83297682 + p*w;
|
||||
}
|
||||
return p*x;
|
||||
}
|
||||
|
||||
Float erf(Float x) {
|
||||
Float a1 = (Float) 0.254829592;
|
||||
Float a2 = (Float) -0.284496736;
|
||||
Float a3 = (Float) 1.421413741;
|
||||
Float a4 = (Float) -1.453152027;
|
||||
Float a5 = (Float) 1.061405429;
|
||||
Float p = (Float) 0.3275911;
|
||||
|
||||
// Save the sign of x
|
||||
Float sign = math::signum(x);
|
||||
x = std::abs(x);
|
||||
|
||||
// A&S formula 7.1.26
|
||||
Float t = (Float) 1.0 / ((Float) 1.0 + p*x);
|
||||
Float y = (Float) 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*math::fastexp(-x*x);
|
||||
|
||||
return sign*y;
|
||||
}
|
||||
|
||||
float hypot2(float a, float b) {
|
||||
float r;
|
||||
if (std::abs(a) > std::abs(b)) {
|
||||
r = b / a;
|
||||
r = std::abs(a) * std::sqrt(1.0f + r*r);
|
||||
} else if (b != 0.0f) {
|
||||
r = a / b;
|
||||
r = std::abs(b) * std::sqrt(1.0f + r*r);
|
||||
} else {
|
||||
r = 0.0f;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
double hypot2(double a, double b) {
|
||||
double r;
|
||||
if (std::abs(a) > std::abs(b)) {
|
||||
r = b / a;
|
||||
r = std::abs(a) * std::sqrt(1.0 + r*r);
|
||||
} else if (b != 0.0) {
|
||||
r = a / b;
|
||||
r = std::abs(b) * std::sqrt(1.0 + r*r);
|
||||
} else {
|
||||
r = 0.0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
float log2(float value) {
|
||||
const float invLn2 = 1.0f / std::log(2.0f);
|
||||
return fastlog(value) * invLn2;
|
||||
}
|
||||
|
||||
double log2(double value) {
|
||||
const double invLn2 = 1.0 / std::log(2.0);
|
||||
return fastlog(value) * invLn2;
|
||||
}
|
||||
|
||||
int log2i(uint32_t value) {
|
||||
int r = 0;
|
||||
while ((value >> r) != 0)
|
||||
r++;
|
||||
return r-1;
|
||||
}
|
||||
|
||||
int log2i(uint64_t value) {
|
||||
int r = 0;
|
||||
while ((value >> r) != 0)
|
||||
r++;
|
||||
return r-1;
|
||||
}
|
||||
|
||||
/* Fast rounding & power-of-two test algorithms from PBRT */
|
||||
uint32_t roundToPowerOfTwo(uint32_t i) {
|
||||
i--;
|
||||
i |= i >> 1; i |= i >> 2;
|
||||
i |= i >> 4; i |= i >> 8;
|
||||
i |= i >> 16;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
uint64_t roundToPowerOfTwo(uint64_t i) {
|
||||
i--;
|
||||
i |= i >> 1; i |= i >> 2;
|
||||
i |= i >> 4; i |= i >> 8;
|
||||
i |= i >> 16; i |= i >> 32;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
|
@ -196,7 +196,7 @@ Float Spectrum::eval(Float lambda) const {
|
|||
"is configured for RGB-based rendering");
|
||||
return 0.0f;
|
||||
#else
|
||||
int index = floorToInt((lambda - SPECTRUM_MIN_WAVELENGTH) *
|
||||
int index = math::floorToInt((lambda - SPECTRUM_MIN_WAVELENGTH) *
|
||||
((Float) SPECTRUM_SAMPLES / (Float) SPECTRUM_RANGE));
|
||||
|
||||
if (index < 0 || index >= SPECTRUM_SAMPLES)
|
||||
|
@ -676,8 +676,8 @@ Float InterpolatedSpectrum::average(Float lambdaMin, Float lambdaMax) const {
|
|||
if (cb <= ca)
|
||||
continue;
|
||||
|
||||
Float interpA = lerp((ca - a) * invAB, fa, fb);
|
||||
Float interpB = lerp((cb - a) * invAB, fa, fb);
|
||||
Float interpA = math::lerp((ca - a) * invAB, fa, fb);
|
||||
Float interpB = math::lerp((cb - a) * invAB, fa, fb);
|
||||
|
||||
result += 0.5f * (interpA + interpB) * (cb-ca);
|
||||
}
|
||||
|
@ -703,7 +703,7 @@ Float InterpolatedSpectrum::eval(Float lambda) const {
|
|||
b = m_wavelengths[idx1],
|
||||
fa = m_values[idx1-1],
|
||||
fb = m_values[idx1];
|
||||
return lerp((lambda - a) / (b-a), fb, fa);
|
||||
return math::lerp((lambda - a) / (b-a), fb, fa);
|
||||
} else if (idx2 == idx1+1) {
|
||||
/* Hit a value exactly */
|
||||
return m_values[idx1];
|
||||
|
|
|
@ -27,7 +27,7 @@ Point Triangle::sample(const Point *positions, const Normal *normals,
|
|||
const Point &p1 = positions[idx[1]];
|
||||
const Point &p2 = positions[idx[2]];
|
||||
|
||||
Point2 bary = Warp::squareToUniformTriangle(sample);
|
||||
Point2 bary = warp::squareToUniformTriangle(sample);
|
||||
Vector sideA = p1 - p0, sideB = p2 - p0;
|
||||
Point p = p0 + (sideA * bary.x) + (sideB * bary.y);
|
||||
|
||||
|
|
|
@ -399,11 +399,6 @@ std::string getFQDN() {
|
|||
return fqdn;
|
||||
}
|
||||
|
||||
Float log2(Float value) {
|
||||
const Float invLn2 = (Float) 1.0f / math::fastlog((Float) 2.0f);
|
||||
return math::fastlog(value) * invLn2;
|
||||
}
|
||||
|
||||
std::string formatString(const char *fmt, ...) {
|
||||
char tmp[512];
|
||||
va_list iterator;
|
||||
|
@ -444,37 +439,6 @@ std::string formatString(const char *fmt, ...) {
|
|||
return std::string(tmp);
|
||||
}
|
||||
|
||||
int log2i(uint32_t value) {
|
||||
int r = 0;
|
||||
while ((value >> r) != 0)
|
||||
r++;
|
||||
return r-1;
|
||||
}
|
||||
|
||||
int log2i(uint64_t value) {
|
||||
int r = 0;
|
||||
while ((value >> r) != 0)
|
||||
r++;
|
||||
return r-1;
|
||||
}
|
||||
|
||||
/* Fast rounding & power-of-two test algorithms from PBRT */
|
||||
uint32_t roundToPowerOfTwo(uint32_t i) {
|
||||
i--;
|
||||
i |= i >> 1; i |= i >> 2;
|
||||
i |= i >> 4; i |= i >> 8;
|
||||
i |= i >> 16;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
uint64_t roundToPowerOfTwo(uint64_t i) {
|
||||
i--;
|
||||
i |= i >> 1; i |= i >> 2;
|
||||
i |= i >> 4; i |= i >> 8;
|
||||
i |= i >> 16; i |= i >> 32;
|
||||
return i+1;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Numerical utility functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
@ -910,18 +874,4 @@ std::string memString(size_t size, bool precise) {
|
|||
return os.str();
|
||||
}
|
||||
|
||||
Float hypot2(Float a, Float b) {
|
||||
Float r;
|
||||
if (std::abs(a) > std::abs(b)) {
|
||||
r = b / a;
|
||||
r = std::abs(a) * std::sqrt(1 + r*r);
|
||||
} else if (b != 0) {
|
||||
r = a / b;
|
||||
r = std::abs(b) * std::sqrt(1 + r*r);
|
||||
} else {
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -38,7 +38,7 @@ Float VonMisesFisherDistr::eval(Float cosTheta) const {
|
|||
|
||||
Vector VonMisesFisherDistr::sample(const Point2 &sample) const {
|
||||
if (m_kappa == 0)
|
||||
return Warp::squareToUniformSphere(sample);
|
||||
return warp::squareToUniformSphere(sample);
|
||||
|
||||
#if 0
|
||||
Float cosTheta = math::fastlog(math::fastexp(-m_kappa) + 2 *
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
|
||||
MTS_NAMESPACE_BEGIN
|
||||
|
||||
Vector Warp::squareToUniformSphere(const Point2 &sample) {
|
||||
namespace warp {
|
||||
|
||||
Vector squareToUniformSphere(const Point2 &sample) {
|
||||
Float z = 1.0f - 2.0f * sample.y;
|
||||
Float r = math::safe_sqrt(1.0f - z*z);
|
||||
Float sinPhi, cosPhi;
|
||||
|
@ -28,7 +30,7 @@ Vector Warp::squareToUniformSphere(const Point2 &sample) {
|
|||
return Vector(r * cosPhi, r * sinPhi, z);
|
||||
}
|
||||
|
||||
Vector Warp::squareToUniformHemisphere(const Point2 &sample) {
|
||||
Vector squareToUniformHemisphere(const Point2 &sample) {
|
||||
Float z = sample.x;
|
||||
Float tmp = math::safe_sqrt(1.0f - z*z);
|
||||
|
||||
|
@ -38,8 +40,8 @@ Vector Warp::squareToUniformHemisphere(const Point2 &sample) {
|
|||
return Vector(cosPhi * tmp, sinPhi * tmp, z);
|
||||
}
|
||||
|
||||
Vector Warp::squareToCosineHemisphere(const Point2 &sample) {
|
||||
Point2 p = Warp::squareToUniformDiskConcentric(sample);
|
||||
Vector squareToCosineHemisphere(const Point2 &sample) {
|
||||
Point2 p = squareToUniformDiskConcentric(sample);
|
||||
Float z = math::safe_sqrt(1.0f - p.x*p.x - p.y*p.y);
|
||||
|
||||
/* Guard against numerical imprecisions */
|
||||
|
@ -49,7 +51,7 @@ Vector Warp::squareToCosineHemisphere(const Point2 &sample) {
|
|||
return Vector(p.x, p.y, z);
|
||||
}
|
||||
|
||||
Vector Warp::squareToUniformCone(Float cosCutoff, const Point2 &sample) {
|
||||
Vector squareToUniformCone(Float cosCutoff, const Point2 &sample) {
|
||||
Float cosTheta = (1-sample.x) + sample.x * cosCutoff;
|
||||
Float sinTheta = math::safe_sqrt(1.0f - cosTheta * cosTheta);
|
||||
|
||||
|
@ -60,7 +62,7 @@ Vector Warp::squareToUniformCone(Float cosCutoff, const Point2 &sample) {
|
|||
sinPhi * sinTheta, cosTheta);
|
||||
}
|
||||
|
||||
Point2 Warp::squareToUniformDisk(const Point2 &sample) {
|
||||
Point2 squareToUniformDisk(const Point2 &sample) {
|
||||
Float r = std::sqrt(sample.x);
|
||||
Float sinPhi, cosPhi;
|
||||
math::sincos(2.0f * M_PI * sample.y, &sinPhi, &cosPhi);
|
||||
|
@ -71,12 +73,12 @@ Point2 Warp::squareToUniformDisk(const Point2 &sample) {
|
|||
);
|
||||
}
|
||||
|
||||
Point2 Warp::squareToUniformTriangle(const Point2 &sample) {
|
||||
Point2 squareToUniformTriangle(const Point2 &sample) {
|
||||
Float a = math::safe_sqrt(1.0f - sample.x);
|
||||
return Point2(1 - a, a * sample.y);
|
||||
}
|
||||
|
||||
Point2 Warp::squareToUniformDiskConcentric(const Point2 &sample) {
|
||||
Point2 squareToUniformDiskConcentric(const Point2 &sample) {
|
||||
Float r1 = 2.0f*sample.x - 1.0f;
|
||||
Float r2 = 2.0f*sample.y - 1.0f;
|
||||
|
||||
|
@ -99,7 +101,7 @@ Point2 Warp::squareToUniformDiskConcentric(const Point2 &sample) {
|
|||
return Point2(r * cosPhi, r * sinPhi);
|
||||
}
|
||||
|
||||
Point2 Warp::uniformDiskToSquareConcentric(const Point2 &p) {
|
||||
Point2 uniformDiskToSquareConcentric(const Point2 &p) {
|
||||
Float r = std::sqrt(p.x * p.x + p.y * p.y),
|
||||
phi = std::atan2(p.y, p.x),
|
||||
a, b;
|
||||
|
@ -126,7 +128,7 @@ Point2 Warp::uniformDiskToSquareConcentric(const Point2 &p) {
|
|||
return Point2(0.5f * (a+1), 0.5f * (b+1));
|
||||
}
|
||||
|
||||
Point2 Warp::squareToStdNormal(const Point2 &sample) {
|
||||
Point2 squareToStdNormal(const Point2 &sample) {
|
||||
Float r = std::sqrt(-2 * math::fastlog(1-sample.x)),
|
||||
phi = 2 * M_PI * sample.y;
|
||||
Point2 result;
|
||||
|
@ -134,7 +136,7 @@ Point2 Warp::squareToStdNormal(const Point2 &sample) {
|
|||
return result * r;
|
||||
}
|
||||
|
||||
Float Warp::squareToStdNormalPdf(const Point2 &pos) {
|
||||
Float squareToStdNormalPdf(const Point2 &pos) {
|
||||
return INV_TWOPI * math::fastexp(-(pos.x*pos.x + pos.y*pos.y)/2.0f);
|
||||
}
|
||||
|
||||
|
@ -152,14 +154,14 @@ static Float intervalToTent(Float sample) {
|
|||
return sign * (1 - std::sqrt(sample));
|
||||
}
|
||||
|
||||
Point2 Warp::squareToTent(const Point2 &sample) {
|
||||
Point2 squareToTent(const Point2 &sample) {
|
||||
return Point2(
|
||||
intervalToTent(sample.x),
|
||||
intervalToTent(sample.y)
|
||||
);
|
||||
}
|
||||
|
||||
Float Warp::intervalToNonuniformTent(Float a, Float b, Float c, Float sample) {
|
||||
Float intervalToNonuniformTent(Float a, Float b, Float c, Float sample) {
|
||||
Float factor;
|
||||
|
||||
if (sample * (c-a) < b-a) {
|
||||
|
@ -173,4 +175,6 @@ Float Warp::intervalToNonuniformTent(Float a, Float b, Float c, Float sample) {
|
|||
return b + factor * (1-math::safe_sqrt(sample));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
MTS_NAMESPACE_END
|
||||
|
|
|
@ -121,7 +121,7 @@ void GLTexture::init() {
|
|||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
|
||||
GL_COLOR_ATTACHMENT0_EXT, m_glType, m_id, 0);
|
||||
} else if (m_type == ETextureCubeMap) {
|
||||
Assert(m_size.x == m_size.y && isPowerOfTwo(m_size.x));
|
||||
Assert(m_size.x == m_size.y && math::isPowerOfTwo(m_size.x));
|
||||
Assert(m_fbType == EColorBuffer);
|
||||
Assert(m_samples == 1);
|
||||
|
||||
|
@ -178,7 +178,7 @@ void GLTexture::init() {
|
|||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
|
||||
GL_DEPTH_ATTACHMENT_EXT, m_glType, m_id, 0);
|
||||
} else if (m_type == ETextureCubeMap) {
|
||||
Assert(m_size.x == m_size.y && isPowerOfTwo(m_size.x));
|
||||
Assert(m_size.x == m_size.y && math::isPowerOfTwo(m_size.x));
|
||||
for (int i=0; i<6; i++)
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, m_internalFormat,
|
||||
m_size.x, m_size.y, 0, m_format, m_dataFormat, NULL);
|
||||
|
@ -260,8 +260,8 @@ void GLTexture::refresh() {
|
|||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
if (m_type == ETexture1D) {
|
||||
Assert((isPowerOfTwo(m_size.x) && m_size.y == 1)
|
||||
|| (isPowerOfTwo(m_size.y) && m_size.x == 1));
|
||||
Assert((math::isPowerOfTwo(m_size.x) && m_size.y == 1)
|
||||
|| (math::isPowerOfTwo(m_size.y) && m_size.x == 1));
|
||||
|
||||
if (isMipMapped()) {
|
||||
/* Let GLU generate mipmaps for us */
|
||||
|
@ -282,7 +282,7 @@ void GLTexture::refresh() {
|
|||
} else if (m_type == ETextureCubeMap) {
|
||||
Assert(bitmap != NULL);
|
||||
Assert(bitmap->getWidth() == bitmap->getHeight());
|
||||
Assert(isPowerOfTwo(bitmap->getWidth()));
|
||||
Assert(math::isPowerOfTwo(bitmap->getWidth()));
|
||||
if (isMipMapped())
|
||||
glTexParameteri(m_glType, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||
|
||||
|
|
|
@ -319,7 +319,7 @@ void VPLShaderManager::setVPL(const VPL &vpl) {
|
|||
if (vpl.type == ESurfaceVPL || (vpl.type == EPointEmitterVPL &&
|
||||
vpl.emitter->getType() & Emitter::EOnSurface)) {
|
||||
ray = Ray(vpl.its.p, vpl.its.shFrame.toWorld(
|
||||
Warp::squareToCosineHemisphere(sample)), 0);
|
||||
warp::squareToCosineHemisphere(sample)), 0);
|
||||
|
||||
#if defined(MTS_VPL_USE_PARABOLOID_MAPS)
|
||||
m_shadowMapType = ShadowMapGenerator::EParaboloid;
|
||||
|
@ -329,7 +329,7 @@ void VPLShaderManager::setVPL(const VPL &vpl) {
|
|||
m_shadowMapType = ShadowMapGenerator::EHemicube;
|
||||
#endif
|
||||
} else if (vpl.type == EPointEmitterVPL) {
|
||||
ray = Ray(vpl.its.p, Warp::squareToUniformSphere(sample), 0);
|
||||
ray = Ray(vpl.its.p, warp::squareToUniformSphere(sample), 0);
|
||||
#if defined(MTS_VPL_USE_SINGLE_PASS)
|
||||
m_shadowMapType = ShadowMapGenerator::ECubeSinglePass;
|
||||
#else
|
||||
|
|
|
@ -2352,7 +2352,6 @@ void export_core() {
|
|||
bp::def("getTotalSystemMemory", &getTotalSystemMemory);
|
||||
bp::def("getFQDN", &getFQDN);
|
||||
bp::def("rdtsc", &rdtsc);
|
||||
bp::def("hypot2", &hypot2);
|
||||
|
||||
/* Functions from qmc.h */
|
||||
bp::def("radicalInverse2Single", radicalInverse2Single);
|
||||
|
|
|
@ -75,7 +75,7 @@ Spectrum SamplingIntegrator::E(const Scene *scene, const Intersection &its,
|
|||
/* Sample the indirect illumination component */
|
||||
if (handleIndirect) {
|
||||
query.newQuery(RadianceQueryRecord::ERadianceNoEmission, medium);
|
||||
Vector d = frame.toWorld(Warp::squareToCosineHemisphere(query.nextSample2D()));
|
||||
Vector d = frame.toWorld(warp::squareToCosineHemisphere(query.nextSample2D()));
|
||||
++query.depth;
|
||||
query.medium = medium;
|
||||
E += Li(RayDifferential(its.p, d, its.time), query) * M_PI;
|
||||
|
|
|
@ -63,9 +63,9 @@ inline static Float noiseWeight(Float t) {
|
|||
|
||||
Float Noise::perlinNoise(const Point &p) {
|
||||
// Compute noise cell coordinates and offsets
|
||||
int ix = floorToInt(p.x),
|
||||
iy = floorToInt(p.y),
|
||||
iz = floorToInt(p.z);
|
||||
int ix = math::floorToInt(p.x),
|
||||
iy = math::floorToInt(p.y),
|
||||
iz = math::floorToInt(p.z);
|
||||
|
||||
Float dx = p.x - ix,
|
||||
dy = p.y - iy,
|
||||
|
@ -90,21 +90,21 @@ Float Noise::perlinNoise(const Point &p) {
|
|||
wy = noiseWeight(dy),
|
||||
wz = noiseWeight(dz);
|
||||
|
||||
Float x00 = lerp(wx, w000, w100),
|
||||
x10 = lerp(wx, w010, w110),
|
||||
x01 = lerp(wx, w001, w101),
|
||||
x11 = lerp(wx, w011, w111),
|
||||
y0 = lerp(wy, x00, x10),
|
||||
y1 = lerp(wy, x01, x11);
|
||||
Float x00 = math::lerp(wx, w000, w100),
|
||||
x10 = math::lerp(wx, w010, w110),
|
||||
x01 = math::lerp(wx, w001, w101),
|
||||
x11 = math::lerp(wx, w011, w111),
|
||||
y0 = math::lerp(wy, x00, x10),
|
||||
y1 = math::lerp(wy, x01, x11);
|
||||
|
||||
return lerp(wz, y0, y1);
|
||||
return math::lerp(wz, y0, y1);
|
||||
}
|
||||
|
||||
Float Noise::fbm(const Point &p, const Vector &dpdx,
|
||||
const Vector &dpdy, Float omega, int maxOctaves) {
|
||||
// Compute number of octaves for antialiased FBm
|
||||
Float s2 = std::max(dpdx.lengthSquared(), dpdy.lengthSquared());
|
||||
Float foctaves = std::min((Float) maxOctaves, 1.f - .5f * log2(s2));
|
||||
Float foctaves = std::min((Float) maxOctaves, 1.f - .5f * math::log2(s2));
|
||||
int octaves = (int) foctaves;
|
||||
|
||||
// Compute sum of octaves of noise for FBm
|
||||
|
@ -115,7 +115,7 @@ Float Noise::fbm(const Point &p, const Vector &dpdx,
|
|||
o *= omega;
|
||||
}
|
||||
Float partialOctave = foctaves - octaves;
|
||||
sum += o * smoothStep(.3f, .7f, partialOctave)
|
||||
sum += o * math::smoothStep((Float) .3f, (Float) .7f, partialOctave)
|
||||
* perlinNoise(lambda * p);
|
||||
return sum;
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ Float Noise::turbulence(const Point &p, const Vector &dpdx,
|
|||
const Vector &dpdy, Float omega, int maxOctaves) {
|
||||
// Compute number of octaves for antialiased FBm
|
||||
Float s2 = std::max(dpdx.lengthSquared(), dpdy.lengthSquared());
|
||||
Float foctaves = std::min((Float) maxOctaves, 1.f - .5f * log2(s2));
|
||||
Float foctaves = std::min((Float) maxOctaves, 1.f - .5f * math::log2(s2));
|
||||
int octaves = (int) foctaves;
|
||||
|
||||
// Compute sum of octaves of noise for turbulence
|
||||
|
@ -135,7 +135,7 @@ Float Noise::turbulence(const Point &p, const Vector &dpdx,
|
|||
o *= omega;
|
||||
}
|
||||
Float partialOctave = foctaves - octaves;
|
||||
sum += o * smoothStep(.3f, .7f, partialOctave)
|
||||
sum += o * math::smoothStep((Float) .3f, (Float) .7f, partialOctave)
|
||||
* std::abs(perlinNoise(lambda * p));
|
||||
return sum;
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ size_t generateVPLs(const Scene *scene, Random *random,
|
|||
appendVPL(scene, random, lumVPL, false, vpls);
|
||||
dRec.d = -diRec.d;
|
||||
|
||||
Point2 offset = Warp::squareToUniformDiskConcentric(sampler->next2D());
|
||||
Point2 offset = warp::squareToUniformDiskConcentric(sampler->next2D());
|
||||
Vector perpOffset = Frame(diRec.d).toWorld(Vector(offset.x, offset.y, 0));
|
||||
BSphere geoBSphere = scene->getKDTree()->getAABB().getBSphere();
|
||||
pRec.p = geoBSphere.center + (perpOffset - dRec.d) * geoBSphere.radius;
|
||||
|
|
|
@ -1080,17 +1080,17 @@ void MainWindow::on_glView_crop(int type, int x, int y, int width, int height) {
|
|||
int maxNewSize = std::max(width, height);
|
||||
Float magnification = maxOldSize / (Float) maxNewSize;
|
||||
|
||||
width = floorToInt(width*magnification);
|
||||
height = floorToInt(height*magnification);
|
||||
width = math::floorToInt(width*magnification);
|
||||
height = math::floorToInt(height*magnification);
|
||||
|
||||
filmProps.setInteger("cropOffsetX", floorToInt(magnification
|
||||
filmProps.setInteger("cropOffsetX", math::floorToInt(magnification
|
||||
* (x + oldCropOffset.x)), false);
|
||||
filmProps.setInteger("cropOffsetY", floorToInt(magnification
|
||||
filmProps.setInteger("cropOffsetY", math::floorToInt(magnification
|
||||
* (y + oldCropOffset.y)), false);
|
||||
filmProps.setInteger("cropWidth", width);
|
||||
filmProps.setInteger("cropHeight", height);
|
||||
filmProps.setInteger("width", ceilToInt(oldSize.x*magnification), false);
|
||||
filmProps.setInteger("height", ceilToInt(oldSize.y*magnification), false);
|
||||
filmProps.setInteger("width", math::ceilToInt(oldSize.x*magnification), false);
|
||||
filmProps.setInteger("height", math::ceilToInt(oldSize.y*magnification), false);
|
||||
} else {
|
||||
width = context->originalSize.x;
|
||||
height = context->originalSize.y;
|
||||
|
|
|
@ -474,11 +474,11 @@ void RenderSettingsDialog::apply(SceneContext *ctx) {
|
|||
Vector2i oldCropSize = oldFilm->getCropSize();
|
||||
Point2i oldCropOffset = oldFilm->getCropOffset();
|
||||
|
||||
Vector2i size(std::ceil((oldSize.x * cropSize.x) / (Float) oldCropSize.x),
|
||||
std::ceil((oldSize.y * cropSize.y) / (Float) oldCropSize.y));
|
||||
Vector2i size(math::roundToInt((oldSize.x * cropSize.x / (Float) oldCropSize.x)),
|
||||
math::roundToInt((oldSize.y * cropSize.y / (Float) oldCropSize.y)));
|
||||
|
||||
Point2i cropOffset(std::floor((oldCropOffset.x * cropSize.x) / (Float) oldCropSize.x),
|
||||
std::floor((oldCropOffset.y * cropSize.y) / (Float) oldCropSize.y));
|
||||
Point2i cropOffset(math::roundToInt((oldCropOffset.x * cropSize.x / (Float) oldCropSize.x)),
|
||||
math::roundToInt((oldCropOffset.y * cropSize.y / (Float) oldCropSize.y)));
|
||||
|
||||
filmProps.setInteger("width", size.x, false);
|
||||
filmProps.setInteger("height", size.y, false);
|
||||
|
|
|
@ -93,6 +93,8 @@ inline mitsuba::math::SSEVector4f am_log(const mitsuba::math::SSEVector4f& x) {
|
|||
typedef mitsuba::math::SSEVector4f v4f;
|
||||
typedef mitsuba::math::SSEVector4i v4i;
|
||||
using mitsuba::math::castAsFloat;
|
||||
using mitsuba::math::clamp_ps;
|
||||
using mitsuba::math::fastpow_ps;
|
||||
|
||||
// Constants
|
||||
const v4f min_normal(castAsFloat(v4i::constant<0x00800000>()));
|
||||
|
@ -280,7 +282,7 @@ void tonemap(const PixelRGBA32FGroup* const begin,
|
|||
buffer[aOffset+i] = it->p[3];
|
||||
transpose(buffer[rOffset+i], buffer[gOffset+i],
|
||||
buffer[bOffset+i], buffer[aOffset+i]);
|
||||
buffer[aOffset+i] = clamp(buffer[aOffset+i],
|
||||
buffer[aOffset+i] = clamp_ps(buffer[aOffset+i],
|
||||
V4f::zero(), const_1f);
|
||||
}
|
||||
|
||||
|
@ -299,12 +301,12 @@ void tonemap(const PixelRGBA32FGroup* const begin,
|
|||
// Clamp and nonlinear display transform of the color components
|
||||
if (displayMethod == ESRGB) {
|
||||
for (ptrdiff_t i = 0; i != numColorIter; ++i) {
|
||||
const V4f s = clamp(buffer[i], V4f::zero(), const_1f);
|
||||
const V4f s = clamp_ps(buffer[i], V4f::zero(), const_1f);
|
||||
buffer[i] = sRGB_Remez43(s);
|
||||
}
|
||||
} else if (displayMethod == EGamma) {
|
||||
for (ptrdiff_t i = 0; i != numColorIter; ++i) {
|
||||
const V4f s = clamp(buffer[i], V4f::zero(), const_1f);
|
||||
const V4f s = clamp_ps(buffer[i], V4f::zero(), const_1f);
|
||||
buffer[i] = fastpow_ps(s, invGamma);
|
||||
}
|
||||
}
|
||||
|
@ -534,9 +536,13 @@ bool luminance(const mitsuba::Bitmap* source, const float multiplier,
|
|||
result.maxLuminance = max(rTail.maxLuminance, result.maxLuminance);
|
||||
}
|
||||
|
||||
outMaxLuminance = hmax(result.maxLuminance);
|
||||
const float sumLogLuminance = hsum(result.sumLogLuminance);
|
||||
outAvgLogLuminance = mitsuba::math::fastexp(sumLogLuminance / pixelCount);
|
||||
using mitsuba::math::hmax_ps;
|
||||
using mitsuba::math::hsum_ps;
|
||||
using mitsuba::math::fastexp;
|
||||
|
||||
outMaxLuminance = hmax_ps(result.maxLuminance);
|
||||
const float sumLogLuminance = hsum_ps(result.sumLogLuminance);
|
||||
outAvgLogLuminance = fastexp(sumLogLuminance / pixelCount);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
|
@ -62,19 +62,19 @@ public:
|
|||
Float sample(PhaseFunctionSamplingRecord &pRec,
|
||||
Sampler *sampler) const {
|
||||
Point2 sample(sampler->next2D());
|
||||
pRec.wo = Warp::squareToUniformSphere(sample);
|
||||
pRec.wo = warp::squareToUniformSphere(sample);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Float sample(PhaseFunctionSamplingRecord &pRec,
|
||||
Float &pdf, Sampler *sampler) const {
|
||||
pRec.wo = Warp::squareToUniformSphere(sampler->next2D());
|
||||
pdf = Warp::squareToUniformSpherePdf();
|
||||
pRec.wo = warp::squareToUniformSphere(sampler->next2D());
|
||||
pdf = warp::squareToUniformSpherePdf();
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
Float eval(const PhaseFunctionSamplingRecord &pRec) const {
|
||||
return Warp::squareToUniformSpherePdf();
|
||||
return warp::squareToUniformSpherePdf();
|
||||
}
|
||||
|
||||
Float getMeanCosine() const {
|
||||
|
|
|
@ -84,19 +84,19 @@ public:
|
|||
|
||||
Float sample(PhaseFunctionSamplingRecord &pRec,
|
||||
Sampler *sampler) const {
|
||||
pRec.wo = Warp::squareToUniformSphere(sampler->next2D());
|
||||
pRec.wo = warp::squareToUniformSphere(sampler->next2D());
|
||||
return eval(pRec) * (4 * M_PI);
|
||||
}
|
||||
|
||||
Float sample(PhaseFunctionSamplingRecord &pRec,
|
||||
Float &pdf, Sampler *sampler) const {
|
||||
pRec.wo = Warp::squareToUniformSphere(sampler->next2D());
|
||||
pdf = Warp::squareToUniformSpherePdf();
|
||||
pRec.wo = warp::squareToUniformSphere(sampler->next2D());
|
||||
pdf = warp::squareToUniformSpherePdf();
|
||||
return eval(pRec) * (4 * M_PI);
|
||||
}
|
||||
|
||||
Float pdf(const PhaseFunctionSamplingRecord &pRec) const {
|
||||
return Warp::squareToUniformSpherePdf();
|
||||
return warp::squareToUniformSpherePdf();
|
||||
}
|
||||
|
||||
Float eval(const PhaseFunctionSamplingRecord &pRec) const {
|
||||
|
|
|
@ -129,7 +129,7 @@ public:
|
|||
if (pRec.mRec.orientation.isZero()) {
|
||||
/* What to do when the local orientation is undefined */
|
||||
#if 0
|
||||
pRec.wo = Warp::squareToUniformSphere(sampler->next2D());
|
||||
pRec.wo = warp::squareToUniformSphere(sampler->next2D());
|
||||
return 1.0f;
|
||||
#else
|
||||
return 0.0f;
|
||||
|
|
|
@ -226,21 +226,15 @@ public:
|
|||
y = x_ - (int64_t) (d * y_);
|
||||
}
|
||||
|
||||
/// Positive modulo for 64-bit integers
|
||||
uint64_t modulo(int64_t a, int64_t b) {
|
||||
int64_t result = a - (a/b) * b;
|
||||
return (uint64_t) ((result < 0) ? result+b : result);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the multiplicative inverse of a modulo n,
|
||||
* \brief Compute the multiplicative inverse of a math::modulo n,
|
||||
* where a and n a re relative prime. The result is in the
|
||||
* range 1, ..., n - 1.
|
||||
*/
|
||||
uint64_t multiplicativeInverse(int64_t a, int64_t n) {
|
||||
int64_t x, y;
|
||||
extendedGCD(a, n, x, y);
|
||||
return modulo(x, n);
|
||||
return math::modulo(x, n);
|
||||
}
|
||||
|
||||
void setFilmResolution(const Vector2i &res, bool blocked) {
|
||||
|
|
|
@ -184,8 +184,8 @@ public:
|
|||
dimensions. This is required to support blocked rendering. */
|
||||
for (int i=0; i<2; ++i)
|
||||
m_resolution[i] = std::min((uint32_t) MAX_RESOLUTION,
|
||||
roundToPowerOfTwo((uint32_t) res[i]));
|
||||
m_logHeight = log2i((uint32_t) m_resolution.y);
|
||||
math::roundToPowerOfTwo((uint32_t) res[i]));
|
||||
m_logHeight = math::log2i((uint32_t) m_resolution.y);
|
||||
|
||||
m_samplesPerBatch = m_sampleCount;
|
||||
m_factor = (Float) 1.0f / (m_sampleCount *
|
||||
|
|
|
@ -80,8 +80,8 @@ public:
|
|||
/* Dimension, up to which which low discrepancy samples are guaranteed to be available. */
|
||||
m_maxDimension = props.getInteger("dimension", 4);
|
||||
|
||||
if (!isPowerOfTwo(m_sampleCount)) {
|
||||
m_sampleCount = roundToPowerOfTwo(m_sampleCount);
|
||||
if (!math::isPowerOfTwo(m_sampleCount)) {
|
||||
m_sampleCount = math::roundToPowerOfTwo(m_sampleCount);
|
||||
Log(EWarn, "Sample count should be a power of two -- rounding to "
|
||||
SIZE_T_FMT, m_sampleCount);
|
||||
}
|
||||
|
|
|
@ -149,11 +149,11 @@ public:
|
|||
m_resolution = 1;
|
||||
m_logResolution = 0;
|
||||
} else {
|
||||
uint32_t resolution = roundToPowerOfTwo(
|
||||
uint32_t resolution = math::roundToPowerOfTwo(
|
||||
(uint32_t) std::max(res.x, res.y));
|
||||
|
||||
m_resolution = (Float) resolution;
|
||||
m_logResolution = log2i(resolution);
|
||||
m_logResolution = math::log2i(resolution);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ public:
|
|||
|
||||
const Transform &trafo = m_worldTransform->eval(ray.time);
|
||||
ray.setOrigin(trafo(Point(0.0f)));
|
||||
ray.setDirection(trafo(Warp::squareToUniformSphere(pixelSample)));
|
||||
ray.setDirection(trafo(warp::squareToUniformSphere(pixelSample)));
|
||||
return Spectrum(1.0f);
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ public:
|
|||
PositionSamplingRecord &pRec,
|
||||
const Point2 &sample,
|
||||
const Point2 *extra) const {
|
||||
dRec.d = Warp::squareToUniformSphere(sample);
|
||||
dRec.d = warp::squareToUniformSphere(sample);
|
||||
dRec.pdf = INV_FOURPI;
|
||||
dRec.measure = ESolidAngle;
|
||||
return Spectrum(1.0f);
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
|
||||
ray.setOrigin(pRec.p);
|
||||
ray.setDirection(Frame(pRec.n).toWorld(
|
||||
Warp::squareToCosineHemisphere(otherSample)));
|
||||
warp::squareToCosineHemisphere(otherSample)));
|
||||
|
||||
return Spectrum(M_PI);
|
||||
}
|
||||
|
@ -149,9 +149,9 @@ public:
|
|||
Spectrum sampleDirection(DirectionSamplingRecord &dRec,
|
||||
PositionSamplingRecord &pRec,
|
||||
const Point2 &sample, const Point2 *extra) const {
|
||||
Vector local = Warp::squareToCosineHemisphere(sample);
|
||||
Vector local = warp::squareToCosineHemisphere(sample);
|
||||
dRec.d = Frame(pRec.n).toWorld(local);
|
||||
dRec.pdf = Warp::squareToCosineHemispherePdf(local);
|
||||
dRec.pdf = warp::squareToCosineHemispherePdf(local);
|
||||
dRec.measure = ESolidAngle;
|
||||
return Spectrum(1.0f);
|
||||
}
|
||||
|
|
|
@ -155,7 +155,7 @@ public:
|
|||
Vector d = normalize(m_worldTransform->eval(pRec.time).inverse()(dRec.d));
|
||||
|
||||
samplePosition = Point2(
|
||||
modulo(std::atan2(d.x, -d.z) * INV_TWOPI, (Float) 1) * m_resolution.x,
|
||||
math::modulo(std::atan2(d.x, -d.z) * INV_TWOPI, (Float) 1) * m_resolution.x,
|
||||
math::safe_acos(d.y) * INV_PI * m_resolution.y
|
||||
);
|
||||
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
d *= invDist;
|
||||
|
||||
dRec.uv = Point2(
|
||||
modulo(std::atan2(d.x, -d.z) * INV_TWOPI, (Float) 1) * m_resolution.x,
|
||||
math::modulo(std::atan2(d.x, -d.z) * INV_TWOPI, (Float) 1) * m_resolution.x,
|
||||
math::safe_acos(d.y) * INV_PI * m_resolution.y
|
||||
);
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ public:
|
|||
|
||||
Spectrum sampleRay(Ray &ray, const Point2 &pixelSample,
|
||||
const Point2 &otherSample, Float timeSample) const {
|
||||
Point2 diskSample = Warp::squareToUniformDiskConcentric(otherSample)
|
||||
Point2 diskSample = warp::squareToUniformDiskConcentric(otherSample)
|
||||
* (m_apertureRadius / m_scale.x);
|
||||
ray.time = sampleTime(timeSample);
|
||||
|
||||
|
@ -223,7 +223,7 @@ public:
|
|||
|
||||
Spectrum sampleRayDifferential(RayDifferential &ray, const Point2 &pixelSample,
|
||||
const Point2 &otherSample, Float timeSample) const {
|
||||
Point2 diskSample = Warp::squareToUniformDiskConcentric(otherSample)
|
||||
Point2 diskSample = warp::squareToUniformDiskConcentric(otherSample)
|
||||
* (m_apertureRadius / m_scale.x);
|
||||
ray.time = sampleTime(timeSample);
|
||||
|
||||
|
@ -285,7 +285,7 @@ public:
|
|||
double rand4 = (tmp2 & 0x3FFFFFF) * (1.0 / 0x3FFFFFF);
|
||||
#endif
|
||||
|
||||
Point2 aperturePos = Warp::squareToUniformDiskConcentric(Point2(rand1, rand2))
|
||||
Point2 aperturePos = warp::squareToUniformDiskConcentric(Point2(rand1, rand2))
|
||||
* (m_apertureRadius / m_scale.x);
|
||||
Point2 samplePos(rand3, rand4);
|
||||
|
||||
|
@ -382,7 +382,7 @@ public:
|
|||
radius += apertureRadius;
|
||||
|
||||
/* Sample the ray origin */
|
||||
Point2 disk = Warp::squareToUniformDiskConcentric(sample);
|
||||
Point2 disk = warp::squareToUniformDiskConcentric(sample);
|
||||
Point diskP(disk.x*radius+localP.x, disk.y*radius+localP.y, 0.0f);
|
||||
|
||||
/* Compute the intersection with the focal plane */
|
||||
|
|
|
@ -292,7 +292,7 @@ public:
|
|||
|
||||
Spectrum sampleRay(Ray &ray, const Point2 &pixelSample,
|
||||
const Point2 &otherSample, Float timeSample) const {
|
||||
Point2 tmp = Warp::squareToUniformDiskConcentric(otherSample)
|
||||
Point2 tmp = warp::squareToUniformDiskConcentric(otherSample)
|
||||
* m_apertureRadius;
|
||||
ray.time = sampleTime(timeSample);
|
||||
|
||||
|
@ -323,7 +323,7 @@ public:
|
|||
|
||||
Spectrum sampleRayDifferential(RayDifferential &ray, const Point2 &pixelSample,
|
||||
const Point2 &otherSample, Float timeSample) const {
|
||||
Point2 tmp = Warp::squareToUniformDiskConcentric(otherSample)
|
||||
Point2 tmp = warp::squareToUniformDiskConcentric(otherSample)
|
||||
* m_apertureRadius;
|
||||
ray.time = sampleTime(timeSample);
|
||||
|
||||
|
@ -364,7 +364,7 @@ public:
|
|||
const Point2 &sample, const Point2 *extra) const {
|
||||
const Transform &trafo = m_worldTransform->eval(pRec.time);
|
||||
|
||||
Point2 aperturePos = Warp::squareToUniformDiskConcentric(sample)
|
||||
Point2 aperturePos = warp::squareToUniformDiskConcentric(sample)
|
||||
* m_apertureRadius;
|
||||
|
||||
pRec.p = trafo.transformAffine(
|
||||
|
@ -449,7 +449,7 @@ public:
|
|||
}
|
||||
|
||||
/* Sample a position on the aperture (in local coordinates) */
|
||||
Point2 tmp = Warp::squareToUniformDiskConcentric(sample)
|
||||
Point2 tmp = warp::squareToUniformDiskConcentric(sample)
|
||||
* m_apertureRadius;
|
||||
Point apertureP(tmp.x, tmp.y, 0);
|
||||
|
||||
|
@ -495,7 +495,7 @@ public:
|
|||
const Point2 &aaSample) const {
|
||||
Float right = std::tan(m_xfov * M_PI/360) * m_nearClip, left = -right;
|
||||
Float top = right / m_aspect, bottom = -top;
|
||||
Point2 apertureP = Warp::squareToUniformDiskConcentric(apertureSample)
|
||||
Point2 apertureP = warp::squareToUniformDiskConcentric(apertureSample)
|
||||
* m_apertureRadius;
|
||||
|
||||
Vector2 jitterScale(
|
||||
|
|
|
@ -249,7 +249,7 @@ public:
|
|||
|
||||
void samplePosition(PositionSamplingRecord &pRec, const Point2 &sample) const {
|
||||
const Transform &trafo = m_objectToWorld->eval(pRec.time);
|
||||
Point2 p = Warp::squareToUniformDiskConcentric(sample);
|
||||
Point2 p = warp::squareToUniformDiskConcentric(sample);
|
||||
|
||||
pRec.p = trafo(Point3(p.x, p.y, 0));
|
||||
pRec.n = trafo(normalize(Normal(0,0,1)));
|
||||
|
|
|
@ -199,6 +199,15 @@ public:
|
|||
return (size_t) m_levelSize[0].x * (size_t) m_levelSize[0].y;
|
||||
}
|
||||
|
||||
inline static int signumToInt(Float value) {
|
||||
if (value < 0)
|
||||
return -1;
|
||||
else if (value > 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool rayIntersect(const Ray &_ray, Float mint, Float maxt, Float &t, void *tmp) const {
|
||||
StackEntry stack[MTS_QTREE_MAXDEPTH];
|
||||
|
||||
|
@ -233,14 +242,14 @@ public:
|
|||
maxY = (int) std::max(enterPt.y, exitPt.y);
|
||||
|
||||
/* Determine quadtree level */
|
||||
int level = clamp(1 + log2i(
|
||||
int level = math::clamp(1 + math::log2i(
|
||||
std::max((uint32_t) (minX ^ maxX), (uint32_t) (minY ^ maxY))),
|
||||
0, m_levelCount-1);
|
||||
|
||||
/* Compute X and Y coordinates at that level */
|
||||
const Vector2i &blockSize = m_blockSize[level];
|
||||
int x = clamp(minX / blockSize.x, 0, m_levelSize[level].x-1),
|
||||
y = clamp(minY / blockSize.y, 0, m_levelSize[level].y-1);
|
||||
int x = math::clamp(minX / blockSize.x, 0, m_levelSize[level].x-1),
|
||||
y = math::clamp(minY / blockSize.y, 0, m_levelSize[level].y-1);
|
||||
|
||||
stack[stackIdx].level = level;
|
||||
stack[stackIdx].x = x;
|
||||
|
@ -504,8 +513,8 @@ public:
|
|||
m_dataSize = m_bitmap->getSize();
|
||||
if (m_dataSize.x < 2) m_dataSize.x = 2;
|
||||
if (m_dataSize.y < 2) m_dataSize.y = 2;
|
||||
if (!isPowerOfTwo(m_dataSize.x - 1)) m_dataSize.x = (int) roundToPowerOfTwo((uint32_t) m_dataSize.x - 1) + 1;
|
||||
if (!isPowerOfTwo(m_dataSize.y - 1)) m_dataSize.y = (int) roundToPowerOfTwo((uint32_t) m_dataSize.y - 1) + 1;
|
||||
if (!math::isPowerOfTwo(m_dataSize.x - 1)) m_dataSize.x = (int) math::roundToPowerOfTwo((uint32_t) m_dataSize.x - 1) + 1;
|
||||
if (!math::isPowerOfTwo(m_dataSize.y - 1)) m_dataSize.y = (int) math::roundToPowerOfTwo((uint32_t) m_dataSize.y - 1) + 1;
|
||||
|
||||
if (m_bitmap->getSize() != m_dataSize) {
|
||||
m_bitmap = m_bitmap->convert(Bitmap::ELuminance, Bitmap::EFloat);
|
||||
|
@ -533,7 +542,7 @@ public:
|
|||
Log(EInfo, "Building acceleration data structure for %ix%i height field ..", m_dataSize.x, m_dataSize.y);
|
||||
|
||||
ref<Timer> timer = new Timer();
|
||||
m_levelCount = (int) std::max(log2i((uint32_t) m_dataSize.x-1), log2i((uint32_t) m_dataSize.y-1)) + 1;
|
||||
m_levelCount = (int) std::max(math::log2i((uint32_t) m_dataSize.x-1), math::log2i((uint32_t) m_dataSize.y-1)) + 1;
|
||||
|
||||
m_levelSize = new Vector2i[m_levelCount];
|
||||
m_numChildren = new Vector2i[m_levelCount];
|
||||
|
|
|
@ -256,7 +256,7 @@ public:
|
|||
}
|
||||
|
||||
void samplePosition(PositionSamplingRecord &pRec, const Point2 &sample) const {
|
||||
Vector v = Warp::squareToUniformSphere(sample);
|
||||
Vector v = warp::squareToUniformSphere(sample);
|
||||
|
||||
pRec.p = Point(v * m_radius) + m_center;
|
||||
pRec.n = Normal(v);
|
||||
|
@ -300,8 +300,8 @@ public:
|
|||
Float cosAlpha = math::safe_sqrt(1.0f - sinAlpha * sinAlpha);
|
||||
|
||||
dRec.d = Frame(refToCenter * invRefDist).toWorld(
|
||||
Warp::squareToUniformCone(cosAlpha, sample));
|
||||
dRec.pdf = Warp::squareToUniformConePdf(cosAlpha);
|
||||
warp::squareToUniformCone(cosAlpha, sample));
|
||||
dRec.pdf = warp::squareToUniformConePdf(cosAlpha);
|
||||
|
||||
/* Distance to the projection of the sphere center
|
||||
onto the ray (dRec.ref, dRec.d) */
|
||||
|
@ -336,7 +336,7 @@ public:
|
|||
} else {
|
||||
/* The reference point lies inside the sphere
|
||||
=> use uniform sphere sampling. */
|
||||
Vector d = Warp::squareToUniformSphere(sample);
|
||||
Vector d = warp::squareToUniformSphere(sample);
|
||||
|
||||
dRec.p = m_center + d * m_radius;
|
||||
dRec.n = Normal(d);
|
||||
|
@ -366,7 +366,7 @@ public:
|
|||
if (sinAlpha < 1-Epsilon) {
|
||||
/* The reference point lies outside the sphere */
|
||||
Float cosAlpha = math::safe_sqrt(1 - sinAlpha*sinAlpha);
|
||||
Float pdfSA = Warp::squareToUniformConePdf(cosAlpha);
|
||||
Float pdfSA = warp::squareToUniformConePdf(cosAlpha);
|
||||
|
||||
if (dRec.measure == ESolidAngle)
|
||||
return pdfSA;
|
||||
|
|
|
@ -100,7 +100,7 @@ void blueNoisePointSet(const Scene *scene, const std::vector<Shape *> &shapes,
|
|||
sa = areaDistr.getSum();
|
||||
|
||||
/* Start with a fairly dense set of white noise points */
|
||||
int nsamples = ceilToInt(15 * sa / (M_PI * radius * radius));
|
||||
int nsamples = math::ceilToInt(15 * sa / (M_PI * radius * radius));
|
||||
|
||||
SLog(EInfo, "Creating a blue noise point set (radius=%f, "
|
||||
"surface area = %f)", radius, sa);
|
||||
|
@ -145,7 +145,7 @@ void blueNoisePointSet(const Scene *scene, const std::vector<Shape *> &shapes,
|
|||
|
||||
Vector3i cellCount;
|
||||
for (int i=0; i<3; ++i)
|
||||
cellCount[i] = std::max(1, ceilToInt(extents[i] * invCellWidth));
|
||||
cellCount[i] = std::max(1, math::ceilToInt(extents[i] * invCellWidth));
|
||||
|
||||
SLog(EInfo, " phase 2: computing cell indices ..");
|
||||
#if defined(MTS_OPENMP)
|
||||
|
|
|
@ -419,9 +419,9 @@ public:
|
|||
Vector wi;
|
||||
|
||||
if (bsdf->getType() & BSDF::EBackSide)
|
||||
wi = Warp::squareToUniformSphere(sampler->next2D());
|
||||
wi = warp::squareToUniformSphere(sampler->next2D());
|
||||
else
|
||||
wi = Warp::squareToCosineHemisphere(sampler->next2D());
|
||||
wi = warp::squareToCosineHemisphere(sampler->next2D());
|
||||
|
||||
BSDFAdapter adapter(bsdf, sampler, wi, -1);
|
||||
ref<ChiSquare> chiSqr = new ChiSquare(thetaBins, 2*thetaBins, wiSamples);
|
||||
|
@ -466,9 +466,9 @@ public:
|
|||
Vector wi;
|
||||
|
||||
if (bsdf->getType(comp) & BSDF::EBackSide)
|
||||
wi = Warp::squareToUniformSphere(sampler->next2D());
|
||||
wi = warp::squareToUniformSphere(sampler->next2D());
|
||||
else
|
||||
wi = Warp::squareToCosineHemisphere(sampler->next2D());
|
||||
wi = warp::squareToCosineHemisphere(sampler->next2D());
|
||||
|
||||
BSDFAdapter adapter(bsdf, sampler, wi, comp);
|
||||
|
||||
|
@ -533,11 +533,11 @@ public:
|
|||
MediumSamplingRecord mRec;
|
||||
|
||||
/* Sampler fiber/particle orientation */
|
||||
mRec.orientation = Warp::squareToUniformSphere(sampler->next2D());
|
||||
mRec.orientation = warp::squareToUniformSphere(sampler->next2D());
|
||||
|
||||
/* Test for a number of different incident directions */
|
||||
for (int j=0; j<wiSamples; ++j) {
|
||||
Vector wi = Warp::squareToUniformSphere(sampler->next2D());
|
||||
Vector wi = warp::squareToUniformSphere(sampler->next2D());
|
||||
|
||||
PhaseFunctionAdapter adapter(mRec, phase, sampler, wi);
|
||||
ref<ChiSquare> chiSqr = new ChiSquare(thetaBins, 2*thetaBins, wiSamples);
|
||||
|
|
|
@ -112,8 +112,8 @@ public:
|
|||
for (size_t i=0; i<nRays; ++i) {
|
||||
Point2 sample1(random->nextFloat(), random->nextFloat()),
|
||||
sample2(random->nextFloat(), random->nextFloat());
|
||||
Point p1 = bsphere.center + Warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + Warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Point p1 = bsphere.center + warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Ray r(p1, normalize(p2-p1), 0.0f);
|
||||
Intersection its;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
for (int m=-l; m<=l; ++m)
|
||||
vec1(l, m) = random->nextFloat();
|
||||
|
||||
Vector axis(Warp::squareToUniformSphere(Point2(random->nextFloat(), random->nextFloat())));
|
||||
Vector axis(warp::squareToUniformSphere(Point2(random->nextFloat(), random->nextFloat())));
|
||||
Transform trafo = Transform::rotate(axis, random->nextFloat()*360);
|
||||
SHRotation rot(vec1.getBands());
|
||||
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
rot(vec1, vec2);
|
||||
|
||||
for (int i=0; i<100; ++i) {
|
||||
Vector dir1(Warp::squareToUniformSphere(Point2(random->nextFloat(), random->nextFloat()))), dir2;
|
||||
Vector dir1(warp::squareToUniformSphere(Point2(random->nextFloat(), random->nextFloat()))), dir2;
|
||||
trafo(dir1, dir2);
|
||||
|
||||
Float value1 = vec1.eval(dir2);
|
||||
|
|
|
@ -64,8 +64,8 @@ public:
|
|||
}
|
||||
|
||||
inline Spectrum eval(const Point2 &uv) const {
|
||||
int x = 2*modulo((int) (uv.x * 2), 2) - 1,
|
||||
y = 2*modulo((int) (uv.y * 2), 2) - 1;
|
||||
int x = 2*math::modulo((int) (uv.x * 2), 2) - 1,
|
||||
y = 2*math::modulo((int) (uv.y * 2), 2) - 1;
|
||||
|
||||
if (x*y == 1)
|
||||
return m_color0;
|
||||
|
|
|
@ -73,8 +73,8 @@ public:
|
|||
}
|
||||
|
||||
inline Spectrum eval(const Point2 &uv) const {
|
||||
Float x = uv.x - floorToInt(uv.x);
|
||||
Float y = uv.y - floorToInt(uv.y);
|
||||
Float x = uv.x - math::floorToInt(uv.x);
|
||||
Float y = uv.y - math::floorToInt(uv.y);
|
||||
|
||||
if (x > .5)
|
||||
x -= 1;
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
minDist = std::min(minDist, (cur + d1 * dot(d1, d2) - its.p).lengthSquared());
|
||||
}
|
||||
|
||||
Float a = smoothStep(m_lineWidth*(1.f-m_stepWidth), m_lineWidth, std::sqrt(minDist));
|
||||
Float a = math::smoothStep(m_lineWidth*(1.f-m_stepWidth), m_lineWidth, std::sqrt(minDist));
|
||||
return m_edgeColor*(1-a) + m_interiorColor*a;
|
||||
}
|
||||
|
||||
|
|
|
@ -223,8 +223,8 @@ public:
|
|||
for (size_t i=0; i<nRays; ++i) {
|
||||
Point2 sample1(random->nextFloat(), random->nextFloat()),
|
||||
sample2(random->nextFloat(), random->nextFloat());
|
||||
Point p1 = bsphere.center + Warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + Warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Point p1 = bsphere.center + warp::squareToUniformSphere(sample1) * bsphere.radius;
|
||||
Point p2 = bsphere.center + warp::squareToUniformSphere(sample2) * bsphere.radius;
|
||||
Ray r(p1, normalize(p2-p1), 0.0f);
|
||||
|
||||
Intersection its;
|
||||
|
|
|
@ -336,9 +336,9 @@ public:
|
|||
|
||||
Float lookupFloat(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x1 = floorToInt(p.x),
|
||||
y1 = floorToInt(p.y),
|
||||
z1 = floorToInt(p.z),
|
||||
const int x1 = math::floorToInt(p.x),
|
||||
y1 = math::floorToInt(p.y),
|
||||
z1 = math::floorToInt(p.z),
|
||||
x2 = x1+1, y2 = y1+1, z2 = z1+1;
|
||||
|
||||
if (x1 < 0 || y1 < 0 || z1 < 0 || x2 >= m_res.x ||
|
||||
|
@ -389,9 +389,9 @@ public:
|
|||
|
||||
Spectrum lookupSpectrum(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x1 = floorToInt(p.x),
|
||||
y1 = floorToInt(p.y),
|
||||
z1 = floorToInt(p.z),
|
||||
const int x1 = math::floorToInt(p.x),
|
||||
y1 = math::floorToInt(p.y),
|
||||
z1 = math::floorToInt(p.z),
|
||||
x2 = x1+1, y2 = y1+1, z2 = z1+1;
|
||||
|
||||
if (x1 < 0 || y1 < 0 || z1 < 0 || x2 >= m_res.x ||
|
||||
|
@ -466,9 +466,9 @@ public:
|
|||
|
||||
Vector lookupVector(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x1 = floorToInt(p.x),
|
||||
y1 = floorToInt(p.y),
|
||||
z1 = floorToInt(p.z),
|
||||
const int x1 = math::floorToInt(p.x),
|
||||
y1 = math::floorToInt(p.y),
|
||||
z1 = math::floorToInt(p.z),
|
||||
x2 = x1+1, y2 = y1+1, z2 = z1+1;
|
||||
|
||||
if (x1 < 0 || y1 < 0 || z1 < 0 || x2 >= m_res.x ||
|
||||
|
|
|
@ -143,9 +143,9 @@ public:
|
|||
|
||||
Float lookupFloat(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x = floorToInt(p.x),
|
||||
y = floorToInt(p.y),
|
||||
z = floorToInt(p.z);
|
||||
const int x = math::floorToInt(p.x),
|
||||
y = math::floorToInt(p.y),
|
||||
z = math::floorToInt(p.z);
|
||||
if (x < 0 || x >= m_res.x ||
|
||||
y < 0 || y >= m_res.y ||
|
||||
z < 0 || z >= m_res.z)
|
||||
|
@ -160,9 +160,9 @@ public:
|
|||
|
||||
Spectrum lookupSpectrum(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x = floorToInt(p.x),
|
||||
y = floorToInt(p.y),
|
||||
z = floorToInt(p.z);
|
||||
const int x = math::floorToInt(p.x),
|
||||
y = math::floorToInt(p.y),
|
||||
z = math::floorToInt(p.z);
|
||||
if (x < 0 || x >= m_res.x ||
|
||||
y < 0 || y >= m_res.y ||
|
||||
z < 0 || z >= m_res.z)
|
||||
|
@ -177,9 +177,9 @@ public:
|
|||
|
||||
Vector lookupVector(const Point &_p) const {
|
||||
const Point p = m_worldToGrid.transformAffine(_p);
|
||||
const int x = floorToInt(p.x),
|
||||
y = floorToInt(p.y),
|
||||
z = floorToInt(p.z);
|
||||
const int x = math::floorToInt(p.x),
|
||||
y = math::floorToInt(p.y),
|
||||
z = math::floorToInt(p.z);
|
||||
if (x < 0 || x >= m_res.x ||
|
||||
y < 0 || y >= m_res.y ||
|
||||
z < 0 || z >= m_res.z)
|
||||
|
|
|
@ -86,7 +86,7 @@ public:
|
|||
/// Size of an individual block (must be a power of 2)
|
||||
m_blockSize = props.getInteger("blockSize", 8);
|
||||
|
||||
if (!isPowerOfTwo(m_blockSize))
|
||||
if (!math::isPowerOfTwo(m_blockSize))
|
||||
Log(EError, "Block size must be a power of two!");
|
||||
|
||||
/* Width of an individual voxel. Will use the step size of the
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
* Transform::translate(-Vector(m_aabb.min)) * m_worldToVolume;
|
||||
m_voxelMask = m_blockSize-1;
|
||||
m_blockMask = ~(m_blockSize-1);
|
||||
m_blockShift = log2i((uint32_t) m_blockSize);
|
||||
m_blockShift = math::log2i((uint32_t) m_blockSize);
|
||||
|
||||
Log(EInfo, "Volume cache configuration");
|
||||
Log(EInfo, " Block size in voxels = %i", m_blockSize);
|
||||
|
|
Loading…
Reference in New Issue