diff options
Diffstat (limited to 'source/blender/python/mathutils/mathutils_bvhtree.c')
-rw-r--r-- | source/blender/python/mathutils/mathutils_bvhtree.c | 106 |
1 files changed, 99 insertions, 7 deletions
diff --git a/source/blender/python/mathutils/mathutils_bvhtree.c b/source/blender/python/mathutils/mathutils_bvhtree.c index bf06b889e25..ff1761eb6d7 100644 --- a/source/blender/python/mathutils/mathutils_bvhtree.c +++ b/source/blender/python/mathutils/mathutils_bvhtree.c @@ -72,10 +72,16 @@ " :type distance: float\n" #define PYBVH_FIND_GENERIC_RETURN_DOC \ -" :return: Returns a tuple (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ +" :return: Returns a tuple\n" \ +" (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ " Values will all be None if no hit is found.\n" \ " :rtype: :class:`tuple`\n" +#define PYBVH_FIND_GENERIC_RETURN_LIST_DOC \ +" :return: Returns a list of tuples\n" \ +" (:class:`Vector` location, :class:`Vector` normal, int index, float distance),\n" \ +" :rtype: :class:`list`\n" + #define PYBVH_FROM_GENERIC_EPSILON_DOC \ " :arg epsilon: Increase the threshold for detecting overlap and raycast hits.\n" \ " :type epsilon: float\n" @@ -328,7 +334,7 @@ static void py_bvhtree_nearest_point_cb(void *userdata, int index, const float c } PyDoc_STRVAR(py_bvhtree_ray_cast_doc, -".. method:: ray_cast(co, direction, distance=sys.float_info.max)\n" +".. method:: ray_cast(origin, direction, distance=sys.float_info.max)\n" "\n" " Cast a ray onto the mesh.\n" "\n" @@ -352,7 +358,7 @@ static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args) if (!PyArg_ParseTuple( args, (char *)"OO|f:ray_cast", - &py_co, &py_direction, max_dist)) + &py_co, &py_direction, &max_dist)) { return NULL; } @@ -383,7 +389,7 @@ static PyObject *py_bvhtree_ray_cast(PyBVHTree *self, PyObject *args) } PyDoc_STRVAR(py_bvhtree_find_nearest_doc, -".. method:: find_nearest(co, distance=" PYBVH_MAX_DIST_STR ")\n" +".. method:: find_nearest(origin, distance=" PYBVH_MAX_DIST_STR ")\n" "\n" " Find the nearest element to a point.\n" "\n" @@ -432,6 +438,91 @@ static PyObject *py_bvhtree_find_nearest(PyBVHTree *self, PyObject *args) return py_bvhtree_nearest_to_py_none(); } +struct PyBVH_RangeData { + PyBVHTree *self; + PyObject *result; + float dist_sq; +}; + +static void py_bvhtree_nearest_point_range_cb(void *userdata, int index, const float co[3], float UNUSED(dist_sq_bvh)) +{ + struct PyBVH_RangeData *data = userdata; + PyBVHTree *self = data->self; + + const float (*coords)[3] = (const float (*)[3])self->coords; + const unsigned int *tri = self->tris[index]; + const float *tri_co[3] = {coords[tri[0]], coords[tri[1]], coords[tri[2]]}; + float nearest_tmp[3], dist_sq; + + closest_on_tri_to_point_v3(nearest_tmp, co, UNPACK3(tri_co)); + dist_sq = len_squared_v3v3(co, nearest_tmp); + + if (dist_sq < data->dist_sq) { + BVHTreeNearest nearest; + nearest.index = self->orig_index ? self->orig_index[index] : index; + nearest.dist_sq = dist_sq; + copy_v3_v3(nearest.co, nearest_tmp); + if (self->orig_normal) { + copy_v3_v3(nearest.no, self->orig_normal[nearest.index]); + } + else { + normal_tri_v3(nearest.no, UNPACK3(tri_co)); + } + + PyList_APPEND(data->result, py_bvhtree_nearest_to_py(&nearest)); + } +} + +PyDoc_STRVAR(py_bvhtree_find_nearest_range_doc, +".. method:: find_nearest_range(origin, distance=" PYBVH_MAX_DIST_STR ")\n" +"\n" +" Find the nearest elements to a point in the distance range.\n" +"\n" +" :arg co: Find nearest elements to this point.\n" +" :type co: :class:`Vector`\n" +PYBVH_FIND_GENERIC_DISTANCE_DOC +PYBVH_FIND_GENERIC_RETURN_LIST_DOC +); +static PyObject *py_bvhtree_find_nearest_range(PyBVHTree *self, PyObject *args) +{ + const char *error_prefix = "find_nearest_range"; + float co[3]; + float max_dist = max_dist_default; + + /* parse args */ + { + PyObject *py_co; + + if (!PyArg_ParseTuple( + args, (char *)"O|f:find_nearest_range", + &py_co, &max_dist)) + { + return NULL; + } + + if (mathutils_array_parse(co, 2, 3 | MU_ARRAY_ZERO, py_co, error_prefix) == -1) { + return NULL; + } + } + + PyObject *ret = PyList_New(0); + + if (self->tree) { + struct PyBVH_RangeData data = { + .self = self, + .result = ret, + .dist_sq = SQUARE(max_dist), + }; + + BLI_bvhtree_range_query( + self->tree, co, max_dist, + py_bvhtree_nearest_point_range_cb, &data); + } + + return ret; +} + + BLI_INLINE unsigned int overlap_hash(const void *overlap_v) { const BVHTreeOverlap *overlap = overlap_v; @@ -777,7 +868,7 @@ static PyObject *C_BVHTree_FromPolygons(PyObject *UNUSED(cls), PyObject *args, P axis_dominant_v3_to_m3_negate(axis_mat, normal); for (j = 0; j < plink->len; j++) { - mul_v2_m3v3(proj_coords[i], axis_mat, coords[plink->poly[j]]); + mul_v2_m3v3(proj_coords[j], axis_mat, coords[plink->poly[j]]); } BLI_polyfill_calc_arena((const float (*)[2])proj_coords, plink->len, 1, tris_offset, pf_arena); @@ -894,7 +985,7 @@ static PyObject *C_BVHTree_FromBMesh(PyObject *UNUSED(cls), PyObject *args, PyOb looptris = MEM_mallocN(sizeof(*looptris) * (size_t)tris_len, __func__); - BM_bmesh_calc_tessellation(bm, looptris, &tris_len_dummy); + BM_mesh_calc_tessellation(bm, looptris, &tris_len_dummy); BLI_assert(tris_len_dummy == (int)tris_len); } @@ -1132,7 +1223,8 @@ static PyObject *C_BVHTree_FromObject(PyObject *UNUSED(cls), PyObject *args, PyO static PyMethodDef py_bvhtree_methods[] = { {"ray_cast", (PyCFunction)py_bvhtree_ray_cast, METH_VARARGS, py_bvhtree_ray_cast_doc}, - {"find", (PyCFunction)py_bvhtree_find_nearest, METH_VARARGS, py_bvhtree_find_nearest_doc}, + {"find_nearest", (PyCFunction)py_bvhtree_find_nearest, METH_VARARGS, py_bvhtree_find_nearest_doc}, + {"find_nearest_range", (PyCFunction)py_bvhtree_find_nearest_range, METH_VARARGS, py_bvhtree_find_nearest_range_doc}, {"overlap", (PyCFunction)py_bvhtree_overlap, METH_O, py_bvhtree_overlap_doc}, /* class methods */ |