Spaces:
Runtime error
Runtime error
template <typename T> | |
struct TVector2 { | |
DEVICE TVector2() {} | |
template <typename T2> | |
DEVICE | |
TVector2(T2 x, T2 y) : x(T(x)), y(T(y)) {} | |
template <typename T2> | |
DEVICE | |
TVector2(const TVector2<T2> &v) : x(T(v.x)), y(T(v.y)) {} | |
DEVICE T& operator[](int i) { | |
return *(&x + i); | |
} | |
DEVICE T operator[](int i) const { | |
return *(&x + i); | |
} | |
T x, y; | |
}; | |
template <typename T> | |
struct TVector3 { | |
DEVICE TVector3() {} | |
template <typename T2> | |
DEVICE | |
TVector3(T2 x, T2 y, T2 z) : x(T(x)), y(T(y)), z(T(z)) {} | |
template <typename T2> | |
DEVICE | |
TVector3(const TVector3<T2> &v) : x(T(v.x)), y(T(v.y)), z(T(v.z)) {} | |
DEVICE T& operator[](int i) { | |
return *(&x + i); | |
} | |
DEVICE T operator[](int i) const { | |
return *(&x + i); | |
} | |
T x, y, z; | |
}; | |
template <typename T> | |
struct TVector4 { | |
DEVICE TVector4() {} | |
template <typename T2> | |
DEVICE | |
TVector4(T2 x, T2 y, T2 z, T2 w) : x(T(x)), y(T(y)), z(T(z)), w(T(w)) {} | |
template <typename T2> | |
DEVICE | |
TVector4(const TVector4<T2> &v) : x(T(v.x)), y(T(v.y)), z(T(v.z)), w(T(v.w)) {} | |
DEVICE T& operator[](int i) { | |
return *(&x + i); | |
} | |
DEVICE T operator[](int i) const { | |
return *(&x + i); | |
} | |
T x, y, z, w; | |
}; | |
using Vector2f = TVector2<float>; | |
using Vector2d = TVector2<double>; | |
using Vector2i = TVector2<int>; | |
using Vector2 = TVector2<Real>; | |
using Vector3i = TVector3<int>; | |
using Vector3f = TVector3<float>; | |
using Vector3d = TVector3<double>; | |
using Vector3 = TVector3<Real>; | |
using Vector4f = TVector4<float>; | |
using Vector4d = TVector4<double>; | |
using Vector4 = TVector4<Real>; | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0[0] + v1[0])> { | |
return TVector2<decltype(v0[0] + v1[0])>{ | |
v0[0] + v1[0], v0[1] + v1[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const T0 &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0 + v1[0])> { | |
return TVector2<decltype(v0 + v1[0])>{v0 + v1[0], v0 + v1[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const T0 &v0, | |
const TVector3<T1> &v1) -> TVector3<decltype(v0[0] + v1)> { | |
return TVector3<decltype(v0 + v1[0])>{ | |
v0 + v1[0], v0 + v1[1], v0 + v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const TVector2<T0> &v0, | |
const T1 &v1) -> TVector2<decltype(v0[0] + v1)> { | |
return TVector2<decltype(v0[0] + v1)>{ | |
v0[0] + v1, v0[1] + v1}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const TVector3<T0> &v0, | |
const T1 &v1) -> TVector3<decltype(v0[0] + v1[0])> { | |
return TVector3<decltype(v0[0] + v1)>{ | |
v0[0] + v1, v0[1] + v1, v0[2] + v1}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<decltype(v0[0] + v1[0])> { | |
return TVector3<decltype(v0[0] + v1[0])>{ | |
v0[0] + v1[0], v0[1] + v1[1], v0[2] + v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+(const TVector4<T0> &v0, | |
const TVector4<T1> &v1) -> TVector4<decltype(v0[0] + v1[0])> { | |
return TVector4<decltype(v0[0] + v1[0])>{ | |
v0[0] + v1[0], v0[1] + v1[1], v0[2] + v1[2], v0[3] + v1[3]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+=(TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<T0>& { | |
v0[0] += v1[0]; | |
v0[1] += v1[1]; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+=(TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<T0>& { | |
v0[0] += v1[0]; | |
v0[1] += v1[1]; | |
v0[2] += v1[2]; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+=(TVector3<T0> &v0, | |
const T1 &v1) -> TVector3<T0>& { | |
v0[0] += v1; | |
v0[1] += v1; | |
v0[2] += v1; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+=(TVector4<T0> &v0, | |
const TVector4<T1> &v1) -> TVector4<T0>& { | |
v0[0] += v1[0]; | |
v0[1] += v1[1]; | |
v0[2] += v1[2]; | |
v0[3] += v1[3]; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator+=(TVector4<T0> &v0, | |
const T1 &v1) -> TVector4<T0>& { | |
v0[0] += v1; | |
v0[1] += v1; | |
v0[2] += v1; | |
v0[3] += v1; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const T0 &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0 - v1[0])> { | |
return TVector2<decltype(v0 - v1[0])>{v0 - v1[0], v0 - v1[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const T0 &v0, | |
const TVector3<T1> &v1) -> TVector2<decltype(v0 - v1[0])> { | |
return TVector3<decltype(v0 - v1[0])>{v0 - v1[0], v0 - v1[1], v0 - v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const TVector2<T0> &v0, | |
const T1 &v1) -> TVector2<decltype(v0[0] - v1)> { | |
return TVector2<decltype(v0[0] - v1)>{v0[0] - v1, v0[1] - v1}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const TVector3<T0> &v0, | |
const T1 &v1) -> TVector3<decltype(v0[0] - v1)> { | |
return TVector3<decltype(v0[0] - v1)>{v0[0] - v1, v0[1] - v1, v0[2] - v1}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0[0] - v1[0])> { | |
return TVector2<decltype(v0[0] - v1[0])>{ | |
v0[0] - v1[0], v0[1] - v1[1]}; | |
} | |
template <typename T> | |
DEVICE | |
inline auto operator-(const TVector2<T> &v) -> TVector2<T> { | |
return TVector2<T>{-v[0], -v[1]}; | |
} | |
template <typename T> | |
DEVICE | |
inline auto operator-(const TVector3<T> &v) -> TVector3<T> { | |
return TVector3<T>{-v[0], -v[1], -v[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<decltype(v0[0] - v1[0])> { | |
return TVector3<decltype(v0[0] - v1[0])>{ | |
v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-(const TVector4<T0> &v0, | |
const TVector4<T1> &v1) -> TVector4<decltype(v0[0] - v1[0])> { | |
return TVector4<decltype(v0[0] - v1[0])>{ | |
v0[0] - v1[0], v0[1] - v1[1], v0[2] - v1[2], v0[3] - v1[3]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-=(TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<T0>& { | |
v0[0] -= v1[0]; | |
v0[1] -= v1[1]; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator-=(TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<T0>& { | |
v0[0] -= v1[0]; | |
v0[1] -= v1[1]; | |
v0[2] -= v1[2]; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0[0] * v1[0])> { | |
return TVector2<decltype(v0[0] * v1[0])>{ | |
v0[0] * v1[0], v0[1] * v1[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector2<T0> &v0, | |
const T1 &s) -> TVector2<decltype(v0[0] * s)> { | |
return TVector2<decltype(v0[0] * s)>{ | |
v0[0] * s, v0[1] * s}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const T0 &s, | |
const TVector2<T1> &v0) -> TVector2<decltype(s * v0[0])> { | |
return TVector2<decltype(s * v0[0])>{s * v0[0], s * v0[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*=(TVector2<T0> &v0, | |
const T1 &s) -> TVector2<T0>& { | |
v0[0] *= s; | |
v0[1] *= s; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector3<T0> &v0, | |
const T1 &s) -> TVector3<decltype(v0[0] * s)> { | |
return TVector3<decltype(v0[0] * s)>{ | |
v0[0] * s, v0[1] * s, v0[2] * s}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const T0 &s, | |
const TVector3<T1> &v0) -> TVector3<decltype(s * v0[0])> { | |
return TVector3<decltype(s * v0[0])>{ | |
s * v0[0], s * v0[1], s * v0[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*=(TVector3<T0> &v0, | |
const T1 &s) -> TVector3<T0>& { | |
v0[0] *= s; | |
v0[1] *= s; | |
v0[2] *= s; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*=(TVector4<T0> &v0, | |
const T1 &s) -> TVector4<T0>& { | |
v0[0] *= s; | |
v0[1] *= s; | |
v0[2] *= s; | |
v0[3] *= s; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<decltype(v0[0] * v1[0])> { | |
return TVector3<decltype(v0[0] * v1[0])>{ | |
v0[0] * v1[0], v0[1] * v1[1], v0[2] * v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector4<T0> &v0, | |
const T1 &s) -> TVector4<decltype(v0[0] * s)> { | |
return TVector4<decltype(v0[0] * s)>{ | |
v0[0] * s, v0[1] * s, v0[2] * s, v0[3] * s}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const T0 &s, | |
const TVector4<T1> &v0) -> TVector4<decltype(s * v0[0])> { | |
return TVector4<decltype(s * v0[0])>{ | |
s * v0[0], s * v0[1], s * v0[2], s * v0[3]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator*(const TVector4<T0> &v0, | |
const TVector4<T1> &v1) -> TVector4<decltype(v0[0] * v1[0])> { | |
return TVector4<decltype(v0[0] * v1[0])>{ | |
v0[0] * v1[0], v0[1] * v1[1], v0[2] * v1[2], v0[3] * v1[3]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const TVector2<T0> &v0, | |
const T1 &s) -> TVector2<decltype(v0[0] / s)> { | |
auto inv_s = 1.f / s; | |
return v0 * inv_s; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const TVector3<T0> &v0, | |
const T1 &s) -> TVector3<decltype(v0[0] / s)> { | |
auto inv_s = 1.f / s; | |
return v0 * inv_s; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const TVector4<T0> &v0, | |
const T1 &s) -> TVector4<decltype(v0[0] / s)> { | |
auto inv_s = 1.f / s; | |
return v0 * inv_s; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const T0 &s, | |
const TVector3<T1> &v1) -> TVector3<decltype(s / v1[0])> { | |
return TVector3<decltype(s / v1[0])>{ | |
s / v1[0], s / v1[2], s / v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> TVector3<decltype(v0[0] / v1[0])> { | |
return TVector3<decltype(v0[0] / v1[0])>{ | |
v0[0] / v1[0], v0[1] / v1[2], v0[2] / v1[2]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> TVector2<decltype(v0[0] / v1[0])> { | |
return TVector2<decltype(v0[0] / v1[0])>{ | |
v0[0] / v1[0], v0[1] / v1[1]}; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/=(TVector3<T0> &v0, | |
const T1 &s) -> TVector3<T0>& { | |
auto inv_s = 1.f / s; | |
v0[0] *= inv_s; | |
v0[1] *= inv_s; | |
v0[2] *= inv_s; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto operator/=(TVector4<T0> &v0, | |
const T1 &s) -> TVector4<T0>& { | |
auto inv_s = 1.f / s; | |
v0[0] *= inv_s; | |
v0[1] *= inv_s; | |
v0[2] *= inv_s; | |
v0[3] *= inv_s; | |
return v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline bool operator==(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) { | |
return v0.x == v1.x && v0.y == v1.y; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline bool operator==(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) { | |
return v0.x == v1.x && v0.y == v1.y && v0.z == v1.z; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline bool operator!=(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) { | |
return v0.x != v1.x || v0.y != v1.y || v0.z != v1.z; | |
} | |
template <typename T> | |
DEVICE | |
inline TVector2<T> get_normal(const TVector2<T> &v) { | |
return TVector2<T>{v.y, -v.x}; | |
} | |
template <typename T> | |
DEVICE | |
inline T length_squared(const TVector2<T> &v0) { | |
return square(v0[0]) + square(v0[1]); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector2<T> d_length_squared(const TVector2<T> &v0, const T &d_l_sq) { | |
//l_sq = square(v0[0]) + square(v0[1]) | |
return 2 * d_l_sq * v0; | |
} | |
template <typename T> | |
DEVICE | |
inline T length(const TVector2<T> &v0) { | |
return sqrt(length_squared(v0)); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector2<T> d_length(const TVector2<T> &v0, const T &d_l) { | |
auto l_sq = length_squared(v0); | |
auto l = sqrt(l_sq); | |
auto d_l_sq = 0.5f * d_l / l; | |
return d_length_squared(v0, T(d_l_sq)); | |
} | |
template <typename T> | |
DEVICE | |
inline T length_squared(const TVector3<T> &v0) { | |
return square(v0[0]) + square(v0[1]) + square(v0[2]); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector3<T> d_length_squared(const TVector3<T> &v0, const T &d_l_sq) { | |
//l_sq = square(v0[0]) + square(v0[1]) + square(v0[2]) | |
return 2 * d_l_sq * v0; | |
} | |
template <typename T> | |
DEVICE | |
inline T length(const TVector3<T> &v0) { | |
return sqrt(length_squared(v0)); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector3<T> d_length(const TVector3<T> &v0, const T &d_l) { | |
auto l_sq = length_squared(v0); | |
auto l = sqrt(l_sq); | |
auto d_l_sq = 0.5f * d_l / l; | |
return d_length_squared(v0, d_l_sq); | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto distance_squared(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> decltype(length_squared(v1 - v0)) { | |
return length_squared(v1 - v0); | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto distance_squared(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> decltype(length_squared(v1 - v0)) { | |
return length_squared(v1 - v0); | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto distance(const TVector2<T0> &v0, | |
const TVector2<T1> &v1) -> decltype(length(v1 - v0)) { | |
return length(v1 - v0); | |
} | |
template <typename T> | |
DEVICE | |
inline void d_distance(const TVector2<T> &v0, | |
const TVector2<T> &v1, | |
const T &d_output, | |
TVector2<T> &d_v0, | |
TVector2<T> &d_v1) { | |
auto d_v1_v0 = d_length(v1 - v0, d_output); | |
d_v0 -= d_v1_v0; | |
d_v1 += d_v1_v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto distance(const TVector3<T0> &v0, | |
const TVector3<T1> &v1) -> decltype(length(v1 - v0)) { | |
return length(v1 - v0); | |
} | |
template <typename T> | |
DEVICE | |
inline void d_distance(const TVector3<T> &v0, | |
const TVector3<T> &v1, | |
const T &d_output, | |
TVector3<T> &d_v0, | |
TVector3<T> &d_v1) { | |
auto d_v1_v0 = d_length(v1 - v0, d_output); | |
d_v0 -= d_v1_v0; | |
d_v1 += d_v1_v0; | |
} | |
template <typename T> | |
DEVICE | |
inline TVector2<T> normalize(const TVector2<T> &v0) { | |
return v0 / length(v0); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector2<T> d_normalize(const TVector2<T> &v0, const TVector2<T> &d_n) { | |
auto l = length(v0); | |
auto n = v0 / l; | |
auto d_v0 = d_n / l; | |
auto d_l = -dot(d_n, n) / l; | |
// l = length(v0) | |
d_v0 += d_length(v0, d_l); | |
return d_v0; | |
} | |
template <typename T> | |
DEVICE | |
inline TVector3<T> normalize(const TVector3<T> &v0) { | |
return v0 / length(v0); | |
} | |
template <typename T> | |
DEVICE | |
inline TVector3<T> d_normalize(const TVector3<T> &v0, const TVector3<T> &d_n) { | |
auto l = length(v0); | |
auto n = v0 / l; | |
auto d_v0 = d_n / l; | |
auto d_l = -dot(d_n, n) / l; | |
// l = length(v0) | |
d_v0 += d_length(v0, d_l); | |
return d_v0; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto dot(const TVector2<T0> &v0, const TVector2<T1> &v1) -> decltype(v0[0] * v1[0]) { | |
return v0[0] * v1[0] + | |
v0[1] * v1[1]; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto dot(const TVector3<T0> &v0, const TVector3<T1> &v1) -> decltype(v0[0] * v1[0]) { | |
return v0[0] * v1[0] + | |
v0[1] * v1[1] + | |
v0[2] * v1[2]; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto dot(const TVector4<T0> &v0, const TVector4<T1> &v1) -> decltype(v0[0] * v1[0]) { | |
return v0[0] * v1[0] + | |
v0[1] * v1[1] + | |
v0[2] * v1[2] + | |
v0[3] * v1[3]; | |
} | |
template <typename T0, typename T1> | |
DEVICE | |
inline auto cross(const TVector3<T0> &v0, const TVector3<T1> &v1) -> TVector3<decltype(v0[1] * v1[2] - v0[2] * v1[1])> { | |
return TVector3<decltype(v0[1] * v1[2] - v0[2] * v1[1])>{ | |
v0[1] * v1[2] - v0[2] * v1[1], | |
v0[2] * v1[0] - v0[0] * v1[2], | |
v0[0] * v1[1] - v0[1] * v1[0]}; | |
} | |
template <typename T> | |
DEVICE | |
inline void d_cross(const TVector3<T> &v0, const TVector3<T> &v1, const TVector3<T> &d_output, | |
TVector3<T> &d_v0, TVector3<T> &d_v1) { | |
d_v0 += cross(v1, d_output); | |
d_v1 += cross(d_output, v0); | |
} | |
template <typename T> | |
DEVICE | |
inline T luminance(const TVector3<T> &v) { | |
return 0.212671f * v[0] + | |
0.715160f * v[1] + | |
0.072169f * v[2]; | |
} | |
template <typename T> | |
DEVICE | |
inline T sum(const T &v) { | |
return v; | |
} | |
template <typename T> | |
DEVICE | |
inline T sum(const TVector2<T> &v) { | |
return v[0] + v[1]; | |
} | |
template <typename T> | |
DEVICE | |
inline T sum(const TVector3<T> &v) { | |
return v[0] + v[1] + v[2]; | |
} | |
template <typename T> | |
DEVICE | |
inline T sum(const TVector4<T> &v) { | |
return v[0] + v[1] + v[2] + v[3]; | |
} | |
template <typename T> | |
DEVICE | |
void coordinate_system(const TVector3<T> &n, TVector3<T> &x, TVector3<T> &y) { | |
if (n[2] < -1.f + 1e-6f) { | |
x = TVector3<T>{T(0), T(-1), T(0)}; | |
y = TVector3<T>{T(-1), T(0), T(0)}; | |
} else { | |
auto a = 1.f / (1.f + n[2]); | |
auto b = -n[0] * n[1] * a; | |
x = TVector3<T>{1.f - square(n[0]) * a, b, -n[0]}; | |
y = TVector3<T>{b, 1.f - square(n[1]) * a, -n[1]}; | |
} | |
} | |
template <typename T> | |
DEVICE | |
void d_coordinate_system(const TVector3<T> &n, const TVector3<T> &d_x, const TVector3<T> &d_y, | |
TVector3<T> &d_n) { | |
if (n[2] < -1.f + 1e-6f) { | |
//x = TVector3<T>{T(0), T(-1), T(0)}; | |
//y = TVector3<T>{T(-1), T(0), T(0)}; | |
// don't need to do anything | |
} else { | |
auto a = 1.f / (1.f + n[2]); | |
// auto b = -n[0] * n[1] * a; | |
// x = TVector3<T>{1.f - square(n[0]) * a, b, -n[0]} | |
d_n[0] -= 2.f * n[0] * d_x[0] * a; | |
auto d_a = -square(n[0]) * d_x[0]; | |
auto d_b = d_x[1]; | |
d_n[0] -= d_x[2]; | |
// y = TVector3<T>{b, 1.f - square(n[1]) * a, -n[1]} | |
d_b += d_y[0]; | |
d_n[1] -= 2.f * d_y[1] * n[1] * a; | |
d_a -= d_y[1] * square(n[1]); | |
d_n[1] -= d_y[2]; | |
// b = -n[0] * n[1] * a | |
d_n[0] -= d_b * n[1] * a; | |
d_n[1] -= d_b * n[0] * a; | |
d_a -= d_b * n[0] * n[1]; | |
// a = 1 / (1 + n[2]) | |
d_n[2] -= d_a * a / (1 + n[2]); | |
} | |
} | |
DEVICE | |
inline bool isfinite(const Vector2 &v) { | |
return isfinite(v.x) && | |
isfinite(v.y); | |
} | |
DEVICE | |
inline bool isfinite(const Vector3 &v) { | |
return isfinite(v.x) && | |
isfinite(v.y) && | |
isfinite(v.z); | |
} | |
DEVICE | |
inline bool isfinite(const Vector4 &v) { | |
return isfinite(v.x) && | |
isfinite(v.y) && | |
isfinite(v.z) && | |
isfinite(v.w); | |
} | |
DEVICE | |
inline bool is_zero(const Vector3 &v) { | |
return v.x == 0 && v.y == 0 && v.z == 0; | |
} | |
template <typename T> | |
inline std::ostream& operator<<(std::ostream &os, const TVector2<T> &v) { | |
return os << "(" << v[0] << ", " << v[1] << ")"; | |
} | |
template <typename T> | |
inline std::ostream& operator<<(std::ostream &os, const TVector3<T> &v) { | |
return os << "(" << v[0] << ", " << v[1] << ", " << v[2] << ")"; | |
} | |
template <typename T> | |
inline std::ostream& operator<<(std::ostream &os, const TVector4<T> &v) { | |
return os << "(" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << ")"; | |
} | |
DEVICE | |
inline | |
float det(const Vector2f &a, const Vector2f &b) { | |
return a.x*b.y-b.x*a.y; | |
} | |
DEVICE | |
inline | |
Vector2f quadratic_closest_pt_approx(const Vector2f &b0, | |
const Vector2f &b1, | |
const Vector2f &b2, | |
float *t_ = nullptr) { | |
// From http://w3.impa.br/~diego/publications/NehHop08.pdf | |
float a=det(b0,b2), b=2*det(b1,b0), d=2*det(b2,b1); | |
float f=b*d-a*a; | |
Vector2f d21=b2-b1, d10=b1-b0, d20=b2-b0; | |
Vector2f gf=2*(b*d21+d*d10+a*d20); | |
gf=Vector2f(gf.y,-gf.x); | |
Vector2f pp=-f*gf/dot(gf,gf); | |
Vector2f d0p=b0-pp; | |
float ap=det(d0p,d20), bp=2*det(d10,d0p); | |
float t=clamp((ap+bp)/(2*a+b+d),0.f,1.f); | |
float tt = 1 - t; | |
if (t_ != nullptr) { | |
*t_ = t; | |
} | |
return (tt*tt)*b0 + (2*tt*t)*b1 + (t*t)*b2; | |
} | |
DEVICE | |
inline | |
Vector2f quadratic_closest_pt_approx(const Vector2f &b0, | |
const Vector2f &b1, | |
const Vector2f &b2, | |
const Vector2f &pt, | |
float *t = nullptr) { | |
// Approximate closest point to a quadratic curve | |
return quadratic_closest_pt_approx(b0 - pt, b1 - pt, b2 - pt, t) + pt; | |
} | |