Blender V4.3
BLI_mesh_intersect.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
14#ifdef WITH_GMP
15
16# include <iosfwd>
17
18# include "BLI_array.hh"
19# include "BLI_function_ref.hh"
20# include "BLI_index_range.hh"
21# include "BLI_map.hh"
22# include "BLI_math_mpq.hh"
25# include "BLI_span.hh"
26# include "BLI_utility_mixins.hh"
27# include "BLI_vector.hh"
28
29namespace blender::meshintersect {
30
31constexpr int NO_INDEX = -1;
32
48struct Vert {
49 mpq3 co_exact;
50 double3 co;
51 int id = NO_INDEX;
52 int orig = NO_INDEX;
53
54 Vert() = default;
55 Vert(const mpq3 &mco, const double3 &dco, int id, int orig);
56 ~Vert() = default;
57
59 bool operator==(const Vert &other) const;
60
62 uint64_t hash() const;
63};
64
65std::ostream &operator<<(std::ostream &os, const Vert *v);
66
74struct Plane {
75 mpq3 norm_exact;
76 mpq_class d_exact;
78 double d;
79
80 Plane() = default;
81 Plane(const mpq3 &norm_exact, const mpq_class &d_exact);
82 Plane(const double3 &norm, double d);
83
85 bool operator==(const Plane &other) const;
86
88 uint64_t hash() const;
89
90 void make_canonical();
94 bool exact_populated() const;
95 void populate_exact();
96};
97
98std::ostream &operator<<(std::ostream &os, const Plane *plane);
99
116struct Face : NonCopyable {
117 Array<const Vert *> vert;
118 Array<int> edge_orig;
119 Array<bool> is_intersect;
120 Plane *plane = nullptr;
121 int id = NO_INDEX;
122 int orig = NO_INDEX;
123
124 using FacePos = int;
125
126 Face() = default;
127 Face(Span<const Vert *> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect);
128 Face(Span<const Vert *> verts, int id, int orig);
129 ~Face();
130
131 bool is_tri() const
132 {
133 return vert.size() == 3;
134 }
135
136 /* Test equality of verts, in same positions. */
137 bool operator==(const Face &other) const;
138
139 /* Test equality faces allowing cyclic shifts. */
140 bool cyclic_equal(const Face &other) const;
141
142 FacePos next_pos(FacePos p) const
143 {
144 return (p + 1) % vert.size();
145 }
146
147 FacePos prev_pos(FacePos p) const
148 {
149 return (p + vert.size() - 1) % vert.size();
150 }
151
152 const Vert *const &operator[](int index) const
153 {
154 return vert[index];
155 }
156
157 int size() const
158 {
159 return vert.size();
160 }
161
162 const Vert *const *begin() const
163 {
164 return vert.begin();
165 }
166
167 const Vert *const *end() const
168 {
169 return vert.end();
170 }
171
172 IndexRange index_range() const
173 {
174 return IndexRange(vert.size());
175 }
176
177 void populate_plane(bool need_exact);
178
179 bool plane_populated() const
180 {
181 return plane != nullptr;
182 }
183};
184
185std::ostream &operator<<(std::ostream &os, const Face *f);
186
194class IMeshArena : NonCopyable, NonMovable {
195 class IMeshArenaImpl;
196 std::unique_ptr<IMeshArenaImpl> pimpl_;
197
198 public:
199 IMeshArena();
200 ~IMeshArena();
201
206 void reserve(int vert_num_hint, int face_num_hint);
207
208 int tot_allocated_verts() const;
209 int tot_allocated_faces() const;
210
217 const Vert *add_or_find_vert(const mpq3 &co, int orig);
218 const Vert *add_or_find_vert(const double3 &co, int orig);
219 const Vert *add_or_find_vert(Vert *vert);
220
221 Face *add_face(Span<const Vert *> verts,
222 int orig,
223 Span<int> edge_origs,
224 Span<bool> is_intersect);
225 Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs);
226 Face *add_face(Span<const Vert *> verts, int orig);
227
229 const Vert *find_vert(const mpq3 &co) const;
230 const Face *find_face(Span<const Vert *> verts) const;
231};
232
243class IMesh {
244 Array<Face *> face_; /* Not `const` so can lazily populate planes. */
245 Array<const Vert *> vert_; /* Only valid if vert_populated_. */
246 Map<const Vert *, int> vert_to_index_; /* Only valid if vert_populated_. */
247 bool vert_populated_ = false;
248
249 public:
250 IMesh() = default;
251 IMesh(Span<Face *> faces) : face_(faces) {}
252
253 void set_faces(Span<Face *> faces);
254 Face *face(int index) const
255 {
256 return face_[index];
257 }
258
259 int face_size() const
260 {
261 return face_.size();
262 }
263
264 int vert_size() const
265 {
266 return vert_.size();
267 }
268
269 bool has_verts() const
270 {
271 return vert_populated_;
272 }
273
274 void set_dirty_verts()
275 {
276 vert_populated_ = false;
277 vert_to_index_.clear();
278 vert_ = Array<const Vert *>();
279 }
280
281 /* Pass `max_verts` if there is a good bound estimate on the maximum number of verts. */
282 void populate_vert();
283 void populate_vert(int max_verts);
284
285 const Vert *vert(int index) const
286 {
287 BLI_assert(vert_populated_);
288 return vert_[index];
289 }
290
292 int lookup_vert(const Vert *v) const;
293
294 IndexRange vert_index_range() const
295 {
296 BLI_assert(vert_populated_);
297 return IndexRange(vert_.size());
298 }
299
300 IndexRange face_index_range() const
301 {
302 return IndexRange(face_.size());
303 }
304
305 Span<const Vert *> vertices() const
306 {
307 BLI_assert(vert_populated_);
308 return Span<const Vert *>(vert_);
309 }
310
311 Span<Face *> faces() const
312 {
313 return Span<Face *>(face_);
314 }
315
325 bool erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena);
326
327 void remove_null_faces();
328};
329
330std::ostream &operator<<(std::ostream &os, const IMesh &mesh);
331
336struct BoundingBox {
338 float3 max{-FLT_MAX, -FLT_MAX, -FLT_MAX};
339
340 BoundingBox() = default;
341 BoundingBox(const float3 &min, const float3 &max) : min(min), max(max) {}
342
343 void combine(const float3 &p)
344 {
345 math::min_max(p, this->min, this->max);
346 }
347
348 void combine(const double3 &p)
349 {
350 math::min_max(float3(p), this->min, this->max);
351 }
352
353 void combine(const BoundingBox &bb)
354 {
355 min = math::min(this->min, bb.min);
356 max = math::max(this->max, bb.max);
357 }
358
359 void expand(float pad)
360 {
361 min -= pad;
362 max += pad;
363 }
364};
365
371bool bbs_might_intersect(const BoundingBox &bb_a, const BoundingBox &bb_b);
372
385IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena);
386
387IMesh trimesh_nary_intersect(const IMesh &tm_in,
388 int nshapes,
389 FunctionRef<int(int)> shape_fn,
390 bool use_self,
391 IMeshArena *arena);
392
399IMesh triangulate_polymesh(IMesh &imesh, IMeshArena *arena);
400
404void write_obj_mesh(IMesh &m, const std::string &objname);
405
406} /* namespace blender::meshintersect */
407
408#endif /* WITH_GMP */
#define BLI_assert(a)
Definition BLI_assert.h:50
bool operator==(const AssetWeakReference &a, const AssetWeakReference &b)
int pad[32 - sizeof(int)]
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE btVector3 & operator[](int i)
Get a mutable reference to a row of the matrix as a vector.
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static float verts[][3]
struct BoundingBox { packed_float3 min; packed_float3 max;} BoundingBox
static char faces[256]
std::ostream & operator<<(std::ostream &stream, EulerOrder order)
T min(const T &a, const T &b)
void min_max(const T &value, T &min, T &max)
T max(const T &a, const T &b)
VecBase< double, 3 > double3
#define hash
Definition noise.c:154
#define min(a, b)
Definition sort.c:32
#define FLT_MAX
Definition stdcycles.h:14
unsigned __int64 uint64_t
Definition stdint.h:90