Toast Engine
Loading...
Searching...
No Matches
voxel_edit.hpp
Go to the documentation of this file.
1
7
8#pragma once
9#include "stamp.hpp"
10#include "voxel_volume.hpp"
11
12#include <array>
13#include <cstdint>
14#include <glm/glm.hpp>
15#include <optional>
16#include <span>
17#include <toast/export.hpp>
18#include <vector>
19
20namespace voxel {
21
32
33[[nodiscard]]
34constexpr auto canWrite(uint8_t current, WriteMode mode, uint8_t match_id) noexcept -> bool {
35 switch (mode) {
36 case WriteMode::replace: return true;
37 case WriteMode::empty_only: return current == k_empty_palette_index;
38 case WriteMode::solid_only: return current != k_empty_palette_index;
39 case WriteMode::match: return current == match_id;
40 }
41 return false;
42}
43
44[[nodiscard]]
45constexpr auto canAdd(uint8_t id, WriteMode mode, uint8_t match_id) noexcept -> bool {
46 return id != k_empty_palette_index && canWrite(k_empty_palette_index, mode, match_id);
47}
48
49struct EditBounds {
50 glm::ivec3 min {0};
51 glm::ivec3 max {-1};
52
53 [[nodiscard]]
54 auto empty() const noexcept -> bool {
55 return glm::any(glm::lessThan(max, min));
56 }
57};
58
59struct EditResult {
60 uint32_t changed = 0;
61
62 bool pool_exhausted = false;
63
64 auto operator+=(const EditResult& other) noexcept -> EditResult& {
65 changed += other.changed;
66 pool_exhausted = pool_exhausted || other.pool_exhausted;
67 return *this;
68 }
69};
70
71struct WriteBrush {
72 uint8_t id = k_empty_palette_index;
74 uint8_t match_id = k_empty_palette_index;
75};
76
77struct Region {
78 glm::ivec3 size {0};
79 std::vector<uint8_t> ids;
80};
81
82// Bounds calculation
83// I'm using this to know when to grow the volume
84
85[[nodiscard]]
86TOAST_API auto boxBounds(glm::ivec3 a, glm::ivec3 b) noexcept -> EditBounds;
87
88[[nodiscard]]
89TOAST_API auto sphereBounds(glm::vec3 center, float radius) noexcept -> EditBounds;
90
91[[nodiscard]]
92TOAST_API auto segmentBounds(glm::vec3 a, glm::vec3 b, float radius) noexcept -> EditBounds;
93
94[[nodiscard]]
95TOAST_API auto placedBounds(glm::uvec3 piece_brick_dims, const LatticePlacement& placement) noexcept -> EditBounds;
96
97[[nodiscard]]
98TOAST_API auto boundsUnion(const EditBounds& a, const EditBounds& b) noexcept -> EditBounds;
99
100[[nodiscard]]
101TOAST_API auto occupiedBounds(const Volume& volume) -> std::optional<EditBounds>;
102
103// Primitives
104
105TOAST_API auto fillBox(Volume& volume, glm::ivec3 a, glm::ivec3 b, const WriteBrush& brush) -> EditResult;
106TOAST_API auto fillSphere(Volume& volume, glm::vec3 center, float radius, const WriteBrush& brush) -> EditResult;
107TOAST_API auto fillCylinder(Volume& volume, glm::vec3 a, glm::vec3 b, float radius, const WriteBrush& brush) -> EditResult;
108TOAST_API auto fillCapsule(Volume& volume, glm::vec3 a, glm::vec3 b, float radius, const WriteBrush& brush) -> EditResult;
109
110// Basic operations
111
117TOAST_API auto replaceId(Volume& volume, uint8_t from, uint8_t to) -> EditResult;
118
125TOAST_API auto slice(Volume& volume, glm::vec3 point, glm::vec3 normal, int side) -> EditResult;
126
130[[nodiscard]]
131TOAST_API auto collectFace(const Volume& volume, glm::ivec3 start, glm::ivec3 normal, size_t limit = size_t {1} << 20)
132 -> std::vector<glm::ivec3>;
133
137TOAST_API auto extrudeFace(Volume& volume, std::span<const glm::ivec3> face, glm::ivec3 normal, int distance) -> EditResult;
138
139[[nodiscard]]
140TOAST_API auto copyRegion(const Volume& volume, glm::ivec3 a, glm::ivec3 b) -> Region;
141
142TOAST_API auto pasteRegion(Volume& volume, const Region& region, glm::ivec3 at, WriteMode mode, uint8_t match_id) -> EditResult;
143
144TOAST_API auto stampVolume(
145 Volume& target, const Volume& piece, const LatticePlacement& placement, const PaletteRemapTable& remap, WriteMode mode,
146 uint8_t match_id
147) -> EditResult;
148
153TOAST_API auto carveVolume(Volume& target, const Volume& piece, const LatticePlacement& placement) -> EditResult;
154
155// Shapes that fit a box instead of a radius
156
158TOAST_API auto fillRoundBox(Volume& volume, glm::ivec3 a, glm::ivec3 b, float radius, const WriteBrush& brush) -> EditResult;
159
161TOAST_API auto fillEllipsoid(Volume& volume, glm::ivec3 a, glm::ivec3 b, const WriteBrush& brush) -> EditResult;
162
163// Clip planes
164//
165// A plane is a vec4 with the normal in xyz and the offset in w, in voxels
166// A voxel is kept when dot(normal, centre) + w >= 0
167
169TOAST_API auto clipByPlanes(Volume& volume, std::span<const glm::vec4> planes) -> EditResult;
170
172[[nodiscard]]
173TOAST_API auto complementPlane(glm::vec4 plane) noexcept -> glm::vec4;
174
175// Tiling
176
177enum class TileFit : uint8_t {
178 crop,
179 stretch,
180 center,
181};
182
183enum class TileAnchor : uint8_t {
184 min,
185 center,
186 max,
187};
188
190 TileFit fit = TileFit::crop;
191 std::array<TileAnchor, 3> anchor {TileAnchor::min, TileAnchor::min, TileAnchor::min};
192 glm::ivec3 offset {0};
193 glm::bvec3 mirror {false};
194};
195
200TOAST_API auto tileVolume(
201 Volume& target, const Volume& pattern, glm::ivec3 a, glm::ivec3 b, const TileOptions& options, const PaletteRemapTable& remap,
202 WriteMode mode = WriteMode::replace, uint8_t match_id = k_empty_palette_index
203) -> EditResult;
204
206TOAST_API auto floodFill(Volume& volume, glm::ivec3 seed, uint8_t id) -> EditResult;
207
208struct VolumeHit {
209 glm::ivec3 voxel {0};
210 glm::ivec3 normal {0};
211 float t = 0.0f;
212};
213
219[[nodiscard]]
220TOAST_API auto raycast(const Volume& volume, glm::vec3 origin, glm::vec3 direction, float max_t) -> std::optional<VolumeHit>;
221
223[[nodiscard]]
224TOAST_API auto idHistogram(const Volume& volume) -> std::array<uint32_t, k_palette_size>;
225
226[[nodiscard]]
227TOAST_API auto snapOrientation(const glm::mat3& rotation) noexcept -> LatticeOrientation;
228
229[[nodiscard]]
230TOAST_API auto dominantAxis(glm::vec3 normal) noexcept -> glm::ivec3;
231
232}
Definition voxel_volume.hpp:21
Definition voxel_edit.hpp:49
Definition voxel_edit.hpp:59
Definition stamp.hpp:72
Definition voxel_edit.hpp:77
Definition voxel_edit.hpp:189
glm::ivec3 offset
Shifts the tiles by this many voxels.
Definition voxel_edit.hpp:192
glm::bvec3 mirror
Flips every other tile on that axis.
Definition voxel_edit.hpp:193
Definition voxel_edit.hpp:208
glm::ivec3 normal
The face it came through, zero when it started inside.
Definition voxel_edit.hpp:210
glm::ivec3 voxel
The solid voxel it stopped in.
Definition voxel_edit.hpp:209
Definition voxel_edit.hpp:71
WriteMode
Which voxels we should override.
Definition voxel_edit.hpp:26
@ replace
Everything.
Definition voxel_edit.hpp:27
@ empty_only
Only empty space.
Definition voxel_edit.hpp:28
@ solid_only
Only non-empty space.
Definition voxel_edit.hpp:29
@ match
Only voxels with the match id.
Definition voxel_edit.hpp:30