HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
quad.hpp
1
2
3#pragma once
4
5#include "vector.hpp"
6#include "point.hpp"
7#include "extent.hpp"
8#include "axis_aligned_rectangle.hpp"
9#include "rectangle.hpp"
10#include <tuple>
11
12namespace hi::inline v1 {
13
14class quad {
15public:
20
21 constexpr quad() noexcept : p0(), p1(), p2(), p3() {}
22
23 constexpr quad(point3 p0, point3 p1, point3 p2, point3 p3) noexcept : p0(p0), p1(p1), p2(p2), p3(p3) {}
24
25 constexpr quad(quad const &) noexcept = default;
26 constexpr quad(quad &&) noexcept = default;
27 constexpr quad &operator=(quad const &) noexcept = default;
28 constexpr quad &operator=(quad &&) noexcept = default;
29
30 constexpr quad(aarectangle const &rhs) noexcept
31 {
32 hilet tmp = f32x4{rhs};
33 p0 = point3{tmp.xy01()};
34 p1 = point3{tmp.zy01()};
35 p2 = point3{tmp.xw01()};
36 p3 = point3{tmp.zw01()};
37 }
38
39 constexpr quad(rectangle const &rhs) noexcept : p0(get<0>(rhs)), p1(get<1>(rhs)), p2(get<2>(rhs)), p3(get<3>(rhs)) {}
40
43 [[nodiscard]] constexpr vector3 bottom() const noexcept
44 {
45 return p1 - p0;
46 }
47
50 [[nodiscard]] constexpr vector3 top() const noexcept
51 {
52 return p3 - p2;
53 }
54
57 [[nodiscard]] constexpr vector3 left() const noexcept
58 {
59 return p2 - p0;
60 }
61
64 [[nodiscard]] constexpr vector3 right() const noexcept
65 {
66 return p3 - p1;
67 }
68
73 [[nodiscard]] constexpr f32x4 edge_hypots() const noexcept
74 {
75 hilet[x, y, z, zeros] = transpose(f32x4{bottom()}, f32x4{left()}, f32x4{top()}, f32x4{right()});
76 return sqrt(x * x + y * y + z * z);
77 }
78
79 [[nodiscard]] constexpr point3 &operator[](std::size_t index) noexcept
80 {
81 switch (index) {
82 case 0: return p0;
83 case 1: return p1;
84 case 2: return p2;
85 case 3: return p3;
86 default: hi_no_default();
87 }
88 }
89
90 [[nodiscard]] constexpr point3 const &operator[](std::size_t index) const noexcept
91 {
92 switch (index) {
93 case 0: return p0;
94 case 1: return p1;
95 case 2: return p2;
96 case 3: return p3;
97 default: hi_no_default();
98 }
99 }
100
101 template<std::size_t I>
102 [[nodiscard]] constexpr friend point3 const &get(quad const &rhs) noexcept
103 {
104 static_assert(I < 4, "Index out of range.");
105
106 if constexpr (I == 0) {
107 return rhs.p0;
108 } else if constexpr (I == 1) {
109 return rhs.p1;
110 } else if constexpr (I == 2) {
111 return rhs.p2;
112 } else {
113 return rhs.p3;
114 }
115 }
116
117 template<std::size_t I>
118 [[nodiscard]] constexpr friend point3 &get(quad &rhs) noexcept
119 {
120 static_assert(I < 4, "Index out of range.");
121
122 if constexpr (I == 0) {
123 return rhs.p0;
124 } else if constexpr (I == 1) {
125 return rhs.p1;
126 } else if constexpr (I == 2) {
127 return rhs.p2;
128 } else {
129 return rhs.p3;
130 }
131 }
132
141 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, f32x4 const &rhs) noexcept
142 {
143 hilet t = f32x4{lhs.top()};
144 hilet l = f32x4{lhs.left()};
145 hilet b = f32x4{lhs.bottom()};
146 hilet r = f32x4{lhs.right()};
147
148 hilet[x, y, z, ones] = transpose(t, l, b, r);
149 hilet square_lengths = x * x + y * y + z * z;
150 hilet inv_lengths = rcp_sqrt(square_lengths);
151 hilet norm_t = t * inv_lengths.xxxx();
152 hilet norm_l = l * inv_lengths.yyyy();
153 hilet norm_b = b * inv_lengths.zzzz();
154 hilet norm_r = r * inv_lengths.wwww();
155
156 hilet width = rhs.xxxx();
157 hilet height = rhs.yyyy();
158
159 hilet top_extra = vector3{norm_t * width};
160 hilet left_extra = vector3{norm_l * height};
161 hilet bottom_extra = vector3{norm_b * width};
162 hilet right_extra = vector3{norm_r * height};
163
164 hilet lengths = rcp(inv_lengths);
165
166 hilet rhs_times_2 = rhs + rhs;
167
168 return {
169 quad{
170 lhs.p0 - bottom_extra - left_extra,
171 lhs.p1 + bottom_extra - right_extra,
172 lhs.p2 - top_extra + left_extra,
173 lhs.p3 + top_extra + right_extra},
174 lengths + rhs_times_2.xyxy()};
175 }
176
185 [[nodiscard]] friend constexpr std::pair<quad, f32x4> expand_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
186 {
187 return expand_and_edge_hypots(lhs, f32x4{rhs});
188 }
189
198 [[nodiscard]] friend constexpr std::pair<quad, f32x4> shrink_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
199 {
200 return expand_and_edge_hypots(lhs, -f32x4{rhs});
201 }
202
211 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
212 {
213 hilet[expanded_quad, new_lengths] = expand_and_edge_hypots(lhs, rhs);
214 return expanded_quad;
215 }
216
217 [[nodiscard]] friend constexpr quad operator+(quad const &lhs, float rhs) noexcept
218 {
219 return lhs + extent2{rhs, rhs};
220 }
221
230 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
231 {
232 hilet[expanded_quad, new_lengths] = shrink_and_edge_hypots(lhs, rhs);
233 return expanded_quad;
234 }
235
236 [[nodiscard]] friend constexpr quad operator-(quad const &lhs, float rhs) noexcept
237 {
238 return lhs - extent2{rhs, rhs};
239 }
240
241 [[nodiscard]] friend constexpr aarectangle bounding_rectangle(quad const &rhs) noexcept
242 {
243 auto min_p = rhs.p0;
244 auto max_p = rhs.p0;
245
246 min_p = min(min_p, rhs.p1);
247 max_p = max(max_p, rhs.p1);
248 min_p = min(min_p, rhs.p2);
249 max_p = max(max_p, rhs.p2);
250 min_p = min(min_p, rhs.p3);
251 max_p = max(max_p, rhs.p3);
252 return aarectangle{point2{min_p}, point2{max_p}};
253 }
254
255 constexpr quad &operator+=(extent2 const &rhs) noexcept
256 {
257 return *this = *this + rhs;
258 }
259
260 [[nodiscard]] friend constexpr bool operator==(quad const &lhs, quad const &rhs) noexcept = default;
261};
262
263} // namespace hi::inline v1
#define hilet
Invariant should be the default for variables.
Definition required.hpp:23
@ bottom
Align to the bottom.
@ top
Align to the top.
Definition quad.hpp:14
friend constexpr std::pair< quad, f32x4 > expand_and_edge_hypots(quad const &lhs, f32x4 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:141
point3 p3
Right-top.
Definition quad.hpp:19
constexpr vector3 right() const noexcept
The vector from right-bottom to right-top.
Definition quad.hpp:64
friend constexpr std::pair< quad, f32x4 > shrink_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
Subtract a border from the quad.
Definition quad.hpp:198
point3 p1
Right-bottom.
Definition quad.hpp:17
friend constexpr quad operator+(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:211
constexpr vector3 left() const noexcept
The vector from left-bottom to left-top.
Definition quad.hpp:57
friend constexpr quad operator-(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:230
point3 p0
Left-bottom.
Definition quad.hpp:16
constexpr vector3 bottom() const noexcept
The vector from left-bottom to right-bottom.
Definition quad.hpp:43
constexpr vector3 top() const noexcept
The vector from left-top to right-top.
Definition quad.hpp:50
point3 p2
Left-top.
Definition quad.hpp:18
constexpr f32x4 edge_hypots() const noexcept
Return the length of each edge.
Definition quad.hpp:73
friend constexpr std::pair< quad, f32x4 > expand_and_edge_hypots(quad const &lhs, extent2 const &rhs) noexcept
Add a border around the quad.
Definition quad.hpp:185
T max(T... args)
T min(T... args)