[Bf-blender-cvs] [3378782eeeb] blender2.8: Implement additional modes for Shrinkwrap to a surface.

Alexander Gavrilov noreply at git.blender.org
Wed Sep 26 15:53:06 CEST 2018


Commit: 3378782eeeb55a6ed64dba479e37f8b98fab63b1
Author: Alexander Gavrilov
Date:   Sat Jul 7 18:39:45 2018 +0300
Branches: blender2.8
https://developer.blender.org/rB3378782eeeb55a6ed64dba479e37f8b98fab63b1

Implement additional modes for Shrinkwrap to a surface.

In addition to the original map to surface and Keep Above Surface,
add modes that only affect vertices that are inside or outside
the object. This is inspired by the Limit Distance constraint,
and can be useful for crude collision detection in rigs.

The inside/outside test works based on face normals and may not be
completely reliable near 90 degree or sharper angles in the target.

Reviewers: campbellbarton, mont29

Differential Revision: https://developer.blender.org/D3717

===================================================================

M	release/scripts/startup/bl_ui/properties_constraint.py
M	release/scripts/startup/bl_ui/properties_data_modifier.py
M	source/blender/blenkernel/BKE_shrinkwrap.h
M	source/blender/blenkernel/intern/constraint.c
M	source/blender/blenkernel/intern/shrinkwrap.c
M	source/blender/blenloader/intern/versioning_280.c
M	source/blender/makesdna/DNA_constraint_types.h
M	source/blender/makesdna/DNA_modifier_types.h
M	source/blender/makesrna/RNA_enum_types.h
M	source/blender/makesrna/intern/rna_constraint.c
M	source/blender/makesrna/intern/rna_modifier.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 76b87a9011d..c76f3255d97 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -748,6 +748,9 @@ class ConstraintButtonsPanel:
         layout.prop(con, "distance")
         layout.prop(con, "shrinkwrap_type")
 
+        if con.shrinkwrap_type in {'PROJECT', 'NEAREST_SURFACE'}:
+            layout.prop(con, 'wrap_mode', text="Snap Mode")
+
         if con.shrinkwrap_type == 'PROJECT':
             row = layout.row(align=True)
             row.prop(con, "project_axis", expand=True)
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 8833db28056..803abe98055 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -825,6 +825,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
         col.label(text="Mode:")
         col.prop(md, "wrap_method", text="")
 
+        if md.wrap_method in {'PROJECT', 'NEAREST_SURFACEPOINT'}:
+            col.prop(md, "wrap_mode", text="")
+
         if md.wrap_method == 'PROJECT':
             split = layout.split()
             col = split.column()
@@ -851,9 +854,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
 
             layout.prop(md, "auxiliary_target")
 
-        elif md.wrap_method == 'NEAREST_SURFACEPOINT':
-            layout.prop(md, "use_keep_above_surface")
-
     def SIMPLE_DEFORM(self, layout, ob, md):
 
         layout.row().prop(md, "deform_method", expand=True)
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index d4df12783fa..40f3808b94b 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -94,6 +94,11 @@ bool BKE_shrinkwrap_project_normal(
         const struct SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit,
         BVHTree_RayCastCallback callback, void *userdata);
 
+/* Apply the shrink to surface modes to the given original coordinates and nearest point. */
+void BKE_shrinkwrap_snap_point_to_surface(
+        int mode, const float hit_co[3], const float hit_no[3], float goal_dist,
+        const float point_co[3], float r_point_co[3]);
+
 /*
  * NULL initializers to local data
  */
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 3ea2f4e0ee4..b1a7c98dc9c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -3456,7 +3456,6 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con,
 				case MOD_SHRINKWRAP_NEAREST_VERTEX:
 				{
 					BVHTreeNearest nearest;
-					float dist;
 
 					nearest.index = -1;
 					nearest.dist_sq = FLT_MAX;
@@ -3475,10 +3474,22 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con,
 
 					BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData);
 
