Blender V4.3
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
12#include <Python.h>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_ghash.h"
17#include "BLI_kdopbvh.h"
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" /* Keep last. */
51
52/* -------------------------------------------------------------------- */
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
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/* -------------------------------------------------------------------- */
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
132/* -------------------------------------------------------------------- */
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
186/* -------------------------------------------------------------------- */
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
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/* -------------------------------------------------------------------- */
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) {
272 dist = bvhtree_ray_tri_intersection(ray, hit->dist, UNPACK3(tri_co));
273 }
274 else {
275 dist = bvhtree_sphereray_tri_intersection(ray, self->epsilon, hit->dist, UNPACK3(tri_co));
276 }
277
278 if (dist >= 0 && dist < hit->dist) {
279 hit->index = self->orig_index ? self->orig_index[index] : index;
280 hit->dist = dist;
281 madd_v3_v3v3fl(hit->co, ray->origin, ray->direction, dist);
282 if (self->orig_normal) {
283 copy_v3_v3(hit->no, self->orig_normal[hit->index]);
284 }
285 else {
286 normal_tri_v3(hit->no, UNPACK3(tri_co));
287 }
288 }
289}
290
291static void py_bvhtree_nearest_point_cb(void *userdata,
292 int index,
293 const float co[3],
294 BVHTreeNearest *nearest)
295{
296 PyBVHTree *self = static_cast<PyBVHTree *>(userdata);
297
298 const float(*coords)[3] = (const float(*)[3])self->coords;
299 const uint *tri = self->tris[index];
300 const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
301 float nearest_tmp[3], dist_sq;
302
303 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co));
304 dist_sq = len_squared_v3v3(co, nearest_tmp);
305
306 if (dist_sq < nearest->dist_sq) {
307 nearest->index = self->orig_index ? self->orig_index[index] : index;
308 nearest->dist_sq = dist_sq;
309 copy_v3_v3(nearest->co, nearest_tmp);
310 if (self->orig_normal) {
311 copy_v3_v3(nearest->no, self->orig_normal[nearest->index]);
312 }
313 else {
314 normal_tri_v3(nearest->no, UNPACK3(tri_co));
315 }
316 }
317}
318
320 /* Wrap. */
321 py_bvhtree_ray_cast_doc,
322 ".. method:: ray_cast(origin, direction, distance=sys.float_info.max)\n"
323 "\n"
324 " Cast a ray onto the mesh.\n"
325 "\n"
326 " :arg origin: Start location of the ray in object space.\n"
327 " :type origin: :class:`Vector`\n"
328 " :arg direction: Direction of the ray in object space.\n"
329 " :type direction: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
331static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args)
332{
333 const char *error_prefix = "ray_cast";
334 float co[3], direction[3];
335 float max_dist = FLT_MAX;
336 BVHTreeRayHit hit;
337
338 /* parse args */
339 {
340 PyObject *py_co, *py_direction;
341
342 if (!PyArg_ParseTuple(args, "OO|f:ray_cast", &py_co, &py_direction, &max_dist)) {
343 return nullptr;
344 }
345
346 if ((mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) ||
347 (mathutils_array_parse(direction, 2, 3 | MU_ARRAY_ZERO, py_direction, error_prefix) == -1))
348 {
349 return nullptr;
350 }
351
352 normalize_v3(direction);
353 }
354
355 hit.dist = max_dist;
356 hit.index = -1;
357
358 /* may fail if the mesh has no faces, in that case the ray-cast misses */
359 if (self->tree) {
360 if (BLI_bvhtree_ray_cast(self->tree, co, direction, 0.0f, &hit, py_bvhtree_raycast_cb, self) !=
361 -1)
362 {
363 return py_bvhtree_raycast_to_py(&hit);
364 }
365 }
366
368}
369
371 /* Wrap. */
372 py_bvhtree_find_nearest_doc,
373 ".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR
374 ")\n"
375 "\n"
376 " Find the nearest element (typically face index) to a point.\n"
377 "\n"
378 " :arg co: Find nearest element to this point.\n"
379 " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
381static PyObject *py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args)
382{
383 const char *error_prefix = "find_nearest";
384 float co[3];
385 float max_dist = max_dist_default;
386
387 BVHTreeNearest nearest;
388
389 /* parse args */
390 {
391 PyObject *py_co;
392
393 if (!PyArg_ParseTuple(args, "O|f:find_nearest", &py_co, &max_dist)) {
394 return nullptr;
395 }
396
397 if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) {
398 return nullptr;
399 }
400 }
401
402 nearest.index = -1;
403 nearest.dist_sq = max_dist * max_dist;
404
405 /* may fail if the mesh has no faces, in that case the ray-cast misses */
406 if (self->tree) {
408 -1)
409 {
410 return py_bvhtree_nearest_to_py(&nearest);
411 }
412 }
413
415}
416
419 PyObject *result;
420 float dist_sq;
421};
422
423static void py_bvhtree_nearest_point_range_cb(void *userdata,
424 int index,
425 const float co[3],
426 float /*dist_sq_bvh*/)
427{
428 PyBVH_RangeData *data = static_cast<PyBVH_RangeData *>(userdata);
429 PyBVHTree *self = data->self;
430
431 const float(*coords)[3] = self->coords;
432 const uint *tri = self->tris[index];
433 const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]};
434 float nearest_tmp[3], dist_sq;
435
436 closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co));
437 dist_sq = len_squared_v3v3(co, nearest_tmp);
438
439 if (dist_sq < data->dist_sq) {
440 BVHTreeNearest nearest;
441 nearest.index = self->orig_index ? self->orig_index[index] : index;
442 nearest.dist_sq = dist_sq;
443 copy_v3_v3(nearest.co, nearest_tmp);
444 if (self->orig_normal) {
445 copy_v3_v3(nearest.no, self->orig_normal[nearest.index]);
446 }
447 else {
448 normal_tri_v3(nearest.no, UNPACK3(tri_co));
449 }
450
451 PyList_APPEND(data->result, py_bvhtree_nearest_to_py(&nearest));
452 }
453}
454
456 /* Wrap. */
457 py_bvhtree_find_nearest_range_doc,
458 ".. method:: find_nearest_range(origin, distance=" PYBVH_MAX_DIST_STR
459 ")\n"
460 "\n"
461 " Find the nearest elements (typically face index) to a point in the distance range.\n"
462 "\n"
463 " :arg co: Find nearest elements to this point.\n"
464 " :type co: :class:`Vector`\n" PYBVH_FIND_GENERIC_DISTANCE_DOC
466static PyObject *py_bvhtree_find_nearest_range(PyBVHTree *self, PyObject *args)
467{
468 const char *error_prefix = "find_nearest_range";
469 float co[3];
470 float max_dist = max_dist_default;
471
472 /* parse args */
473 {
474 PyObject *py_co;
475
476 if (!PyArg_ParseTuple(args, "O|f:find_nearest_range", &py_co, &max_dist)) {
477 return nullptr;
478 }
479
480 if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) {
481 return nullptr;
482 }
483 }
484
485 PyObject *ret = PyList_New(0);
486
487 if (self->tree) {
488 PyBVH_RangeData data{};
489 data.self = self;
490 data.result = ret;
491 data.dist_sq = square_f(max_dist);
493 }
494
495 return ret;
496}
497
498BLI_INLINE uint overlap_hash(const void *overlap_v)
499{
500 const BVHTreeOverlap *overlap = static_cast<const BVHTreeOverlap *>(overlap_v);
501 /* same constants as edge-hash */
502 return ((uint(overlap->indexA) * 65) ^ (uint(overlap->indexA) * 31));
503}
504
505BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v)
506{
507 const BVHTreeOverlap *a = static_cast<const BVHTreeOverlap *>(a_v);
508 const BVHTreeOverlap *b = static_cast<const BVHTreeOverlap *>(b_v);
509 return (memcmp(a, b, sizeof(*a)) != 0);
510}
511
516
517static bool py_bvhtree_overlap_cb(void *userdata, int index_a, int index_b, int /*thread*/)
518{
519 PyBVHTree_OverlapData *data = static_cast<PyBVHTree_OverlapData *>(userdata);
520 PyBVHTree *tree_a = data->tree_pair[0];
521 PyBVHTree *tree_b = data->tree_pair[1];
522 const uint *tri_a = tree_a->tris[index_a];
523 const uint *tri_b = tree_b->tris[index_b];
524 const float *tri_a_co[3] = {
525 tree_a->coords[tri_a[0]], tree_a->coords[tri_a[1]], tree_a->coords[tri_a[2]]};
526 const float *tri_b_co[3] = {
527 tree_b->coords[tri_b[0]], tree_b->coords[tri_b[1]], tree_b->coords[tri_b[2]]};
528 float ix_pair[2][3];
529 int verts_shared = 0;
530
531 if (tree_a == tree_b) {
532 if (UNLIKELY(index_a == index_b)) {
533 return false;
534 }
535
536 verts_shared = (ELEM(tri_a_co[0], UNPACK3(tri_b_co)) + ELEM(tri_a_co[1], UNPACK3(tri_b_co)) +
537 ELEM(tri_a_co[2], UNPACK3(tri_b_co)));
538
539 /* if 2 points are shared, bail out */
540 if (verts_shared >= 2) {
541 return false;
542 }
543 }
544
545 return (isect_tri_tri_v3(UNPACK3(tri_a_co), UNPACK3(tri_b_co), ix_pair[0], ix_pair[1]) &&
546 ((verts_shared == 0) || (len_squared_v3v3(ix_pair[0], ix_pair[1]) > data->epsilon)));
547}
548
550 /* Wrap. */
551 py_bvhtree_overlap_doc,
552 ".. method:: overlap(other_tree)\n"
553 "\n"
554 " Find overlapping indices between 2 trees.\n"
555 "\n"
556 " :arg other_tree: Other tree to perform overlap test on.\n"
557 " :type other_tree: :class:`BVHTree`\n"
558 " :return: Returns a list of unique index pairs,"
559 " the first index referencing this tree, the second referencing the **other_tree**.\n"
560 " :rtype: list[tuple[int, int]]\n");
561static PyObject *py_bvhtree_overlap(PyBVHTree *self, PyBVHTree *other)
562{
564 BVHTreeOverlap *overlap;
565 uint overlap_len = 0;
566 PyObject *ret;
567
568 if (!PyBVHTree_CheckExact(other)) {
569 PyErr_SetString(PyExc_ValueError, "Expected a BVHTree argument");
570 return nullptr;
571 }
572
573 data.tree_pair[0] = self;
574 data.tree_pair[1] = other;
575 data.epsilon = max_ff(self->epsilon, other->epsilon);
576
577 overlap = BLI_bvhtree_overlap(
578 self->tree, other->tree, &overlap_len, py_bvhtree_overlap_cb, &data);
579
580 ret = PyList_New(0);
581
582 if (overlap == nullptr) {
583 /* pass */
584 }
585 else {
586 const bool use_unique = (self->orig_index || other->orig_index);
587 GSet *pair_test = use_unique ?
588 BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, overlap_len) :
589 nullptr;
590 /* simple case, no index remapping */
591 uint i;
592
593 for (i = 0; i < overlap_len; i++) {
594 PyObject *item;
595 if (use_unique) {
596 if (self->orig_index) {
597 overlap[i].indexA = self->orig_index[overlap[i].indexA];
598 }
599 if (other->orig_index) {
600 overlap[i].indexB = other->orig_index[overlap[i].indexB];
601 }
602
603 /* skip if its already added */
604 if (!BLI_gset_add(pair_test, &overlap[i])) {
605 continue;
606 }
607 }
608
609 item = PyTuple_New(2);
611 item, PyLong_FromLong(overlap[i].indexA), PyLong_FromLong(overlap[i].indexB));
612
613 PyList_Append(ret, item);
614 Py_DECREF(item);
615 }
616
617 if (pair_test) {
618 BLI_gset_free(pair_test, nullptr);
619 }
620 }
621
622 if (overlap) {
623 MEM_freeN(overlap);
624 }
625
626 return ret;
627}
628
631/* -------------------------------------------------------------------- */
636 /* Wrap. */
637 C_BVHTree_FromPolygons_doc,
638 ".. classmethod:: FromPolygons(vertices, polygons, all_triangles=False, epsilon=0.0)\n"
639 "\n"
640 " BVH tree constructed geometry passed in as arguments.\n"
641 "\n"
642 " :arg vertices: float triplets each representing ``(x, y, z)``\n"
643 " :type vertices: Sequence[Sequence[float]]\n"
644 " :arg polygons: Sequence of polygons, each containing indices to the vertices argument.\n"
645 " :type polygons: Sequence[Sequence[int]]\n"
646 " :arg all_triangles: Use when all **polygons** are triangles for more efficient "
647 "conversion.\n"
648 " :type all_triangles: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
649static PyObject *C_BVHTree_FromPolygons(PyObject * /*cls*/, PyObject *args, PyObject *kwargs)
650{
651 const char *error_prefix = "BVHTree.FromPolygons";
652 const char *keywords[] = {"vertices", "polygons", "all_triangles", "epsilon", nullptr};
653
654 PyObject *py_coords, *py_tris;
655 PyObject *py_coords_fast = nullptr, *py_tris_fast = nullptr;
656
657 MemArena *poly_arena = nullptr;
658 MemArena *pf_arena = nullptr;
659
660 float(*coords)[3] = nullptr;
661 uint(*tris)[3] = nullptr;
662 uint coords_len, tris_len;
663 float epsilon = 0.0f;
664 bool all_triangles = false;
665
666 /* when all_triangles is False */
667 int *orig_index = nullptr;
668 float(*orig_normal)[3] = nullptr;
669
670 uint i;
671 bool valid = true;
672
673 if (!PyArg_ParseTupleAndKeywords(args,
674 kwargs,
675 "OO|$O&f:BVHTree.FromPolygons",
676 (char **)keywords,
677 &py_coords,
678 &py_tris,
680 &all_triangles,
681 &epsilon))
682 {
683 return nullptr;
684 }
685
686 if (!(py_coords_fast = PySequence_Fast(py_coords, error_prefix)) ||
687 !(py_tris_fast = PySequence_Fast(py_tris, error_prefix)))
688 {
689 Py_XDECREF(py_coords_fast);
690 return nullptr;
691 }
692
693 if (valid) {
694 PyObject **py_coords_fast_items = PySequence_Fast_ITEMS(py_coords_fast);
695 coords_len = uint(PySequence_Fast_GET_SIZE(py_coords_fast));
696 coords = static_cast<float(*)[3]>(MEM_mallocN(size_t(coords_len) * sizeof(*coords), __func__));
697
698 for (i = 0; i < coords_len; i++) {
699 PyObject *py_vert = py_coords_fast_items[i];
700
701 if (mathutils_array_parse(coords[i], 3, 3, py_vert, "BVHTree vertex: ") == -1) {
702 valid = false;
703 break;
704 }
705 }
706 }
707
708 if (valid == false) {
709 /* pass */
710 }
711 else if (all_triangles) {
712 /* all triangles, simple case */
713 PyObject **py_tris_fast_items = PySequence_Fast_ITEMS(py_tris_fast);
714 tris_len = uint(PySequence_Fast_GET_SIZE(py_tris_fast));
715 tris = static_cast<uint(*)[3]>(MEM_mallocN(size_t(tris_len) * sizeof(*tris), __func__));
716
717 for (i = 0; i < tris_len; i++) {
718 PyObject *py_tricoords = py_tris_fast_items[i];
719 PyObject *py_tricoords_fast;
720 PyObject **py_tricoords_fast_items;
721 uint *tri = tris[i];
722 int j;
723
724 if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
725 valid = false;
726 break;
727 }
728
729 if (PySequence_Fast_GET_SIZE(py_tricoords_fast) != 3) {
730 Py_DECREF(py_tricoords_fast);
731 PyErr_Format(PyExc_ValueError,
732 "%s: non triangle found at index %d with length of %d",
733 error_prefix,
734 i,
735 PySequence_Fast_GET_SIZE(py_tricoords_fast));
736 valid = false;
737 break;
738 }
739
740 py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
741
742 for (j = 0; j < 3; j++) {
743 tri[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
744 if (UNLIKELY(tri[j] >= uint(coords_len))) {
745 PyErr_Format(PyExc_ValueError,
746 "%s: index %d must be less than %d",
747 error_prefix,
748 tri[j],
749 coords_len);
750
751 /* decref below */
752 valid = false;
753 break;
754 }
755 }
756
757 Py_DECREF(py_tricoords_fast);
758 }
759 }
760 else {
761 /* ngon support (much more involved) */
762 const uint polys_len = uint(PySequence_Fast_GET_SIZE(py_tris_fast));
763 struct PolyLink {
764 PolyLink *next;
765 uint len;
766 uint poly[0];
767 } *plink_first = nullptr, **p_plink_prev = &plink_first, *plink = nullptr;
768 int poly_index;
769
770 tris_len = 0;
771
772 poly_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
773
774 for (i = 0; i < polys_len; i++) {
775 PyObject *py_tricoords = PySequence_Fast_GET_ITEM(py_tris_fast, i);
776 PyObject *py_tricoords_fast;
777 PyObject **py_tricoords_fast_items;
778 uint py_tricoords_len;
779 uint j;
780
781 if (!(py_tricoords_fast = PySequence_Fast(py_tricoords, error_prefix))) {
782 valid = false;
783 break;
784 }
785
786 py_tricoords_len = uint(PySequence_Fast_GET_SIZE(py_tricoords_fast));
787 py_tricoords_fast_items = PySequence_Fast_ITEMS(py_tricoords_fast);
788
789 plink = static_cast<PolyLink *>(BLI_memarena_alloc(
790 poly_arena, sizeof(*plink) + (sizeof(int) * size_t(py_tricoords_len))));
791
792 plink->len = uint(py_tricoords_len);
793 *p_plink_prev = plink;
794 p_plink_prev = &plink->next;
795
796 for (j = 0; j < py_tricoords_len; j++) {
797 plink->poly[j] = PyC_Long_AsU32(py_tricoords_fast_items[j]);
798 if (UNLIKELY(plink->poly[j] >= uint(coords_len))) {
799 PyErr_Format(PyExc_ValueError,
800 "%s: index %d must be less than %d",
801 error_prefix,
802 plink->poly[j],
803 coords_len);
804 /* decref below */
805 valid = false;
806 break;
807 }
808 }
809
810 Py_DECREF(py_tricoords_fast);
811
812 if (py_tricoords_len >= 3) {
813 tris_len += (py_tricoords_len - 2);
814 }
815 }
816 *p_plink_prev = nullptr;
817
818 /* All NGON's are parsed, now tessellate. */
819
820 pf_arena = BLI_memarena_new(BLI_POLYFILL_ARENA_SIZE, __func__);
821 tris = static_cast<uint(*)[3]>(MEM_mallocN(sizeof(*tris) * size_t(tris_len), __func__));
822
823 orig_index = static_cast<int *>(MEM_mallocN(sizeof(*orig_index) * size_t(tris_len), __func__));
824 orig_normal = static_cast<float(*)[3]>(
825 MEM_mallocN(sizeof(*orig_normal) * 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 = static_cast<float(*)[3]>(MEM_mallocN(sizeof(*coords) * size_t(coords_len), __func__));
969 tris = static_cast<uint(*)[3]>(MEM_mallocN(sizeof(*tris) * 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 = static_cast<int *>(
988 MEM_mallocN(sizeof(*orig_index) * size_t(tris_len), __func__));
989 orig_normal = static_cast<float(*)[3]>(
990 MEM_mallocN(sizeof(*orig_normal) * size_t(bm->totface), __func__));
991
993 copy_v3_v3(coords[i], v->co);
994 BM_elem_index_set(v, int(i)); /* set_inline */
995 }
996 BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
997 copy_v3_v3(orig_normal[i], f->no);
998 BM_elem_index_set(f, int(i)); /* set_inline */
999 }
1000 bm->elem_index_dirty &= char(~(BM_VERT | BM_FACE));
1001
1002 for (i = 0; i < tris_len; i++) {
1003 float co[3][3];
1004
1005 tris[i][0] = uint(BM_elem_index_get(corner_tris[i][0]->v));
1006 tris[i][1] = uint(BM_elem_index_get(corner_tris[i][1]->v));
1007 tris[i][2] = uint(BM_elem_index_get(corner_tris[i][2]->v));
1008
1009 copy_v3_v3(co[0], coords[tris[i][0]]);
1010 copy_v3_v3(co[1], coords[tris[i][1]]);
1011 copy_v3_v3(co[2], coords[tris[i][2]]);
1012
1013 BLI_bvhtree_insert(tree, int(i), co[0], 3);
1014 orig_index[i] = BM_elem_index_get(corner_tris[i][0]->f);
1015 }
1016
1018 }
1019
1021 tree, epsilon, coords, coords_len, tris, tris_len, orig_index, orig_normal);
1022 }
1023}
1024
1026static const Mesh *bvh_get_mesh(const char *funcname,
1027 Depsgraph *depsgraph,
1028 Scene *scene,
1029 Object *ob,
1030 const bool use_deform,
1031 const bool use_cage,
1032 bool *r_free_mesh)
1033{
1035 /* we only need minimum mesh data for topology and vertex locations */
1036 const CustomData_MeshMasks data_masks = CD_MASK_BAREMESH;
1037 const bool use_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER;
1038 *r_free_mesh = false;
1039
1040 /* Write the display mesh into the dummy mesh */
1041 if (use_deform) {
1042 if (use_render) {
1043 if (use_cage) {
1044 PyErr_Format(
1045 PyExc_ValueError,
1046 "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER",
1047 funcname);
1048 return nullptr;
1049 }
1050
1051 *r_free_mesh = true;
1052 return blender::bke::mesh_create_eval_final(depsgraph, scene, ob, &data_masks);
1053 }
1054 if (ob_eval != nullptr) {
1055 if (use_cage) {
1056 return blender::bke::mesh_get_eval_deform(depsgraph, scene, ob_eval, &data_masks);
1057 }
1058
1059 return BKE_object_get_evaluated_mesh(ob_eval);
1060 }
1061
1062 PyErr_Format(PyExc_ValueError,
1063 "%s(...): Cannot get evaluated data from given dependency graph / object pair",
1064 funcname);
1065 return nullptr;
1066 }
1067
1068 /* !use_deform */
1069 if (use_render) {
1070 if (use_cage) {
1071 PyErr_Format(
1072 PyExc_ValueError,
1073 "%s(...): cage arg is unsupported when dependency graph evaluation mode is RENDER",
1074 funcname);
1075 return nullptr;
1076 }
1077
1078 *r_free_mesh = true;
1079 return blender::bke::mesh_create_eval_no_deform_render(depsgraph, scene, ob, &data_masks);
1080 }
1081
1082 if (use_cage) {
1083 PyErr_Format(PyExc_ValueError,
1084 "%s(...): cage arg is unsupported when deform=False and dependency graph "
1085 "evaluation mode is not RENDER",
1086 funcname);
1087 return nullptr;
1088 }
1089
1090 *r_free_mesh = true;
1091 return blender::bke::mesh_create_eval_no_deform(depsgraph, scene, ob, &data_masks);
1092}
1093
1095 /* Wrap. */
1096 C_BVHTree_FromObject_doc,
1097 ".. classmethod:: FromObject(object, depsgraph, deform=True, render=False, "
1098 "cage=False, epsilon=0.0)\n"
1099 "\n"
1100 " BVH tree based on :class:`Object` data.\n"
1101 "\n"
1102 " :arg object: Object data.\n"
1103 " :type object: :class:`Object`\n"
1104 " :arg depsgraph: Depsgraph to use for evaluating the mesh.\n"
1105 " :type depsgraph: :class:`Depsgraph`\n"
1106 " :arg deform: Use mesh with deformations.\n"
1107 " :type deform: bool\n"
1108 " :arg cage: Use modifiers cage.\n"
1109 " :type cage: bool\n" PYBVH_FROM_GENERIC_EPSILON_DOC);
1110static PyObject *C_BVHTree_FromObject(PyObject * /*cls*/, PyObject *args, PyObject *kwargs)
1111{
1112 /* NOTE: options here match #bpy_bmesh_from_object. */
1113 const char *keywords[] = {"object", "depsgraph", "deform", "cage", "epsilon", nullptr};
1114
1115 PyObject *py_ob, *py_depsgraph;
1116 Object *ob;
1117 Depsgraph *depsgraph;
1118 Scene *scene;
1119 const Mesh *mesh;
1120 bool use_deform = true;
1121 bool use_cage = false;
1122 bool free_mesh = false;
1123
1124 float epsilon = 0.0f;
1125
1126 if (!PyArg_ParseTupleAndKeywords(args,
1127 kwargs,
1128 "OO|$O&O&f:BVHTree.FromObject",
1129 (char **)keywords,
1130 &py_ob,
1131 &py_depsgraph,
1133 &use_deform,
1135 &use_cage,
1136 &epsilon) ||
1137 ((ob = static_cast<Object *>(PyC_RNA_AsPointer(py_ob, "Object"))) == nullptr) ||
1138 ((depsgraph = static_cast<Depsgraph *>(PyC_RNA_AsPointer(py_depsgraph, "Depsgraph"))) ==
1139 nullptr))
1140 {
1141 return nullptr;
1142 }
1143
1145 mesh = bvh_get_mesh("BVHTree", depsgraph, scene, ob, use_deform, use_cage, &free_mesh);
1146
1147 if (mesh == nullptr) {
1148 return nullptr;
1149 }
1150
1151 const blender::Span<int> corner_verts = mesh->corner_verts();
1152 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
1153 const blender::Span<int> tri_faces = mesh->corner_tri_faces();
1154
1155 /* Get data for tessellation */
1156
1157 const uint coords_len = uint(mesh->verts_num);
1158
1159 float(*coords)[3] = static_cast<float(*)[3]>(
1160 MEM_mallocN(sizeof(*coords) * size_t(coords_len), __func__));
1161 uint(*tris)[3] = static_cast<uint(*)[3]>(
1162 MEM_mallocN(sizeof(*tris) * size_t(corner_tris.size()), __func__));
1163 memcpy(coords, mesh->vert_positions().data(), sizeof(float[3]) * size_t(mesh->verts_num));
1164
1165 BVHTree *tree;
1166
1167 int *orig_index = nullptr;
1168 blender::float3 *orig_normal = nullptr;
1169
1171 int(corner_tris.size()), epsilon, PY_BVH_TREE_TYPE_DEFAULT, PY_BVH_AXIS_DEFAULT);
1172 if (tree) {
1173 orig_index = static_cast<int *>(
1174 MEM_mallocN(sizeof(*orig_index) * size_t(corner_tris.size()), __func__));
1176 const blender::Span<blender::float3> face_normals = mesh->face_normals();
1177 orig_normal = static_cast<blender::float3 *>(
1178 MEM_malloc_arrayN(size_t(mesh->faces_num), sizeof(blender::float3), __func__));
1179 blender::MutableSpan(orig_normal, face_normals.size()).copy_from(face_normals);
1180 }
1181
1182 for (const int64_t i : corner_tris.index_range()) {
1183 float co[3][3];
1184
1185 tris[i][0] = uint(corner_verts[corner_tris[i][0]]);
1186 tris[i][1] = uint(corner_verts[corner_tris[i][1]]);
1187 tris[i][2] = uint(corner_verts[corner_tris[i][2]]);
1188
1189 copy_v3_v3(co[0], coords[tris[i][0]]);
1190 copy_v3_v3(co[1], coords[tris[i][1]]);
1191 copy_v3_v3(co[2], coords[tris[i][2]]);
1192
1193 BLI_bvhtree_insert(tree, int(i), co[0], 3);
1194 orig_index[i] = int(tri_faces[i]);
1195 }
1196
1198 }
1199
1200 if (free_mesh) {
1201 BKE_id_free(nullptr, const_cast<Mesh *>(mesh));
1202 }
1203
1205 epsilon,
1206 coords,
1207 coords_len,
1208 tris,
1209 uint(corner_tris.size()),
1210 orig_index,
1211 reinterpret_cast<float(*)[3]>(orig_normal));
1212}
1213#endif /* MATH_STANDALONE */
1214
1217/* -------------------------------------------------------------------- */
1221#if (defined(__GNUC__) && !defined(__clang__))
1222# pragma GCC diagnostic push
1223# pragma GCC diagnostic ignored "-Wcast-function-type"
1224#endif
1225
1226static PyMethodDef py_bvhtree_methods[] = {
1227 {"ray_cast",
1228 reinterpret_cast<PyCFunction>(py_bvhtree_ray_cast),
1229 METH_VARARGS,
1230 py_bvhtree_ray_cast_doc},
1231 {"find_nearest",
1232 reinterpret_cast<PyCFunction>(py_bvhtree_find_nearest),
1233 METH_VARARGS,
1234 py_bvhtree_find_nearest_doc},
1235 {"find_nearest_range",
1236 reinterpret_cast<PyCFunction>(py_bvhtree_find_nearest_range),
1237 METH_VARARGS,
1238 py_bvhtree_find_nearest_range_doc},
1239 {"overlap", reinterpret_cast<PyCFunction>(py_bvhtree_overlap), METH_O, py_bvhtree_overlap_doc},
1240
1241 /* class methods */
1242 {"FromPolygons",
1243 reinterpret_cast<PyCFunction>(C_BVHTree_FromPolygons),
1244 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1245 C_BVHTree_FromPolygons_doc},
1246#ifndef MATH_STANDALONE
1247 {"FromBMesh",
1248 reinterpret_cast<PyCFunction>(C_BVHTree_FromBMesh),
1249 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1250 C_BVHTree_FromBMesh_doc},
1251 {"FromObject",
1252 reinterpret_cast<PyCFunction>(C_BVHTree_FromObject),
1253 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
1254 C_BVHTree_FromObject_doc},
1255#endif
1256 {nullptr, nullptr, 0, nullptr},
1257};
1258
1259#if (defined(__GNUC__) && !defined(__clang__))
1260# pragma GCC diagnostic pop
1261#endif
1262
1263PyTypeObject PyBVHTree_Type = {
1264 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
1265 /*tp_name*/ "BVHTree",
1266 /*tp_basicsize*/ sizeof(PyBVHTree),
1267 /*tp_itemsize*/ 0,
1268 /*tp_dealloc*/ (destructor)py_bvhtree__tp_dealloc,
1269 /*tp_vectorcall_offset*/ 0,
1270 /*tp_getattr*/ nullptr,
1271 /*tp_setattr*/ nullptr,
1272 /*tp_as_async*/ nullptr,
1273 /*tp_repr*/ nullptr,
1274 /*tp_as_number*/ nullptr,
1275 /*tp_as_sequence*/ nullptr,
1276 /*tp_as_mapping*/ nullptr,
1277 /*tp_hash*/ nullptr,
1278 /*tp_call*/ nullptr,
1279 /*tp_str*/ nullptr,
1280 /*tp_getattro*/ nullptr,
1281 /*tp_setattro*/ nullptr,
1282 /*tp_as_buffer*/ nullptr,
1283 /*tp_flags*/ Py_TPFLAGS_DEFAULT,
1284 /*tp_doc*/ nullptr,
1285 /*tp_traverse*/ nullptr,
1286 /*tp_clear*/ nullptr,
1287 /*tp_richcompare*/ nullptr,
1288 /*tp_weaklistoffset*/ 0,
1289 /*tp_iter*/ nullptr,
1290 /*tp_iternext*/ nullptr,
1291 /*tp_methods*/ py_bvhtree_methods,
1292 /*tp_members*/ nullptr,
1293 /*tp_getset*/ nullptr,
1294 /*tp_base*/ nullptr,
1295 /*tp_dict*/ nullptr,
1296 /*tp_descr_get*/ nullptr,
1297 /*tp_descr_set*/ nullptr,
1298 /*tp_dictoffset*/ 0,
1299 /*tp_init*/ nullptr,
1300 /*tp_alloc*/ (allocfunc)PyType_GenericAlloc,
1301 /*tp_new*/ (newfunc)PyType_GenericNew,
1302 /*tp_free*/ (freefunc) nullptr,
1303 /*tp_is_gc*/ nullptr,
1304 /*tp_bases*/ nullptr,
1305 /*tp_mro*/ nullptr,
1306 /*tp_cache*/ nullptr,
1307 /*tp_subclasses*/ nullptr,
1308 /*tp_weaklist*/ nullptr,
1309 /*tp_del*/ (destructor) nullptr,
1310 /*tp_version_tag*/ 0,
1311 /*tp_finalize*/ nullptr,
1312 /*tp_vectorcall*/ nullptr,
1313};
1314
1315/* -------------------------------------------------------------------- */
1316/* Module definition */
1317
1319 /* Wrap. */
1320 py_bvhtree_doc,
1321 "BVH tree structures for proximity searches and ray casts on geometry.");
1322static PyModuleDef bvhtree_moduledef = {
1323 /*m_base*/ PyModuleDef_HEAD_INIT,
1324 /*m_name*/ "mathutils.bvhtree",
1325 /*m_doc*/ py_bvhtree_doc,
1326 /*m_size*/ 0,
1327 /*m_methods*/ nullptr,
1328 /*m_slots*/ nullptr,
1329 /*m_traverse*/ nullptr,
1330 /*m_clear*/ nullptr,
1331 /*m_free*/ nullptr,
1332};
1333
1335{
1336 PyObject *m = PyModule_Create(&bvhtree_moduledef);
1337
1338 if (m == nullptr) {
1339 return nullptr;
1340 }
1341
1342 /* Register classes */
1343 if (PyType_Ready(&PyBVHTree_Type) < 0) {
1344 return nullptr;
1345 }
1346
1347 PyModule_AddType(m, &PyBVHTree_Type);
1348
1349 return m;
1350}
1351
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:173
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:194
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:50
#define BLI_INLINE
struct GSet GSet
Definition BLI_ghash.h:341
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.c:936
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition BLI_ghash.c:1034
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.c: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:39
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])
void * BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2)
void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1)
struct MemArena * BLI_memarena_new(size_t bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL ATTR_NONNULL(2) ATTR_MALLOC
#define BLI_MEMARENA_STD_BUFSIZE
void 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)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
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
ATTR_WARN_UNUSED_RESULT 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
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
#define sqrtf(x)
int len
KDTree_3d * tree
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
Definition mathutils.cc:97
#define MU_ARRAY_ZERO
Definition mathutils.hh:206
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)
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)
#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)
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
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)
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)
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)
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
#define FLT_MAX
Definition stdcycles.h:14
__int64 int64_t
Definition stdint.h:89
float no[3]
float co[3]
int totvert
char elem_index_dirty
int totloop
int totface
PyObject_VAR_HEAD BMesh * bm
float(* coords)[3]
float(* orig_normal)[3]
uint(* tris)[3]
PyObject_HEAD BVHTree * tree