PyAPI: Change ray_cast to fix & improve behavior

- It wasn't possible to know when Object.ray_cast was successful
  in the case when it hit a face with no original index.
- Take (ray_start, ray_direction) vectors.
- Take an optional distance argument.
- Scene/Object.ray_cast now use matching arguments & return values.

See D1650 (own patch)
This commit is contained in:
Campbell Barton 2015-12-02 19:07:24 +11:00
parent e16d39b793
commit 08fb55eea2
Notes: blender-bot 2023-02-14 10:21:11 +01:00
Referenced by issue #53714, Object.raycast() does not detect intersections where it should
2 changed files with 68 additions and 48 deletions

View File

@ -315,8 +315,10 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt)
return index_mp_to_orig ? index_mp_to_orig[lt->poly] : lt->poly;
}
static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start[3], float ray_end[3],
float r_location[3], float r_normal[3], int *index)
static void rna_Object_ray_cast(
Object *ob, ReportList *reports,
float origin[3], float direction[3], float distance,
int *r_success, float r_location[3], float r_normal[3], int *r_index)
{
BVHTreeFromMesh treeData = {NULL};
@ -331,33 +333,41 @@ static void rna_Object_ray_cast(Object *ob, ReportList *reports, float ray_start
/* may fail if the mesh has no faces, in that case the ray-cast misses */
if (treeData.tree != NULL) {
BVHTreeRayHit hit;
float ray_nor[3], dist;
sub_v3_v3v3(ray_nor, ray_end, ray_start);
dist = hit.dist = normalize_v3(ray_nor);
hit.index = -1;
hit.dist = distance;
if (BLI_bvhtree_ray_cast(treeData.tree, ray_start, ray_nor, 0.0f, &hit,
normalize_v3(direction);
if (BLI_bvhtree_ray_cast(treeData.tree, origin, direction, 0.0f, &hit,
treeData.raycast_callback, &treeData) != -1)
{
if (hit.dist <= dist) {
if (hit.dist <= distance) {
*r_success = true;
copy_v3_v3(r_location, hit.co);
copy_v3_v3(r_normal, hit.no);
*index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
free_bvhtree_from_mesh(&treeData);
return;
*r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[hit.index]);
goto finally;
}
}
}
*r_success = false;
zero_v3(r_location);
zero_v3(r_normal);
*index = -1;
*r_index = -1;
finally:
free_bvhtree_from_mesh(&treeData);
}
static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, float point_co[3], float max_dist,
float n_location[3], float n_normal[3], int *index)
static void rna_Object_closest_point_on_mesh(
Object *ob, ReportList *reports, float origin[3], float distance,
int *r_success, float r_location[3], float r_normal[3], int *r_index)
{
BVHTreeFromMesh treeData = {NULL};
@ -379,20 +389,26 @@ static void rna_Object_closest_point_on_mesh(Object *ob, ReportList *reports, fl
BVHTreeNearest nearest;
nearest.index = -1;
nearest.dist_sq = max_dist * max_dist;
nearest.dist_sq = distance * distance;
if (BLI_bvhtree_find_nearest(treeData.tree, point_co, &nearest, treeData.nearest_callback, &treeData) != -1) {
copy_v3_v3(n_location, nearest.co);
copy_v3_v3(n_normal, nearest.no);
*index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[nearest.index]);
free_bvhtree_from_mesh(&treeData);
return;
if (BLI_bvhtree_find_nearest(treeData.tree, origin, &nearest, treeData.nearest_callback, &treeData) != -1) {
*r_success = true;
copy_v3_v3(r_location, nearest.co);
copy_v3_v3(r_normal, nearest.no);
*r_index = dm_looptri_to_poly_index(ob->derivedFinal, &treeData.looptri[nearest.index]);
goto finally;
}
}
zero_v3(n_location);
zero_v3(n_normal);
*index = -1;
*r_success = false;
zero_v3(r_location);
zero_v3(r_normal);
*r_index = -1;
finally:
free_bvhtree_from_mesh(&treeData);
}
@ -593,12 +609,15 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* ray start and end */
parm = RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
parm = RNA_def_float_vector(func, "direction", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_float(func, "distance", FLT_MAX, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
parm = RNA_def_boolean(func, "result", 0, "", "");
RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The hit location of this ray cast", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@ -607,8 +626,7 @@ void RNA_api_object(StructRNA *srna)
"The face normal at the ray cast hit location", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no intersection is found", 0, 0);
parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
RNA_def_function_output(func, parm);
/* Nearest Point */
@ -617,12 +635,14 @@ void RNA_api_object(StructRNA *srna)
RNA_def_function_flag(func, FUNC_USE_REPORTS);
/* location of point for test and max distance */
parm = RNA_def_float_vector(func, "point", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
/* default is sqrt(FLT_MAX) */
RNA_def_float(func, "max_dist", 1.844674352395373e+19, 0.0, FLT_MAX, "", "", 0.0, FLT_MAX);
RNA_def_float(func, "distance", 1.844674352395373e+19, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
parm = RNA_def_boolean(func, "result", 0, "", "");
RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The location on the object closest to the point", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@ -632,7 +652,7 @@ void RNA_api_object(StructRNA *srna)
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when no closest point is found", 0, 0);
parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
RNA_def_function_output(func, parm);
/* View */

View File

@ -137,31 +137,28 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, int previe
}
}
static void rna_Scene_ray_cast(Scene *scene, float ray_start[3], float ray_end[3],
int *r_success, Object **r_ob, float r_obmat[16],
float r_location[3], float r_normal[3])
static void rna_Scene_ray_cast(
Scene *scene, float origin[3], float direction[3], float ray_dist,
int *r_success, float r_location[3], float r_normal[3], int *r_index,
Object **r_ob, float r_obmat[16])
{
float ray_nor[3];
float ray_dist;
sub_v3_v3v3(ray_nor, ray_end, ray_start);
ray_dist = normalize_v3(ray_nor);
normalize_v3(direction);
if (snapObjectsRayEx(
scene, NULL, NULL, NULL, NULL,
NULL, SNAP_ALL, SCE_SNAP_MODE_FACE,
ray_start, ray_nor, &ray_dist,
r_location, r_normal, NULL, NULL,
origin, direction, &ray_dist,
r_location, r_normal, NULL, r_index,
r_ob, (float(*)[4])r_obmat))
{
*r_success = true;
}
else {
*r_success = false;
unit_m4((float(*)[4])r_obmat);
zero_v3(r_location);
zero_v3(r_normal);
*r_success = false;
}
}
@ -231,18 +228,15 @@ void RNA_api_scene(StructRNA *srna)
RNA_def_function_ui_description(func, "Cast a ray onto in object space");
/* ray start and end */
parm = RNA_def_float_vector(func, "start", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
parm = RNA_def_float_vector(func, "origin", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
parm = RNA_def_float_vector(func, "end", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
parm = RNA_def_float_vector(func, "direction", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_REQUIRED);
RNA_def_float(func, "distance", FLT_MAX, 0.0, FLT_MAX, "", "Maximum distance", 0.0, FLT_MAX);
/* return location and normal */
parm = RNA_def_boolean(func, "result", 0, "", "");
RNA_def_function_output(func, parm);
parm = RNA_def_pointer(func, "object", "Object", "", "Ray cast object");
RNA_def_function_output(func, parm);
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_function_output(func, parm);
parm = RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location",
"The hit location of this ray cast", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
@ -251,6 +245,12 @@ void RNA_api_scene(StructRNA *srna)
"The face normal at the ray cast hit location", -1e4, 1e4);
RNA_def_property_flag(parm, PROP_THICK_WRAP);
RNA_def_function_output(func, parm);
parm = RNA_def_int(func, "index", 0, 0, 0, "", "The face index, -1 when original data isn't available", 0, 0);
RNA_def_function_output(func, parm);
parm = RNA_def_pointer(func, "object", "Object", "", "Ray cast object");
RNA_def_function_output(func, parm);
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_function_output(func, parm);
#ifdef WITH_COLLADA
/* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */