diff options
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_pbvh.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pbvh.c | 43 |
2 files changed, 49 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index f8c21a1fa16..7ef120e26af 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -97,6 +97,12 @@ int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use const float ray_start[3], const float ray_normal[3], float *dist); +/* for orthographic cameras, project the far away ray segment points to the root node so + * we can have better precision. Warning, this function assumes that ray begins and ends outside + * bounding box! */ +void BKE_pbvh_raycast_project_ray_root(PBVH *bvh, bool original, float ray_start[3], + float ray_end[3], float ray_normal[3]); + /* Drawing */ void BKE_pbvh_node_draw(PBVHNode *node, void *data); diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index c9822600fe7..061a54da96f 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1541,6 +1541,49 @@ int BKE_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], int use return hit; } +void BKE_pbvh_raycast_project_ray_root (PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]) +{ + if (bvh->nodes) { + float rootmin_start, rootmin_end; + float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3]; + IsectRayAABBData ray; + float ray_normal_inv[3]; + float offset = 1.0f + 1e-3f; + float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f}; + + if (original) + BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root); + else + BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root); + + /* slightly offset min and max in case we have a zero width node (due to a plane mesh for instance), + * or faces very close to the bounding box boundary. */ + mid_v3_v3v3(bb_center, bb_max_root, bb_min_root); + /* diff should be same for both min/max since it's calculated from center */ + sub_v3_v3v3(bb_diff, bb_max_root, bb_center); + /* handles case of zero width bb */ + add_v3_v3(bb_diff, offset_vec); + madd_v3_v3v3fl(bb_max_root, bb_center, bb_diff, offset); + madd_v3_v3v3fl(bb_min_root, bb_center, bb_diff, -offset); + + /* first project start ray */ + isect_ray_aabb_initialize(&ray, ray_start, ray_normal); + if (!isect_ray_aabb(&ray, bb_min_root, bb_max_root, &rootmin_start)) + return; + + /* then the end ray */ + mul_v3_v3fl(ray_normal_inv, ray_normal, -1.0); + isect_ray_aabb_initialize(&ray, ray_end, ray_normal_inv); + /* unlikely to fail exiting if entering succeeded, still keep this here */ + if (!isect_ray_aabb(&ray, bb_min_root, bb_max_root, &rootmin_end)) + return; + + madd_v3_v3v3fl(ray_start, ray_start, ray_normal, rootmin_start); + madd_v3_v3v3fl(ray_end, ray_end, ray_normal_inv, rootmin_end); + } +} + + //#include <GL/glew.h> typedef struct { |