-					dist = len_v3v3(co, nearest.co);
-					if (dist != 0.0f) {
-						interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist);   /* linear interpolation */
+					if (nearest.index < 0) {
+						fail = true;
+						break;
 					}
+
+					if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE) {
+						BKE_shrinkwrap_snap_point_to_surface(scon->shrinkMode, nearest.co, nearest.no, scon->dist, co, co);
+					}
+					else {
+						const float dist = len_v3v3(co, nearest.co);
+
+						if (dist != 0.0f) {
+							interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist) / dist);   /* linear interpolation */
+						}
+					}
+
 					BLI_space_transform_invert(&transform, co);
 					break;
 				}
@@ -3522,13 +3533,14 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *depsgraph, bConstraint *con,
 						break;
 					}
 
-					if (BKE_shrinkwrap_project_normal(0, co, no, scon->dist, &transform, treeData.tree,
+					if (BKE_shrinkwrap_project_normal(0, co, no, 0.0f, &transform, treeData.tree,
 					                                  &hit, treeData.raycast_callback, &treeData) == false)
 					{
 						fail = true;
 						break;
 					}
-					copy_v3_v3(co, hit.co);
+
+					BKE_shrinkwrap_snap_point_to_surface(scon->shrinkMode, hit.co, hit.no, scon->dist, co, co);
 					break;
 				}
 			}
diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c
index b5888856250..21b21d6ddd8 100644
--- a/source/blender/blenkernel/intern/shrinkwrap.c
+++ b/source/blender/blenkernel/intern/shrinkwrap.c
@@ -363,7 +363,7 @@ static void shrinkwrap_calc_normal_projection_cb_ex(
 	}
 
 	if (hit->index != -1) {
-		madd_v3_v3v3fl(hit->co, hit->co, tmp_no, calc->keepDist);
+		BKE_shrinkwrap_snap_point_to_surface(calc->smd->shrinkMode, hit->co, hit->no, calc->keepDist, tmp_co, hit->co);
 		interp_v3_v3v3(co, co, hit->co, weight);
 	}
 }
