Blender V5.0
mathutils_bvhtree.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11
12#include <Python.h>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_ghash.h"
17#include "BLI_kdopbvh.hh"
18#include "BLI_math_geom.h"
19#include "BLI_math_matrix.h"
20#include "BLI_math_vector.h"
21#include "BLI_memarena.h"
22#include "BLI_polyfill_2d.h"
23#include "BLI_utildefines.h"
24
25#include "BKE_bvhutils.hh"
26
29
30#include "mathutils.hh"
31#include "mathutils_bvhtree.hh" /* own include */
32
33#ifndef MATH_STANDALONE
34# include "DNA_mesh_types.h"
35# include "DNA_object_types.h"
36
37# include "BKE_customdata.hh"
38# include "BKE_lib_id.hh"
39# include "BKE_mesh.hh"
40# include "BKE_mesh_runtime.hh"
41# include "BKE_object.hh"
42
43# include "DEG_depsgraph_query.hh"
44
45# include "bmesh.hh"
46
48#endif /* MATH_STANDALONE */
49
50#include "BLI_strict_flags.h" /* IWYU pragma: keep. Keep last. */
51
52/* -------------------------------------------------------------------- */
55
56#define PYBVH_FIND_GENERIC_DISTANCE_DOC \
57 " :arg distance: Maximum distance threshold.\n" \
58 " :type distance: float\n"
59
60#define PYBVH_FIND_GENERIC_RETURN_DOC \
61 " :return: Returns a tuple: (position, normal, index, distance),\n" \
62 " Values will all be None if no hit is found.\n" \
63 " :rtype: tuple[:class:`Vector` | None, :class:`Vector` | None, int | None, float | None]\n"
64
65#define PYBVH_FIND_GENERIC_RETURN_LIST_DOC \
66 " :return: Returns a list of tuples (position, normal, index, distance)\n" \
67 " :rtype: list[tuple[:class:`Vector`, :class:`Vector`, int, float]]\n"
68
69#define PYBVH_FROM_GENERIC_EPSILON_DOC \
70 " :arg epsilon: Increase the threshold for detecting overlap and raycast hits.\n" \
71 " :type epsilon: float\n"
72
74
75/* sqrt(FLT_MAX) */
76#define PYBVH_MAX_DIST_STR "1.84467e+19"
77static const float max_dist_default = 1.844674352395373e+19f;
78
79static const char PY_BVH_TREE_TYPE_DEFAULT = 4;
80static const char PY_BVH_AXIS_DEFAULT = 6;
81
82struct PyBVHTree {
83 PyObject_HEAD
85 float epsilon;
86
88 uint (*tris)[3];
90
91 /* Optional members */
92 /* aligned with 'tris' */
94 /* aligned with array that 'orig_index' points to */
96};
97
98/* -------------------------------------------------------------------- */
101
103 float epsilon,
104
105 float (*coords)[3],
106 uint coords_len,
107 uint (*tris)[3],
108 uint tris_len,
109
110 /* optional arrays */
111 int *orig_index,
112 float (*orig_normal)[3])
113{
114 PyBVHTree *result = PyObject_New(PyBVHTree, &PyBVHTree_Type);
115
116 result->tree = tree;
117 result->epsilon = epsilon;
118
119 result->coords = coords;
120 result->tris = tris;
121 result->coords_len = coords_len;
122 result->tris_len = tris_len;
123
124 result->orig_index = orig_index;
125 result->orig_normal = orig_normal;
126
127 return (PyObject *)result;
128}
129
131
132/* -------------------------------------------------------------------- */
135
136static void py_bvhtree_raycast_to_py_tuple(const BVHTreeRayHit *hit, PyObject *py_retval)
137{
138 BLI_assert(hit->index >= 0);
139 BLI_assert(PyTuple_GET_SIZE(py_retval) == 4);
140
141 PyTuple_SET_ITEMS(py_retval,
142 Vector_CreatePyObject(hit->co, 3, nullptr),
143 Vector_CreatePyObject(hit->no, 3, nullptr),
144 PyLong_FromLong(hit->index),
145 PyFloat_FromDouble(hit->dist));
146}
147
148static PyObject *py_bvhtree_raycast_to_py(const BVHTreeRayHit *hit)
149{
150 PyObject *py_retval = PyTuple_New(4);
151
152 py_bvhtree_raycast_to_py_tuple(hit, py_retval);
153
154 return py_retval;
155}
156
158{
159 PyObject *py_retval = PyTuple_New(4);
160
161 PyC_Tuple_Fill(py_retval, Py_None);
162
163 return py_retval;
164}
165
166#if 0
167static PyObject *py_bvhtree_raycast_to_py_and_check(const BVHTreeRayHit *hit)
168{
169 PyObject *py_retval;
170
171 py_retval = PyTuple_New(4);
172
173 if (hit->index != -1) {
174 py_bvhtree_raycast_to_py_tuple(hit, py_retval);
175 }
176 else {
177 PyC_Tuple_Fill(py_retval, Py_None);
178 }
179
180 return py_retval;
181}
182#endif
183
185
186/* -------------------------------------------------------------------- */
189
190static void py_bvhtree_nearest_to_py_tuple(const BVHTreeNearest *nearest, PyObject *py_retval)
191{
192 BLI_assert(nearest->index >= 0);
193 BLI_assert(PyTuple_GET_SIZE(py_retval) == 4);
194
195 PyTuple_SET_ITEMS(py_retval,
196 Vector_CreatePyObject(nearest->co, 3, nullptr),
197 Vector_CreatePyObject(nearest->no, 3, nullptr),
198 PyLong_FromLong(nearest->index),
199 PyFloat_FromDouble(sqrtf(nearest->dist_sq)));
200}
201
202static PyObject *py_bvhtree_nearest_to_py(const BVHTreeNearest *nearest)
203{
204 PyObject *py_retval = PyTuple_New(4);
205
206 py_bvhtree_nearest_to_py_tuple(nearest, py_retval);
207
208 return py_retval;
209}
210
212{
213 PyObject *py_retval = PyTuple_New(4);
214
215 PyC_Tuple_Fill(py_retval, Py_None);
216
217 return py_retval;
218}
219
220#if 0
221static PyObject *py_bvhtree_nearest_to_py_and_check(const BVHTreeNearest *nearest)
222{
223 PyObject *py_retval;
224
225 py_retval = PyTuple_New(4);
226
227 if (nearest->index != -1) {
228 py_bvhtree_nearest_to_py_tuple(nearest, py_retval);
229 }
230 else {
231 PyC_Tuple_Fill(py_retval, Py_None);
232 }
233
234 return py_retval;
235}
236#endif
237
239
241{
242 if (self->tree) {
243 BLI_bvhtree_free(self->tree);
244 }
245
246 MEM_SAFE_FREE(self->coords);
247 MEM_SAFE_FREE(self->tris);
248
249 MEM_SAFE_FREE(self->orig_index);
250 MEM_SAFE_FREE(self->orig_normal);
251
252 Py_TYPE(self)->tp_free((PyObject *)self);
253}
254
255/* -------------------------------------------------------------------- */
258
259static void py_bvhtree_raycast_cb(void *userdata,
260 int index,
261 const BVHTreeRay *ray,
262 BVHTreeRayHit *hit)
263{
264 const PyBVHTree *self = static_cast<const PyBVHTree *>(userdata);
265
266 const float (*coords)[3] = self->coords;
267 const uint *tri = self->tris[index];
268 const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
269 float dist;
270
271 if (self->epsilon == 0.0f) {
273 }
274 else {
276 ray, self->epsilon, hit->dist, UNPACK3(tri_co));
277 }
278
279 if (dist >= 0 && dist < hit->dist) {
280 hit->index = self->orig_index ? self->orig_index[index] : index;
281 hit->dist = dist;
282 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
283 if (self->orig_normal) {
284 copy_v3_v3(hit->no, self->orig_normal[hit->index]);
285 }
286 else {
287 normal_tri_v3(hit->no, UNPACK3(tri_co));
288 }
289 }
290}
291
292static void py_bvhtree_nearest_point_cb(void *userdata,
293 int index,
294 const float co[3],
295 BVHTreeNearest *nearest)
296{
297 PyBVHTree *self = static_cast<PyBVHTree *>(userdata);
298
299 const float (*coords)[3] = (const float (*)[3])self->coords;
300 const uint *tri = self->tris[index];
301 const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
302 float nearest_tmp[3], dist_sq;
303
304 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co));
305 dist_sq = len_squared_v3v3(co, nearest_tmp);
306
307 if (dist_sq < nearest->dist_sq) {
308 nearest->index = self->orig_index ? self->orig_index[index] : index;
309 nearest->dist_sq = dist_sq;
310 copy_v3_v3(nearest->co, nearest_tmp);
311 if (self->orig_normal) {
312 copy_v3_v3(nearest->no, self->orig_normal[nearest->index]);
313 }
314 else {
315 normal_tri_v3(nearest->no, UNPACK3(tri_co));
316 }
317 }
318}
319
321 /* Wrap. */
322 py_bvhtree_ray_cast_doc,
323 ".. method:: ray_cast(origin, direction, distance=sys.float_info.max, /)\n"
324 "\n"
325 " Cast a ray onto the mesh.\n"
326 "\n"
327 " :arg origin: Start location of the ray in object space.\n"
328 " :type origin: :class:`Vector`\n"
329 " :arg direction: Direction of the ray in object space.\n"
330 " :type direction: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
332static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
333{
334 const char *error_prefix = "ray_cast";
335 float co[3], direction[3];
336 float max_dist = FLT_MAX;
337 BVHTreeRayHit hit;
338
339 /* parse args */
340 {
341 PyObject *py_co, *py_direction;
342
343 if (!PyArg_ParseTuple(args, "OO|f:ray_cast", &py_co, &py_direction, &max_dist)) {
344 return nullptr;
345 }
346
347 if ((mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) ||
348 (mathutils_array_parse(direction, 2, 3 | MU_ARRAY_ZERO, py_direction, error_prefix) == -1))
349 {
350 return nullptr;
351 }
352
353 normalize_v3(direction);
354 }
355
356 hit.dist = max_dist;
357 hit.index = -1;
358
359 /* may fail if the mesh has no faces, in that case the ray-cast misses */
360 if (self->tree) {
361 if (BLI_bvhtree_ray_cast(self->tree, co, direction, 0.0f, &hit, py_bvhtree_raycast_cb, self) !=
362 -1)
363 {
364 return py_bvhtree_raycast_to_py(&hit);
365 }
366 }
367
369}
370
372 /* Wrap. */
373 py_bvhtree_find_nearest_doc,
374 ".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR
375 ", /)\n"
376 "\n"
377 " Find the nearest element (typically face index) to a point.\n"
378 "\n"
379 " :arg co: Find nearest element to this point.\n"
380 " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
382static PyObject *py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args)
383{
384 const char *error_prefix = "find_nearest";
385 float co[3];
386 float max_dist = max_dist_default;
387
388 BVHTreeNearest nearest;
389
390 /* parse args */
391 {
392 PyObject *py_co;
393
394 if (!PyArg_ParseTuple(args, "O|f:find_nearest", &py_co, &max_dist)) {
395 return nullptr;
396 }
397
398 if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) {
399 return nullptr;
400 }
401 }
402
403 nearest.index = -1;
404 nearest.dist_sq = max_dist * max_dist;
405
406 /* may fail if the mesh has no faces, in that case the ray-cast misses */
407 if (self->tree) {
409 -1)
410 {
411 return py_bvhtree_nearest_to_py(&nearest);
412 }
413 }
414
416}
417
420 PyObject *result;
421 float dist_sq;
422};
423
424static void py_bvhtree_nearest_point_range_cb(void *userdata,
425 int index,
426 const float co[3],
427 float /*dist_sq_bvh*/)
428{
429 PyBVH_RangeData *data = static_cast<PyBVH_RangeData *>(userdata);
430 PyBVHTree *self = data->self;
431
432 const float (*coords)[3] = self->coords;
433 const uint *tri = self->tris[index];
434 const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
435 float nearest_tmp[3], dist_sq;
436
437 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co));
438 dist_sq = len_squared_v3v3(co, nearest_tmp);
439
440 if (dist_sq < data->dist_sq) {
441 BVHTreeNearest nearest;
442 nearest.index = self->orig_index ? self->orig_index[index] : index;
443 nearest.dist_sq = dist_sq;
444 copy_v3_v3(nearest.co, nearest_tmp);
445 if (self->orig_normal) {
446 copy_v3_v3(nearest.no, self->orig_normal[nearest.index]);
447 }
448 else {
449 normal_tri_v3(nearest.no, UNPACK3(tri_co));
450 }
451
452 PyList_APPEND(data->result, py_bvhtree_nearest_to_py(&nearest));
453 }
454}
455
457 /* Wrap. */
458 py_bvhtree_find_nearest_range_doc,
459 ".. method:: find_nearest_range(origin, distance=" PYBVH_MAX_DIST_STR
460 ", /)\n"
461 "\n"
462 " Find the nearest elements (typically face index) to a point in the distance range.\n"
463 "\n"
464 " :arg co: Find nearest elements to this point.\n"
465 " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
467static PyObject *py_bvhtree_find_nearest_range(PyBVHTree *self, PyObject *args)
468{
469 const char *error_prefix = "find_nearest_range";
470 float co[3];
471 float max_dist = max_dist_default;
472
473 /* parse args */
474 {
475 PyObject *py_co;
476
477 if (!PyArg_ParseTuple(args, "O|f:find_nearest_range", &py_co, &max_dist)) {
478 return nullptr;
479 }
480
481 if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) {
482 return nullptr;
483 }
484 }
485
486 PyObject *ret = PyList_New(0);
487
488 if (self->tree) {
490 data.self = self;
491 data.result = ret;
492 data.dist_sq = square_f(max_dist);
494 }
495
496 return ret;
497}
498
499BLI_INLINE uint overlap_hash(const void *overlap_v)
500{
501 const BVHTreeOverlap *overlap = static_cast<const BVHTreeOverlap *>(overlap_v);
502 /* same constants as edge-hash */
503 return ((uint(overlap->indexA) * 65) ^ (uint(overlap->indexA) * 31));
504}
505
506BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
507{
508 const BVHTreeOverlap *a = static_cast<const BVHTreeOverlap *>(a_v);
509 const BVHTreeOverlap *b = static_cast<const BVHTreeOverlap *>(b_v);
510 return (memcmp(a, b, sizeof(*a)) != 0);
511}
512
517
518static bool py_bvhtree_overlap_cb(void *userdata, int index_a, int index_b, int /*thread*/)
519{
520 PyBVHTree_OverlapData *data = static_cast<PyBVHTree_OverlapData *>(userdata);
521 PyBVHTree *tree_a = data->tree_pair[0];
522 PyBVHTree *tree_b = data->tree_pair[1];
523 const uint *tri_a = tree_a->tris[index_a];
524 const uint *tri_b = tree_b->tris[index_b];
525 const float *tri_a_co[3] = {
526 tree_a->coords[tri_a[0]], tree_a->coords[tri_a[1]], tree_a->coords[tri_a[2]]};
527 const float *tri_b_co[3] = {
528 tree_b->coords[tri_b[0]], tree_b->coords[tri_b[1]], tree_b->coords[tri_b[2]]};
529 float ix_pair[2][3];
530 int verts_shared = 0;
531
532 if (tree_a == tree_b) {
533 if (UNLIKELY(index_a == index_b)) {
534 return false;
535 }
536
537 verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
538 ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
539
540 /* if 2 points are shared, bail out */
541 if (verts_shared >= 2) {
542 return false;
543 }
544 }
545
546 return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
547 ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
548}
549
551 /* Wrap. */
552 py_bvhtree_overlap_doc,
553 ".. method:: overlap(other_tree, /)\n"
554 "\n"
555 " Find overlapping indices between 2 trees.\n"
556 "\n"
557 " :arg other_tree: Other tree to perform overlap test on.\n"
558 " :type other_tree: :class:`BVHTree`\n"
559 " :return: Returns a list of unique index pairs,"
560 " the first index referencing this tree, the second referencing the **other_tree**.\n"
561 " :rtype: list[tuple[int, int]]\n");
562static PyObject *py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other)
563{
565 BVHTreeOverlap *overlap;
566 uint overlap_len = 0;
567 PyObject *ret;
568
569 if (!PyBVHTree_CheckExact(other)) {
570 PyErr_SetString(PyExc_ValueError, "Expected a BVHTree argument");
571 return nullptr;
572 }
573
574 data.tree_pair[0] = self;
575 data.tree_pair[1] = other;
576 data.epsilon = max_ff(self->epsilon, other->epsilon);
577
578 overlap = BLI_bvhtree_overlap(
579 self->tree, other->tree, &overlap_len, py_bvhtree_overlap_cb, &data);
580
581 ret = PyList_New(0);
582
583 if (overlap == nullptr) {
584 /* pass */
585 }
586 else {
587 const bool use_unique = (self->orig_index || other->orig_index);
588 GSet *pair_test = use_unique ?
589 BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) :
590 nullptr;
591 /* simple case, no index remapping */
592 uint i;
593
594 for (i = 0; i < overlap_len; i++) {
595 PyObject *item;
596 if (use_unique) {
597 if (self->orig_index) {
598 overlap[i].indexA = self->orig_index[overlap[i].indexA];
599 }
600 if (other->orig_index) {
601 overlap[i].indexB = other->orig_index[overlap[i].indexB];
602 }
603
604 /* skip if its already added */
605 if (!BLI_gset_add(pair_test, &overlap[i])) {
606 continue;
607 }
608 }
609
610 item = PyTuple_New(2);
612 item, PyLong_FromLong(overlap[i].indexA), PyLong_FromLong(overlap[i].indexB));
613
614 PyList_Append(ret, item);
615 Py_DECREF(item);
616 }
617
618 if (pair_test) {
619 BLI_gset_free(pair_test, nullptr);
620 }
621 }
622
623 if (overlap) {
624 MEM_freeN(overlap);
625 }
626
627 return ret;
628}
629
631
632/* -------------------------------------------------------------------- */
635
637 /* Wrap. */
638 C_BVHTree_FromPolygons_doc,
639 ".. classmethod:: FromPolygons(vertices, polygons, *, all_triangles=False, epsilon=0.0)\n"
640 "\n"
641 " BVH tree constructed geometry passed in as arguments.\n"
642 "\n"
643 " :arg vertices: float triplets each representing ``(x, y, z)``\n"
644 " :type vertices: Sequence[Sequence[float]]\n"
645 " :arg polygons: Sequence of polygons, each containing indices to the vertices argument.\n"
646 " :type polygons: Sequence[Sequence[int]]\n"
647 " :arg all_triangles: Use when all **polygons** are triangles for more efficient "
648 "conversion.\n"
649 " :type all_triangles: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
650static PyObject *C_BVHTree_FromPolygons(PyObject * /*cls*/, PyObject *args, PyObject *kwargs)
651{
652 const char *error_prefix = "BVHTree.FromPolygons";
653 const char *keywords[] = {"vertices", "polygons", "all_triangles", "epsilon", nullptr};
654
655 PyObject *py_coords, *py_tris;
656 PyObject *py_coords_fast = nullptr, *py_tris_fast = nullptr;
657
658 MemArena *poly_arena = nullptr;
659 MemArena *pf_arena = nullptr;
660
661 float (*coords)[3] = nullptr;
662 uint(*tris)[3] = nullptr;
663 uint coords_len, tris_len;
664 float epsilon = 0.0f;
665 bool all_triangles = false;
666
667 /* when all_triangles is False */
668 int *orig_index = nullptr;
669 float (*orig_normal)[3] = nullptr;
670
671 uint i;
672 bool valid = true;
673
674 if (!PyArg_ParseTupleAndKeywords(args,
675 kwargs,
676 "OO|$O&f:BVHTree.FromPolygons",
677 (char **)keywords,
678 &py_coords,
679 &py_tris,
681 &all_triangles,
682 &epsilon))
683 {
684 return nullptr;
685 }
686
687 if (!(py_coords_fast = PySequence_Fast(py_coords, error_prefix)) ||
688 !(py_tris_fast = PySequence_Fast(py_tris, error_prefix)))
689 {
690 Py_XDECREF(py_coords_fast);
691 return nullptr;
692 }
693
694 if (valid) {
695 PyObject **py_coords_fast_items = PySequence_Fast_ITEMS(py_coords_fast);
696 coords_len = uint(PySequence_Fast_GET_SIZE(py_coords_fast));
697 coords = MEM_malloc_arrayN<float[3]>(size_t(coords_len), __func__);
698
699 for (i = 0; i < coords_len; i++) {
700 PyObject *py_vert = py_coords_fast_items[i];
701
702 if (mathutils_array_parse(coords[i], 3, 3, py_vert, "BVHTree vertex: ") == -1) {
703 valid = false;
704 break;
705 }
706 }
707 }
708
709 if (valid == false) {
710 /* pass */
711 }
712 else if (all_triangles) {
713 /* all triangles, simple case */
714 PyObject **py_tris_fast_items = PySequence_Fast_ITEMS(py_tris_fast);
715 tris_len = uint(PySequence_Fast_GET_SIZE(py_tris_fast));
716 tris = MEM_malloc_arrayN<uint[3]>(size_t(tris_len), __func__);
717
718 for (i = 0; i < tris_len; i++) {
719 PyObject *py_tricoords = py_tris_fast_items[i];
720 PyObject *py_tricoords_fast;
721 PyObject **py_tricoords_fast_items;
722 uint *tri = tris[i];
723 int j;
724
725 if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
726 valid = false;
727 break;
728 }
729
730 if (PySequence_Fast_GET_SIZE(py_tricoords_fast) != 3) {
731 Py_DECREF(py_tricoords_fast);
732 PyErr_Format(PyExc_ValueError,
733 "%s: non triangle found at index %d with length of %d",
734 error_prefix,
735 i,
736 PySequence_Fast_GET_SIZE(py_tricoords_fast));
737 valid = false;
738 break;
739 }
740
741 py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
742
743 for (j = 0; j < 3; j++) {
744 tri[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
745 if (UNLIKELY(tri[j] >= uint(coords_len))) {
746 PyErr_Format(PyExc_ValueError,
747 "%s: index %d must be less than %d",
748 error_prefix,
749 tri[j],
750 coords_len);
751
752 /* decref below */
753 valid = false;
754 break;
755 }
756 }
757
758 Py_DECREF(py_tricoords_fast);
759 }
760 }
761 else {
762 /* ngon support (much more involved) */
763 const uint polys_len = uint(PySequence_Fast_GET_SIZE(py_tris_fast));
764 struct PolyLink {
765 PolyLink *next;
766 uint len;
767 uint poly[0];
768 } *plink_first = nullptr, **p_plink_prev = &plink_first, *plink = nullptr;
769 int poly_index;
770
771 tris_len = 0;
772
773 poly_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
774
775 for (i = 0; i < polys_len; i++) {
776 PyObject *py_tricoords = PySequence_Fast_GET_ITEM(py_tris_fast, i);
777 PyObject *py_tricoords_fast;
778 PyObject **py_tricoords_fast_items;
779 uint py_tricoords_len;
780 uint j;
781
782 if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
783 valid = false;
784 break;
785 }
786
787 py_tricoords_len = uint(PySequence_Fast_GET_SIZE(py_tricoords_fast));
788 py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
789
790 plink = static_cast<PolyLink *>(BLI_memarena_alloc(
791 poly_arena, sizeof(*plink) + (sizeof(int) * size_t(py_tricoords_len))));
792
793 plink->len = py_tricoords_len;
794 *p_plink_prev = plink;
795 p_plink_prev = &plink->next;
796
797 for (j = 0; j < py_tricoords_len; j++) {
798 plink->poly[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
799 if (UNLIKELY(plink->poly[j] >= uint(coords_len))) {
800 PyErr_Format(PyExc_ValueError,
801 "%s: index %d must be less than %d",
802 error_prefix,
803 plink->poly[j],
804 coords_len);
805 /* decref below */
806 valid = false;
807 break;
808 }
809 }
810
811 Py_DECREF(py_tricoords_fast);
812
813 if (py_tricoords_len >= 3) {
814 tris_len += (py_tricoords_len - 2);
815 }
816 }
817 *p_plink_prev = nullptr;
818
819 /* All NGON's are parsed, now tessellate. */
820
821 pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
822 tris = MEM_malloc_arrayN<uint[3]>(size_t(tris_len), __func__);
823
824 orig_index = MEM_malloc_arrayN<int>(size_t(tris_len), __func__);
825 orig_normal = MEM_malloc_arrayN<float[3]>(size_t(polys_len), __func__);
826
827 for (plink = plink_first, poly_index = 0, i = 0; plink; plink = plink->next, poly_index++) {
828 if (plink->len == 3) {
829 uint *tri = tris[i];
830 memcpy(tri, plink->poly, sizeof(uint[3]));
831 orig_index[i] = poly_index;
832 normal_tri_v3(orig_normal[poly_index], coords[tri[0]], coords[tri[1]], coords[tri[2]]);
833 i++;
834 }
835 else if (plink->len > 3) {
836 float (*proj_coords)[2] = static_cast<float (*)[2]>(
837 BLI_memarena_alloc(pf_arena, sizeof(*proj_coords) * plink->len));
838 float *normal = orig_normal[poly_index];
839 const float *co_prev;
840 const float *co_curr;
841 float axis_mat[3][3];
842 uint(*tris_offset)[3] = &tris[i];
843 uint j;
844
845 /* calc normal and setup 'proj_coords' */
846 zero_v3(normal);
847 co_prev = coords[plink->poly[plink->len - 1]];
848 for (j = 0; j < plink->len; j++) {
849 co_curr = coords[plink->poly[j]];
850 add_newell_cross_v3_v3v3(normal, co_prev, co_curr);
851 co_prev = co_curr;
852 }
853 normalize_v3(normal);
854
855 axis_dominant_v3_to_m3_negate(axis_mat, normal);
856
857 for (j = 0; j < plink->len; j++) {
858 mul_v2_m3v3(proj_coords[j], axis_mat, coords[plink->poly[j]]);
859 }
860
861 BLI_polyfill_calc_arena(proj_coords, plink->len, 1, tris_offset, pf_arena);
862
863 j = plink->len - 2;
864 while (j--) {
865 uint *tri = tris_offset[j];
866 /* remap to global indices */
867 tri[0] = plink->poly[tri[0]];
868 tri[1] = plink->poly[tri[1]];
869 tri[2] = plink->poly[tri[2]];
870
871 orig_index[i] = poly_index;
872 i++;
873 }
874
875 BLI_memarena_clear(pf_arena);
876 }
877 else {
878 zero_v3(orig_normal[poly_index]);
879 }
880 }
881 }
882
883 Py_DECREF(py_coords_fast);
884 Py_DECREF(py_tris_fast);
885
886 if (pf_arena) {
887 BLI_memarena_free(pf_arena);
888 }
889
890 if (poly_arena) {
891 BLI_memarena_free(poly_arena);
892 }
893
894 if (valid) {
895 BVHTree *tree;
896
898 if (tree) {
899 for (i = 0; i < tris_len; i++) {
900 float co[3][3];
901
902 copy_v3_v3(co[0], coords[tris[i][0]]);
903 copy_v3_v3(co[1], coords[tris[i][1]]);
904 copy_v3_v3(co[2], coords[tris[i][2]]);
905
906 BLI_bvhtree_insert(tree, int(i), co[0], 3);
907 }
908
910 }
911
913 tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal);
914 }
915
916 if (coords) {
917 MEM_freeN(coords);
918 }
919 if (tris) {
920 MEM_freeN(tris);
921 }
922
923 return nullptr;
924}
925
926#ifndef MATH_STANDALONE
927
929 /* Wrap. */
930 C_BVHTree_FromBMesh_doc,
931 ".. classmethod:: FromBMesh(bmesh, *, epsilon=0.0)\n"
932 "\n"
933 " BVH tree based on :class:`BMesh` data.\n"
934 "\n"
935 " :arg bmesh: BMesh data.\n"
936 " :type bmesh: :class:`BMesh`\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
937static PyObject *C_BVHTree_FromBMesh(PyObject * /*cls*/, PyObject *args, PyObject *kwargs)
938{
939 const char *keywords[] = {"bmesh", "epsilon", nullptr};
940
941 BPy_BMesh *py_bm;
942
943 float (*coords)[3] = nullptr;
944 uint(*tris)[3] = nullptr;
945 uint coords_len, tris_len;
946 float epsilon = 0.0f;
947
948 BMesh *bm;
949
950 if (!PyArg_ParseTupleAndKeywords(args,
951 kwargs,
952 "O!|$f:BVHTree.FromBMesh",
953 (char **)keywords,
955 &py_bm,
956 &epsilon))
957 {
958 return nullptr;
959 }
960
961 bm = py_bm->bm;
962
963 /* Get data for tessellation */
964
965 coords_len = uint(bm->totvert);
966 tris_len = uint(poly_to_tri_count(bm->totface, bm->totloop));
967
968 coords = MEM_malloc_arrayN<float[3]>(size_t(coords_len), __func__);
969 tris = MEM_malloc_arrayN<uint[3]>(size_t(tris_len), __func__);
970
971 blender::Array<std::array<BMLoop *, 3>> corner_tris(tris_len);
972 BM_mesh_calc_tessellation(bm, corner_tris);
973
974 {
975 BMIter iter;
976 BVHTree *tree;
977 uint i;
978
979 int *orig_index = nullptr;
980 float (*orig_normal)[3] = nullptr;
981
983 if (tree) {
984 BMFace *f;
985 BMVert *v;
986
987 orig_index = MEM_malloc_arrayN<int>(size_t(tris_len), __func__);
988 orig_normal = MEM_malloc_arrayN<float[3]>(size_t(bm->totface), __func__);
989
991 copy_v3_v3(coords[i], v->co);
992 BM_elem_index_set(v, int(i)); /* set_inline */
993 }
995 copy_v3_v3(orig_normal[i], f->no);
996 BM_elem_index_set(f, int(i)); /* set_inline */
997 }
998 bm->elem_index_dirty &= char(~(BM_VERT | BM_FACE));
999
1000 for (i = 0; i < tris_len; i++) {
1001 float co[3][3];
1002
1003 tris[i][0] = uint(BM_elem_index_get(corner_tris[i][0]->v));
1004 tris[i][1] = uint(BM_elem_index_get(corner_tris[i][1]->v));
1005 tris[i][2] = uint(BM_elem_index_get(corner_tris[i][2]->v));
1006
1007 copy_v3_v3(co[0], coords[tris[i][0]]);
1008 copy_v3_v3(co[1], coords[tris[i][1]]);
1009 copy_v3_v3(co[2], coords[tris[i][2]]);
1010
1011 BLI_bvhtree_insert(tree, int(i), co[0], 3);
1012 orig_index[i] = BM_elem_index_get(corner_tris[i][0]->f);
1013 }
1014
1016 }
1017
1019 tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal);
1020 }
1021}
1022
1024static const Mesh *bvh_get_mesh(const char *funcname,
1025 Depsgraph *depsgraph,
1026 Scene *scene,
1027 Object *ob,
1028 const bool use_deform,
1029 const bool use_cage,
1030 bool *r_free_mesh)
1031{
1032 Object *ob_eval = DEG_get_evaluated(depsgraph, ob);
1033 /* we only need minimum mesh data for topology and vertex locations */
1034 const CustomData_MeshMasks data_masks = CD_MASK_BAREMESH;
1035 const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
1036 *r_free_mesh = false;
1037 Mesh *mesh;
1038
1039 /* Write the display mesh into the dummy mesh */
1040 if (use_deform) {
1041 if (use_render) {
1042 if (use_cage) {
1043 PyErr_Format(
1044 PyExc_ValueError,
1045 "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER",
1046 funcname);
1047 return nullptr;
1048 }
1049
1050 mesh = blender::bke::mesh_create_eval_final(depsgraph, scene, ob, &data_masks);
1051 if (mesh == nullptr) {
1052 PyErr_Format(PyExc_ValueError,
1053 "%s(...): Cannot get a mesh from object '%s'",
1054 ob->id.name + 2,
1055 funcname);
1056 return nullptr;
1057 }
1058
1059 *r_free_mesh = true;
1060 return mesh;
1061 }
1062 if (ob_eval != nullptr) {
1063 if (use_cage) {
1064 mesh = blender::bke::mesh_get_eval_deform(depsgraph, scene, ob_eval, &data_masks);
1065 }
1066 else {
1067 mesh = BKE_object_get_evaluated_mesh(ob_eval);
1068 }
1069 if (mesh == nullptr) {
1070 PyErr_Format(PyExc_ValueError,
1071 "%s(...): Cannot get a mesh from object '%s'",
1072 ob->id.name + 2,
1073 funcname);
1074 return nullptr;
1075 }
1076 return mesh;
1077 }
1078
1079 PyErr_Format(PyExc_ValueError,
1080 "%s(...): Cannot get evaluated data from given dependency graph / object pair",
1081 funcname);
1082 return nullptr;
1083 }
1084
1085 /* !use_deform */
1086 if (use_render) {
1087 if (use_cage) {
1088 PyErr_Format(
1089 PyExc_ValueError,
1090 "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER",
1091 funcname);
1092 return nullptr;
1093 }
1094 mesh = blender::bke::mesh_create_eval_no_deform_render(depsgraph, scene, ob, &data_masks);
1095 if (mesh == nullptr) {
1096 PyErr_Format(PyExc_ValueError,
1097 "%s(...): Cannot get a mesh from object '%s'",
1098 ob->id.name + 2,
1099 funcname);
1100 return nullptr;
1101 }
1102 *r_free_mesh = true;
1103 return mesh;
1104 }
1105
1106 if (use_cage) {
1107 PyErr_Format(PyExc_ValueError,
1108 "%s(...): cage arg is unsupported when deform=False and dependency graph "
1109 "evaluation mode is not RENDER",
1110 funcname);
1111 return nullptr;
1112 }
1113
1114 mesh = blender::bke::mesh_create_eval_no_deform(depsgraph, scene, ob, &data_masks);
1115 if (mesh == nullptr) {
1116 PyErr_Format(PyExc_ValueError,
1117 "%s(...): Cannot get a mesh from object '%s'",
1118 ob->id.name + 2,
1119 funcname);
1120 return nullptr;
1121 }
1122 *r_free_mesh = true;
1123 return mesh;
1124}
1125
1127 /* Wrap. */
1128 C_BVHTree_FromObject_doc,
1129 ".. classmethod:: FromObject(object, depsgraph, *, deform=True, render=False, "
1130 "cage=False, epsilon=0.0)\n"
1131 "\n"
1132 " BVH tree based on :class:`Object` data.\n"
1133 "\n"
1134 " :arg object: Object data.\n"
1135 " :type object: :class:`Object`\n"
1136 " :arg depsgraph: Depsgraph to use for evaluating the mesh.\n"
1137 " :type depsgraph: :class:`Depsgraph`\n"
1138 " :arg deform: Use mesh with deformations.\n"
1139 " :type deform: bool\n"
1140 " :arg cage: Use modifiers cage.\n"
1141 " :type cage: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
1142static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObject *kwargs)
1143{
1144 /* NOTE: options here match #bpy_bmesh_from_object. */
1145 const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", nullptr};
1146
1147 PyObject *py_ob, *py_depsgraph;
1148 Object *ob;
1149 Depsgraph *depsgraph;
1150 Scene *scene;
1151 const Mesh *mesh;
1152 bool use_deform = true;
1153 bool use_cage = false;
1154 bool free_mesh = false;
1155
1156 float epsilon = 0.0f;
1157
1158 if (!PyArg_ParseTupleAndKeywords(args,
1159 kwargs,
1160 "OO|$O&O&f:BVHTree.FromObject",
1161 (char **)keywords,
1162 &py_ob,
1163 &py_depsgraph,
1165 &use_deform,
1167 &use_cage,
1168 &epsilon) ||
1169 ((ob = static_cast<Object *>(PyC_RNA_AsPointer(py_ob, "Object"))) == nullptr) ||
1170 ((depsgraph = static_cast<Depsgraph *>(PyC_RNA_AsPointer(py_depsgraph, "Depsgraph"))) ==
1171 nullptr))
1172 {
1173 return nullptr;
1174 }
1175
1177 mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh);
1178
1179 if (mesh == nullptr) {
1180 return nullptr;
1181 }
1182
1183 const blender::Span<int> corner_verts = mesh->corner_verts();
1184 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
1185 const blender::Span<int> tri_faces = mesh->corner_tri_faces();
1186
1187 /* Get data for tessellation */
1188
1189 const uint coords_len = uint(mesh->verts_num);
1190
1191 float (*coords)[3] = MEM_malloc_arrayN<float[3]>(size_t(coords_len), __func__);
1192 uint(*tris)[3] = MEM_malloc_arrayN<uint[3]>(size_t(corner_tris.size()), __func__);
1193 memcpy(coords, mesh->vert_positions().data(), sizeof(float[3]) * size_t(mesh->verts_num));
1194
1195 BVHTree *tree;
1196
1197 int *orig_index = nullptr;
1198 blender::float3 *orig_normal = nullptr;
1199
1201 int(corner_tris.size()), epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
1202 if (tree) {
1203 orig_index = MEM_malloc_arrayN<int>(size_t(corner_tris.size()), __func__);
1205 const blender::Span<blender::float3> face_normals = mesh->face_normals();
1206 orig_normal = MEM_malloc_arrayN<blender::float3>(size_t(mesh->faces_num), __func__);
1207 blender::MutableSpan(orig_normal, face_normals.size()).copy_from(face_normals);
1208 }
1209
1210 for (const int64_t i : corner_tris.index_range()) {
1211 float co[3][3];
1212
1213 tris[i][0] = uint(corner_verts[corner_tris[i][0]]);
1214 tris[i][1] = uint(corner_verts[corner_tris[i][1]]);
1215 tris[i][2] = uint(corner_verts[corner_tris[i][2]]);
1216
1217 copy_v3_v3(co[0], coords[tris[i][0]]);
1218 copy_v3_v3(co[1], coords[tris[i][1]]);
1219 copy_v3_v3(co[2], coords[tris[i][2]]);
1220
1221 BLI_bvhtree_insert(tree, int(i), co[0], 3);
1222 orig_index[i] = int(tri_faces[i]);
1223 }
1224
1226 }
1227
1228 if (free_mesh) {
1229 BKE_id_free(nullptr, const_cast<Mesh *>(mesh));
1230 }
1231
1233 epsilon,
1234 coords,
1235 coords_len,
1236 tris,
1237 uint(corner_tris.size()),
1238 orig_index,
1239 reinterpret_cast<float (*)[3]>(orig_normal));
1240}
1241#endif /* MATH_STANDALONE */
1242
1244
1245/* -------------------------------------------------------------------- */
1248
1249#ifdef __GNUC__
1250# ifdef __clang__
1251# pragma clang diagnostic push
1252# pragma clang diagnostic ignored "-Wcast-function-type"
1253# else
1254# pragma GCC diagnostic push
1255# pragma GCC diagnostic ignored "-Wcast-function-type"
1256# endif
1257#endif
1258
1259static PyMethodDef py_bvhtree_methods[] = {
1260 {"ray_cast",
1261 reinterpret_cast<PyCFunction>(py_bvhtree_ray_cast),
1262 METH_VARARGS,
1263 py_bvhtree_ray_cast_doc},
1264 {"find_nearest",
1265 reinterpret_cast<PyCFunction>(py_bvhtree_find_nearest),
1266 METH_VARARGS,
1267 py_bvhtree_find_nearest_doc},
1268 {"find_nearest_range",
1269 reinterpret_cast<PyCFunction>(py_bvhtree_find_nearest_range),
1270 METH_VARARGS,
1271 py_bvhtree_find_nearest_range_doc},
1272 {"overlap", reinterpret_cast<PyCFunction>(py_bvhtree_overlap), METH_O, py_bvhtree_overlap_doc},
1273
1274 /* class methods */
1275 {"FromPolygons",
1276 reinterpret_cast<PyCFunction>(C_BVHTree_FromPolygons),
1277 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1278 C_BVHTree_FromPolygons_doc},
1279#ifndef MATH_STANDALONE
1280 {"FromBMesh",
1281 reinterpret_cast<PyCFunction>(C_BVHTree_FromBMesh),
1282 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1283 C_BVHTree_FromBMesh_doc},
1284 {"FromObject",
1285 reinterpret_cast<PyCFunction>(C_BVHTree_FromObject),
1286 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1287 C_BVHTree_FromObject_doc},
1288#endif
1289 {nullptr, nullptr, 0, nullptr},
1290};
1291
1292#ifdef __GNUC__
1293# ifdef __clang__
1294# pragma clang diagnostic pop
1295# else
1296# pragma GCC diagnostic pop
1297# endif
1298#endif
1299
1300PyTypeObject PyBVHTree_Type = {
1301 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1302 /*tp_name*/ "BVHTree",
1303 /*tp_basicsize*/ sizeof(PyBVHTree),
1304 /*tp_itemsize*/ 0,
1305 /*tp_dealloc*/ (destructor)py_bvhtree__tp_dealloc,
1306 /*tp_vectorcall_offset*/ 0,
1307 /*tp_getattr*/ nullptr,
1308 /*tp_setattr*/ nullptr,
1309 /*tp_as_async*/ nullptr,
1310 /*tp_repr*/ nullptr,
1311 /*tp_as_number*/ nullptr,
1312 /*tp_as_sequence*/ nullptr,
1313 /*tp_as_mapping*/ nullptr,
1314 /*tp_hash*/ nullptr,
1315 /*tp_call*/ nullptr,
1316 /*tp_str*/ nullptr,
1317 /*tp_getattro*/ nullptr,
1318 /*tp_setattro*/ nullptr,
1319 /*tp_as_buffer*/ nullptr,
1320 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
1321 /*tp_doc*/ nullptr,
1322 /*tp_traverse*/ nullptr,
1323 /*tp_clear*/ nullptr,
1324 /*tp_richcompare*/ nullptr,
1325 /*tp_weaklistoffset*/ 0,
1326 /*tp_iter*/ nullptr,
1327 /*tp_iternext*/ nullptr,
1328 /*tp_methods*/ py_bvhtree_methods,
1329 /*tp_members*/ nullptr,
1330 /*tp_getset*/ nullptr,
1331 /*tp_base*/ nullptr,
1332 /*tp_dict*/ nullptr,
1333 /*tp_descr_get*/ nullptr,
1334 /*tp_descr_set*/ nullptr,
1335 /*tp_dictoffset*/ 0,
1336 /*tp_init*/ nullptr,
1337 /*tp_alloc*/ (allocfunc)PyType_GenericAlloc,
1338 /*tp_new*/ (newfunc)PyType_GenericNew,
1339 /*tp_free*/ (freefunc) nullptr,
1340 /*tp_is_gc*/ nullptr,
1341 /*tp_bases*/ nullptr,
1342 /*tp_mro*/ nullptr,
1343 /*tp_cache*/ nullptr,
1344 /*tp_subclasses*/ nullptr,
1345 /*tp_weaklist*/ nullptr,
1346 /*tp_del*/ (destructor) nullptr,
1347 /*tp_version_tag*/ 0,
1348 /*tp_finalize*/ nullptr,
1349 /*tp_vectorcall*/ nullptr,
1350};
1351
1352/* -------------------------------------------------------------------- */
1353/* Module definition */
1354
1356 /* Wrap. */
1357 py_bvhtree_doc,
1358 "BVH tree structures for proximity searches and ray casts on geometry.");
1359static PyModuleDef bvhtree_moduledef = {
1360 /*m_base*/ PyModuleDef_HEAD_INIT,
1361 /*m_name*/ "mathutils.bvhtree",
1362 /*m_doc*/ py_bvhtree_doc,
1363 /*m_size*/ 0,
1364 /*m_methods*/ nullptr,
1365 /*m_slots*/ nullptr,
1366 /*m_traverse*/ nullptr,
1367 /*m_clear*/ nullptr,
1368 /*m_free*/ nullptr,
1369};
1370
1372{
1373 PyObject *m = PyModule_Create(&bvhtree_moduledef);
1374
1375 if (m == nullptr) {
1376 return nullptr;
1377 }
1378
1379 /* Register classes */
1380 if (PyType_Ready(&PyBVHTree_Type) < 0) {
1381 return nullptr;
1382 }
1383
1384 PyModule_AddType(m, &PyBVHTree_Type);
1385
1386 return m;
1387}
1388
CustomData interface, see also DNA_customdata_types.h.
const CustomData_MeshMasks CD_MASK_BAREMESH
void BKE_id_free(Main *bmain, void *idv)
bool BKE_mesh_face_normals_are_dirty(const Mesh *mesh)
General operations, lookup, etc. for blender objects.
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_INLINE
struct GSet GSet
Definition BLI_ghash.h:337
GSet * BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:936
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
BVHTree * BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis)
void BLI_bvhtree_balance(BVHTree *tree)
void BLI_bvhtree_free(BVHTree *tree)
void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints)
int BLI_bvhtree_find_nearest(const BVHTree *tree, const float co[3], BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata)
int BLI_bvhtree_ray_cast(const BVHTree *tree, const float co[3], const float dir[3], float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata)
int BLI_bvhtree_range_query(const BVHTree *tree, const float co[3], float radius, BVHTree_RangeQuery callback, void *userdata)
BVHTreeOverlap * BLI_bvhtree_overlap(const BVHTree *tree1, const BVHTree *tree2, unsigned int *r_overlap_num, BVHTree_OverlapCallback callback, void *userdata)
MINLINE float max_ff(float a, float b)
MINLINE float square_f(float a)
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
void axis_dominant_v3_to_m3_negate(float r_mat[3][3], const float normal[3])
bool isect_tri_tri_v3(const float t_a0[3], const float t_a1[3], const float t_a2[3], const float t_b0[3], const float t_b1[3], const float t_b2[3], float r_i1[3], float r_i2[3])
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition math_geom.cc:41
void mul_v2_m3v3(float r[2], const float M[3][3], const float a[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
MINLINE float normalize_v3(float n[3])
#define BLI_MEMARENA_STD_BUFSIZE
MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
void BLI_memarena_free(MemArena *ma) ATTR_NONNULL(1)
void * BLI_memarena_alloc(MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1)
#define BLI_POLYFILL_ARENA_SIZE
void BLI_polyfill_calc_arena(const float(*coords)[2], unsigned int coords_num, int coords_sign, unsigned int(*r_tris)[3], struct MemArena *arena)
unsigned int uint
#define UNPACK3(a)
#define UNLIKELY(x)
#define ELEM(...)
@ DAG_EVAL_RENDER
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define BM_elem_index_get(ele)
#define BM_elem_index_set(ele, index)
#define BM_ITER_MESH_INDEX(ele, iter, bm, itype, indexvar)
@ BM_VERTS_OF_MESH
@ BM_FACES_OF_MESH
BMesh const char void * data
BMesh * bm
void BM_mesh_calc_tessellation(BMesh *bm, MutableSpan< std::array< BMLoop *, 3 > > looptris)
#define BM_FACE
#define BM_VERT
PyTypeObject BPy_BMesh_Type
ATTR_WARN_UNUSED_RESULT const BMVert * v
PyObject * self
BPy_StructRNA * depsgraph
long long int int64_t
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
nullptr float
KDTree_3d * tree
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:96
#define MU_ARRAY_ZERO
Definition mathutils.hh:239
PyObject * Vector_CreatePyObject(const float *vec, const int vec_num, PyTypeObject *base_type)
static const Mesh * bvh_get_mesh(const char *funcname, Depsgraph *depsgraph, Scene *scene, Object *ob, const bool use_deform, const bool use_cage, bool *r_free_mesh)
#define PYBVH_FIND_GENERIC_RETURN_DOC
static PyObject * py_bvhtree_raycast_to_py(const BVHTreeRayHit *hit)
static PyObject * py_bvhtree_find_nearest_range(PyBVHTree *self, PyObject *args)
static void py_bvhtree_raycast_to_py_tuple(const BVHTreeRayHit *hit, PyObject *py_retval)
BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
static void py_bvhtree__tp_dealloc(PyBVHTree *self)
PyDoc_STRVAR(py_bvhtree_ray_cast_doc, ".. method:: ray_cast(origin, direction, distance=sys.float_info.max, /)\n" "\n" " Cast a ray onto the mesh.\n" "\n" " :arg origin: Start location of the ray in object space.\n" " :type origin: :class:`Vector`\n" " :arg direction: Direction of the ray in object space.\n" " :type direction: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC PYBVH_FIND_GENERIC_RETURN_DOC)
static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float co[3], BVHTreeNearest *nearest)
static const char PY_BVH_AXIS_DEFAULT
static PyObject * C_BVHTree_FromPolygons(PyObject *, PyObject *args, PyObject *kwargs)
#define PYBVH_MAX_DIST_STR
static PyObject * C_BVHTree_FromBMesh(PyObject *, PyObject *args, PyObject *kwargs)
#define PYBVH_FROM_GENERIC_EPSILON_DOC
static PyObject * py_bvhtree_nearest_to_py_none()
static PyObject * py_bvhtree_nearest_to_py(const BVHTreeNearest *nearest)
static void py_bvhtree_nearest_point_range_cb(void *userdata, int index, const float co[3], float)
static void py_bvhtree_raycast_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
static PyObject * py_bvhtree_raycast_to_py_none()
BLI_INLINE uint overlap_hash(const void *overlap_v)
static PyMethodDef py_bvhtree_methods[]
static PyObject * bvhtree_CreatePyObject(BVHTree *tree, float epsilon, float(*coords)[3], uint coords_len, uint(*tris)[3], uint tris_len, int *orig_index, float(*orig_normal)[3])
static const char PY_BVH_TREE_TYPE_DEFAULT
PyTypeObject PyBVHTree_Type
static PyObject * py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args)
static PyObject * py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other)
PyMODINIT_FUNC PyInit_mathutils_bvhtree()
#define PYBVH_FIND_GENERIC_DISTANCE_DOC
#define PYBVH_FIND_GENERIC_RETURN_LIST_DOC
static void py_bvhtree_nearest_to_py_tuple(const BVHTreeNearest *nearest, PyObject *py_retval)
static PyModuleDef bvhtree_moduledef
static const float max_dist_default
static PyObject * py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
static PyObject * C_BVHTree_FromObject(PyObject *, PyObject *args, PyObject *kwargs)
static bool py_bvhtree_overlap_cb(void *userdata, int index_a, int index_b, int)
#define PyBVHTree_CheckExact(v)
static ulong * next
float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray, float radius, float m_dist, const float v0[3], const float v1[3], const float v2[3])
Definition bvhutils.cc:49
Mesh * mesh_create_eval_no_deform_render(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
Mesh * mesh_create_eval_no_deform(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
float bvhtree_ray_tri_intersection(const BVHTreeRay *ray, float m_dist, const float v0[3], const float v1[3], const float v2[3])
Definition bvhutils.cc:28
Mesh * mesh_get_eval_deform(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
Mesh * mesh_create_eval_final(Depsgraph *depsgraph, const Scene *scene, Object *ob, const CustomData_MeshMasks *dataMask)
VecBase< float, 3 > float3
void * PyC_RNA_AsPointer(PyObject *value, const char *type_name)
uint32_t PyC_Long_AsU32(PyObject *value)
int PyC_ParseBool(PyObject *o, void *p)
void PyC_Tuple_Fill(PyObject *tuple, PyObject *value)
Py_DECREF(oname)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
#define sqrtf
#define FLT_MAX
Definition stdcycles.h:14
float no[3]
PyObject_VAR_HEAD BMesh * bm
float origin[3]
float direction[3]
char name[258]
Definition DNA_ID.h:432
int faces_num
int verts_num
float(* coords)[3]
float(* orig_normal)[3]
uint(* tris)[3]
PyObject_HEAD BVHTree * tree
i
Definition text_draw.cc:230
BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
BLI_INLINE uint overlap_hash(const void *overlap_v)
uint len