cgv
Loading...
Searching...
No Matches
distance.h
1#pragma once
2
3#include "fvec.h"
4
6namespace cgv {
7namespace math {
8
16template <typename T>
17T point_box_distance(const fvec<T, 3>& point, fvec<T, 3> extent) {
18
19 fvec<T, 3> q = abs(point) - T(0.5) * extent;
20 return length(max(q, T(0))) + std::min(std::max(q.x(), std::max(q.y(), q.z())), T(0));
21}
22
31template <typename T>
32T point_plane_distance(const fvec<T, 3>& point, const fvec<T, 3>& origin, const fvec<T, 3>& normal) {
33
34 return dot(point - origin, normal);
35};
36
46template <typename T, cgv::type::uint32_type N>
47T point_sphere_distance(const fvec<T, N>& point, const fvec<T, N>& center, T radius) {
48
49 return length(center - point) - radius;
50}
51
60template<typename T>
61static std::pair<T, T> point_quadratic_bezier_distance(const fvec<T, 3>& point, const fvec<T, 3>& p0, const fvec<T, 3>& p1, const fvec<T, 3>& p2) {
62 // (Copyright 2013 Inigo Quilez: https://iquilezles.org/articles/bezierbbox/ and https://www.shadertoy.com/view/ldj3Wh)
63 using vec_type = fvec<T, 3>;
64 vec_type a = p1 - p0;
65 vec_type b = p0 - T(2) * p1 + p2;
66 vec_type c = a * T(2);
67 vec_type d = p0 - point;
68
69 T kk = T(1) / dot(b, b);
70 T kx = kk * dot(a, b);
71 T ky = kk * (T(2) * dot(a, a) + dot(d, b)) / T(3);
72 T kz = kk * dot(d, a);
73
74 T dist = T(0);
75 T t = T(0);
76
77 T p = ky - kx * kx;
78 T p3 = p * p * p;
79 T q = kx * (T(2) * kx * kx - T(3) * ky) + kz;
80 T h = q * q + T(4) * p3;
81
82 if(h >= T(0)) {
83 h = std::sqrt(h);
84 fvec<T, 2> x = (vec2(h, -h) - q) / T(2);
85 fvec<T, 2> uv = sign(x) * pow(abs(x), vec2(T(1) / T(3)));
86 t = clamp(uv.x() + uv.y() - kx, T(0), T(1));
87
88 // 1 root
89 dist = sqr_length(d + (c + b * t) * t);
90 } else {
91 T z = std::sqrt(-p);
92 T v = std::acos(q / (p * z * T(2))) / T(3);
93 T m = std::cos(v);
94 T n = std::sin(v) * T(1.732050808);
95 vec_type ts = clamp(vec_type(m + m, -n - m, n - m) * z - kx, T(0), T(1));
96
97 // 3 roots, but only need two
98 T dt = sqr_length(d + (c + b * ts.x()) * ts.x());
99 dist = dt;
100 t = ts.x();
101
102 dt = sqr_length(d + (c + b * ts.y()) * ts.y());
103 if(dt < dist) {
104 dist = dt;
105 t = ts.y();
106 }
107 }
108
109 dist = sqrt(dist);
110
111 return { dist, t };
112}
113
114} // namespace math
115} // namespace cgv
the cgv namespace
Definition print.h:11
cgv::math::fvec< float, 2 > vec2
declare type of 2d single precision floating point vectors
Definition fvec.h:668