Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h6
-rw-r--r--source/blender/blenkernel/intern/pbvh.c43
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c19
3 files changed, 65 insertions, 3 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 {
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 74776d65a57..74afda731ea 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -4290,12 +4290,16 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
float ray_start[3], ray_end[3], ray_normal[3], dist;
float obimat[4][4];
SculptRaycastData srd;
+ bool original;
+ RegionView3D *rv3d;
view3d_set_viewcontext(C, &vc);
+ rv3d = vc.ar->regiondata;
ob = vc.obact;
ss = ob->sculpt;
cache = ss->cache;
+ original = (cache) ? cache->original : 0;
sculpt_stroke_modifiers_check(C, ob);
@@ -4309,15 +4313,24 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
sub_v3_v3v3(ray_normal, ray_end, ray_start);
dist = normalize_v3(ray_normal);
+ if (!rv3d->is_persp) {
+ BKE_pbvh_raycast_project_ray_root(ss->pbvh, srd.original, ray_start, ray_end, ray_normal);
+
+ /* recalculate the normal */
+ sub_v3_v3v3(ray_normal, ray_end, ray_start);
+ dist = normalize_v3(ray_normal);
+ }
+
+ srd.original = original;
srd.ss = vc.obact->sculpt;
+ srd.hit = 0;
srd.ray_start = ray_start;
srd.ray_normal = ray_normal;
srd.dist = dist;
- srd.hit = 0;
- srd.original = (cache) ? cache->original : 0;
+
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd,
ray_start, ray_normal, srd.original);
-
+
copy_v3_v3(out, ray_normal);
mul_v3_fl(out, srd.dist);
add_v3_v3(out, ray_start);