Changeset View
Changeset View
Standalone View
Standalone View
source/blender/makesrna/intern/rna_object_api.c
| Show First 20 Lines • Show All 481 Lines • ▼ Show 20 Lines | |||||
| /* TOOD(sergey): Make the Python API more clear that evaluation might happen, or requite | /* TOOD(sergey): Make the Python API more clear that evaluation might happen, or requite | ||||
| * passing fully evaluated depsgraph. */ | * passing fully evaluated depsgraph. */ | ||||
| static Object *eval_object_ensure(Object *ob, | static Object *eval_object_ensure(Object *ob, | ||||
| bContext *C, | bContext *C, | ||||
| ReportList *reports, | ReportList *reports, | ||||
| PointerRNA *rnaptr_depsgraph) | PointerRNA *rnaptr_depsgraph) | ||||
| { | { | ||||
| if (ob->runtime.mesh_eval == NULL) { | if (ob->runtime.data_eval == NULL) { | ||||
| Object *ob_orig = ob; | Object *ob_orig = ob; | ||||
| Depsgraph *depsgraph = rnaptr_depsgraph != NULL ? rnaptr_depsgraph->data : NULL; | Depsgraph *depsgraph = rnaptr_depsgraph != NULL ? rnaptr_depsgraph->data : NULL; | ||||
| if (depsgraph == NULL) { | if (depsgraph == NULL) { | ||||
| depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | ||||
| } | } | ||||
| if (depsgraph != NULL) { | if (depsgraph != NULL) { | ||||
| ob = DEG_get_evaluated_object(depsgraph, ob); | ob = DEG_get_evaluated_object(depsgraph, ob); | ||||
| } | } | ||||
| if (ob == NULL || ob->runtime.mesh_eval == NULL) { | if (ob == NULL || BKE_object_get_evaluated_mesh(ob) == NULL) { | ||||
| BKE_reportf( | BKE_reportf( | ||||
| reports, RPT_ERROR, "Object '%s' has no evaluated mesh data", ob_orig->id.name + 2); | reports, RPT_ERROR, "Object '%s' has no evaluated mesh data", ob_orig->id.name + 2); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| return ob; | return ob; | ||||
| } | } | ||||
| static void rna_Object_ray_cast(Object *ob, | static void rna_Object_ray_cast(Object *ob, | ||||
| bContext *C, | bContext *C, | ||||
| ReportList *reports, | ReportList *reports, | ||||
| float origin[3], | float origin[3], | ||||
| float direction[3], | float direction[3], | ||||
| float distance, | float distance, | ||||
| PointerRNA *rnaptr_depsgraph, | PointerRNA *rnaptr_depsgraph, | ||||
| bool *r_success, | bool *r_success, | ||||
| float r_location[3], | float r_location[3], | ||||
| float r_normal[3], | float r_normal[3], | ||||
| int *r_index) | int *r_index) | ||||
| { | { | ||||
| bool success = false; | bool success = false; | ||||
| /* TODO(sergey): This isn't very reliable check. It is possible to have non-NULL pointer | /* TODO(sergey): This isn't very reliable check. It is possible to have non-NULL pointer | ||||
| * but which is out of date, and possibly dangling one. */ | * but which is out of date, and possibly dangling one. */ | ||||
| if (ob->runtime.mesh_eval == NULL && | if ((ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { | ||||
| (ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { | |||||
| return; | return; | ||||
| } | } | ||||
| /* Test BoundBox first (efficiency) */ | /* Test BoundBox first (efficiency) */ | ||||
| BoundBox *bb = BKE_object_boundbox_get(ob); | BoundBox *bb = BKE_object_boundbox_get(ob); | ||||
| float distmin; | float distmin; | ||||
| normalize_v3( | normalize_v3( | ||||
| direction); /* Needed for valid distance check from isect_ray_aabb_v3_simple() call. */ | direction); /* Needed for valid distance check from isect_ray_aabb_v3_simple() call. */ | ||||
| if (!bb || | if (!bb || | ||||
| (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && | (isect_ray_aabb_v3_simple(origin, direction, bb->vec[0], bb->vec[6], &distmin, NULL) && | ||||
| distmin <= distance)) { | distmin <= distance)) { | ||||
| BVHTreeFromMesh treeData = {NULL}; | BVHTreeFromMesh treeData = {NULL}; | ||||
| /* No need to managing allocation or freeing of the BVH data. | /* No need to managing allocation or freeing of the BVH data. | ||||
| * This is generated and freed as needed. */ | * This is generated and freed as needed. */ | ||||
| BKE_bvhtree_from_mesh_get(&treeData, ob->runtime.mesh_eval, BVHTREE_FROM_LOOPTRI, 4); | Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); | ||||
| BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_LOOPTRI, 4); | |||||
| /* may fail if the mesh has no faces, in that case the ray-cast misses */ | /* may fail if the mesh has no faces, in that case the ray-cast misses */ | ||||
| if (treeData.tree != NULL) { | if (treeData.tree != NULL) { | ||||
| BVHTreeRayHit hit; | BVHTreeRayHit hit; | ||||
| hit.index = -1; | hit.index = -1; | ||||
| hit.dist = distance; | hit.dist = distance; | ||||
| if (BLI_bvhtree_ray_cast(treeData.tree, | if (BLI_bvhtree_ray_cast(treeData.tree, | ||||
| origin, | origin, | ||||
| direction, | direction, | ||||
| 0.0f, | 0.0f, | ||||
| &hit, | &hit, | ||||
| treeData.raycast_callback, | treeData.raycast_callback, | ||||
| &treeData) != -1) { | &treeData) != -1) { | ||||
| if (hit.dist <= distance) { | if (hit.dist <= distance) { | ||||
| *r_success = success = true; | *r_success = success = true; | ||||
| copy_v3_v3(r_location, hit.co); | copy_v3_v3(r_location, hit.co); | ||||
| copy_v3_v3(r_normal, hit.no); | copy_v3_v3(r_normal, hit.no); | ||||
| *r_index = mesh_looptri_to_poly_index(ob->runtime.mesh_eval, | *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[hit.index]); | ||||
| &treeData.looptri[hit.index]); | |||||
| } | } | ||||
| } | } | ||||
| free_bvhtree_from_mesh(&treeData); | free_bvhtree_from_mesh(&treeData); | ||||
| } | } | ||||
| } | } | ||||
| if (success == false) { | if (success == false) { | ||||
| *r_success = false; | *r_success = false; | ||||
| Show All 12 Lines | static void rna_Object_closest_point_on_mesh(Object *ob, | ||||
| PointerRNA *rnaptr_depsgraph, | PointerRNA *rnaptr_depsgraph, | ||||
| bool *r_success, | bool *r_success, | ||||
| float r_location[3], | float r_location[3], | ||||
| float r_normal[3], | float r_normal[3], | ||||
| int *r_index) | int *r_index) | ||||
| { | { | ||||
| BVHTreeFromMesh treeData = {NULL}; | BVHTreeFromMesh treeData = {NULL}; | ||||
| if (ob->runtime.mesh_eval == NULL && | if ((ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { | ||||
| (ob = eval_object_ensure(ob, C, reports, rnaptr_depsgraph)) == NULL) { | |||||
| return; | return; | ||||
| } | } | ||||
| /* No need to managing allocation or freeing of the BVH data. | /* No need to managing allocation or freeing of the BVH data. | ||||
| * this is generated and freed as needed. */ | * this is generated and freed as needed. */ | ||||
| BKE_bvhtree_from_mesh_get(&treeData, ob->runtime.mesh_eval, BVHTREE_FROM_LOOPTRI, 4); | Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob); | ||||
| BKE_bvhtree_from_mesh_get(&treeData, mesh_eval, BVHTREE_FROM_LOOPTRI, 4); | |||||
| if (treeData.tree == NULL) { | if (treeData.tree == NULL) { | ||||
| BKE_reportf(reports, | BKE_reportf(reports, | ||||
| RPT_ERROR, | RPT_ERROR, | ||||
| "Object '%s' could not create internal data for finding nearest point", | "Object '%s' could not create internal data for finding nearest point", | ||||
| ob->id.name + 2); | ob->id.name + 2); | ||||
| return; | return; | ||||
| } | } | ||||
| else { | else { | ||||
| BVHTreeNearest nearest; | BVHTreeNearest nearest; | ||||
| nearest.index = -1; | nearest.index = -1; | ||||
| nearest.dist_sq = distance * distance; | nearest.dist_sq = distance * distance; | ||||
| if (BLI_bvhtree_find_nearest( | if (BLI_bvhtree_find_nearest( | ||||
| treeData.tree, origin, &nearest, treeData.nearest_callback, &treeData) != -1) { | treeData.tree, origin, &nearest, treeData.nearest_callback, &treeData) != -1) { | ||||
| *r_success = true; | *r_success = true; | ||||
| copy_v3_v3(r_location, nearest.co); | copy_v3_v3(r_location, nearest.co); | ||||
| copy_v3_v3(r_normal, nearest.no); | copy_v3_v3(r_normal, nearest.no); | ||||
| *r_index = mesh_looptri_to_poly_index(ob->runtime.mesh_eval, | *r_index = mesh_looptri_to_poly_index(mesh_eval, &treeData.looptri[nearest.index]); | ||||
| &treeData.looptri[nearest.index]); | |||||
| goto finally; | goto finally; | ||||
| } | } | ||||
| } | } | ||||
| *r_success = false; | *r_success = false; | ||||
| zero_v3(r_location); | zero_v3(r_location); | ||||
| Show All 24 Lines | void rna_Object_me_eval_info( | ||||
| Mesh *me_eval = NULL; | Mesh *me_eval = NULL; | ||||
| char *ret = NULL; | char *ret = NULL; | ||||
| result[0] = '\0'; | result[0] = '\0'; | ||||
| switch (type) { | switch (type) { | ||||
| case 1: | case 1: | ||||
| case 2: | case 2: | ||||
| if (ob->runtime.mesh_eval == NULL && | if ((ob = eval_object_ensure(ob, C, NULL, rnaptr_depsgraph)) == NULL) { | ||||
| (ob = eval_object_ensure(ob, C, NULL, rnaptr_depsgraph)) == NULL) { | |||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| switch (type) { | switch (type) { | ||||
| case 0: | case 0: | ||||
| if (ob->type == OB_MESH) { | if (ob->type == OB_MESH) { | ||||
| me_eval = ob->data; | me_eval = ob->data; | ||||
| } | } | ||||
| break; | break; | ||||
| case 1: | case 1: | ||||
| me_eval = ob->runtime.mesh_deform_eval; | me_eval = ob->runtime.mesh_deform_eval; | ||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| me_eval = ob->runtime.mesh_eval; | me_eval = BKE_object_get_evaluated_mesh(ob); | ||||
| break; | break; | ||||
| } | } | ||||
| if (me_eval) { | if (me_eval) { | ||||
| ret = BKE_mesh_runtime_debug_info(me_eval); | ret = BKE_mesh_runtime_debug_info(me_eval); | ||||
| if (ret) { | if (ret) { | ||||
| strcpy(result, ret); | strcpy(result, ret); | ||||
| MEM_freeN(ret); | MEM_freeN(ret); | ||||
| ▲ Show 20 Lines • Show All 509 Lines • Show Last 20 Lines | |||||