@@ -541,26 +541,85 @@ static void shrinkwrap_calc_nearest_surface_point_cb_ex(
 
 	/* Found the nearest vertex */
 	if (nearest->index != -1) {
-		if (calc->smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
-			/* Make the vertex stay on the front side of the face */
-			madd_v3_v3v3fl(tmp_co, nearest->co, nearest->no, calc->keepDist);
+		BKE_shrinkwrap_snap_point_to_surface(calc->smd->shrinkMode, nearest->co, nearest->no, calc->keepDist, tmp_co, tmp_co);
+
+		/* Convert the coordinates back to mesh coordinates */
+		BLI_space_transform_invert(&calc->local2target, tmp_co);
+		interp_v3_v3v3(co, co, tmp_co, weight);  /* linear interpolation */
+	}
+}
+
+/* Helper for MOD_SHRINKWRAP_INSIDE, MOD_SHRINKWRAP_OUTSIDE and MOD_SHRINKWRAP_OUTSIDE_SURFACE. */
+static void shrinkwrap_snap_with_side(float r_point_co[3], const float point_co[3], const float hit_co[3], const float hit_no[3], float goal_dist, float forcesign, bool forcesnap)
+{
+	float dist = len_v3v3(point_co, hit_co);
+
+	/* If exactly on the surface, push out along normal */
+	if (dist < FLT_EPSILON) {
+		madd_v3_v3v3fl(r_point_co, hit_co, hit_no, goal_dist * forcesign);
+	}
+	/* Move to the correct side if needed */
+	else {
+		float delta[3];
+		sub_v3_v3v3(delta, point_co, hit_co);
+		float dsign = signf(dot_v3v3(delta, hit_no));
+
+		/* If on the wrong side or too close, move to correct */
+		if (forcesnap || dsign * forcesign < 0 || dist < goal_dist) {
+			interp_v3_v3v3(r_point_co, point_co, hit_co, (dist - goal_dist * dsign * forcesign) / dist);
 		}
 		else {
-			/* Adjusting the vertex weight,
-			 * so that after interpolating it keeps a certain distance from the nearest position */
-			const float dist = sasqrt(nearest->dist_sq);
-			if (dist > FLT_EPSILON) {
-				/* linear interpolation */
-				interp_v3_v3v3(tmp_co, tmp_co, nearest->co, (dist - calc->keepDist) / dist);
+			copy_v3_v3(r_point_co, point_co);
+		}
+	}
+}
+
+/**
+ * Apply the shrink to surface modes to the given original coordinates and nearest point.
+ * r_point_co may be the same memory location as point_co, hit_co, or hit_no.
+ */
+void BKE_shrinkwrap_snap_point_to_surface(
+        int mode, const float hit_co[3], const float hit_no[3], float goal_dist,
+        const float point_co[3], float r_point_co[3])
+{
+	float dist;
+
+	switch (mode) {
+		/* Offsets along the line between point_co and hit_co. */
+		case MOD_SHRINKWRAP_ON_SURFACE:
+			if (goal_dist > 0 && (dist = len_v3v3(point_co, hit_co)) > FLT_EPSILON) {
+				interp_v3_v3v3(r_point_co, point_co, hit_co, (dist - goal_dist) / dist);
 			}
 			else {
-				copy_v3_v3(tmp_co, nearest->co);
+				copy_v3_v3(r_point_co, hit_co);
 			}
-		}
+			break;
 
-		/* Convert the coordinates back to mesh coordinates */
-		BLI_space_transform_invert(&calc->local2target, tmp_co);
-		interp_v3_v3v3(co, co, tmp_co, weight);  /* linear interpolation */
+		case MOD_SHRINKWRAP_INSIDE:
+			shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, -1, false);
+			break;
+
+		case MOD_SHRINKWRAP_OUTSIDE:
+			shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, +1, false);
+			break;
+
+		case MOD_SHRINKWRAP_OUTSIDE_SURFACE:
+			if (goal_dist > 0) {
+				shrinkwrap_snap_with_side(r_point_co, point_co, hit_co, hit_no, goal_dist, +1, true);
+			}
+			else {
+				copy_v3_v3(r_point_co, hit_co);
+			}
+			break;
+
+		/* Offsets along the normal */
+		case MOD_SHRINKWRAP_ABOVE_SURFACE:
+			madd_v3_v3v3fl(r_point_co, hit_co, hit_no, goal_dist);
+			break;
+
+		default:
+			printf("Unknown Shrinkwrap surface snap mode: %d\n", mode);
+			copy_v3_v3(r_point_co, hit_co);
 	}
 }
 
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 6b74e4f2239..4ec283c35ca 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -2074,4 +2074,20 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
 			}
 		}
 	}
+
+	{
+		if (!DNA_struct_elem_find(fd->filesdna, "ShrinkwrapModifierData", "char", "shrinkMode")) {
+			for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+				for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
+					if (md->type == eModifierType_Shrinkwrap) {
+						ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*)md;
+						if (smd->shrinkOpts & MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE) {
+							smd->shrinkMode = MOD_SHRINKWRAP_ABOVE_SURFACE;
+							smd->shrinkOpts &= ~MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE;
+						}
+					}
+				}
+			}
+		}
+	}
 }
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 4f3f3891240..e7d9e1fa7dd 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -428,7 +428,8 @@ typedef struct bShrinkwrapConstraint {
 	char		projAxis;		/* axis to project/constrain */
 	char		projAxisSpace;	/* space to project axis in */
 	float		projLimit;		/* distance to search */
-	char 		pad[4];
+	char		shrinkMode;		/* inside/outside/on surface (see MOD shrinkwrap) 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list