Blender  V2.93
mesh_intersect.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 /* The #blender::meshintersect API needs GMP. */
22 #ifdef WITH_GMP
23 
24 # include <algorithm>
25 # include <fstream>
26 # include <iostream>
27 # include <memory>
28 
29 # include "BLI_allocator.hh"
30 # include "BLI_array.hh"
31 # include "BLI_assert.h"
32 # include "BLI_delaunay_2d.h"
33 # include "BLI_double3.hh"
34 # include "BLI_float3.hh"
35 # include "BLI_hash.hh"
36 # include "BLI_kdopbvh.h"
37 # include "BLI_map.hh"
38 # include "BLI_math_boolean.hh"
39 # include "BLI_math_mpq.hh"
40 # include "BLI_mpq2.hh"
41 # include "BLI_mpq3.hh"
42 # include "BLI_polyfill_2d.h"
43 # include "BLI_set.hh"
44 # include "BLI_span.hh"
45 # include "BLI_task.h"
46 # include "BLI_threads.h"
47 # include "BLI_vector.hh"
48 # include "BLI_vector_set.hh"
49 
50 # include "PIL_time.h"
51 
52 # include "BLI_mesh_intersect.hh"
53 
54 // # define PERFDEBUG
55 
56 namespace blender::meshintersect {
57 
58 # ifdef PERFDEBUG
59 static void perfdata_init(void);
60 static void incperfcount(int countnum);
61 static void bumpperfcount(int countnum, int amt);
62 static void doperfmax(int maxnum, int val);
63 static void dump_perfdata(void);
64 # endif
65 
67 static constexpr bool intersect_use_threading = true;
68 
69 Vert::Vert(const mpq3 &mco, const double3 &dco, int id, int orig)
70  : co_exact(mco), co(dco), id(id), orig(orig)
71 {
72 }
73 
74 bool Vert::operator==(const Vert &other) const
75 {
76  return this->co_exact == other.co_exact;
77 }
78 
79 uint64_t Vert::hash() const
80 {
81  uint64_t x = *reinterpret_cast<const uint64_t *>(&co.x);
82  uint64_t y = *reinterpret_cast<const uint64_t *>(&co.y);
83  uint64_t z = *reinterpret_cast<const uint64_t *>(&co.z);
84  x = (x >> 56) ^ (x >> 46) ^ x;
85  y = (y >> 55) ^ (y >> 45) ^ y;
86  z = (z >> 54) ^ (z >> 44) ^ z;
87  return x ^ y ^ z;
88 }
89 
90 std::ostream &operator<<(std::ostream &os, const Vert *v)
91 {
92  constexpr int dbg_level = 0;
93  os << "v" << v->id;
94  if (v->orig != NO_INDEX) {
95  os << "o" << v->orig;
96  }
97  os << v->co;
98  if (dbg_level > 0) {
99  os << "=" << v->co_exact;
100  }
101  return os;
102 }
103 
104 bool Plane::operator==(const Plane &other) const
105 {
106  return norm_exact == other.norm_exact && d_exact == other.d_exact;
107 }
108 
109 void Plane::make_canonical()
110 {
111  if (norm_exact[0] != 0) {
112  mpq_class den = norm_exact[0];
113  norm_exact = mpq3(1, norm_exact[1] / den, norm_exact[2] / den);
114  d_exact = d_exact / den;
115  }
116  else if (norm_exact[1] != 0) {
117  mpq_class den = norm_exact[1];
118  norm_exact = mpq3(0, 1, norm_exact[2] / den);
119  d_exact = d_exact / den;
120  }
121  else {
122  if (norm_exact[2] != 0) {
123  mpq_class den = norm_exact[2];
124  norm_exact = mpq3(0, 0, 1);
125  d_exact = d_exact / den;
126  }
127  else {
128  /* A degenerate plane. */
129  d_exact = 0;
130  }
131  }
132  norm = double3(norm_exact[0].get_d(), norm_exact[1].get_d(), norm_exact[2].get_d());
133  d = d_exact.get_d();
134 }
135 
136 Plane::Plane(const mpq3 &norm_exact, const mpq_class &d_exact)
137  : norm_exact(norm_exact), d_exact(d_exact)
138 {
139  norm = double3(norm_exact[0].get_d(), norm_exact[1].get_d(), norm_exact[2].get_d());
140  d = d_exact.get_d();
141 }
142 
143 Plane::Plane(const double3 &norm, const double d) : norm(norm), d(d)
144 {
145  norm_exact = mpq3(0, 0, 0); /* Marks as "exact not yet populated". */
146 }
147 
149 bool Plane::exact_populated() const
150 {
151  return norm_exact[0] != 0 || norm_exact[1] != 0 || norm_exact[2] != 0;
152 }
153 
154 uint64_t Plane::hash() const
155 {
156  uint64_t x = *reinterpret_cast<const uint64_t *>(&this->norm.x);
157  uint64_t y = *reinterpret_cast<const uint64_t *>(&this->norm.y);
158  uint64_t z = *reinterpret_cast<const uint64_t *>(&this->norm.z);
159  uint64_t d = *reinterpret_cast<const uint64_t *>(&this->d);
160  x = (x >> 56) ^ (x >> 46) ^ x;
161  y = (y >> 55) ^ (y >> 45) ^ y;
162  z = (z >> 54) ^ (z >> 44) ^ z;
163  d = (d >> 53) ^ (d >> 43) ^ d;
164  return x ^ y ^ z ^ d;
165 }
166 
167 std::ostream &operator<<(std::ostream &os, const Plane *plane)
168 {
169  os << "[" << plane->norm << ";" << plane->d << "]";
170  return os;
171 }
172 
173 Face::Face(
174  Span<const Vert *> verts, int id, int orig, Span<int> edge_origs, Span<bool> is_intersect)
175  : vert(verts), edge_orig(edge_origs), is_intersect(is_intersect), id(id), orig(orig)
176 {
177 }
178 
179 Face::Face(Span<const Vert *> verts, int id, int orig) : vert(verts), id(id), orig(orig)
180 {
181 }
182 
183 void Face::populate_plane(bool need_exact)
184 {
185  if (plane != nullptr) {
186  if (!need_exact || plane->exact_populated()) {
187  return;
188  }
189  }
190  if (need_exact) {
191  mpq3 normal_exact;
192  if (vert.size() > 3) {
193  Array<mpq3> co(vert.size());
194  for (int i : index_range()) {
195  co[i] = vert[i]->co_exact;
196  }
197  normal_exact = mpq3::cross_poly(co);
198  }
199  else {
200  mpq3 tr02 = vert[0]->co_exact - vert[2]->co_exact;
201  mpq3 tr12 = vert[1]->co_exact - vert[2]->co_exact;
202  normal_exact = mpq3::cross(tr02, tr12);
203  }
204  mpq_class d_exact = -mpq3::dot(normal_exact, vert[0]->co_exact);
205  plane = new Plane(normal_exact, d_exact);
206  }
207  else {
208  double3 normal;
209  if (vert.size() > 3) {
210  Array<double3> co(vert.size());
211  for (int i : index_range()) {
212  co[i] = vert[i]->co;
213  }
214  normal = double3::cross_poly(co);
215  }
216  else {
217  double3 tr02 = vert[0]->co - vert[2]->co;
218  double3 tr12 = vert[1]->co - vert[2]->co;
219  normal = double3::cross_high_precision(tr02, tr12);
220  }
221  double d = -double3::dot(normal, vert[0]->co);
222  plane = new Plane(normal, d);
223  }
224 }
225 
226 Face::~Face()
227 {
228  delete plane;
229 }
230 
231 bool Face::operator==(const Face &other) const
232 {
233  if (this->size() != other.size()) {
234  return false;
235  }
236  for (FacePos i : index_range()) {
237  /* Can test pointer equality since we will have
238  * unique vert pointers for unique co_equal's. */
239  if (this->vert[i] != other.vert[i]) {
240  return false;
241  }
242  }
243  return true;
244 }
245 
246 bool Face::cyclic_equal(const Face &other) const
247 {
248  if (this->size() != other.size()) {
249  return false;
250  }
251  int flen = this->size();
252  for (FacePos start : index_range()) {
253  for (FacePos start_other : index_range()) {
254  bool ok = true;
255  for (int i = 0; ok && i < flen; ++i) {
256  FacePos p = (start + i) % flen;
257  FacePos p_other = (start_other + i) % flen;
258  if (this->vert[p] != other.vert[p_other]) {
259  ok = false;
260  }
261  }
262  if (ok) {
263  return true;
264  }
265  }
266  }
267  return false;
268 }
269 
270 std::ostream &operator<<(std::ostream &os, const Face *f)
271 {
272  os << "f" << f->id << "o" << f->orig << "[";
273  for (const Vert *v : *f) {
274  os << v;
275  if (v != f->vert[f->size() - 1]) {
276  os << " ";
277  }
278  }
279  os << "]";
280  if (f->orig != NO_INDEX) {
281  os << "o" << f->orig;
282  }
283  os << " e_orig[";
284  for (int i : f->index_range()) {
285  os << f->edge_orig[i];
286  if (f->is_intersect[i]) {
287  os << "#";
288  }
289  if (i != f->size() - 1) {
290  os << " ";
291  }
292  }
293  os << "]";
294  return os;
295 }
296 
303 // #define USE_SPINLOCK
304 
312 class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
313 
319  struct VSetKey {
320  Vert *vert;
321 
322  VSetKey(Vert *p) : vert(p)
323  {
324  }
325 
326  uint64_t hash() const
327  {
328  return vert->hash();
329  }
330 
331  bool operator==(const VSetKey &other) const
332  {
333  return *this->vert == *other.vert;
334  }
335  };
336 
337  Set<VSetKey> vset_;
338 
344  Vector<std::unique_ptr<Vert>> allocated_verts_;
345  Vector<std::unique_ptr<Face>> allocated_faces_;
346 
347  /* Use these to allocate ids when Verts and Faces are allocated. */
348  int next_vert_id_ = 0;
349  int next_face_id_ = 0;
350 
351  /* Need a lock when multi-threading to protect allocation of new elements. */
352 # ifdef USE_SPINLOCK
353  SpinLock lock_;
354 # else
355  ThreadMutex *mutex_;
356 # endif
357 
358  public:
359  IMeshArenaImpl()
360  {
361  if (intersect_use_threading) {
362 # ifdef USE_SPINLOCK
363  BLI_spin_init(&lock_);
364 # else
365  mutex_ = BLI_mutex_alloc();
366 # endif
367  }
368  }
369  ~IMeshArenaImpl()
370  {
371  if (intersect_use_threading) {
372 # ifdef USE_SPINLOCK
373  BLI_spin_end(&lock_);
374 # else
375  BLI_mutex_free(mutex_);
376 # endif
377  }
378  }
379 
380  void reserve(int vert_num_hint, int face_num_hint)
381  {
382  vset_.reserve(vert_num_hint);
383  allocated_verts_.reserve(vert_num_hint);
384  allocated_faces_.reserve(face_num_hint);
385  }
386 
387  int tot_allocated_verts() const
388  {
389  return allocated_verts_.size();
390  }
391 
392  int tot_allocated_faces() const
393  {
394  return allocated_faces_.size();
395  }
396 
397  const Vert *add_or_find_vert(const mpq3 &co, int orig)
398  {
399  double3 dco(co[0].get_d(), co[1].get_d(), co[2].get_d());
400  return add_or_find_vert(co, dco, orig);
401  }
402 
403  const Vert *add_or_find_vert(const double3 &co, int orig)
404  {
405  mpq3 mco(co[0], co[1], co[2]);
406  return add_or_find_vert(mco, co, orig);
407  }
408 
409  Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs, Span<bool> is_intersect)
410  {
411  Face *f = new Face(verts, next_face_id_++, orig, edge_origs, is_intersect);
412  if (intersect_use_threading) {
413 # ifdef USE_SPINLOCK
414  BLI_spin_lock(&lock_);
415 # else
416  BLI_mutex_lock(mutex_);
417 # endif
418  }
419  allocated_faces_.append(std::unique_ptr<Face>(f));
420  if (intersect_use_threading) {
421 # ifdef USE_SPINLOCK
422  BLI_spin_unlock(&lock_);
423 # else
424  BLI_mutex_unlock(mutex_);
425 # endif
426  }
427  return f;
428  }
429 
430  Face *add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs)
431  {
432  Array<bool> is_intersect(verts.size(), false);
433  return add_face(verts, orig, edge_origs, is_intersect);
434  }
435 
436  Face *add_face(Span<const Vert *> verts, int orig)
437  {
438  Array<int> edge_origs(verts.size(), NO_INDEX);
439  Array<bool> is_intersect(verts.size(), false);
440  return add_face(verts, orig, edge_origs, is_intersect);
441  }
442 
443  const Vert *find_vert(const mpq3 &co)
444  {
445  Vert vtry(co, double3(co[0].get_d(), co[1].get_d(), co[2].get_d()), NO_INDEX, NO_INDEX);
446  VSetKey vskey(&vtry);
447  if (intersect_use_threading) {
448 # ifdef USE_SPINLOCK
449  BLI_spin_lock(&lock_);
450 # else
451  BLI_mutex_lock(mutex_);
452 # endif
453  }
454  const VSetKey *lookup = vset_.lookup_key_ptr(vskey);
455  if (intersect_use_threading) {
456 # ifdef USE_SPINLOCK
457  BLI_spin_unlock(&lock_);
458 # else
459  BLI_mutex_unlock(mutex_);
460 # endif
461  }
462  if (!lookup) {
463  return nullptr;
464  }
465  return lookup->vert;
466  }
467 
473  const Face *find_face(Span<const Vert *> vs)
474  {
475  Array<int> eorig(vs.size(), NO_INDEX);
476  Array<bool> is_intersect(vs.size(), false);
477  Face ftry(vs, NO_INDEX, NO_INDEX, eorig, is_intersect);
478  for (const int i : allocated_faces_.index_range()) {
479  if (ftry.cyclic_equal(*allocated_faces_[i])) {
480  return allocated_faces_[i].get();
481  }
482  }
483  return nullptr;
484  }
485 
486  private:
487  const Vert *add_or_find_vert(const mpq3 &mco, const double3 &dco, int orig)
488  {
489  /* Don't allocate Vert yet, in case it is already there. */
490  Vert vtry(mco, dco, NO_INDEX, NO_INDEX);
491  const Vert *ans;
492  VSetKey vskey(&vtry);
493  if (intersect_use_threading) {
494 # ifdef USE_SPINLOCK
495  BLI_spin_lock(&lock_);
496 # else
497  BLI_mutex_lock(mutex_);
498 # endif
499  }
500  const VSetKey *lookup = vset_.lookup_key_ptr(vskey);
501  if (!lookup) {
502  vskey.vert = new Vert(mco, dco, next_vert_id_++, orig);
503  vset_.add_new(vskey);
504  allocated_verts_.append(std::unique_ptr<Vert>(vskey.vert));
505  ans = vskey.vert;
506  }
507  else {
508  /* It was a duplicate, so return the existing one.
509  * Note that the returned Vert may have a different orig.
510  * This is the intended semantics: if the Vert already
511  * exists then we are merging verts and using the first-seen
512  * one as the canonical one. */
513  ans = lookup->vert;
514  }
515  if (intersect_use_threading) {
516 # ifdef USE_SPINLOCK
517  BLI_spin_unlock(&lock_);
518 # else
519  BLI_mutex_unlock(mutex_);
520 # endif
521  }
522  return ans;
523  };
524 };
525 
526 IMeshArena::IMeshArena()
527 {
528  pimpl_ = std::make_unique<IMeshArenaImpl>();
529 }
530 
531 IMeshArena::~IMeshArena() = default;
532 
533 void IMeshArena::reserve(int vert_num_hint, int face_num_hint)
534 {
535  pimpl_->reserve(vert_num_hint, face_num_hint);
536 }
537 
538 int IMeshArena::tot_allocated_verts() const
539 {
540  return pimpl_->tot_allocated_verts();
541 }
542 
543 int IMeshArena::tot_allocated_faces() const
544 {
545  return pimpl_->tot_allocated_faces();
546 }
547 
548 const Vert *IMeshArena::add_or_find_vert(const mpq3 &co, int orig)
549 {
550  return pimpl_->add_or_find_vert(co, orig);
551 }
552 
553 Face *IMeshArena::add_face(Span<const Vert *> verts,
554  int orig,
555  Span<int> edge_origs,
556  Span<bool> is_intersect)
557 {
558  return pimpl_->add_face(verts, orig, edge_origs, is_intersect);
559 }
560 
561 Face *IMeshArena::add_face(Span<const Vert *> verts, int orig, Span<int> edge_origs)
562 {
563  return pimpl_->add_face(verts, orig, edge_origs);
564 }
565 
566 Face *IMeshArena::add_face(Span<const Vert *> verts, int orig)
567 {
568  return pimpl_->add_face(verts, orig);
569 }
570 
571 const Vert *IMeshArena::add_or_find_vert(const double3 &co, int orig)
572 {
573  return pimpl_->add_or_find_vert(co, orig);
574 }
575 
576 const Vert *IMeshArena::find_vert(const mpq3 &co) const
577 {
578  return pimpl_->find_vert(co);
579 }
580 
581 const Face *IMeshArena::find_face(Span<const Vert *> verts) const
582 {
583  return pimpl_->find_face(verts);
584 }
585 
586 void IMesh::set_faces(Span<Face *> faces)
587 {
588  face_ = faces;
589 }
590 
591 int IMesh::lookup_vert(const Vert *v) const
592 {
593  BLI_assert(vert_populated_);
594  return vert_to_index_.lookup_default(v, NO_INDEX);
595 }
596 
597 void IMesh::populate_vert()
598 {
599  /* This is likely an overestimate, since verts are shared between
600  * faces. It is ok if estimate is over or even under. */
601  constexpr int ESTIMATE_VERTS_PER_FACE = 4;
602  int estimate_num_verts = ESTIMATE_VERTS_PER_FACE * face_.size();
603  populate_vert(estimate_num_verts);
604 }
605 
606 void IMesh::populate_vert(int max_verts)
607 {
608  if (vert_populated_) {
609  return;
610  }
611  vert_to_index_.reserve(max_verts);
612  int next_allocate_index = 0;
613  for (const Face *f : face_) {
614  for (const Vert *v : *f) {
615  if (v->id == 1) {
616  }
617  int index = vert_to_index_.lookup_default(v, NO_INDEX);
618  if (index == NO_INDEX) {
619  BLI_assert(next_allocate_index < UINT_MAX - 2);
620  vert_to_index_.add(v, next_allocate_index++);
621  }
622  }
623  }
624  int tot_v = next_allocate_index;
625  vert_ = Array<const Vert *>(tot_v);
626  for (auto item : vert_to_index_.items()) {
627  int index = item.value;
628  BLI_assert(index < tot_v);
629  vert_[index] = item.key;
630  }
631  /* Easier debugging (at least when there are no merged input verts)
632  * if output vert order is same as input, with new verts at the end.
633  * TODO: when all debugged, set fix_order = false. */
634  const bool fix_order = true;
635  if (fix_order) {
636  std::sort(vert_.begin(), vert_.end(), [](const Vert *a, const Vert *b) {
637  if (a->orig != NO_INDEX && b->orig != NO_INDEX) {
638  return a->orig < b->orig;
639  }
640  if (a->orig != NO_INDEX) {
641  return true;
642  }
643  if (b->orig != NO_INDEX) {
644  return false;
645  }
646  return a->id < b->id;
647  });
648  for (int i : vert_.index_range()) {
649  const Vert *v = vert_[i];
650  vert_to_index_.add_overwrite(v, i);
651  }
652  }
653  vert_populated_ = true;
654 }
655 
656 bool IMesh::erase_face_positions(int f_index, Span<bool> face_pos_erase, IMeshArena *arena)
657 {
658  const Face *cur_f = this->face(f_index);
659  int cur_len = cur_f->size();
660  int num_to_erase = 0;
661  for (int i : cur_f->index_range()) {
662  if (face_pos_erase[i]) {
663  ++num_to_erase;
664  }
665  }
666  if (num_to_erase == 0) {
667  return false;
668  }
669  int new_len = cur_len - num_to_erase;
670  if (new_len < 3) {
671  /* This erase causes removal of whole face.
672  * Because this may be called from a loop over the face array,
673  * we don't want to compress that array right here; instead will
674  * mark with null pointer and caller should call remove_null_faces().
675  * the loop is done.
676  */
677  this->face_[f_index] = NULL;
678  return true;
679  }
680  Array<const Vert *> new_vert(new_len);
681  Array<int> new_edge_orig(new_len);
682  Array<bool> new_is_intersect(new_len);
683  int new_index = 0;
684  for (int i : cur_f->index_range()) {
685  if (!face_pos_erase[i]) {
686  new_vert[new_index] = (*cur_f)[i];
687  new_edge_orig[new_index] = cur_f->edge_orig[i];
688  new_is_intersect[new_index] = cur_f->is_intersect[i];
689  ++new_index;
690  }
691  }
692  BLI_assert(new_index == new_len);
693  this->face_[f_index] = arena->add_face(new_vert, cur_f->orig, new_edge_orig, new_is_intersect);
694  return false;
695 }
696 
697 void IMesh::remove_null_faces()
698 {
699  int64_t nullcount = 0;
700  for (Face *f : this->face_) {
701  if (f == nullptr) {
702  ++nullcount;
703  }
704  }
705  if (nullcount == 0) {
706  return;
707  }
708  int64_t new_size = this->face_.size() - nullcount;
709  int64_t copy_to_index = 0;
710  int64_t copy_from_index = 0;
711  Array<Face *> new_face(new_size);
712  while (copy_from_index < face_.size()) {
713  Face *f_from = face_[copy_from_index++];
714  if (f_from) {
715  new_face[copy_to_index++] = f_from;
716  }
717  }
718  this->face_ = new_face;
719 }
720 
721 std::ostream &operator<<(std::ostream &os, const IMesh &mesh)
722 {
723  if (mesh.has_verts()) {
724  os << "Verts:\n";
725  int i = 0;
726  for (const Vert *v : mesh.vertices()) {
727  os << i << ": " << v << "\n";
728  ++i;
729  }
730  }
731  os << "\nFaces:\n";
732  int i = 0;
733  for (const Face *f : mesh.faces()) {
734  os << i << ": " << f << "\n";
735  if (f->plane != nullptr) {
736  os << " plane=" << f->plane << " eorig=[";
737  for (Face::FacePos p = 0; p < f->size(); ++p) {
738  os << f->edge_orig[p] << " ";
739  }
740  os << "]\n";
741  }
742  ++i;
743  }
744  return os;
745 }
746 
747 struct BoundingBox {
748  float3 min{FLT_MAX, FLT_MAX, FLT_MAX};
749  float3 max{-FLT_MAX, -FLT_MAX, -FLT_MAX};
750 
751  BoundingBox() = default;
752  BoundingBox(const float3 &min, const float3 &max) : min(min), max(max)
753  {
754  }
755 
756  void combine(const float3 &p)
757  {
758  min.x = min_ff(min.x, p.x);
759  min.y = min_ff(min.y, p.y);
760  min.z = min_ff(min.z, p.z);
761  max.x = max_ff(max.x, p.x);
762  max.y = max_ff(max.y, p.y);
763  max.z = max_ff(max.z, p.z);
764  }
765 
766  void combine(const double3 &p)
767  {
768  min.x = min_ff(min.x, static_cast<float>(p.x));
769  min.y = min_ff(min.y, static_cast<float>(p.y));
770  min.z = min_ff(min.z, static_cast<float>(p.z));
771  max.x = max_ff(max.x, static_cast<float>(p.x));
772  max.y = max_ff(max.y, static_cast<float>(p.y));
773  max.z = max_ff(max.z, static_cast<float>(p.z));
774  }
775 
776  void combine(const BoundingBox &bb)
777  {
778  min.x = min_ff(min.x, bb.min.x);
779  min.y = min_ff(min.y, bb.min.y);
780  min.z = min_ff(min.z, bb.min.z);
781  max.x = max_ff(max.x, bb.max.x);
782  max.y = max_ff(max.y, bb.max.y);
783  max.z = max_ff(max.z, bb.max.z);
784  }
785 
786  void expand(float pad)
787  {
788  min.x -= pad;
789  min.y -= pad;
790  min.z -= pad;
791  max.x += pad;
792  max.y += pad;
793  max.z += pad;
794  }
795 };
796 
802 static bool bbs_might_intersect(const BoundingBox &bb_a, const BoundingBox &bb_b)
803 {
804  return isect_aabb_aabb_v3(bb_a.min, bb_a.max, bb_b.min, bb_b.max);
805 }
806 
813 struct BBChunkData {
814  double max_abs_val = 0.0;
815 };
816 
817 struct BBCalcData {
818  const IMesh &im;
819  Array<BoundingBox> *face_bounding_box;
820 
821  BBCalcData(const IMesh &im, Array<BoundingBox> *fbb) : im(im), face_bounding_box(fbb){};
822 };
823 
824 static void calc_face_bb_range_func(void *__restrict userdata,
825  const int iter,
826  const TaskParallelTLS *__restrict tls)
827 {
828  BBCalcData *bbdata = static_cast<BBCalcData *>(userdata);
829  double max_abs = 0.0;
830  const Face &face = *bbdata->im.face(iter);
831  BoundingBox &bb = (*bbdata->face_bounding_box)[iter];
832  for (const Vert *v : face) {
833  bb.combine(v->co);
834  for (int i = 0; i < 3; ++i) {
835  max_abs = max_dd(max_abs, fabs(v->co[i]));
836  }
837  }
838  BBChunkData *chunk = static_cast<BBChunkData *>(tls->userdata_chunk);
839  chunk->max_abs_val = max_dd(max_abs, chunk->max_abs_val);
840 }
841 
842 struct BBPadData {
843  Array<BoundingBox> *face_bounding_box;
844  double pad;
845 
846  BBPadData(Array<BoundingBox> *fbb, double pad) : face_bounding_box(fbb), pad(pad){};
847 };
848 
849 static void pad_face_bb_range_func(void *__restrict userdata,
850  const int iter,
851  const TaskParallelTLS *__restrict UNUSED(tls))
852 {
853  BBPadData *pad_data = static_cast<BBPadData *>(userdata);
854  (*pad_data->face_bounding_box)[iter].expand(pad_data->pad);
855 }
856 
857 static void calc_face_bb_reduce(const void *__restrict UNUSED(userdata),
858  void *__restrict chunk_join,
859  void *__restrict chunk)
860 {
861  BBChunkData *bbchunk_join = static_cast<BBChunkData *>(chunk_join);
862  BBChunkData *bbchunk = static_cast<BBChunkData *>(chunk);
863  bbchunk_join->max_abs_val = max_dd(bbchunk_join->max_abs_val, bbchunk->max_abs_val);
864 }
865 
871 static Array<BoundingBox> calc_face_bounding_boxes(const IMesh &m)
872 {
873  int n = m.face_size();
874  Array<BoundingBox> ans(n);
875  TaskParallelSettings settings;
876  BBCalcData data(m, &ans);
877  BBChunkData chunk_data;
879  settings.userdata_chunk = &chunk_data;
880  settings.userdata_chunk_size = sizeof(chunk_data);
881  settings.func_reduce = calc_face_bb_reduce;
882  settings.min_iter_per_thread = 1000;
883  settings.use_threading = intersect_use_threading;
884  BLI_task_parallel_range(0, n, &data, calc_face_bb_range_func, &settings);
885  double max_abs_val = chunk_data.max_abs_val;
886  constexpr float pad_factor = 10.0f;
887  float pad = max_abs_val == 0.0f ? FLT_EPSILON : 2 * FLT_EPSILON * max_abs_val;
888  pad *= pad_factor; /* For extra safety. */
889  TaskParallelSettings pad_settings;
891  settings.min_iter_per_thread = 1000;
892  settings.use_threading = intersect_use_threading;
893  BBPadData pad_data(&ans, pad);
894  BLI_task_parallel_range(0, n, &pad_data, pad_face_bb_range_func, &pad_settings);
895  return ans;
896 }
897 
907 class CoplanarCluster {
908  Vector<int> tris_;
909  BoundingBox bb_;
910 
911  public:
912  CoplanarCluster() = default;
913  CoplanarCluster(int t, const BoundingBox &bb)
914  {
915  this->add_tri(t, bb);
916  }
917 
918  /* Assume that caller knows this will not be a duplicate. */
919  void add_tri(int t, const BoundingBox &bb)
920  {
921  tris_.append(t);
922  bb_.combine(bb);
923  }
924  int tot_tri() const
925  {
926  return tris_.size();
927  }
928  int tri(int index) const
929  {
930  return tris_[index];
931  }
932  const int *begin() const
933  {
934  return tris_.begin();
935  }
936  const int *end() const
937  {
938  return tris_.end();
939  }
940 
941  const BoundingBox &bounding_box() const
942  {
943  return bb_;
944  }
945 };
946 
953 class CoplanarClusterInfo {
954  Vector<CoplanarCluster> clusters_;
955  Array<int> tri_cluster_;
956 
957  public:
958  CoplanarClusterInfo() = default;
959  explicit CoplanarClusterInfo(int numtri) : tri_cluster_(Array<int>(numtri))
960  {
961  tri_cluster_.fill(-1);
962  }
963 
964  int tri_cluster(int t) const
965  {
966  BLI_assert(t < tri_cluster_.size());
967  return tri_cluster_[t];
968  }
969 
970  int add_cluster(CoplanarCluster cl)
971  {
972  int c_index = clusters_.append_and_get_index(cl);
973  for (int t : cl) {
974  BLI_assert(t < tri_cluster_.size());
975  tri_cluster_[t] = c_index;
976  }
977  return c_index;
978  }
979 
980  int tot_cluster() const
981  {
982  return clusters_.size();
983  }
984 
985  const CoplanarCluster *begin()
986  {
987  return clusters_.begin();
988  }
989 
990  const CoplanarCluster *end()
991  {
992  return clusters_.end();
993  }
994 
995  IndexRange index_range() const
996  {
997  return clusters_.index_range();
998  }
999 
1000  const CoplanarCluster &cluster(int index) const
1001  {
1002  BLI_assert(index < clusters_.size());
1003  return clusters_[index];
1004  }
1005 };
1006 
1007 static std::ostream &operator<<(std::ostream &os, const CoplanarCluster &cl);
1008 
1009 static std::ostream &operator<<(std::ostream &os, const CoplanarClusterInfo &clinfo);
1010 
1011 enum ITT_value_kind { INONE, IPOINT, ISEGMENT, ICOPLANAR };
1012 
1013 struct ITT_value {
1014  mpq3 p1; /* Only relevant for IPOINT and ISEGMENT kind. */
1015  mpq3 p2; /* Only relevant for ISEGMENT kind. */
1016  int t_source = -1; /* Index of the source triangle that intersected the target one. */
1017  enum ITT_value_kind kind = INONE;
1018 
1019  ITT_value() = default;
1020  explicit ITT_value(ITT_value_kind k) : kind(k)
1021  {
1022  }
1023  ITT_value(ITT_value_kind k, int tsrc) : t_source(tsrc), kind(k)
1024  {
1025  }
1026  ITT_value(ITT_value_kind k, const mpq3 &p1) : p1(p1), kind(k)
1027  {
1028  }
1029  ITT_value(ITT_value_kind k, const mpq3 &p1, const mpq3 &p2) : p1(p1), p2(p2), kind(k)
1030  {
1031  }
1032 };
1033 
1034 static std::ostream &operator<<(std::ostream &os, const ITT_value &itt);
1035 
1041 static mpq2 project_3d_to_2d(const mpq3 &p3d, int proj_axis)
1042 {
1043  mpq2 p2d;
1044  switch (proj_axis) {
1045  case (0): {
1046  p2d[0] = p3d[1];
1047  p2d[1] = p3d[2];
1048  break;
1049  }
1050  case (1): {
1051  p2d[0] = p3d[0];
1052  p2d[1] = p3d[2];
1053  break;
1054  }
1055  case (2): {
1056  p2d[0] = p3d[0];
1057  p2d[1] = p3d[1];
1058  break;
1059  }
1060  default:
1061  BLI_assert(false);
1062  }
1063  return p2d;
1064 }
1065 
1096 static double supremum_dot_cross(const double3 &a, const double3 &b)
1097 {
1098  double3 abs_a = double3::abs(a);
1099  double3 abs_b = double3::abs(b);
1100  double3 c;
1101  /* This is dot(cross(a, b), cross(a,b)) but using absolute values for a and b
1102  * and always using + when operation is + or -. */
1103  c[0] = abs_a[1] * abs_b[2] + abs_a[2] * abs_b[1];
1104  c[1] = abs_a[2] * abs_b[0] + abs_a[0] * abs_b[2];
1105  c[2] = abs_a[0] * abs_b[1] + abs_a[1] * abs_b[0];
1106  return double3::dot(c, c);
1107 }
1108 
1109 /* The index of dot when inputs are plane_coords with index 1 is much higher.
1110  * Plane coords have index 6.
1111  */
1112 constexpr int index_dot_plane_coords = 15;
1113 
1124 constexpr int index_dot_cross = 11;
1125 
1134 constexpr int index_plane_side = 3 + 2 * index_dot_plane_coords;
1135 
1136 static int filter_plane_side(const double3 &p,
1137  const double3 &plane_p,
1138  const double3 &plane_no,
1139  const double3 &abs_p,
1140  const double3 &abs_plane_p,
1141  const double3 &abs_plane_no)
1142 {
1143  double d = double3::dot(p - plane_p, plane_no);
1144  if (d == 0.0) {
1145  return 0;
1146  }
1147  double supremum = double3::dot(abs_p + abs_plane_p, abs_plane_no);
1148  double err_bound = supremum * index_plane_side * DBL_EPSILON;
1149  if (fabs(d) > err_bound) {
1150  return d > 0 ? 1 : -1;
1151  }
1152  return 0;
1153 }
1154 
1155 /*
1156  * interesect_tri_tri and helper functions.
1157  * This code uses the algorithm of Guigue and Devillers, as described
1158  * in "Faster Triangle-Triangle Intersection Tests".
1159  * Adapted from github code by Eric Haines:
1160  * github.com/erich666/jgt-code/tree/master/Volume_08/Number_1/Guigue2003
1161  */
1162 
1169 static inline mpq3 tti_interp(const mpq3 &a, const mpq3 &b, const mpq3 &c, const mpq3 &n)
1170 {
1171  mpq3 ab = a - b;
1172  mpq_class den = mpq3::dot(ab, n);
1173  BLI_assert(den != 0);
1174  mpq_class alpha = mpq3::dot(a - c, n) / den;
1175  return a - alpha * ab;
1176 }
1177 
1183 static inline int tti_above(const mpq3 &a, const mpq3 &b, const mpq3 &c, const mpq3 &ad)
1184 {
1185  mpq3 n = mpq3::cross(b - a, c - a);
1186  return sgn(mpq3::dot(ad, n));
1187 }
1188 
1202 static ITT_value itt_canon2(const mpq3 &p1,
1203  const mpq3 &q1,
1204  const mpq3 &r1,
1205  const mpq3 &p2,
1206  const mpq3 &q2,
1207  const mpq3 &r2,
1208  const mpq3 &n1,
1209  const mpq3 &n2)
1210 {
1211  constexpr int dbg_level = 0;
1212  if (dbg_level > 0) {
1213  std::cout << "\ntri_tri_intersect_canon:\n";
1214  std::cout << "p1=" << p1 << " q1=" << q1 << " r1=" << r1 << "\n";
1215  std::cout << "p2=" << p2 << " q2=" << q2 << " r2=" << r2 << "\n";
1216  std::cout << "n1=" << n1 << " n2=" << n2 << "\n";
1217  std::cout << "approximate values:\n";
1218  std::cout << "p1=(" << p1[0].get_d() << "," << p1[1].get_d() << "," << p1[2].get_d() << ")\n";
1219  std::cout << "q1=(" << q1[0].get_d() << "," << q1[1].get_d() << "," << q1[2].get_d() << ")\n";
1220  std::cout << "r1=(" << r1[0].get_d() << "," << r1[1].get_d() << "," << r1[2].get_d() << ")\n";
1221  std::cout << "p2=(" << p2[0].get_d() << "," << p2[1].get_d() << "," << p2[2].get_d() << ")\n";
1222  std::cout << "q2=(" << q2[0].get_d() << "," << q2[1].get_d() << "," << q2[2].get_d() << ")\n";
1223  std::cout << "r2=(" << r2[0].get_d() << "," << r2[1].get_d() << "," << r2[2].get_d() << ")\n";
1224  std::cout << "n1=(" << n1[0].get_d() << "," << n1[1].get_d() << "," << n1[2].get_d() << ")\n";
1225  std::cout << "n2=(" << n2[0].get_d() << "," << n2[1].get_d() << "," << n2[2].get_d() << ")\n";
1226  }
1227  mpq3 p1p2 = p2 - p1;
1228  mpq3 intersect_1;
1229  mpq3 intersect_2;
1230  bool no_overlap = false;
1231  /* Top test in classification tree. */
1232  if (tti_above(p1, q1, r2, p1p2) > 0) {
1233  /* Middle right test in classification tree. */
1234  if (tti_above(p1, r1, r2, p1p2) <= 0) {
1235  /* Bottom right test in classification tree. */
1236  if (tti_above(p1, r1, q2, p1p2) > 0) {
1237  /* Overlap is [k [i l] j]. */
1238  if (dbg_level > 0) {
1239  std::cout << "overlap [k [i l] j]\n";
1240  }
1241  /* i is intersect with p1r1. l is intersect with p2r2. */
1242  intersect_1 = tti_interp(p1, r1, p2, n2);
1243  intersect_2 = tti_interp(p2, r2, p1, n1);
1244  }
1245  else {
1246  /* Overlap is [i [k l] j]. */
1247  if (dbg_level > 0) {
1248  std::cout << "overlap [i [k l] j]\n";
1249  }
1250  /* k is intersect with p2q2. l is intersect is p2r2. */
1251  intersect_1 = tti_interp(p2, q2, p1, n1);
1252  intersect_2 = tti_interp(p2, r2, p1, n1);
1253  }
1254  }
1255  else {
1256  /* No overlap: [k l] [i j]. */
1257  if (dbg_level > 0) {
1258  std::cout << "no overlap: [k l] [i j]\n";
1259  }
1260  no_overlap = true;
1261  }
1262  }
1263  else {
1264  /* Middle left test in classification tree. */
1265  if (tti_above(p1, q1, q2, p1p2) < 0) {
1266  /* No overlap: [i j] [k l]. */
1267  if (dbg_level > 0) {
1268  std::cout << "no overlap: [i j] [k l]\n";
1269  }
1270  no_overlap = true;
1271  }
1272  else {
1273  /* Bottom left test in classification tree. */
1274  if (tti_above(p1, r1, q2, p1p2) >= 0) {
1275  /* Overlap is [k [i j] l]. */
1276  if (dbg_level > 0) {
1277  std::cout << "overlap [k [i j] l]\n";
1278  }
1279  /* i is intersect with p1r1. j is intersect with p1q1. */
1280  intersect_1 = tti_interp(p1, r1, p2, n2);
1281  intersect_2 = tti_interp(p1, q1, p2, n2);
1282  }
1283  else {
1284  /* Overlap is [i [k j] l]. */
1285  if (dbg_level > 0) {
1286  std::cout << "overlap [i [k j] l]\n";
1287  }
1288  /* k is intersect with p2q2. j is intersect with p1q1. */
1289  intersect_1 = tti_interp(p2, q2, p1, n1);
1290  intersect_2 = tti_interp(p1, q1, p2, n2);
1291  }
1292  }
1293  }
1294  if (no_overlap) {
1295  return ITT_value(INONE);
1296  }
1297  if (intersect_1 == intersect_2) {
1298  if (dbg_level > 0) {
1299  std::cout << "single intersect: " << intersect_1 << "\n";
1300  }
1301  return ITT_value(IPOINT, intersect_1);
1302  }
1303  if (dbg_level > 0) {
1304  std::cout << "intersect segment: " << intersect_1 << ", " << intersect_2 << "\n";
1305  }
1306  return ITT_value(ISEGMENT, intersect_1, intersect_2);
1307 }
1308 
1309 /* Helper function for intersect_tri_tri. Arguments have been canonicalized for triangle 1. */
1310 
1311 static ITT_value itt_canon1(const mpq3 &p1,
1312  const mpq3 &q1,
1313  const mpq3 &r1,
1314  const mpq3 &p2,
1315  const mpq3 &q2,
1316  const mpq3 &r2,
1317  const mpq3 &n1,
1318  const mpq3 &n2,
1319  int sp2,
1320  int sq2,
1321  int sr2)
1322 {
1323  constexpr int dbg_level = 0;
1324  if (sp2 > 0) {
1325  if (sq2 > 0) {
1326  return itt_canon2(p1, r1, q1, r2, p2, q2, n1, n2);
1327  }
1328  if (sr2 > 0) {
1329  return itt_canon2(p1, r1, q1, q2, r2, p2, n1, n2);
1330  }
1331  return itt_canon2(p1, q1, r1, p2, q2, r2, n1, n2);
1332  }
1333  if (sp2 < 0) {
1334  if (sq2 < 0) {
1335  return itt_canon2(p1, q1, r1, r2, p2, q2, n1, n2);
1336  }
1337  if (sr2 < 0) {
1338  return itt_canon2(p1, q1, r1, q2, r2, p2, n1, n2);
1339  }
1340  return itt_canon2(p1, r1, q1, p2, q2, r2, n1, n2);
1341  }
1342  if (sq2 < 0) {
1343  if (sr2 >= 0) {
1344  return itt_canon2(p1, r1, q1, q2, r2, p2, n1, n2);
1345  }
1346  return itt_canon2(p1, q1, r1, p2, q2, r2, n1, n2);
1347  }
1348  if (sq2 > 0) {
1349  if (sr2 > 0) {
1350  return itt_canon2(p1, r1, q1, p2, q2, r2, n1, n2);
1351  }
1352  return itt_canon2(p1, q1, r1, q2, r2, p2, n1, n2);
1353  }
1354  if (sr2 > 0) {
1355  return itt_canon2(p1, q1, r1, r2, p2, q2, n1, n2);
1356  }
1357  if (sr2 < 0) {
1358  return itt_canon2(p1, r1, q1, r2, p2, q2, n1, n2);
1359  }
1360  if (dbg_level > 0) {
1361  std::cout << "triangles are co-planar\n";
1362  }
1363  return ITT_value(ICOPLANAR);
1364 }
1365 
1366 static ITT_value intersect_tri_tri(const IMesh &tm, int t1, int t2)
1367 {
1368  constexpr int dbg_level = 0;
1369 # ifdef PERFDEBUG
1370  incperfcount(1); /* Intersect_tri_tri calls. */
1371 # endif
1372  const Face &tri1 = *tm.face(t1);
1373  const Face &tri2 = *tm.face(t2);
1374  BLI_assert(tri1.plane_populated() && tri2.plane_populated());
1375  const Vert *vp1 = tri1[0];
1376  const Vert *vq1 = tri1[1];
1377  const Vert *vr1 = tri1[2];
1378  const Vert *vp2 = tri2[0];
1379  const Vert *vq2 = tri2[1];
1380  const Vert *vr2 = tri2[2];
1381  if (dbg_level > 0) {
1382  std::cout << "\nINTERSECT_TRI_TRI t1=" << t1 << ", t2=" << t2 << "\n";
1383  std::cout << " p1 = " << vp1 << "\n";
1384  std::cout << " q1 = " << vq1 << "\n";
1385  std::cout << " r1 = " << vr1 << "\n";
1386  std::cout << " p2 = " << vp2 << "\n";
1387  std::cout << " q2 = " << vq2 << "\n";
1388  std::cout << " r2 = " << vr2 << "\n";
1389  }
1390 
1391  /* Get signs of t1's vertices' distances to plane of t2 and vice versa. */
1392 
1393  /* Try first getting signs with double arithmetic, with error bounds.
1394  * If the signs calculated in this section are not 0, they are the same
1395  * as what they would be using exact arithmetic. */
1396  const double3 &d_p1 = vp1->co;
1397  const double3 &d_q1 = vq1->co;
1398  const double3 &d_r1 = vr1->co;
1399  const double3 &d_p2 = vp2->co;
1400  const double3 &d_q2 = vq2->co;
1401  const double3 &d_r2 = vr2->co;
1402  const double3 &d_n2 = tri2.plane->norm;
1403 
1404  const double3 &abs_d_p1 = double3::abs(d_p1);
1405  const double3 &abs_d_q1 = double3::abs(d_q1);
1406  const double3 &abs_d_r1 = double3::abs(d_r1);
1407  const double3 &abs_d_r2 = double3::abs(d_r2);
1408  const double3 &abs_d_n2 = double3::abs(d_n2);
1409 
1410  int sp1 = filter_plane_side(d_p1, d_r2, d_n2, abs_d_p1, abs_d_r2, abs_d_n2);
1411  int sq1 = filter_plane_side(d_q1, d_r2, d_n2, abs_d_q1, abs_d_r2, abs_d_n2);
1412  int sr1 = filter_plane_side(d_r1, d_r2, d_n2, abs_d_r1, abs_d_r2, abs_d_n2);
1413  if ((sp1 > 0 && sq1 > 0 && sr1 > 0) || (sp1 < 0 && sq1 < 0 && sr1 < 0)) {
1414 # ifdef PERFDEBUG
1415  incperfcount(2); /* Tri tri intersects decided by filter plane tests. */
1416 # endif
1417  if (dbg_level > 0) {
1418  std::cout << "no intersection, all t1's verts above or below t2\n";
1419  }
1420  return ITT_value(INONE);
1421  }
1422 
1423  const double3 &d_n1 = tri1.plane->norm;
1424  const double3 &abs_d_p2 = double3::abs(d_p2);
1425  const double3 &abs_d_q2 = double3::abs(d_q2);
1426  const double3 &abs_d_n1 = double3::abs(d_n1);
1427 
1428  int sp2 = filter_plane_side(d_p2, d_r1, d_n1, abs_d_p2, abs_d_r1, abs_d_n1);
1429  int sq2 = filter_plane_side(d_q2, d_r1, d_n1, abs_d_q2, abs_d_r1, abs_d_n1);
1430  int sr2 = filter_plane_side(d_r2, d_r1, d_n1, abs_d_r2, abs_d_r1, abs_d_n1);
1431  if ((sp2 > 0 && sq2 > 0 && sr2 > 0) || (sp2 < 0 && sq2 < 0 && sr2 < 0)) {
1432 # ifdef PERFDEBUG
1433  incperfcount(2); /* Tri tri intersects decided by filter plane tests. */
1434 # endif
1435  if (dbg_level > 0) {
1436  std::cout << "no intersection, all t2's verts above or below t1\n";
1437  }
1438  return ITT_value(INONE);
1439  }
1440 
1441  const mpq3 &p1 = vp1->co_exact;
1442  const mpq3 &q1 = vq1->co_exact;
1443  const mpq3 &r1 = vr1->co_exact;
1444  const mpq3 &p2 = vp2->co_exact;
1445  const mpq3 &q2 = vq2->co_exact;
1446  const mpq3 &r2 = vr2->co_exact;
1447 
1448  const mpq3 &n2 = tri2.plane->norm_exact;
1449  if (sp1 == 0) {
1450  sp1 = sgn(mpq3::dot(p1 - r2, n2));
1451  }
1452  if (sq1 == 0) {
1453  sq1 = sgn(mpq3::dot(q1 - r2, n2));
1454  }
1455  if (sr1 == 0) {
1456  sr1 = sgn(mpq3::dot(r1 - r2, n2));
1457  }
1458 
1459  if (dbg_level > 1) {
1460  std::cout << " sp1=" << sp1 << " sq1=" << sq1 << " sr1=" << sr1 << "\n";
1461  }
1462 
1463  if ((sp1 * sq1 > 0) && (sp1 * sr1 > 0)) {
1464  if (dbg_level > 0) {
1465  std::cout << "no intersection, all t1's verts above or below t2 (exact)\n";
1466  }
1467 # ifdef PERFDEBUG
1468  incperfcount(3); /* Tri tri intersects decided by exact plane tests. */
1469 # endif
1470  return ITT_value(INONE);
1471  }
1472 
1473  /* Repeat for signs of t2's vertices with respect to plane of t1. */
1474  const mpq3 &n1 = tri1.plane->norm_exact;
1475  if (sp2 == 0) {
1476  sp2 = sgn(mpq3::dot(p2 - r1, n1));
1477  }
1478  if (sq2 == 0) {
1479  sq2 = sgn(mpq3::dot(q2 - r1, n1));
1480  }
1481  if (sr2 == 0) {
1482  sr2 = sgn(mpq3::dot(r2 - r1, n1));
1483  }
1484 
1485  if (dbg_level > 1) {
1486  std::cout << " sp2=" << sp2 << " sq2=" << sq2 << " sr2=" << sr2 << "\n";
1487  }
1488 
1489  if ((sp2 * sq2 > 0) && (sp2 * sr2 > 0)) {
1490  if (dbg_level > 0) {
1491  std::cout << "no intersection, all t2's verts above or below t1 (exact)\n";
1492  }
1493 # ifdef PERFDEBUG
1494  incperfcount(3); /* Tri tri intersects decided by exact plane tests. */
1495 # endif
1496  return ITT_value(INONE);
1497  }
1498 
1499  /* Do rest of the work with vertices in a canonical order, where p1 is on
1500  * positive side of plane and q1, r1 are not, or p1 is on the plane and
1501  * q1 and r1 are off the plane on the same side. */
1502  ITT_value ans;
1503  if (sp1 > 0) {
1504  if (sq1 > 0) {
1505  ans = itt_canon1(r1, p1, q1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1506  }
1507  else if (sr1 > 0) {
1508  ans = itt_canon1(q1, r1, p1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1509  }
1510  else {
1511  ans = itt_canon1(p1, q1, r1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1512  }
1513  }
1514  else if (sp1 < 0) {
1515  if (sq1 < 0) {
1516  ans = itt_canon1(r1, p1, q1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1517  }
1518  else if (sr1 < 0) {
1519  ans = itt_canon1(q1, r1, p1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1520  }
1521  else {
1522  ans = itt_canon1(p1, q1, r1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1523  }
1524  }
1525  else {
1526  if (sq1 < 0) {
1527  if (sr1 >= 0) {
1528  ans = itt_canon1(q1, r1, p1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1529  }
1530  else {
1531  ans = itt_canon1(p1, q1, r1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1532  }
1533  }
1534  else if (sq1 > 0) {
1535  if (sr1 > 0) {
1536  ans = itt_canon1(p1, q1, r1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1537  }
1538  else {
1539  ans = itt_canon1(q1, r1, p1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1540  }
1541  }
1542  else {
1543  if (sr1 > 0) {
1544  ans = itt_canon1(r1, p1, q1, p2, q2, r2, n1, n2, sp2, sq2, sr2);
1545  }
1546  else if (sr1 < 0) {
1547  ans = itt_canon1(r1, p1, q1, p2, r2, q2, n1, n2, sp2, sr2, sq2);
1548  }
1549  else {
1550  if (dbg_level > 0) {
1551  std::cout << "triangles are co-planar\n";
1552  }
1553  ans = ITT_value(ICOPLANAR);
1554  }
1555  }
1556  }
1557  if (ans.kind == ICOPLANAR) {
1558  ans.t_source = t2;
1559  }
1560 
1561 # ifdef PERFDEBUG
1562  if (ans.kind != INONE) {
1563  incperfcount(4);
1564  }
1565 # endif
1566  return ans;
1567 }
1568 
1569 struct CDT_data {
1570  const Plane *t_plane;
1571  Vector<mpq2> vert;
1572  Vector<std::pair<int, int>> edge;
1573  Vector<Vector<int>> face;
1575  Vector<int> input_face;
1577  Vector<bool> is_reversed;
1579  CDT_result<mpq_class> cdt_out;
1582  Map<std::pair<int, int>, int> verts_to_edge;
1583  int proj_axis;
1584 };
1585 
1589 static int prepare_need_vert(CDT_data &cd, const mpq3 &p3d)
1590 {
1591  mpq2 p2d = project_3d_to_2d(p3d, cd.proj_axis);
1592  int v = cd.vert.append_and_get_index(p2d);
1593  return v;
1594 }
1595 
1603 static mpq3 unproject_cdt_vert(const CDT_data &cd, const mpq2 &p2d)
1604 {
1605  mpq3 p3d;
1606  BLI_assert(cd.t_plane->exact_populated());
1607  BLI_assert(cd.t_plane->norm_exact[cd.proj_axis] != 0);
1608  const mpq3 &n = cd.t_plane->norm_exact;
1609  const mpq_class &d = cd.t_plane->d_exact;
1610  switch (cd.proj_axis) {
1611  case (0): {
1612  mpq_class num = n[1] * p2d[0] + n[2] * p2d[1] + d;
1613  num = -num;
1614  p3d[0] = num / n[0];
1615  p3d[1] = p2d[0];
1616  p3d[2] = p2d[1];
1617  break;
1618  }
1619  case (1): {
1620  p3d[0] = p2d[0];
1621  mpq_class num = n[0] * p2d[0] + n[2] * p2d[1] + d;
1622  num = -num;
1623  p3d[1] = num / n[1];
1624  p3d[2] = p2d[1];
1625  break;
1626  }
1627  case (2): {
1628  p3d[0] = p2d[0];
1629  p3d[1] = p2d[1];
1630  mpq_class num = n[0] * p2d[0] + n[1] * p2d[1] + d;
1631  num = -num;
1632  p3d[2] = num / n[2];
1633  break;
1634  }
1635  default:
1636  BLI_assert(false);
1637  }
1638  return p3d;
1639 }
1640 
1641 static void prepare_need_edge(CDT_data &cd, const mpq3 &p1, const mpq3 &p2)
1642 {
1643  int v1 = prepare_need_vert(cd, p1);
1644  int v2 = prepare_need_vert(cd, p2);
1645  cd.edge.append(std::pair<int, int>(v1, v2));
1646 }
1647 
1648 static void prepare_need_tri(CDT_data &cd, const IMesh &tm, int t)
1649 {
1650  const Face &tri = *tm.face(t);
1651  int v0 = prepare_need_vert(cd, tri[0]->co_exact);
1652  int v1 = prepare_need_vert(cd, tri[1]->co_exact);
1653  int v2 = prepare_need_vert(cd, tri[2]->co_exact);
1654  bool rev;
1655  /* How to get CCW orientation of projected triangle? Note that when look down y axis
1656  * as opposed to x or z, the orientation of the other two axes is not right-and-up. */
1657  BLI_assert(cd.t_plane->exact_populated());
1658  if (tri.plane->norm_exact[cd.proj_axis] >= 0) {
1659  rev = cd.proj_axis == 1;
1660  }
1661  else {
1662  rev = cd.proj_axis != 1;
1663  }
1664  int cd_t = cd.face.append_and_get_index(Vector<int>());
1665  cd.face[cd_t].append(v0);
1666  if (rev) {
1667  cd.face[cd_t].append(v2);
1668  cd.face[cd_t].append(v1);
1669  }
1670  else {
1671  cd.face[cd_t].append(v1);
1672  cd.face[cd_t].append(v2);
1673  }
1674  cd.input_face.append(t);
1675  cd.is_reversed.append(rev);
1676 }
1677 
1678 static CDT_data prepare_cdt_input(const IMesh &tm, int t, const Vector<ITT_value> itts)
1679 {
1680  CDT_data ans;
1681  BLI_assert(tm.face(t)->plane_populated());
1682  ans.t_plane = tm.face(t)->plane;
1683  BLI_assert(ans.t_plane->exact_populated());
1684  ans.proj_axis = mpq3::dominant_axis(ans.t_plane->norm_exact);
1685  prepare_need_tri(ans, tm, t);
1686  for (const ITT_value &itt : itts) {
1687  switch (itt.kind) {
1688  case INONE:
1689  break;
1690  case IPOINT: {
1691  prepare_need_vert(ans, itt.p1);
1692  break;
1693  }
1694  case ISEGMENT: {
1695  prepare_need_edge(ans, itt.p1, itt.p2);
1696  break;
1697  }
1698  case ICOPLANAR: {
1699  prepare_need_tri(ans, tm, itt.t_source);
1700  break;
1701  }
1702  }
1703  }
1704  return ans;
1705 }
1706 
1707 static CDT_data prepare_cdt_input_for_cluster(const IMesh &tm,
1708  const CoplanarClusterInfo &clinfo,
1709  int c,
1710  const Vector<ITT_value> itts)
1711 {
1712  CDT_data ans;
1713  BLI_assert(c < clinfo.tot_cluster());
1714  const CoplanarCluster &cl = clinfo.cluster(c);
1715  BLI_assert(cl.tot_tri() > 0);
1716  int t0 = cl.tri(0);
1717  BLI_assert(tm.face(t0)->plane_populated());
1718  ans.t_plane = tm.face(t0)->plane;
1719  BLI_assert(ans.t_plane->exact_populated());
1720  ans.proj_axis = mpq3::dominant_axis(ans.t_plane->norm_exact);
1721  for (const int t : cl) {
1722  prepare_need_tri(ans, tm, t);
1723  }
1724  for (const ITT_value &itt : itts) {
1725  switch (itt.kind) {
1726  case IPOINT: {
1727  prepare_need_vert(ans, itt.p1);
1728  break;
1729  }
1730  case ISEGMENT: {
1731  prepare_need_edge(ans, itt.p1, itt.p2);
1732  break;
1733  }
1734  default:
1735  break;
1736  }
1737  }
1738  return ans;
1739 }
1740 
1741 /* Return a copy of the argument with the integers ordered in ascending order. */
1742 static inline std::pair<int, int> sorted_int_pair(std::pair<int, int> pair)
1743 {
1744  if (pair.first <= pair.second) {
1745  return pair;
1746  }
1747  else {
1748  return std::pair<int, int>(pair.second, pair.first);
1749  }
1750 }
1751 
1756 static void populate_cdt_edge_map(Map<std::pair<int, int>, int> &verts_to_edge,
1757  const CDT_result<mpq_class> &cdt_out)
1758 {
1759  verts_to_edge.reserve(cdt_out.edge.size());
1760  for (int e : cdt_out.edge.index_range()) {
1761  std::pair<int, int> vpair = sorted_int_pair(cdt_out.edge[e]);
1762  /* There should be only one edge for each vertex pair. */
1763  verts_to_edge.add(vpair, e);
1764  }
1765 }
1766 
1770 static void do_cdt(CDT_data &cd)
1771 {
1772  constexpr int dbg_level = 0;
1773  CDT_input<mpq_class> cdt_in;
1774  cdt_in.vert = Span<mpq2>(cd.vert);
1775  cdt_in.edge = Span<std::pair<int, int>>(cd.edge);
1776  cdt_in.face = Span<Vector<int>>(cd.face);
1777  if (dbg_level > 0) {
1778  std::cout << "CDT input\nVerts:\n";
1779  for (int i : cdt_in.vert.index_range()) {
1780  std::cout << "v" << i << ": " << cdt_in.vert[i] << "=(" << cdt_in.vert[i][0].get_d() << ","
1781  << cdt_in.vert[i][1].get_d() << ")\n";
1782  }
1783  std::cout << "Edges:\n";
1784  for (int i : cdt_in.edge.index_range()) {
1785  std::cout << "e" << i << ": (" << cdt_in.edge[i].first << ", " << cdt_in.edge[i].second
1786  << ")\n";
1787  }
1788  std::cout << "Tris\n";
1789  for (int f : cdt_in.face.index_range()) {
1790  std::cout << "f" << f << ": ";
1791  for (int j : cdt_in.face[f].index_range()) {
1792  std::cout << cdt_in.face[f][j] << " ";
1793  }
1794  std::cout << "\n";
1795  }
1796  }
1797  cdt_in.epsilon = 0; /* TODO: needs attention for non-exact T. */
1798  cd.cdt_out = blender::meshintersect::delaunay_2d_calc(cdt_in, CDT_INSIDE);
1799  constexpr int make_edge_map_threshold = 15;
1800  if (cd.cdt_out.edge.size() >= make_edge_map_threshold) {
1801  populate_cdt_edge_map(cd.verts_to_edge, cd.cdt_out);
1802  }
1803  if (dbg_level > 0) {
1804  std::cout << "\nCDT result\nVerts:\n";
1805  for (int i : cd.cdt_out.vert.index_range()) {
1806  std::cout << "v" << i << ": " << cd.cdt_out.vert[i] << "=(" << cd.cdt_out.vert[i][0].get_d()
1807  << "," << cd.cdt_out.vert[i][1].get_d() << "\n";
1808  }
1809  std::cout << "Tris\n";
1810  for (int f : cd.cdt_out.face.index_range()) {
1811  std::cout << "f" << f << ": ";
1812  for (int j : cd.cdt_out.face[f].index_range()) {
1813  std::cout << cd.cdt_out.face[f][j] << " ";
1814  }
1815  std::cout << "orig: ";
1816  for (int j : cd.cdt_out.face_orig[f].index_range()) {
1817  std::cout << cd.cdt_out.face_orig[f][j] << " ";
1818  }
1819  std::cout << "\n";
1820  }
1821  std::cout << "Edges\n";
1822  for (int e : cd.cdt_out.edge.index_range()) {
1823  std::cout << "e" << e << ": (" << cd.cdt_out.edge[e].first << ", "
1824  << cd.cdt_out.edge[e].second << ") ";
1825  std::cout << "orig: ";
1826  for (int j : cd.cdt_out.edge_orig[e].index_range()) {
1827  std::cout << cd.cdt_out.edge_orig[e][j] << " ";
1828  }
1829  std::cout << "\n";
1830  }
1831  }
1832 }
1833 
1834 static int get_cdt_edge_orig(
1835  int i0, int i1, const CDT_data &cd, const IMesh &in_tm, bool *r_is_intersect)
1836 {
1837  int foff = cd.cdt_out.face_edge_offset;
1838  *r_is_intersect = false;
1839  int e = NO_INDEX;
1840  if (cd.verts_to_edge.size() > 0) {
1841  /* Use the populated map to find the edge, if any, between vertices i0 and i1. */
1842  std::pair<int, int> vpair = sorted_int_pair(std::pair<int, int>(i0, i1));
1843  e = cd.verts_to_edge.lookup_default(vpair, NO_INDEX);
1844  }
1845  else {
1846  for (int ee : cd.cdt_out.edge.index_range()) {
1847  std::pair<int, int> edge = cd.cdt_out.edge[ee];
1848  if ((edge.first == i0 && edge.second == i1) || (edge.first == i1 && edge.second == i0)) {
1849  e = ee;
1850  break;
1851  }
1852  }
1853  }
1854  if (e == NO_INDEX) {
1855  return NO_INDEX;
1856  }
1857 
1858  /* Pick an arbitrary orig, but not one equal to NO_INDEX, if we can help it. */
1859  /* TODO: if edge has origs from more than on part of the nary input,
1860  * then want to set *r_is_intersect to true. */
1861  for (int orig_index : cd.cdt_out.edge_orig[e]) {
1862  /* orig_index encodes the triangle and pos within the triangle of the input edge. */
1863  if (orig_index >= foff) {
1864  int in_face_index = (orig_index / foff) - 1;
1865  int pos = orig_index % foff;
1866  /* We need to retrieve the edge orig field from the Face used to populate the
1867  * in_face_index'th face of the CDT, at the pos'th position of the face. */
1868  int in_tm_face_index = cd.input_face[in_face_index];
1869  BLI_assert(in_tm_face_index < in_tm.face_size());
1870  const Face *facep = in_tm.face(in_tm_face_index);
1871  BLI_assert(pos < facep->size());
1872  bool is_rev = cd.is_reversed[in_face_index];
1873  int eorig = is_rev ? facep->edge_orig[2 - pos] : facep->edge_orig[pos];
1874  if (eorig != NO_INDEX) {
1875  return eorig;
1876  }
1877  }
1878  else {
1879  /* This edge came from an edge input to the CDT problem,
1880  * so it is an intersect edge. */
1881  *r_is_intersect = true;
1882  /* TODO: maybe there is an orig index:
1883  * This happens if an input edge was formed by an input face having
1884  * an edge that is co-planar with the cluster, while the face as a whole is not. */
1885  return NO_INDEX;
1886  }
1887  }
1888  return NO_INDEX;
1889 }
1890 
1896 static Face *cdt_tri_as_imesh_face(
1897  int cdt_out_t, int cdt_in_t, const CDT_data &cd, const IMesh &tm, IMeshArena *arena)
1898 {
1899  const CDT_result<mpq_class> &cdt_out = cd.cdt_out;
1900  int t_orig = tm.face(cd.input_face[cdt_in_t])->orig;
1901  BLI_assert(cdt_out.face[cdt_out_t].size() == 3);
1902  int i0 = cdt_out.face[cdt_out_t][0];
1903  int i1 = cdt_out.face[cdt_out_t][1];
1904  int i2 = cdt_out.face[cdt_out_t][2];
1905  mpq3 v0co = unproject_cdt_vert(cd, cdt_out.vert[i0]);
1906  mpq3 v1co = unproject_cdt_vert(cd, cdt_out.vert[i1]);
1907  mpq3 v2co = unproject_cdt_vert(cd, cdt_out.vert[i2]);
1908  /* No need to provide an original index: if coord matches
1909  * an original one, then it will already be in the arena
1910  * with the correct orig field. */
1911  const Vert *v0 = arena->add_or_find_vert(v0co, NO_INDEX);
1912  const Vert *v1 = arena->add_or_find_vert(v1co, NO_INDEX);
1913  const Vert *v2 = arena->add_or_find_vert(v2co, NO_INDEX);
1914  Face *facep;
1915  bool is_isect0;
1916  bool is_isect1;
1917  bool is_isect2;
1918  if (cd.is_reversed[cdt_in_t]) {
1919  int oe0 = get_cdt_edge_orig(i0, i2, cd, tm, &is_isect0);
1920  int oe1 = get_cdt_edge_orig(i2, i1, cd, tm, &is_isect1);
1921  int oe2 = get_cdt_edge_orig(i1, i0, cd, tm, &is_isect2);
1922  facep = arena->add_face(
1923  {v0, v2, v1}, t_orig, {oe0, oe1, oe2}, {is_isect0, is_isect1, is_isect2});
1924  }
1925  else {
1926  int oe0 = get_cdt_edge_orig(i0, i1, cd, tm, &is_isect0);
1927  int oe1 = get_cdt_edge_orig(i1, i2, cd, tm, &is_isect1);
1928  int oe2 = get_cdt_edge_orig(i2, i0, cd, tm, &is_isect2);
1929  facep = arena->add_face(
1930  {v0, v1, v2}, t_orig, {oe0, oe1, oe2}, {is_isect0, is_isect1, is_isect2});
1931  }
1932  facep->populate_plane(false);
1933  return facep;
1934 }
1935 
1948 static Array<Face *> polyfill_triangulate_poly(Face *f, IMeshArena *arena)
1949 {
1950  /* Similar to loop body in BM_mesh_calc_tesselation. */
1951  int flen = f->size();
1952  BLI_assert(flen > 4);
1953  if (!f->plane_populated()) {
1954  f->populate_plane(false);
1955  }
1956  /* Project along negative face normal so (x,y) can be used in 2d. */
1957  const double3 &poly_normal = f->plane->norm;
1958  float no[3] = {float(poly_normal[0]), float(poly_normal[1]), float(poly_normal[2])};
1959  normalize_v3(no);
1960  float axis_mat[3][3];
1961  float(*projverts)[2];
1962  unsigned int(*tris)[3];
1963  const int totfilltri = flen - 2;
1964  /* Prepare projected vertices and array to receive triangles in tesselation. */
1965  tris = static_cast<unsigned int(*)[3]>(MEM_malloc_arrayN(totfilltri, sizeof(*tris), __func__));
1966  projverts = static_cast<float(*)[2]>(MEM_malloc_arrayN(flen, sizeof(*projverts), __func__));
1967  axis_dominant_v3_to_m3_negate(axis_mat, no);
1968  for (int j = 0; j < flen; ++j) {
1969  const double3 &dco = (*f)[j]->co;
1970  float co[3] = {float(dco[0]), float(dco[1]), float(dco[2])};
1971  mul_v2_m3v3(projverts[j], axis_mat, co);
1972  }
1973  BLI_polyfill_calc(projverts, flen, 1, tris);
1974  /* Put tesselation triangles into Face form. Record original edges where they exist. */
1975  Array<Face *> ans(totfilltri);
1976  for (int t = 0; t < totfilltri; ++t) {
1977  unsigned int *tri = tris[t];
1978  int eo[3];
1979  const Vert *v[3];
1980  for (int k = 0; k < 3; k++) {
1981  BLI_assert(tri[k] < flen);
1982  v[k] = (*f)[tri[k]];
1983  /* If tri edge goes between two successive indices in
1984  * the original face, then it is an original edge. */
1985  if ((tri[k] + 1) % flen == tri[(k + 1) % 3]) {
1986  eo[k] = f->edge_orig[tri[k]];
1987  }
1988  else {
1989  eo[k] = NO_INDEX;
1990  }
1991  ans[t] = arena->add_face(
1992  {v[0], v[1], v[2]}, f->orig, {eo[0], eo[1], eo[2]}, {false, false, false});
1993  }
1994  }
1995 
1996  MEM_freeN(tris);
1997  MEM_freeN(projverts);
1998 
1999  return ans;
2000 }
2001 
2017 static Array<Face *> triangulate_poly(Face *f, IMeshArena *arena)
2018 {
2019  int flen = f->size();
2020  CDT_input<mpq_class> cdt_in;
2021  cdt_in.vert = Array<mpq2>(flen);
2022  cdt_in.face = Array<Vector<int>>(1);
2023  cdt_in.face[0].reserve(flen);
2024  for (int i : f->index_range()) {
2025  cdt_in.face[0].append(i);
2026  }
2027  /* Project poly along dominant axis of normal to get 2d coords. */
2028  if (!f->plane_populated()) {
2029  f->populate_plane(false);
2030  }
2031  const double3 &poly_normal = f->plane->norm;
2032  int axis = double3::dominant_axis(poly_normal);
2033  /* If project down y axis as opposed to x or z, the orientation
2034  * of the polygon will be reversed.
2035  * Yet another reversal happens if the poly normal in the dominant
2036  * direction is opposite that of the positive dominant axis. */
2037  bool rev1 = (axis == 1);
2038  bool rev2 = poly_normal[axis] < 0;
2039  bool rev = rev1 ^ rev2;
2040  for (int i = 0; i < flen; ++i) {
2041  int ii = rev ? flen - i - 1 : i;
2042  mpq2 &p2d = cdt_in.vert[ii];
2043  int k = 0;
2044  for (int j = 0; j < 3; ++j) {
2045  if (j != axis) {
2046  p2d[k++] = (*f)[ii]->co_exact[j];
2047  }
2048  }
2049  }
2050  CDT_result<mpq_class> cdt_out = delaunay_2d_calc(cdt_in, CDT_INSIDE);
2051  int n_tris = cdt_out.face.size();
2052  Array<Face *> ans(n_tris);
2053  for (int t = 0; t < n_tris; ++t) {
2054  int i_v_out[3];
2055  const Vert *v[3];
2056  int eo[3];
2057  bool needs_steiner = false;
2058  for (int i = 0; i < 3; ++i) {
2059  i_v_out[i] = cdt_out.face[t][i];
2060  if (cdt_out.vert_orig[i_v_out[i]].size() == 0) {
2061  needs_steiner = true;
2062  break;
2063  }
2064  v[i] = (*f)[cdt_out.vert_orig[i_v_out[i]][0]];
2065  }
2066  if (needs_steiner) {
2067  /* Fall back on the polyfill triangulator. */
2068  return polyfill_triangulate_poly(f, arena);
2069  }
2070  Map<std::pair<int, int>, int> verts_to_edge;
2071  populate_cdt_edge_map(verts_to_edge, cdt_out);
2072  int foff = cdt_out.face_edge_offset;
2073  for (int i = 0; i < 3; ++i) {
2074  std::pair<int, int> vpair(i_v_out[i], i_v_out[(i + 1) % 3]);
2075  std::pair<int, int> vpair_canon = sorted_int_pair(vpair);
2076  int e_out = verts_to_edge.lookup_default(vpair_canon, NO_INDEX);
2077  BLI_assert(e_out != NO_INDEX);
2078  eo[i] = NO_INDEX;
2079  for (int orig : cdt_out.edge_orig[e_out]) {
2080  if (orig >= foff) {
2081  int pos = orig % foff;
2082  BLI_assert(pos < f->size());
2083  eo[i] = f->edge_orig[pos];
2084  break;
2085  }
2086  }
2087  }
2088  if (rev) {
2089  ans[t] = arena->add_face(
2090  {v[0], v[2], v[1]}, f->orig, {eo[2], eo[1], eo[0]}, {false, false, false});
2091  }
2092  else {
2093  ans[t] = arena->add_face(
2094  {v[0], v[1], v[2]}, f->orig, {eo[0], eo[1], eo[2]}, {false, false, false});
2095  }
2096  }
2097  return ans;
2098 }
2099 
2106 IMesh triangulate_polymesh(IMesh &imesh, IMeshArena *arena)
2107 {
2108  Vector<Face *> face_tris;
2109  constexpr int estimated_tris_per_face = 3;
2110  face_tris.reserve(estimated_tris_per_face * imesh.face_size());
2111  for (Face *f : imesh.faces()) {
2112  /* Tessellate face f, following plan similar to #BM_face_calc_tesselation. */
2113  int flen = f->size();
2114  if (flen == 3) {
2115  face_tris.append(f);
2116  }
2117  else if (flen == 4) {
2118  const Vert *v0 = (*f)[0];
2119  const Vert *v1 = (*f)[1];
2120  const Vert *v2 = (*f)[2];
2121  const Vert *v3 = (*f)[3];
2122  int eo_01 = f->edge_orig[0];
2123  int eo_12 = f->edge_orig[1];
2124  int eo_23 = f->edge_orig[2];
2125  int eo_30 = f->edge_orig[3];
2126  Face *f0 = arena->add_face({v0, v1, v2}, f->orig, {eo_01, eo_12, -1}, {false, false, false});
2127  Face *f1 = arena->add_face({v0, v2, v3}, f->orig, {-1, eo_23, eo_30}, {false, false, false});
2128  face_tris.append(f0);
2129  face_tris.append(f1);
2130  }
2131  else {
2132  Array<Face *> tris = triangulate_poly(f, arena);
2133  for (Face *tri : tris) {
2134  face_tris.append(tri);
2135  }
2136  }
2137  }
2138  return IMesh(face_tris);
2139 }
2140 
2145 static IMesh extract_subdivided_tri(const CDT_data &cd,
2146  const IMesh &in_tm,
2147  int t,
2148  IMeshArena *arena)
2149 {
2150  const CDT_result<mpq_class> &cdt_out = cd.cdt_out;
2151  int t_in_cdt = -1;
2152  for (int i = 0; i < cd.input_face.size(); ++i) {
2153  if (cd.input_face[i] == t) {
2154  t_in_cdt = i;
2155  }
2156  }
2157  if (t_in_cdt == -1) {
2158  std::cout << "Could not find " << t << " in cdt input tris\n";
2159  BLI_assert(false);
2160  return IMesh();
2161  }
2162  constexpr int inline_buf_size = 20;
2163  Vector<Face *, inline_buf_size> faces;
2164  for (int f : cdt_out.face.index_range()) {
2165  if (cdt_out.face_orig[f].contains(t_in_cdt)) {
2166  Face *facep = cdt_tri_as_imesh_face(f, t_in_cdt, cd, in_tm, arena);
2167  faces.append(facep);
2168  }
2169  }
2170  return IMesh(faces);
2171 }
2172 
2173 static bool bvhtreeverlap_cmp(const BVHTreeOverlap &a, const BVHTreeOverlap &b)
2174 {
2175  if (a.indexA < b.indexA) {
2176  return true;
2177  }
2178  if ((a.indexA == b.indexA) & (a.indexB < b.indexB)) {
2179  return true;
2180  }
2181  return false;
2182 }
2183 class TriOverlaps {
2184  BVHTree *tree_{nullptr};
2185  BVHTree *tree_b_{nullptr};
2186  BVHTreeOverlap *overlap_{nullptr};
2187  Array<int> first_overlap_;
2188  uint overlap_tot_{0};
2189 
2190  struct CBData {
2191  const IMesh &tm;
2192  std::function<int(int)> shape_fn;
2193  int nshapes;
2194  bool use_self;
2195  };
2196 
2197  public:
2198  TriOverlaps(const IMesh &tm,
2199  const Array<BoundingBox> &tri_bb,
2200  int nshapes,
2201  std::function<int(int)> shape_fn,
2202  bool use_self)
2203  {
2204  constexpr int dbg_level = 0;
2205  if (dbg_level > 0) {
2206  std::cout << "TriOverlaps construction\n";
2207  }
2208  /* Tree type is 8 => octree; axis = 6 => using XYZ axes only. */
2209  tree_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6);
2210  /* In the common case of a binary boolean and no self intersection in
2211  * each shape, we will use two trees and simple bounding box overlap. */
2212  bool two_trees_no_self = nshapes == 2 && !use_self;
2213  if (two_trees_no_self) {
2214  tree_b_ = BLI_bvhtree_new(tm.face_size(), FLT_EPSILON, 8, 6);
2215  }
2216  float bbpts[6];
2217  for (int t : tm.face_index_range()) {
2218  const BoundingBox &bb = tri_bb[t];
2219  copy_v3_v3(bbpts, bb.min);
2220  copy_v3_v3(bbpts + 3, bb.max);
2221  int shape = shape_fn(tm.face(t)->orig);
2222  if (two_trees_no_self) {
2223  if (shape == 0) {
2224  BLI_bvhtree_insert(tree_, t, bbpts, 2);
2225  }
2226  else if (shape == 1) {
2227  BLI_bvhtree_insert(tree_b_, t, bbpts, 2);
2228  }
2229  }
2230  else {
2231  if (shape != -1) {
2232  BLI_bvhtree_insert(tree_, t, bbpts, 2);
2233  }
2234  }
2235  }
2236  BLI_bvhtree_balance(tree_);
2237  if (two_trees_no_self) {
2238  BLI_bvhtree_balance(tree_b_);
2239  /* Don't expect a lot of trivial intersects in this case. */
2240  overlap_ = BLI_bvhtree_overlap(tree_, tree_b_, &overlap_tot_, nullptr, nullptr);
2241  }
2242  else {
2243  CBData cbdata{tm, shape_fn, nshapes, use_self};
2244  if (nshapes == 1) {
2245  overlap_ = BLI_bvhtree_overlap(tree_, tree_, &overlap_tot_, nullptr, nullptr);
2246  }
2247  else {
2248  overlap_ = BLI_bvhtree_overlap(
2249  tree_, tree_, &overlap_tot_, only_different_shapes, &cbdata);
2250  }
2251  }
2252  /* The rest of the code is simpler and easier to parallelize if, in the two-trees case,
2253  * we repeat the overlaps with indexA and indexB reversed. It is important that
2254  * in the repeated part, sorting will then bring things with indexB together. */
2255  if (two_trees_no_self) {
2256  overlap_ = static_cast<BVHTreeOverlap *>(
2257  MEM_reallocN(overlap_, 2 * overlap_tot_ * sizeof(overlap_[0])));
2258  for (uint i = 0; i < overlap_tot_; ++i) {
2259  overlap_[overlap_tot_ + i].indexA = overlap_[i].indexB;
2260  overlap_[overlap_tot_ + i].indexB = overlap_[i].indexA;
2261  }
2262  overlap_tot_ += overlap_tot_;
2263  }
2264  /* Sort the overlaps to bring all the intersects with a given indexA together. */
2265  std::sort(overlap_, overlap_ + overlap_tot_, bvhtreeverlap_cmp);
2266  if (dbg_level > 0) {
2267  std::cout << overlap_tot_ << " overlaps found:\n";
2268  for (BVHTreeOverlap ov : overlap()) {
2269  std::cout << "A: " << ov.indexA << ", B: " << ov.indexB << "\n";
2270  }
2271  }
2272  first_overlap_ = Array<int>(tm.face_size(), -1);
2273  for (int i = 0; i < static_cast<int>(overlap_tot_); ++i) {
2274  int t = overlap_[i].indexA;
2275  if (first_overlap_[t] == -1) {
2276  first_overlap_[t] = i;
2277  }
2278  }
2279  }
2280 
2281  ~TriOverlaps()
2282  {
2283  if (tree_) {
2284  BLI_bvhtree_free(tree_);
2285  }
2286  if (tree_b_) {
2287  BLI_bvhtree_free(tree_b_);
2288  }
2289  if (overlap_) {
2290  MEM_freeN(overlap_);
2291  }
2292  }
2293 
2294  Span<BVHTreeOverlap> overlap() const
2295  {
2296  return Span<BVHTreeOverlap>(overlap_, overlap_tot_);
2297  }
2298 
2299  int first_overlap_index(int t) const
2300  {
2301  return first_overlap_[t];
2302  }
2303 
2304  private:
2305  static bool only_different_shapes(void *userdata, int index_a, int index_b, int UNUSED(thread))
2306  {
2307  CBData *cbdata = static_cast<CBData *>(userdata);
2308  return cbdata->tm.face(index_a)->orig != cbdata->tm.face(index_b)->orig;
2309  }
2310 };
2311 
2315 struct OverlapIttsData {
2316  Vector<std::pair<int, int>> intersect_pairs;
2317  Map<std::pair<int, int>, ITT_value> &itt_map;
2318  const IMesh &tm;
2319  IMeshArena *arena;
2320 
2321  OverlapIttsData(Map<std::pair<int, int>, ITT_value> &itt_map, const IMesh &tm, IMeshArena *arena)
2322  : itt_map(itt_map), tm(tm), arena(arena)
2323  {
2324  }
2325 };
2326 
2331 static std::pair<int, int> canon_int_pair(int a, int b)
2332 {
2333  if (a > b) {
2334  std::swap(a, b);
2335  }
2336  return std::pair<int, int>(a, b);
2337 }
2338 
2339 static void calc_overlap_itts_range_func(void *__restrict userdata,
2340  const int iter,
2341  const TaskParallelTLS *__restrict UNUSED(tls))
2342 {
2343  constexpr int dbg_level = 0;
2344  OverlapIttsData *data = static_cast<OverlapIttsData *>(userdata);
2345  std::pair<int, int> tri_pair = data->intersect_pairs[iter];
2346  int a = tri_pair.first;
2347  int b = tri_pair.second;
2348  if (dbg_level > 0) {
2349  std::cout << "calc_overlap_itts_range_func a=" << a << ", b=" << b << "\n";
2350  }
2351  ITT_value itt = intersect_tri_tri(data->tm, a, b);
2352  if (dbg_level > 0) {
2353  std::cout << "result of intersecting " << a << " and " << b << " = " << itt << "\n";
2354  }
2355  BLI_assert(data->itt_map.contains(tri_pair));
2356  data->itt_map.add_overwrite(tri_pair, itt);
2357 }
2358 
2363 static void calc_overlap_itts(Map<std::pair<int, int>, ITT_value> &itt_map,
2364  const IMesh &tm,
2365  const TriOverlaps &ov,
2366  IMeshArena *arena)
2367 {
2368  OverlapIttsData data(itt_map, tm, arena);
2369  /* Put dummy values in `itt_map` initially,
2370  * so map entries will exist when doing the range function.
2371  * This means we won't have to protect the `itt_map.add_overwrite` function with a lock. */
2372  for (const BVHTreeOverlap &olap : ov.overlap()) {
2373  std::pair<int, int> key = canon_int_pair(olap.indexA, olap.indexB);
2374  if (!itt_map.contains(key)) {
2375  itt_map.add_new(key, ITT_value());
2376  data.intersect_pairs.append(key);
2377  }
2378  }
2379  int tot_intersect_pairs = data.intersect_pairs.size();
2380  TaskParallelSettings settings;
2382  settings.min_iter_per_thread = 1000;
2383  settings.use_threading = intersect_use_threading;
2384  BLI_task_parallel_range(0, tot_intersect_pairs, &data, calc_overlap_itts_range_func, &settings);
2385 }
2386 
2390 struct OverlapTriRange {
2391  int tri_index;
2392  int overlap_start;
2393  int len;
2394 };
2395 struct SubdivideTrisData {
2396  Array<IMesh> &r_tri_subdivided;
2397  const IMesh &tm;
2398  const Map<std::pair<int, int>, ITT_value> &itt_map;
2399  Span<BVHTreeOverlap> overlap;
2400  IMeshArena *arena;
2401 
2402  /* This vector gives, for each triangle in tm that has an intersection
2403  * we want to calculate: what the index of that triangle in tm is,
2404  * where it starts in the ov structure as indexA, and how many
2405  * overlap pairs have that same indexA (they will be continuous). */
2406  Vector<OverlapTriRange> overlap_tri_range;
2407 
2408  SubdivideTrisData(Array<IMesh> &r_tri_subdivided,
2409  const IMesh &tm,
2410  const Map<std::pair<int, int>, ITT_value> &itt_map,
2411  Span<BVHTreeOverlap> overlap,
2412  IMeshArena *arena)
2413  : r_tri_subdivided(r_tri_subdivided),
2414  tm(tm),
2415  itt_map(itt_map),
2416  overlap(overlap),
2417  arena(arena)
2418  {
2419  }
2420 };
2421 
2422 static void calc_subdivided_tri_range_func(void *__restrict userdata,
2423  const int iter,
2424  const TaskParallelTLS *__restrict UNUSED(tls))
2425 {
2426  constexpr int dbg_level = 0;
2427  SubdivideTrisData *data = static_cast<SubdivideTrisData *>(userdata);
2428  OverlapTriRange &otr = data->overlap_tri_range[iter];
2429  int t = otr.tri_index;
2430  if (dbg_level > 0) {
2431  std::cout << "calc_subdivided_tri_range_func\nt=" << t << " start=" << otr.overlap_start
2432  << " len=" << otr.len << "\n";
2433  }
2434  constexpr int inline_capacity = 100;
2435  Vector<ITT_value, inline_capacity> itts(otr.len);
2436  for (int j = otr.overlap_start; j < otr.overlap_start + otr.len; ++j) {
2437  int t_other = data->overlap[j].indexB;
2438  std::pair<int, int> key = canon_int_pair(t, t_other);
2439  ITT_value itt;
2440  if (data->itt_map.contains(key)) {
2441  itt = data->itt_map.lookup(key);
2442  }
2443  if (itt.kind != INONE) {
2444  itts.append(itt);
2445  }
2446  if (dbg_level > 0) {
2447  std::cout << " tri t" << t_other << "; result = " << itt << "\n";
2448  }
2449  }
2450  if (itts.size() > 0) {
2451  CDT_data cd_data = prepare_cdt_input(data->tm, t, itts);
2452  do_cdt(cd_data);
2453  data->r_tri_subdivided[t] = extract_subdivided_tri(cd_data, data->tm, t, data->arena);
2454  if (dbg_level > 0) {
2455  std::cout << "subdivide output\n" << data->r_tri_subdivided[t];
2456  }
2457  }
2458 }
2459 
2466 static void calc_subdivided_non_cluster_tris(Array<IMesh> &r_tri_subdivided,
2467  const IMesh &tm,
2468  const Map<std::pair<int, int>, ITT_value> &itt_map,
2469  const CoplanarClusterInfo &clinfo,
2470  const TriOverlaps &ov,
2471  IMeshArena *arena)
2472 {
2473  const int dbg_level = 0;
2474  if (dbg_level > 0) {
2475  std::cout << "\nCALC_SUBDIVIDED_TRIS\n\n";
2476  }
2477  Span<BVHTreeOverlap> overlap = ov.overlap();
2478  SubdivideTrisData data(r_tri_subdivided, tm, itt_map, overlap, arena);
2479  int overlap_tot = overlap.size();
2480  data.overlap_tri_range = Vector<OverlapTriRange>();
2481  data.overlap_tri_range.reserve(overlap_tot);
2482  int overlap_index = 0;
2483  while (overlap_index < overlap_tot) {
2484  int t = overlap[overlap_index].indexA;
2485  int i = overlap_index;
2486  while (i + 1 < overlap_tot && overlap[i + 1].indexA == t) {
2487  ++i;
2488  }
2489  /* Now overlap[overlap_index] to overlap[i] have indexA == t.
2490  * We only record ranges for triangles that are not in clusters,
2491  * because the ones in clusters are handled separately. */
2492  if (clinfo.tri_cluster(t) == NO_INDEX) {
2493  int len = i - overlap_index + 1;
2494  if (!(len == 1 && overlap[overlap_index].indexB == t)) {
2495  OverlapTriRange range = {t, overlap_index, len};
2496  data.overlap_tri_range.append(range);
2497 # ifdef PERFDEBUG
2498  bumpperfcount(0, len); /* Non-cluster overlaps. */
2499 # endif
2500  }
2501  }
2502  overlap_index = i + 1;
2503  }
2504  int overlap_tri_range_tot = data.overlap_tri_range.size();
2505  TaskParallelSettings settings;
2507  settings.min_iter_per_thread = 50;
2508  settings.use_threading = intersect_use_threading;
2510  0, overlap_tri_range_tot, &data, calc_subdivided_tri_range_func, &settings);
2511  /* Now have to put in the triangles that are the same as the input ones, and not in clusters.
2512  */
2513  for (int t : tm.face_index_range()) {
2514  if (r_tri_subdivided[t].face_size() == 0 && clinfo.tri_cluster(t) == NO_INDEX) {
2515  r_tri_subdivided[t] = IMesh({tm.face(t)});
2516  }
2517  }
2518 }
2519 
2527 static void calc_cluster_tris(Array<IMesh> &tri_subdivided,
2528  const IMesh &tm,
2529  const CoplanarClusterInfo &clinfo,
2530  const Array<CDT_data> &cluster_subdivided,
2531  IMeshArena *arena)
2532 {
2533  for (int c : clinfo.index_range()) {
2534  const CoplanarCluster &cl = clinfo.cluster(c);
2535  const CDT_data &cd = cluster_subdivided[c];
2536  /* Each triangle in cluster c should be an input triangle in cd.input_faces.
2537  * (See prepare_cdt_input_for_cluster.)
2538  * So accumulate a Vector of Face* for each input face by going through the
2539  * output faces and making a Face for each input face that it is part of.
2540  * (The Boolean algorithm wants duplicates if a given output triangle is part
2541  * of more than one input triangle.)
2542  */
2543  int n_cluster_tris = cl.tot_tri();
2544  const CDT_result<mpq_class> &cdt_out = cd.cdt_out;
2545  BLI_assert(cd.input_face.size() == n_cluster_tris);
2546  Array<Vector<Face *>> face_vec(n_cluster_tris);
2547  for (int cdt_out_t : cdt_out.face.index_range()) {
2548  for (int cdt_in_t : cdt_out.face_orig[cdt_out_t]) {
2549  Face *f = cdt_tri_as_imesh_face(cdt_out_t, cdt_in_t, cd, tm, arena);
2550  face_vec[cdt_in_t].append(f);
2551  }
2552  }
2553  for (int cdt_in_t : cd.input_face.index_range()) {
2554  int tm_t = cd.input_face[cdt_in_t];
2555  BLI_assert(tri_subdivided[tm_t].face_size() == 0);
2556  tri_subdivided[tm_t] = IMesh(face_vec[cdt_in_t]);
2557  }
2558  }
2559 }
2560 
2561 static CDT_data calc_cluster_subdivided(const CoplanarClusterInfo &clinfo,
2562  int c,
2563  const IMesh &tm,
2564  const TriOverlaps &ov,
2565  const Map<std::pair<int, int>, ITT_value> &itt_map,
2566  IMeshArena *UNUSED(arena))
2567 {
2568  constexpr int dbg_level = 0;
2569  BLI_assert(c < clinfo.tot_cluster());
2570  const CoplanarCluster &cl = clinfo.cluster(c);
2571  /* Make a CDT input with triangles from C and intersects from other triangles in tm. */
2572  if (dbg_level > 0) {
2573  std::cout << "CALC_CLUSTER_SUBDIVIDED for cluster " << c << " = " << cl << "\n";
2574  }
2575  /* Get vector itts of all intersections of a triangle of cl with any triangle of tm not
2576  * in cl and not co-planar with it (for that latter, if there were an intersection,
2577  * it should already be in cluster cl). */
2578  Vector<ITT_value> itts;
2579  Span<BVHTreeOverlap> ovspan = ov.overlap();
2580  for (int t : cl) {
2581  if (dbg_level > 0) {
2582  std::cout << "find intersects with triangle " << t << " of cluster\n";
2583  }
2584  int first_i = ov.first_overlap_index(t);
2585  if (first_i == -1) {
2586  continue;
2587  }
2588  for (int i = first_i; i < ovspan.size() && ovspan[i].indexA == t; ++i) {
2589  int t_other = ovspan[i].indexB;
2590  if (clinfo.tri_cluster(t_other) != c) {
2591  if (dbg_level > 0) {
2592  std::cout << "use intersect(" << t << "," << t_other << "\n";
2593  }
2594  std::pair<int, int> key = canon_int_pair(t, t_other);
2595  if (itt_map.contains(key)) {
2596  ITT_value itt = itt_map.lookup(key);
2597  if (!ELEM(itt.kind, INONE, ICOPLANAR)) {
2598  itts.append(itt);
2599  if (dbg_level > 0) {
2600  std::cout << " itt = " << itt << "\n";
2601  }
2602  }
2603  }
2604  }
2605  }
2606  }
2607  /* Use CDT to subdivide the cluster triangles and the points and segments in itts. */
2608  CDT_data cd_data = prepare_cdt_input_for_cluster(tm, clinfo, c, itts);
2609  do_cdt(cd_data);
2610  return cd_data;
2611 }
2612 
2613 static IMesh union_tri_subdivides(const blender::Array<IMesh> &tri_subdivided)
2614 {
2615  int tot_tri = 0;
2616  for (const IMesh &m : tri_subdivided) {
2617  tot_tri += m.face_size();
2618  }
2619  Array<Face *> faces(tot_tri);
2620  int face_index = 0;
2621  for (const IMesh &m : tri_subdivided) {
2622  for (Face *f : m.faces()) {
2623  faces[face_index++] = f;
2624  }
2625  }
2626  return IMesh(faces);
2627 }
2628 
2629 static CoplanarClusterInfo find_clusters(const IMesh &tm,
2630  const Array<BoundingBox> &tri_bb,
2631  const Map<std::pair<int, int>, ITT_value> &itt_map)
2632 {
2633  constexpr int dbg_level = 0;
2634  if (dbg_level > 0) {
2635  std::cout << "FIND_CLUSTERS\n";
2636  }
2637  CoplanarClusterInfo ans(tm.face_size());
2638  /* Use a VectorSet to get stable order from run to run. */
2639  VectorSet<int> maybe_coplanar_tris;
2640  maybe_coplanar_tris.reserve(2 * itt_map.size());
2641  for (auto item : itt_map.items()) {
2642  if (item.value.kind == ICOPLANAR) {
2643  int t1 = item.key.first;
2644  int t2 = item.key.second;
2645  maybe_coplanar_tris.add_multiple({t1, t2});
2646  }
2647  }
2648  if (dbg_level > 0) {
2649  std::cout << "found " << maybe_coplanar_tris.size() << " possible coplanar tris\n";
2650  }
2651  if (maybe_coplanar_tris.size() == 0) {
2652  if (dbg_level > 0) {
2653  std::cout << "No possible coplanar tris, so no clusters\n";
2654  }
2655  return ans;
2656  }
2657  /* There can be more than one #CoplanarCluster per plane. Accumulate them in
2658  * a Vector. We will have to merge some elements of the Vector as we discover
2659  * triangles that form intersection bridges between two or more clusters. */
2660  Map<Plane, Vector<CoplanarCluster>> plane_cls;
2661  plane_cls.reserve(maybe_coplanar_tris.size());
2662  for (int t : maybe_coplanar_tris) {
2663  /* Use a canonical version of the plane for map index.
2664  * We can't just store the canonical version in the face
2665  * since canonicalizing loses the orientation of the normal. */
2666  Plane tplane = *tm.face(t)->plane;
2667  BLI_assert(tplane.exact_populated());
2668  tplane.make_canonical();
2669  if (dbg_level > 0) {
2670  std::cout << "plane for tri " << t << " = " << &tplane << "\n";
2671  }
2672  /* Assume all planes are in canonical from (see canon_plane()). */
2673  if (plane_cls.contains(tplane)) {
2674  Vector<CoplanarCluster> &curcls = plane_cls.lookup(tplane);
2675  if (dbg_level > 0) {
2676  std::cout << "already has " << curcls.size() << " clusters\n";
2677  }
2678  /* Partition `curcls` into those that intersect t non-trivially, and those that don't. */
2679  Vector<CoplanarCluster *> int_cls;
2680  Vector<CoplanarCluster *> no_int_cls;
2681  for (CoplanarCluster &cl : curcls) {
2682  if (dbg_level > 1) {
2683  std::cout << "consider intersecting with cluster " << cl << "\n";
2684  }
2685  if (bbs_might_intersect(tri_bb[t], cl.bounding_box())) {
2686  if (dbg_level > 1) {
2687  std::cout << "append to int_cls\n";
2688  }
2689  int_cls.append(&cl);
2690  }
2691  else {
2692  if (dbg_level > 1) {
2693  std::cout << "append to no_int_cls\n";
2694  }
2695  no_int_cls.append(&cl);
2696  }
2697  }
2698  if (int_cls.size() == 0) {
2699  /* t doesn't intersect any existing cluster in its plane, so make one just for it. */
2700  if (dbg_level > 1) {
2701  std::cout << "no intersecting clusters for t, make a new one\n";
2702  }
2703  curcls.append(CoplanarCluster(t, tri_bb[t]));
2704  }
2705  else if (int_cls.size() == 1) {
2706  /* t intersects exactly one existing cluster, so can add t to that cluster. */
2707  if (dbg_level > 1) {
2708  std::cout << "exactly one existing cluster, " << int_cls[0] << ", adding to it\n";
2709  }
2710  int_cls[0]->add_tri(t, tri_bb[t]);
2711  }
2712  else {
2713  /* t intersections 2 or more existing clusters: need to merge them and replace all the
2714  * originals with the merged one in `curcls`. */
2715  if (dbg_level > 1) {
2716  std::cout << "merging\n";
2717  }
2718  CoplanarCluster mergecl;
2719  mergecl.add_tri(t, tri_bb[t]);
2720  for (CoplanarCluster *cl : int_cls) {
2721  for (int t : *cl) {
2722  mergecl.add_tri(t, tri_bb[t]);
2723  }
2724  }
2725  Vector<CoplanarCluster> newvec;
2726  newvec.append(mergecl);
2727  for (CoplanarCluster *cl_no_int : no_int_cls) {
2728  newvec.append(*cl_no_int);
2729  }
2730  plane_cls.add_overwrite(tplane, newvec);
2731  }
2732  }
2733  else {
2734  if (dbg_level > 0) {
2735  std::cout << "first cluster for its plane\n";
2736  }
2737  plane_cls.add_new(tplane, Vector<CoplanarCluster>{CoplanarCluster(t, tri_bb[t])});
2738  }
2739  }
2740  /* Does this give deterministic order for cluster ids? I think so, since
2741  * hash for planes is on their values, not their addresses. */
2742  for (auto item : plane_cls.items()) {
2743  for (const CoplanarCluster &cl : item.value) {
2744  if (cl.tot_tri() > 1) {
2745  ans.add_cluster(cl);
2746  }
2747  }
2748  }
2749 
2750  return ans;
2751 }
2752 
2753 static bool face_is_degenerate(const Face *f)
2754 {
2755  const Face &face = *f;
2756  const Vert *v0 = face[0];
2757  const Vert *v1 = face[1];
2758  const Vert *v2 = face[2];
2759  if (v0 == v1 || v0 == v2 || v1 == v2) {
2760  return true;
2761  }
2762  double3 da = v2->co - v0->co;
2763  double3 db = v2->co - v1->co;
2764  double3 dab = double3::cross_high_precision(da, db);
2765  double dab_length_squared = dab.length_squared();
2766  double err_bound = supremum_dot_cross(dab, dab) * index_dot_cross * DBL_EPSILON;
2767  if (dab_length_squared > err_bound) {
2768  return false;
2769  }
2770  mpq3 a = v2->co_exact - v0->co_exact;
2771  mpq3 b = v2->co_exact - v1->co_exact;
2772  mpq3 ab = mpq3::cross(a, b);
2773  if (ab.x == 0 && ab.y == 0 && ab.z == 0) {
2774  return true;
2775  }
2776 
2777  return false;
2778 }
2779 
2780 /* Data and functions to test triangle degeneracy in parallel. */
2781 struct DegenData {
2782  const IMesh &tm;
2783 };
2784 
2785 struct DegenChunkData {
2786  bool has_degenerate_tri = false;
2787 };
2788 
2789 static void degenerate_range_func(void *__restrict userdata,
2790  const int iter,
2791  const TaskParallelTLS *__restrict tls)
2792 {
2793  DegenData *data = static_cast<DegenData *>(userdata);
2794  DegenChunkData *chunk_data = static_cast<DegenChunkData *>(tls->userdata_chunk);
2795  const Face *f = data->tm.face(iter);
2796  bool is_degenerate = face_is_degenerate(f);
2797  chunk_data->has_degenerate_tri |= is_degenerate;
2798 }
2799 
2800 static void degenerate_reduce(const void *__restrict UNUSED(userdata),
2801  void *__restrict chunk_join,
2802  void *__restrict chunk)
2803 {
2804  DegenChunkData *degen_chunk_join = static_cast<DegenChunkData *>(chunk_join);
2805  DegenChunkData *degen_chunk = static_cast<DegenChunkData *>(chunk);
2806  degen_chunk_join->has_degenerate_tri |= degen_chunk->has_degenerate_tri;
2807 }
2808 
2809 /* Does triangle #IMesh tm have any triangles with zero area? */
2810 static bool has_degenerate_tris(const IMesh &tm)
2811 {
2812  DegenData degen_data = {tm};
2813  DegenChunkData degen_chunk_data;
2814  TaskParallelSettings settings;
2816  settings.userdata_chunk = &degen_chunk_data;
2817  settings.userdata_chunk_size = sizeof(degen_chunk_data);
2818  settings.func_reduce = degenerate_reduce;
2819  settings.min_iter_per_thread = 1000;
2820  settings.use_threading = intersect_use_threading;
2821  BLI_task_parallel_range(0, tm.face_size(), &degen_data, degenerate_range_func, &settings);
2822  return degen_chunk_data.has_degenerate_tri;
2823 }
2824 
2825 static IMesh remove_degenerate_tris(const IMesh &tm_in)
2826 {
2827  IMesh ans;
2828  Vector<Face *> new_faces;
2829  new_faces.reserve(tm_in.face_size());
2830  for (Face *f : tm_in.faces()) {
2831  if (!face_is_degenerate(f)) {
2832  new_faces.append(f);
2833  }
2834  }
2835  ans.set_faces(new_faces);
2836  return ans;
2837 }
2838 
2839 /* This is the main routine for calculating the self_intersection of a triangle mesh. */
2840 IMesh trimesh_self_intersect(const IMesh &tm_in, IMeshArena *arena)
2841 {
2842  return trimesh_nary_intersect(
2843  tm_in, 1, [](int UNUSED(t)) { return 0; }, true, arena);
2844 }
2845 
2846 IMesh trimesh_nary_intersect(const IMesh &tm_in,
2847  int nshapes,
2848  std::function<int(int)> shape_fn,
2849  bool use_self,
2850  IMeshArena *arena)
2851 {
2852  constexpr int dbg_level = 0;
2853  if (dbg_level > 0) {
2854  std::cout << "\nTRIMESH_NARY_INTERSECT nshapes=" << nshapes << " use_self=" << use_self
2855  << "\n";
2856  for (const Face *f : tm_in.faces()) {
2857  BLI_assert(f->is_tri());
2858  UNUSED_VARS_NDEBUG(f);
2859  }
2860  if (dbg_level > 1) {
2861  std::cout << "input mesh:\n" << tm_in;
2862  for (int t : tm_in.face_index_range()) {
2863  std::cout << "shape(" << t << ") = " << shape_fn(tm_in.face(t)->orig) << "\n";
2864  }
2865  write_obj_mesh(const_cast<IMesh &>(tm_in), "trimesh_input");
2866  }
2867  }
2868 # ifdef PERFDEBUG
2869  perfdata_init();
2870  double start_time = PIL_check_seconds_timer();
2871  std::cout << "trimesh_nary_intersect start\n";
2872 # endif
2873  /* Usually can use tm_in but if it has degenerate or illegal triangles,
2874  * then need to work on a copy of it without those triangles. */
2875  const IMesh *tm_clean = &tm_in;
2876  IMesh tm_cleaned;
2877  if (has_degenerate_tris(tm_in)) {
2878  if (dbg_level > 0) {
2879  std::cout << "cleaning degenerate triangles\n";
2880  }
2881  tm_cleaned = remove_degenerate_tris(tm_in);
2882  tm_clean = &tm_cleaned;
2883  if (dbg_level > 1) {
2884  std::cout << "cleaned input mesh:\n" << tm_cleaned;
2885  }
2886  }
2887 # ifdef PERFDEBUG
2888  double clean_time = PIL_check_seconds_timer();
2889  std::cout << "cleaned, time = " << clean_time - start_time << "\n";
2890 # endif
2891  Array<BoundingBox> tri_bb = calc_face_bounding_boxes(*tm_clean);
2892 # ifdef PERFDEBUG
2893  double bb_calc_time = PIL_check_seconds_timer();
2894  std::cout << "bbs calculated, time = " << bb_calc_time - clean_time << "\n";
2895 # endif
2896  TriOverlaps tri_ov(*tm_clean, tri_bb, nshapes, shape_fn, use_self);
2897 # ifdef PERFDEBUG
2898  double overlap_time = PIL_check_seconds_timer();
2899  std::cout << "intersect overlaps calculated, time = " << overlap_time - bb_calc_time << "\n";
2900 # endif
2901  for (int t : tm_clean->face_index_range()) {
2902  if (tri_ov.first_overlap_index(t) != -1) {
2903  tm_clean->face(t)->populate_plane(true);
2904  }
2905  }
2906 # ifdef PERFDEBUG
2907  double plane_populate = PIL_check_seconds_timer();
2908  std::cout << "planes populated, time = " << plane_populate - overlap_time << "\n";
2909 # endif
2910  /* itt_map((a,b)) will hold the intersection value resulting from intersecting
2911  * triangles with indices a and b, where a < b. */
2912  Map<std::pair<int, int>, ITT_value> itt_map;
2913  itt_map.reserve(tri_ov.overlap().size());
2914  calc_overlap_itts(itt_map, *tm_clean, tri_ov, arena);
2915 # ifdef PERFDEBUG
2916  double itt_time = PIL_check_seconds_timer();
2917  std::cout << "itts found, time = " << itt_time - plane_populate << "\n";
2918 # endif
2919  CoplanarClusterInfo clinfo = find_clusters(*tm_clean, tri_bb, itt_map);
2920  if (dbg_level > 1) {
2921  std::cout << clinfo;
2922  }
2923 # ifdef PERFDEBUG
2924  double find_cluster_time = PIL_check_seconds_timer();
2925  std::cout << "clusters found, time = " << find_cluster_time - itt_time << "\n";
2926  doperfmax(0, tm_in.face_size());
2927  doperfmax(1, clinfo.tot_cluster());
2928  doperfmax(2, tri_ov.overlap().size());
2929 # endif
2930  Array<IMesh> tri_subdivided(tm_clean->face_size());
2931  calc_subdivided_non_cluster_tris(tri_subdivided, *tm_clean, itt_map, clinfo, tri_ov, arena);
2932 # ifdef PERFDEBUG
2933  double subdivided_tris_time = PIL_check_seconds_timer();
2934  std::cout << "subdivided non-cluster tris found, time = " << subdivided_tris_time - itt_time
2935  << "\n";
2936 # endif
2937  Array<CDT_data> cluster_subdivided(clinfo.tot_cluster());
2938  for (int c : clinfo.index_range()) {
2939  cluster_subdivided[c] = calc_cluster_subdivided(clinfo, c, *tm_clean, tri_ov, itt_map, arena);
2940  }
2941 # ifdef PERFDEBUG
2942  double cluster_subdivide_time = PIL_check_seconds_timer();
2943  std::cout << "subdivided clusters found, time = "
2944  << cluster_subdivide_time - subdivided_tris_time << "\n";
2945 # endif
2946  calc_cluster_tris(tri_subdivided, *tm_clean, clinfo, cluster_subdivided, arena);
2947 # ifdef PERFDEBUG
2948  double extract_time = PIL_check_seconds_timer();
2949  std::cout << "subdivided cluster tris found, time = " << extract_time - cluster_subdivide_time
2950  << "\n";
2951 # endif
2952  IMesh combined = union_tri_subdivides(tri_subdivided);
2953  if (dbg_level > 1) {
2954  std::cout << "TRIMESH_NARY_INTERSECT answer:\n";
2955  std::cout << combined;
2956  }
2957 # ifdef PERFDEBUG
2958  double end_time = PIL_check_seconds_timer();
2959  std::cout << "triangles combined, time = " << end_time - extract_time << "\n";
2960  std::cout << "trimesh_nary_intersect done, total time = " << end_time - start_time << "\n";
2961  dump_perfdata();
2962 # endif
2963  return combined;
2964 }
2965 
2966 static std::ostream &operator<<(std::ostream &os, const CoplanarCluster &cl)
2967 {
2968  os << "cl(";
2969  bool first = true;
2970  for (const int t : cl) {
2971  if (first) {
2972  first = false;
2973  }
2974  else {
2975  os << ",";
2976  }
2977  os << t;
2978  }
2979  os << ")";
2980  return os;
2981 }
2982 
2983 static std::ostream &operator<<(std::ostream &os, const CoplanarClusterInfo &clinfo)
2984 {
2985  os << "Coplanar Cluster Info:\n";
2986  for (int c : clinfo.index_range()) {
2987  os << c << ": " << clinfo.cluster(c) << "\n";
2988  }
2989  return os;
2990 }
2991 
2992 static std::ostream &operator<<(std::ostream &os, const ITT_value &itt)
2993 {
2994  switch (itt.kind) {
2995  case INONE:
2996  os << "none";
2997  break;
2998  case IPOINT:
2999  os << "point " << itt.p1;
3000  break;
3001  case ISEGMENT:
3002  os << "segment " << itt.p1 << " " << itt.p2;
3003  break;
3004  case ICOPLANAR:
3005  os << "co-planar t" << itt.t_source;
3006  break;
3007  }
3008  return os;
3009 }
3010 
3014 void write_obj_mesh(IMesh &m, const std::string &objname)
3015 {
3016  /* Would like to use #BKE_tempdir_base() here, but that brings in dependence on kernel library.
3017  * This is just for developer debugging anyway,
3018  * and should never be called in production Blender. */
3019 # ifdef _WIN_32
3020  const char *objdir = BLI_getenv("HOME");
3021 # else
3022  const char *objdir = "/tmp/";
3023 # endif
3024  if (m.face_size() == 0) {
3025  return;
3026  }
3027 
3028  std::string fname = std::string(objdir) + objname + std::string(".obj");
3029  std::ofstream f;
3030  f.open(fname);
3031  if (!f) {
3032  std::cout << "Could not open file " << fname << "\n";
3033  return;
3034  }
3035 
3036  if (!m.has_verts()) {
3037  m.populate_vert();
3038  }
3039  for (const Vert *v : m.vertices()) {
3040  const double3 dv = v->co;
3041  f << "v " << dv[0] << " " << dv[1] << " " << dv[2] << "\n";
3042  }
3043  int i = 0;
3044  for (const Face *face : m.faces()) {
3045  /* OBJ files use 1-indexing for vertices. */
3046  f << "f ";
3047  for (const Vert *v : *face) {
3048  int i = m.lookup_vert(v);
3049  BLI_assert(i != NO_INDEX);
3050  /* OBJ files use 1-indexing for vertices. */
3051  f << i + 1 << " ";
3052  }
3053  f << "\n";
3054  ++i;
3055  }
3056  f.close();
3057 }
3058 
3059 # ifdef PERFDEBUG
3060 struct PerfCounts {
3061  Vector<int> count;
3062  Vector<const char *> count_name;
3063  Vector<int> max;
3064  Vector<const char *> max_name;
3065 };
3066 
3067 static PerfCounts *perfdata = nullptr;
3068 
3069 static void perfdata_init(void)
3070 {
3071  perfdata = new PerfCounts;
3072 
3073  /* count 0. */
3074  perfdata->count.append(0);
3075  perfdata->count_name.append("Non-cluster overlaps");
3076 
3077  /* count 1. */
3078  perfdata->count.append(0);
3079  perfdata->count_name.append("intersect_tri_tri calls");
3080 
3081  /* count 2. */
3082  perfdata->count.append(0);
3083  perfdata->count_name.append("tri tri intersects decided by filter plane tests");
3084 
3085  /* count 3. */
3086  perfdata->count.append(0);
3087  perfdata->count_name.append("tri tri intersects decided by exact plane tests");
3088 
3089  /* count 4. */
3090  perfdata->count.append(0);
3091  perfdata->count_name.append("final non-NONE intersects");
3092 
3093  /* max 0. */
3094  perfdata->max.append(0);
3095  perfdata->max_name.append("total faces");
3096 
3097  /* max 1. */
3098  perfdata->max.append(0);
3099  perfdata->max_name.append("total clusters");
3100 
3101  /* max 2. */
3102  perfdata->max.append(0);
3103  perfdata->max_name.append("total overlaps");
3104 }
3105 
3106 static void incperfcount(int countnum)
3107 {
3108  perfdata->count[countnum]++;
3109 }
3110 
3111 static void bumpperfcount(int countnum, int amt)
3112 {
3113  perfdata->count[countnum] += amt;
3114 }
3115 
3116 static void doperfmax(int maxnum, int val)
3117 {
3118  perfdata->max[maxnum] = max_ii(perfdata->max[maxnum], val);
3119 }
3120 
3121 static void dump_perfdata(void)
3122 {
3123  std::cout << "\nPERFDATA\n";
3124  for (int i : perfdata->count.index_range()) {
3125  std::cout << perfdata->count_name[i] << " = " << perfdata->count[i] << "\n";
3126  }
3127  for (int i : perfdata->max.index_range()) {
3128  std::cout << perfdata->max_name[i] << " = " << perfdata->max[i] << "\n";
3129  }
3130  delete perfdata;
3131 }
3132 # endif
3133 
3134 } // namespace blender::meshintersect
3135 
3136 #endif // WITH_GMP
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
@ CDT_INSIDE
BVHTreeOverlap * BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_tot, BVHTree_OverlapCallback callback, void *userdata)
Definition: BLI_kdopbvh.c:1401
void BLI_bvhtree_balance(BVHTree *tree)
Definition: BLI_kdopbvh.c:956
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
Definition: BLI_kdopbvh.c:873
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
Definition: BLI_kdopbvh.c:998
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
MINLINE int max_ii(int a, int b)
MINLINE double max_dd(double a, double b)
Math vector functions needed specifically for mesh intersect and boolean.
bool isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3])
Definition: math_geom.c:3226
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
Definition: math_geom.c:3772
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
Definition: math_matrix.c:921
MINLINE float normalize_v3(float r[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
const char * BLI_getenv(const char *env) ATTR_NONNULL(1)
Definition: path_util.c:1313
void BLI_polyfill_calc(const float(*coords)[2], const unsigned int coords_tot, const int coords_sign, unsigned int(*r_tris)[3])
Definition: polyfill_2d.c:905
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:111
void BLI_mutex_free(ThreadMutex *mutex)
Definition: threads.cc:428
ThreadMutex * BLI_mutex_alloc(void)
Definition: threads.cc:421
void BLI_mutex_lock(ThreadMutex *mutex)
Definition: threads.cc:401
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition: threads.cc:406
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
pthread_mutex_t ThreadMutex
Definition: BLI_threads.h:83
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define UNUSED_VARS_NDEBUG(...)
#define UNUSED(x)
#define ELEM(...)
void swap(T &a, T &b)
Definition: Common.h:33
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint i1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
#define MEM_reallocN(vmemh, len)
Platform independent time functions.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
static CCL_NAMESPACE_BEGIN const double alpha
struct Vert Vert
static float verts[][3]
std::ostream & operator<<(std::ostream &stream, const GeometrySet &geometry_set)
bool operator==(const GeometrySet &UNUSED(a), const GeometrySet &UNUSED(b))
uint pos
#define UINT_MAX
Definition: hash_md5.c:58
IconTextureDrawCall normal
int count
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
static char faces[256]
struct Face Face
static unsigned c
Definition: RandGen.cpp:97
static unsigned a[3]
Definition: RandGen.cpp:92
static int sgn(double x)
#define hash
Definition: noise.c:169
#define min(a, b)
Definition: sort.c:51
__int64 int64_t
Definition: stdint.h:92
unsigned __int64 uint64_t
Definition: stdint.h:93
float co[3]
Definition: bmesh_class.h:99
Point3i begin
Definition: GeoCommon.h:37
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:158
size_t userdata_chunk_size
Definition: BLI_task.h:150
float z
Definition: sky_float3.h:35
float y
Definition: sky_float3.h:35
float x
Definition: sky_float3.h:35
double PIL_check_seconds_timer(void)
Definition: time.c:80
float max
__forceinline avxf cross(const avxf &a, const avxf &b)
Definition: util_avxf.h:119
__forceinline const avxi abs(const avxi &a)
Definition: util_avxi.h:186
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 fabs(const float2 &a)
uint len