MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Lattice.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Bounds.hpp"
4
5namespace MayaFlux::Kinesis {
6
7/**
8 * @struct Lattice3D
9 * @brief A regular subdivision of an AABB3D into a cell count per axis.
10 *
11 * Pairs the continuous extent AABB3D describes with the discrete
12 * resolution a sampled field, a simulation grid, or an extraction pass
13 * imposes on it. Everything else is derived: cell size, cell centre,
14 * corner position, linear index.
15 *
16 * Indexing is x-major, y next, z outermost, matching the layout
17 * volume_common.glsl assumes and the order VolumeGridBuffer allocates in.
18 * A different traversal order is a different type, not a flag on this one.
19 *
20 * Cell-centred and corner-sampled are both expressed here rather than
21 * chosen at construction: marching cubes reads corners of the same
22 * lattice whose centres a simulation writes, and forcing that choice into
23 * the type would require two lattices where one describes the geometry.
24 */
25struct Lattice3D {
26 glm::uvec3 resolution { 1U }; ///< Cell count per axis. Zero on any axis is invalid.
27 AABB3D bounds { .min = glm::vec3(-1.0F), .max = glm::vec3(1.0F) }; ///< Continuous extent subdivided.
28
29 /** @brief Edge length of one cell along each axis. */
30 [[nodiscard]] glm::vec3 cell_size() const noexcept
31 {
32 return bounds.extent() / glm::vec3(resolution);
33 }
34
35 /** @brief Total cell count. */
36 [[nodiscard]] size_t cell_count() const noexcept
37 {
38 return static_cast<size_t>(resolution.x) * resolution.y * resolution.z;
39 }
40
41 /** @brief Corner count, one greater than the cell count on each axis. */
42 [[nodiscard]] size_t corner_count() const noexcept
43 {
44 return static_cast<size_t>(resolution.x + 1U)
45 * (resolution.y + 1U) * (resolution.z + 1U);
46 }
47
48 /**
49 * @brief Linear index of a cell, x-major.
50 * @param c Cell coordinate. Not bounds-checked.
51 */
52 [[nodiscard]] size_t index(const glm::uvec3& c) const noexcept
53 {
54 return (static_cast<size_t>(c.z) * resolution.y + c.y) * resolution.x + c.x;
55 }
56
57 /**
58 * @brief Whether a cell coordinate lies inside the lattice.
59 * @param c Cell coordinate.
60 */
61 [[nodiscard]] bool in_bounds(const glm::uvec3& c) const noexcept
62 {
63 return c.x < resolution.x && c.y < resolution.y && c.z < resolution.z;
64 }
65
66 /**
67 * @brief World position of a cell's centre.
68 * @param c Cell coordinate.
69 */
70 [[nodiscard]] glm::vec3 cell_center(const glm::uvec3& c) const noexcept
71 {
72 return bounds.min + (glm::vec3(c) + 0.5F) * cell_size();
73 }
74
75 /**
76 * @brief World position of a lattice corner.
77 * @param c Corner coordinate, valid up to resolution inclusive.
78 */
79 [[nodiscard]] glm::vec3 corner_position(const glm::uvec3& c) const noexcept
80 {
81 return bounds.min + glm::vec3(c) * cell_size();
82 }
83
84 /**
85 * @brief Cell containing a world position, clamped to the lattice.
86 * @param p World position. Points outside bounds clamp to the edge cell.
87 */
88 [[nodiscard]] glm::uvec3 cell_at(const glm::vec3& p) const noexcept
89 {
90 const glm::vec3 local = (p - bounds.min) / cell_size();
91 const glm::vec3 clamped = glm::clamp(
92 glm::floor(local), glm::vec3(0.0F), glm::vec3(resolution) - 1.0F);
93 return glm::uvec3(clamped);
94 }
95
96 /**
97 * @brief A lattice over the same bounds at a different resolution.
98 * @param res New cell count per axis.
99 *
100 * Extraction resolution independent of simulation resolution is this
101 * call.
102 */
103 [[nodiscard]] Lattice3D resampled(const glm::uvec3& res) const noexcept
104 {
105 return { .resolution = res, .bounds = bounds };
106 }
107};
108
109/**
110 * @struct Lattice2D
111 * @brief A regular subdivision of an AABB2D into a cell count per axis.
112 *
113 * 2D sibling of Lattice3D. Pairs the continuous extent AABB2D describes
114 * with a discrete resolution: quadrant subdivision is resolution {2, 2},
115 * an NDC-space grid for hit testing or occupancy is any other
116 * resolution. Everything else is derived: cell size, cell centre,
117 * corner position, linear index.
118 *
119 * Indexing is x-major, y outermost, matching Lattice3D's convention
120 * with the z axis simply absent rather than fixed at 1: a 2D lattice is
121 * a distinct type from a 3D lattice with unit depth, not a special case
122 * of it, since callers working purely in 2D should never need to reason
123 * about a z coordinate that does not exist for their problem.
124 */
125struct Lattice2D {
126 glm::uvec2 resolution { 1U }; ///< Cell count per axis. Zero on either axis is invalid.
127 AABB2D bounds { .min = glm::vec2(-1.0F), .max = glm::vec2(1.0F) }; ///< Continuous extent subdivided.
128
129 /** @brief Edge length of one cell along each axis. */
130 [[nodiscard]] glm::vec2 cell_size() const noexcept
131 {
132 return glm::vec2(bounds.width(), bounds.height()) / glm::vec2(resolution);
133 }
134
135 /** @brief Total cell count. */
136 [[nodiscard]] size_t cell_count() const noexcept
137 {
138 return static_cast<size_t>(resolution.x) * resolution.y;
139 }
140
141 /** @brief Corner count, one greater than the cell count on each axis. */
142 [[nodiscard]] size_t corner_count() const noexcept
143 {
144 return static_cast<size_t>(resolution.x + 1U) * (resolution.y + 1U);
145 }
146
147 /**
148 * @brief Linear index of a cell, x-major.
149 * @param c Cell coordinate. Not bounds-checked.
150 */
151 [[nodiscard]] size_t index(const glm::uvec2& c) const noexcept
152 {
153 return static_cast<size_t>(c.y) * resolution.x + c.x;
154 }
155
156 /**
157 * @brief Whether a cell coordinate lies inside the lattice.
158 * @param c Cell coordinate.
159 */
160 [[nodiscard]] bool in_bounds(const glm::uvec2& c) const noexcept
161 {
162 return c.x < resolution.x && c.y < resolution.y;
163 }
164
165 /**
166 * @brief Position of a cell's centre.
167 * @param c Cell coordinate.
168 */
169 [[nodiscard]] glm::vec2 cell_center(const glm::uvec2& c) const noexcept
170 {
171 return bounds.min + (glm::vec2(c) + 0.5F) * cell_size();
172 }
173
174 /**
175 * @brief Position of a lattice corner.
176 * @param c Corner coordinate, valid up to resolution inclusive.
177 */
178 [[nodiscard]] glm::vec2 corner_position(const glm::uvec2& c) const noexcept
179 {
180 return bounds.min + glm::vec2(c) * cell_size();
181 }
182
183 /**
184 * @brief Cell containing a position, clamped to the lattice.
185 * @param p Position. Points outside bounds clamp to the edge cell.
186 */
187 [[nodiscard]] glm::uvec2 cell_at(const glm::vec2& p) const noexcept
188 {
189 const glm::vec2 local = (p - bounds.min) / cell_size();
190 const glm::vec2 clamped = glm::clamp(
191 glm::floor(local), glm::vec2(0.0F), glm::vec2(resolution) - 1.0F);
192 return glm::uvec2(clamped);
193 }
194
195 /**
196 * @brief A lattice over the same bounds at a different resolution.
197 * @param res New cell count per axis.
198 */
199 [[nodiscard]] Lattice2D resampled(const glm::uvec2& res) const noexcept
200 {
201 return { .resolution = res, .bounds = bounds };
202 }
203
204 /**
205 * @brief Quadrant lattice over NDC space, resolution {2, 2}.
206 *
207 * The specific case that motivated this type: NDC space split into
208 * four quadrants by sign of x and y. cell_at({0.3, -0.6}) returns
209 * {1, 0} (positive x, negative y quadrant).
210 */
211 [[nodiscard]] static Lattice2D ndc_quadrants() noexcept
212 {
213 return { .resolution = { 2U, 2U }, .bounds = { .min = glm::vec2(-1.0F), .max = glm::vec2(1.0F) } };
214 }
215};
216
217/**
218 * @struct Lattice1D
219 * @brief A regular subdivision of an AABB1D into a number of cells.
220 *
221 * One dimensional sibling of Lattice2D and Lattice3D, in double precision.
222 * Turns a scalar into a symbol: cell_at maps a value to the cell that holds
223 * it, so a SymbolicTrajectory<Lattice1D, uint32_t> observes a scalar stream
224 * the way the 2D and 3D forms observe a moving point. Indexing is the cell
225 * coordinate itself.
226 */
227struct Lattice1D {
228 uint32_t resolution { 1U }; ///< Cell count. Zero is invalid.
229 AABB1D bounds { .min = -1.0, .max = 1.0 }; ///< Continuous extent subdivided.
230
231 /** @brief Width of one cell. */
232 [[nodiscard]] double cell_size() const noexcept
233 {
234 return bounds.width() / static_cast<double>(resolution);
235 }
236
237 /** @brief Total cell count. */
238 [[nodiscard]] size_t cell_count() const noexcept
239 {
240 return resolution;
241 }
242
243 /** @brief Corner count, one greater than the cell count. */
244 [[nodiscard]] size_t corner_count() const noexcept
245 {
246 return static_cast<size_t>(resolution) + 1U;
247 }
248
249 /**
250 * @brief Linear index of a cell, which is its coordinate.
251 * @param c Cell coordinate. Not bounds-checked.
252 */
253 [[nodiscard]] size_t index(uint32_t c) const noexcept
254 {
255 return c;
256 }
257
258 /**
259 * @brief Whether a cell coordinate lies inside the lattice.
260 * @param c Cell coordinate.
261 */
262 [[nodiscard]] bool in_bounds(uint32_t c) const noexcept
263 {
264 return c < resolution;
265 }
266
267 /**
268 * @brief Position of a cell's centre.
269 * @param c Cell coordinate.
270 */
271 [[nodiscard]] double cell_center(uint32_t c) const noexcept
272 {
273 return bounds.min + (static_cast<double>(c) + 0.5) * cell_size();
274 }
275
276 /**
277 * @brief Position of a lattice corner.
278 * @param c Corner coordinate, valid up to resolution inclusive.
279 */
280 [[nodiscard]] double corner_position(uint32_t c) const noexcept
281 {
282 return bounds.min + static_cast<double>(c) * cell_size();
283 }
284
285 /**
286 * @brief Cell containing a value, clamped to the lattice.
287 * @param p Value. Values outside bounds clamp to the edge cell.
288 */
289 [[nodiscard]] uint32_t cell_at(double p) const noexcept
290 {
291 const double local = (p - bounds.min) / cell_size();
292 const double clamped = std::clamp(
293 std::floor(local), 0.0, static_cast<double>(resolution) - 1.0);
294 return static_cast<uint32_t>(clamped);
295 }
296
297 /**
298 * @brief A lattice over the same bounds at a different resolution.
299 * @param res New cell count.
300 */
301 [[nodiscard]] Lattice1D resampled(uint32_t res) const noexcept
302 {
303 return { .resolution = res, .bounds = bounds };
304 }
305};
306
307} // namespace MayaFlux::Kinesis
double width() const noexcept
Definition Bounds.hpp:34
Closed interval on a scalar axis.
Definition Bounds.hpp:20
float height() const noexcept
Definition Bounds.hpp:80
float width() const noexcept
Definition Bounds.hpp:79
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:63
glm::vec3 extent() const noexcept
Definition Bounds.hpp:207
Axis-aligned bounding box in 3D world space.
Definition Bounds.hpp:188
double corner_position(uint32_t c) const noexcept
Position of a lattice corner.
Definition Lattice.hpp:280
double cell_size() const noexcept
Width of one cell.
Definition Lattice.hpp:232
AABB1D bounds
Continuous extent subdivided.
Definition Lattice.hpp:229
size_t index(uint32_t c) const noexcept
Linear index of a cell, which is its coordinate.
Definition Lattice.hpp:253
bool in_bounds(uint32_t c) const noexcept
Whether a cell coordinate lies inside the lattice.
Definition Lattice.hpp:262
uint32_t resolution
Cell count. Zero is invalid.
Definition Lattice.hpp:228
Lattice1D resampled(uint32_t res) const noexcept
A lattice over the same bounds at a different resolution.
Definition Lattice.hpp:301
uint32_t cell_at(double p) const noexcept
Cell containing a value, clamped to the lattice.
Definition Lattice.hpp:289
double cell_center(uint32_t c) const noexcept
Position of a cell's centre.
Definition Lattice.hpp:271
size_t cell_count() const noexcept
Total cell count.
Definition Lattice.hpp:238
size_t corner_count() const noexcept
Corner count, one greater than the cell count.
Definition Lattice.hpp:244
A regular subdivision of an AABB1D into a number of cells.
Definition Lattice.hpp:227
glm::uvec2 cell_at(const glm::vec2 &p) const noexcept
Cell containing a position, clamped to the lattice.
Definition Lattice.hpp:187
size_t cell_count() const noexcept
Total cell count.
Definition Lattice.hpp:136
size_t corner_count() const noexcept
Corner count, one greater than the cell count on each axis.
Definition Lattice.hpp:142
Lattice2D resampled(const glm::uvec2 &res) const noexcept
A lattice over the same bounds at a different resolution.
Definition Lattice.hpp:199
AABB2D bounds
Continuous extent subdivided.
Definition Lattice.hpp:127
glm::uvec2 resolution
Cell count per axis. Zero on either axis is invalid.
Definition Lattice.hpp:126
glm::vec2 cell_center(const glm::uvec2 &c) const noexcept
Position of a cell's centre.
Definition Lattice.hpp:169
bool in_bounds(const glm::uvec2 &c) const noexcept
Whether a cell coordinate lies inside the lattice.
Definition Lattice.hpp:160
size_t index(const glm::uvec2 &c) const noexcept
Linear index of a cell, x-major.
Definition Lattice.hpp:151
static Lattice2D ndc_quadrants() noexcept
Quadrant lattice over NDC space, resolution {2, 2}.
Definition Lattice.hpp:211
glm::vec2 cell_size() const noexcept
Edge length of one cell along each axis.
Definition Lattice.hpp:130
glm::vec2 corner_position(const glm::uvec2 &c) const noexcept
Position of a lattice corner.
Definition Lattice.hpp:178
A regular subdivision of an AABB2D into a cell count per axis.
Definition Lattice.hpp:125
size_t index(const glm::uvec3 &c) const noexcept
Linear index of a cell, x-major.
Definition Lattice.hpp:52
glm::vec3 cell_size() const noexcept
Edge length of one cell along each axis.
Definition Lattice.hpp:30
Lattice3D resampled(const glm::uvec3 &res) const noexcept
A lattice over the same bounds at a different resolution.
Definition Lattice.hpp:103
AABB3D bounds
Continuous extent subdivided.
Definition Lattice.hpp:27
size_t cell_count() const noexcept
Total cell count.
Definition Lattice.hpp:36
glm::uvec3 resolution
Cell count per axis. Zero on any axis is invalid.
Definition Lattice.hpp:26
bool in_bounds(const glm::uvec3 &c) const noexcept
Whether a cell coordinate lies inside the lattice.
Definition Lattice.hpp:61
glm::vec3 corner_position(const glm::uvec3 &c) const noexcept
World position of a lattice corner.
Definition Lattice.hpp:79
glm::vec3 cell_center(const glm::uvec3 &c) const noexcept
World position of a cell's centre.
Definition Lattice.hpp:70
size_t corner_count() const noexcept
Corner count, one greater than the cell count on each axis.
Definition Lattice.hpp:42
glm::uvec3 cell_at(const glm::vec3 &p) const noexcept
Cell containing a world position, clamped to the lattice.
Definition Lattice.hpp:88
A regular subdivision of an AABB3D into a cell count per axis.
Definition Lattice.hpp:25