MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Lattice.hpp
Go to the documentation of this file.
1#pragma once
2
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} // namespace MayaFlux::Kinesis
float height() const noexcept
Definition Bounds.hpp:38
float width() const noexcept
Definition Bounds.hpp:37
Axis-aligned bounding rectangle in a 2D coordinate space.
Definition Bounds.hpp:21
glm::vec3 extent() const noexcept
Definition Bounds.hpp:162
Axis-aligned bounding box in 3D world space.
Definition Bounds.hpp:143
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